deadbyte-mcp 0.15.37 → 0.15.39
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/MANIFEST.SHA256 +41 -22
- package/PROVENANCE.json +55 -20
- package/README.txt +19 -19
- package/RELEASE.json +50 -21
- package/SBOM.cdx.json +2 -2
- package/TEST-MATRIX.json +67 -15
- package/bridge/package.json +1 -1
- package/bridge/src/bridge.mjs +4 -4
- package/bridge/src/r40-governor.mjs +109 -19
- package/controller/deadbyte-process-policy.json +4 -4
- package/docs/R61-TASK-CONTRACT.md +11 -0
- package/docs/r61-reference-evidence.md +18 -0
- package/package.json +5 -3
- package/scripts/gate-windows-r61-prepublish.ps1 +45 -0
- package/scripts/gate-windows-r62-prepublish.ps1 +45 -0
- package/scripts/npm-artifact-identity-r61.mjs +22 -0
- package/scripts/npm-release-r48.mjs +21 -5
- package/scripts/r61-mixed-lane-benchmark.mjs +98 -0
- package/scripts/r62-focused.ps1 +9 -0
- package/scripts/r62-full.ps1 +9 -0
- package/scripts/r62-live-transaction-audit.mjs +17 -0
- package/scripts/r62-unresolved-transaction-inspect.mjs +54 -0
- package/src/deadbyte-cli.mjs +9 -6
- package/src/doctor-transactions-r58.mjs +79 -8
- package/src/remote-live-log.mjs +28 -5
- package/src/runtime-update.mjs +28 -4
- package/src/version.mjs +1 -1
- package/test/bridge-runtime-r59.test.mjs +5 -5
- package/test/commander-schema-differential-r48.test.mjs +1 -1
- package/test/r58-doctor-transactions.test.mjs +2 -2
- package/test/r60-release-contract.test.mjs +4 -3
- package/test/r61-control-lane.test.mjs +154 -0
- package/test/r61-live-timeline-bounds.test.mjs +31 -0
- package/test/r61-npm-artifact-identity.test.mjs +17 -0
- package/test/r61-release-bridge-binding.test.mjs +32 -0
- package/test/r61-release-contract.test.mjs +45 -0
- package/test/r62-doctor-receipt-semantics.test.mjs +50 -0
- package/test/r62-doctor-transactions-reconcile.test.mjs +208 -0
- package/test/r62-release-contract.test.mjs +59 -0
- package/test/r62-rollback-failure-receipt.test.mjs +19 -0
- package/test/remote-live-log-r37.test.mjs +23 -6
- package/test/remote-session-cli.test.mjs +1 -1
package/TEST-MATRIX.json
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "deadbyte.test-matrix.v1",
|
|
3
|
-
"version": "0.15.
|
|
4
|
-
"train": "
|
|
3
|
+
"version": "0.15.39",
|
|
4
|
+
"train": "R62",
|
|
5
5
|
"primary_platform": "win32-x64",
|
|
6
6
|
"reference": {
|
|
7
7
|
"package": "@wonderwhy-er/desktop-commander",
|
|
@@ -11,19 +11,24 @@
|
|
|
11
11
|
},
|
|
12
12
|
"required": [
|
|
13
13
|
{
|
|
14
|
-
"id": "
|
|
15
|
-
"command": "npm run
|
|
16
|
-
"expected": "PASS
|
|
14
|
+
"id": "r62-focused",
|
|
15
|
+
"command": "npm run r62:focused:test",
|
|
16
|
+
"expected": "PASS R62 release identity, signed transaction reconciliation, R31 signed failure receipt producer/consumer, inherited rollback/update contracts"
|
|
17
17
|
},
|
|
18
18
|
{
|
|
19
|
-
"id": "
|
|
20
|
-
"command": "
|
|
21
|
-
"expected": "
|
|
19
|
+
"id": "r62-live-parent-audit",
|
|
20
|
+
"command": "node scripts/r62-live-transaction-audit.mjs",
|
|
21
|
+
"expected": "READ-ONLY complete parent inventory; verify every available signed terminal receipt; preserve unsigned residue"
|
|
22
|
+
},
|
|
23
|
+
{
|
|
24
|
+
"id": "r62-full-regression",
|
|
25
|
+
"command": "npm test",
|
|
26
|
+
"expected": "PASS complete current R62 regression with only documented historical/platform skips"
|
|
22
27
|
},
|
|
23
28
|
{
|
|
24
29
|
"id": "windows-gate",
|
|
25
30
|
"command": "npm run gate:windows",
|
|
26
|
-
"expected": "PASS exact 0.15.
|
|
31
|
+
"expected": "PASS exact sealed 0.15.38 predecessor, focused/full regression, manifest verify and doctor"
|
|
27
32
|
},
|
|
28
33
|
{
|
|
29
34
|
"id": "package-verify",
|
|
@@ -37,18 +42,18 @@
|
|
|
37
42
|
},
|
|
38
43
|
{
|
|
39
44
|
"id": "activation",
|
|
40
|
-
"command": "activate exact packed deadbyte-mcp@0.15.
|
|
41
|
-
"expected": "activate exact
|
|
45
|
+
"command": "activate exact packed deadbyte-mcp@0.15.39 candidate",
|
|
46
|
+
"expected": "activate exact R62 from exact active 0.15.38 only after prepublish/package gates"
|
|
42
47
|
},
|
|
43
48
|
{
|
|
44
49
|
"id": "rollback",
|
|
45
|
-
"command": "runtime-update --rollback-receipt <signed
|
|
46
|
-
"expected": "restore exact signed 0.15.
|
|
50
|
+
"command": "runtime-update --rollback-receipt <signed R62 activation receipt>",
|
|
51
|
+
"expected": "restore exact signed 0.15.38 pointer/runtime and verify release/generation/machine binding"
|
|
47
52
|
},
|
|
48
53
|
{
|
|
49
54
|
"id": "restore",
|
|
50
|
-
"command": "restore exact same packed 0.15.
|
|
51
|
-
"expected": "restore exact immutable
|
|
55
|
+
"command": "restore exact same packed 0.15.39 candidate",
|
|
56
|
+
"expected": "restore exact immutable R62 release and verify public MCP without rebuild"
|
|
52
57
|
}
|
|
53
58
|
],
|
|
54
59
|
"observed_pre_release_evidence": {
|
|
@@ -212,6 +217,39 @@
|
|
|
212
217
|
},
|
|
213
218
|
"r60_activation_rollback_restore": {
|
|
214
219
|
"status": "PENDING"
|
|
220
|
+
},
|
|
221
|
+
"r62_transaction_reconciliation": {
|
|
222
|
+
"tdd_red_receipt_sha256": "16118ec5e0c71957ec5509de6e774e12cbf9d2e657e1fd3e62a66bc86f36c89a",
|
|
223
|
+
"budget_red_receipt_sha256": "e0793a32d9c9d80c14035da3120b502185c784be22e1640bb4e5e71719c38d0d",
|
|
224
|
+
"terminal_proof_red_receipt_sha256": "7528cbba9b90b79aea580d1ef28cb7ae61094ef59782d1c2c68d63d7db67131f",
|
|
225
|
+
"r31_consumer_red_receipt_sha256": "a1689e1401da1b1ef0b58eaab89ad252adc5b603daeb910265c59844a29468fe",
|
|
226
|
+
"r31_producer_red_receipt_sha256": "f545c8a23fd9c80bf4dec6598a0f1c5682f8042826f52857bc21995a75308836",
|
|
227
|
+
"receipt_semantics_red_receipt_sha256": "591be25ff760f5790a7ce9d82a02642fdc71f7c8519e33f4d77de4462408ea94",
|
|
228
|
+
"focused_green_receipt_sha256": "c22d815903145fcd69eec58ca8feb7d6b15357165cb87642473de681c0a401c4",
|
|
229
|
+
"r31_producer_green_receipt_sha256": "0f0211ef085f4e9609b2c86ab78a0cb29bd59c3799093bb9247fe223a0783dcd",
|
|
230
|
+
"parent_live_audit_receipt_sha256": "08eabb45edb661e3542fdbdb985148cd1645f6cbd2dd916cb3c11162ae2e8c2b",
|
|
231
|
+
"parent_states_checked": 341,
|
|
232
|
+
"parent_signed_terminal_receipts_verified": 322,
|
|
233
|
+
"parent_unresolved_unsigned_transactions": 14,
|
|
234
|
+
"historical_evidence_mutation": false,
|
|
235
|
+
"package_boundary_red_receipt_sha256": "df0173b771d7e0170c5e8b6bb4eee26e64d19b42807634af666462cac2b26bb7",
|
|
236
|
+
"package_boundary_green_receipt_sha256": "ccbe983ef796676818f5fcd9a987b589f18472b88e23b59016f5e25525435e7c",
|
|
237
|
+
"full_regression": {
|
|
238
|
+
"tests": 1264,
|
|
239
|
+
"passed": 1226,
|
|
240
|
+
"skipped": 38,
|
|
241
|
+
"failed": 0,
|
|
242
|
+
"status": "PASS_PRE_METADATA_SEAL"
|
|
243
|
+
},
|
|
244
|
+
"windows_gate": {
|
|
245
|
+
"status": "PASS_PRE_METADATA_SEAL",
|
|
246
|
+
"manifest_entries": 2223,
|
|
247
|
+
"manifest_sha256": "034afc13a19c8f7d1cb9e01e95127084f576251bd72b5408a2c378a37907b7ae"
|
|
248
|
+
},
|
|
249
|
+
"package": "PENDING",
|
|
250
|
+
"registry": "PENDING",
|
|
251
|
+
"activation_rollback_restore": "PENDING",
|
|
252
|
+
"status": "PASS_PREPUBLISH_PRE_METADATA_SEAL"
|
|
215
253
|
}
|
|
216
254
|
},
|
|
217
255
|
"inherited_parent_evidence": {
|
|
@@ -282,6 +320,20 @@
|
|
|
282
320
|
"candidate_version": "0.15.37",
|
|
283
321
|
"public_surface_tool_count": 43,
|
|
284
322
|
"status": "PENDING_POST_FREEZE_MEASUREMENT"
|
|
323
|
+
},
|
|
324
|
+
"r61": {
|
|
325
|
+
"baseline_version": "0.15.37",
|
|
326
|
+
"candidate_version": "0.15.38",
|
|
327
|
+
"public_surface_tool_count": 43,
|
|
328
|
+
"governor_benchmark_path": "D:\\Projects\\deadbyte-mcp\\testing\\0.15.38\\r61-ab-nine-rounds.json",
|
|
329
|
+
"governor_benchmark_status": "PASS_SCOPED_DIRECT_GOVERNOR",
|
|
330
|
+
"full_mcp_performance_status": "PENDING"
|
|
331
|
+
},
|
|
332
|
+
"r62": {
|
|
333
|
+
"baseline_version": "0.15.38",
|
|
334
|
+
"candidate_version": "0.15.39",
|
|
335
|
+
"public_surface_tool_count": 43,
|
|
336
|
+
"status": "NO_MCP_HOT_PATH_CHANGE_TRANSACTION_DIAGNOSTIC_ONLY"
|
|
285
337
|
}
|
|
286
338
|
},
|
|
287
339
|
"non_win32": {
|
package/bridge/package.json
CHANGED
package/bridge/src/bridge.mjs
CHANGED
|
@@ -419,9 +419,9 @@ function buildFrontServer() {
|
|
|
419
419
|
if(!currentHealth.core||['STARTING','RECONCILING','STOPPING'].includes(currentHealth.state)) throw new Error(`bridge correlation generation=${downstreamGeneration}; downstream ${currentHealth.state.toLowerCase()}; request not dispatched`);
|
|
420
420
|
if (tool.name !== 'autonomous_goal_run') {
|
|
421
421
|
const audit = auditToolStart(tool.name, args);
|
|
422
|
-
const ticket = await bridgeGovernor.acquire(tool.name,{signal:ctx.mcpReq.signal});
|
|
422
|
+
const ticket = await bridgeGovernor.acquire(tool.name,{signal:ctx.mcpReq.signal,arguments:args});
|
|
423
423
|
try {
|
|
424
|
-
const budget = bridgeDeadlineForTool(tool.name);
|
|
424
|
+
const budget = bridgeDeadlineForTool(tool.name,args);
|
|
425
425
|
const result = await dispatchDownstream(tool,args,ctx,budget);
|
|
426
426
|
enforceDesktopBridgeResult(tool.name, result);
|
|
427
427
|
auditToolFinish(audit, result);
|
|
@@ -442,10 +442,10 @@ function buildFrontServer() {
|
|
|
442
442
|
callArgs.planner_response = { request_id: state.request_id, raw_text: planner.raw_text, model: planner.model };
|
|
443
443
|
}
|
|
444
444
|
const audit = auditToolStart(tool.name, callArgs);
|
|
445
|
-
const ticket = await bridgeGovernor.acquire(tool.name,{signal:ctx.mcpReq.signal});
|
|
445
|
+
const ticket = await bridgeGovernor.acquire(tool.name,{signal:ctx.mcpReq.signal,arguments:callArgs});
|
|
446
446
|
let result;
|
|
447
447
|
try {
|
|
448
|
-
const budget = bridgeDeadlineForTool(tool.name);
|
|
448
|
+
const budget = bridgeDeadlineForTool(tool.name,callArgs);
|
|
449
449
|
result = await dispatchDownstream(tool,callArgs,ctx,budget);
|
|
450
450
|
auditToolFinish(audit, result);
|
|
451
451
|
} catch (error) {
|
|
@@ -4,24 +4,39 @@ const DESKTOP_RAW_KEYS=new Set([
|
|
|
4
4
|
'pixels','pixel_bytes','frame_bytes','raw_bgra','raw_rgba','raw_image','screenshot_bytes','bitmap_bytes'
|
|
5
5
|
]);
|
|
6
6
|
const DEFAULT_LIMITS=Object.freeze({
|
|
7
|
+
control:Object.freeze({max_active:8,max_queue:16,queue_timeout_ms:5000}),
|
|
7
8
|
normal:Object.freeze({max_active:8,max_queue:32,queue_timeout_ms:30000}),
|
|
9
|
+
bulk:Object.freeze({max_active:8,max_queue:16,queue_timeout_ms:30000}),
|
|
8
10
|
autonomous:Object.freeze({max_active:2,max_queue:8,queue_timeout_ms:60000}),
|
|
9
11
|
desktop_observe:Object.freeze({max_active:2,max_queue:4,queue_timeout_ms:10000}),
|
|
10
12
|
desktop_action:Object.freeze({max_active:1,max_queue:2,queue_timeout_ms:5000})
|
|
11
13
|
});
|
|
14
|
+
const DEFAULT_SHARED_LIMITS=Object.freeze({max_active:9,max_non_control_active:8});
|
|
12
15
|
const DEADLINES=Object.freeze({
|
|
16
|
+
control:Object.freeze({timeout:10000,maxTotalTimeout:15000}),
|
|
13
17
|
normal:Object.freeze({timeout:120000,maxTotalTimeout:180000}),
|
|
18
|
+
bulk:Object.freeze({timeout:120000,maxTotalTimeout:180000}),
|
|
14
19
|
autonomous:Object.freeze({timeout:900000,maxTotalTimeout:1200000}),
|
|
15
20
|
desktop_observe:Object.freeze({timeout:30000,maxTotalTimeout:60000}),
|
|
16
21
|
desktop_action:Object.freeze({timeout:30000,maxTotalTimeout:45000})
|
|
17
22
|
});
|
|
18
23
|
|
|
19
24
|
function insist(condition,message){ if(!condition) throw new Error(message); }
|
|
20
|
-
function toolClass(name){
|
|
25
|
+
function toolClass(name,args={}){
|
|
21
26
|
const value=String(name??'');
|
|
22
27
|
if(value==='autonomous_goal_run') return 'autonomous';
|
|
23
|
-
if(value==='desktop_action') return 'desktop_action';
|
|
28
|
+
if(value==='desktop_action'||(value==='desktop_control'&&['action','target'].includes(args?.op))) return 'desktop_action';
|
|
24
29
|
if(value.startsWith('desktop_')) return 'desktop_observe';
|
|
30
|
+
if(value==='desktop_control') return 'desktop_observe';
|
|
31
|
+
if(['machine_ping','machine_status','machine_revoke','machine_list','capability_manifest',
|
|
32
|
+
'autonomous_session_status','coding_session_status'].includes(value))return 'control';
|
|
33
|
+
if(value==='machine_observe'&&['machine_ping','machine_status','machine_list'].includes(args?.op))return 'control';
|
|
34
|
+
if(['coding_search','coding_command_run','coding_benchmark_run','coding_task_run',
|
|
35
|
+
'process_session_start','process_session_read','process_session_action',
|
|
36
|
+
'machine_search_start','machine_search_page'].includes(value))return 'bulk';
|
|
37
|
+
if(value==='coding_inspect'&&['search','symbol_references','symbol_implementations'].includes(args?.op))return 'bulk';
|
|
38
|
+
if(value==='process_session'&&['start','read','action'].includes(args?.op))return 'bulk';
|
|
39
|
+
if(value==='machine_observe'&&['search_start','search_page','process_list'].includes(args?.op))return 'bulk';
|
|
25
40
|
return 'normal';
|
|
26
41
|
}
|
|
27
42
|
function estimateBase64Bytes(value){
|
|
@@ -57,8 +72,8 @@ function scanDesktopPayload(value,{maxPreviewBytes},path='result',seen=new Set()
|
|
|
57
72
|
seen.delete(value);
|
|
58
73
|
}
|
|
59
74
|
|
|
60
|
-
export function bridgeToolClass(name){ return toolClass(name); }
|
|
61
|
-
export function bridgeDeadlineForTool(name){ return DEADLINES[toolClass(name)]; }
|
|
75
|
+
export function bridgeToolClass(name,args){ return toolClass(name,args); }
|
|
76
|
+
export function bridgeDeadlineForTool(name,args){ return DEADLINES[toolClass(name,args)]; }
|
|
62
77
|
export function bridgeCatalogSha256(toolNames){
|
|
63
78
|
insist(Array.isArray(toolNames)&&toolNames.every(x=>typeof x==='string'),'bridge catalog names invalid');
|
|
64
79
|
const sorted=[...new Set(toolNames)].sort();
|
|
@@ -95,8 +110,12 @@ export function enforceDesktopBridgeResult(toolName,result,{maxPreviewBytes=1024
|
|
|
95
110
|
return result;
|
|
96
111
|
}
|
|
97
112
|
|
|
98
|
-
export function createBridgeGovernor({limits=
|
|
99
|
-
const
|
|
113
|
+
export function createBridgeGovernor({limits:overrides={},shared:sharedOverrides={}}={}){
|
|
114
|
+
const limits={...DEFAULT_LIMITS,...overrides};
|
|
115
|
+
const shared={...DEFAULT_SHARED_LIMITS,...sharedOverrides};
|
|
116
|
+
insist(Number.isInteger(shared.max_active)&&shared.max_active>=2&&shared.max_active<=64,'bridge shared max_active invalid');
|
|
117
|
+
insist(Number.isInteger(shared.max_non_control_active)&&shared.max_non_control_active>=1&&shared.max_non_control_active<shared.max_active,'bridge shared max_non_control_active invalid');
|
|
118
|
+
const classes=['control','normal','bulk','autonomous','desktop_observe','desktop_action'];
|
|
100
119
|
for(const name of classes){
|
|
101
120
|
const cfg=limits[name];
|
|
102
121
|
insist(cfg&&Number.isInteger(cfg.max_active)&&cfg.max_active>=1&&cfg.max_active<=64,`bridge limit ${name}.max_active invalid`);
|
|
@@ -104,6 +123,7 @@ export function createBridgeGovernor({limits=DEFAULT_LIMITS}={}){
|
|
|
104
123
|
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
124
|
}
|
|
106
125
|
const state=new Map(classes.map(name=>[name,{active:0,queue:[],admitted:0,completed:0,rejected:0,timed_out:0,cancelled:0}]));
|
|
126
|
+
let sharedActive=0,sharedNonControlActive=0;
|
|
107
127
|
let sequence=0;
|
|
108
128
|
let closed=false;
|
|
109
129
|
const drainWaiters=[];
|
|
@@ -113,13 +133,75 @@ export function createBridgeGovernor({limits=DEFAULT_LIMITS}={}){
|
|
|
113
133
|
while(drainWaiters.length) drainWaiters.shift()();
|
|
114
134
|
}
|
|
115
135
|
|
|
116
|
-
function
|
|
136
|
+
function canAdmit(name){
|
|
117
137
|
const cfg=limits[name],s=state.get(name);
|
|
118
|
-
|
|
138
|
+
if(s.active>=cfg.max_active)return false;
|
|
139
|
+
if(sharedActive>=shared.max_active)return false;
|
|
140
|
+
if(name!=='control'&&sharedNonControlActive>=shared.max_non_control_active)return false;
|
|
141
|
+
return true;
|
|
142
|
+
}
|
|
143
|
+
|
|
144
|
+
function noteAdmit(name){
|
|
145
|
+
sharedActive++;
|
|
146
|
+
if(name!=='control')sharedNonControlActive++;
|
|
147
|
+
}
|
|
148
|
+
|
|
149
|
+
function noteRelease(name){
|
|
150
|
+
sharedActive=Math.max(0,sharedActive-1);
|
|
151
|
+
if(name!=='control')sharedNonControlActive=Math.max(0,sharedNonControlActive-1);
|
|
152
|
+
}
|
|
153
|
+
|
|
154
|
+
function dispatchOne(name){
|
|
155
|
+
const s=state.get(name);
|
|
156
|
+
if(!canAdmit(name))return false;
|
|
157
|
+
|
|
158
|
+
while(s.queue.length){
|
|
119
159
|
const waiter=s.queue.shift();
|
|
120
|
-
if(waiter.done)
|
|
121
|
-
|
|
122
|
-
waiter.
|
|
160
|
+
if(waiter.done)continue;
|
|
161
|
+
|
|
162
|
+
waiter.done=true;
|
|
163
|
+
clearTimeout(waiter.timer);
|
|
164
|
+
waiter.cleanup();
|
|
165
|
+
|
|
166
|
+
s.active++;
|
|
167
|
+
noteAdmit(name);
|
|
168
|
+
s.admitted++;
|
|
169
|
+
|
|
170
|
+
waiter.resolve(
|
|
171
|
+
makeTicket(name,waiter.tool,waiter.id,waiter.queuedAt)
|
|
172
|
+
);
|
|
173
|
+
|
|
174
|
+
return true;
|
|
175
|
+
}
|
|
176
|
+
|
|
177
|
+
return false;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
function oldestAdmissibleQueuedClass(){
|
|
181
|
+
let selected=null;
|
|
182
|
+
|
|
183
|
+
for(const name of classes){
|
|
184
|
+
if(!canAdmit(name))continue;
|
|
185
|
+
|
|
186
|
+
const s=state.get(name);
|
|
187
|
+
const waiter=s.queue.find(item=>!item.done);
|
|
188
|
+
|
|
189
|
+
if(!waiter)continue;
|
|
190
|
+
|
|
191
|
+
if(selected===null||waiter.id<selected.id){
|
|
192
|
+
selected={name,id:waiter.id};
|
|
193
|
+
}
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
return selected?.name??null;
|
|
197
|
+
}
|
|
198
|
+
|
|
199
|
+
function dispatchAvailable(){
|
|
200
|
+
while(true){
|
|
201
|
+
const name=oldestAdmissibleQueuedClass();
|
|
202
|
+
|
|
203
|
+
if(name===null)break;
|
|
204
|
+
if(!dispatchOne(name))break;
|
|
123
205
|
}
|
|
124
206
|
}
|
|
125
207
|
function makeTicket(name,tool,id,queuedAt){
|
|
@@ -130,19 +212,19 @@ export function createBridgeGovernor({limits=DEFAULT_LIMITS}={}){
|
|
|
130
212
|
if(released) return false;
|
|
131
213
|
released=true;
|
|
132
214
|
const s=state.get(name);
|
|
133
|
-
s.active=Math.max(0,s.active-1);s.completed++;
|
|
134
|
-
|
|
215
|
+
s.active=Math.max(0,s.active-1);noteRelease(name);s.completed++;
|
|
216
|
+
dispatchAvailable();
|
|
135
217
|
finishDrain();
|
|
136
218
|
return true;
|
|
137
219
|
}
|
|
138
220
|
});
|
|
139
221
|
}
|
|
140
|
-
async function acquire(tool,{signal}={}){
|
|
141
|
-
const name=toolClass(tool),cfg=limits[name],s=state.get(name),id=++sequence,queuedAt=Date.now();
|
|
222
|
+
async function acquire(tool,{signal,arguments:args}={}){
|
|
223
|
+
const name=toolClass(tool,args),cfg=limits[name],s=state.get(name),id=++sequence,queuedAt=Date.now();
|
|
142
224
|
if(closed){s.rejected++;throw new Error('bridge governor closed');}
|
|
143
225
|
if(signal?.aborted){s.cancelled++;throw signal.reason instanceof Error?signal.reason:new Error('bridge request aborted');}
|
|
144
|
-
if(
|
|
145
|
-
s.active++;s.admitted++;
|
|
226
|
+
if(canAdmit(name)){
|
|
227
|
+
s.active++;noteAdmit(name);s.admitted++;
|
|
146
228
|
return makeTicket(name,String(tool),id,queuedAt);
|
|
147
229
|
}
|
|
148
230
|
if(s.queue.length>=cfg.max_queue){s.rejected++;throw new Error(`bridge backpressure queue full for ${name}`);}
|
|
@@ -193,14 +275,22 @@ export function createBridgeGovernor({limits=DEFAULT_LIMITS}={}){
|
|
|
193
275
|
return removed;
|
|
194
276
|
}
|
|
195
277
|
function snapshot(){
|
|
196
|
-
|
|
278
|
+
const lanes=Object.fromEntries(classes.map(name=>{
|
|
197
279
|
const s=state.get(name),cfg=limits[name];
|
|
198
280
|
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,
|
|
199
281
|
admitted:s.admitted,completed:s.completed,rejected:s.rejected,timed_out:s.timed_out,cancelled:s.cancelled,saturated:s.active>=cfg.max_active})];
|
|
200
|
-
}))
|
|
282
|
+
}));
|
|
283
|
+
return Object.freeze({...lanes,shared:Object.freeze({
|
|
284
|
+
active:sharedActive,
|
|
285
|
+
non_control_active:sharedNonControlActive,
|
|
286
|
+
max_active:shared.max_active,
|
|
287
|
+
max_non_control_active:shared.max_non_control_active,
|
|
288
|
+
saturated:sharedActive>=shared.max_active
|
|
289
|
+
})});
|
|
201
290
|
}
|
|
202
291
|
return Object.freeze({acquire,reconcile,close,snapshot});
|
|
203
292
|
}
|
|
204
293
|
|
|
205
294
|
export const BRIDGE_R40_DEFAULT_LIMITS=DEFAULT_LIMITS;
|
|
295
|
+
export const BRIDGE_R61_SHARED_LIMITS=DEFAULT_SHARED_LIMITS;
|
|
206
296
|
|
|
@@ -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.
|
|
5
|
-
"state_dir": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.
|
|
4
|
+
"grant_file": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.39-r62\\controller\\runtime\\process-grant.json",
|
|
5
|
+
"state_dir": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.39-r62\\controller\\runtime\\process-state",
|
|
6
6
|
"native_host": {
|
|
7
|
-
"path": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.
|
|
7
|
+
"path": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.39-r62\\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.
|
|
12
|
+
"path": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.39-r62",
|
|
13
13
|
"deny_paths": [
|
|
14
14
|
"node_modules",
|
|
15
15
|
"controller/runtime",
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
# R61 LIVELOG and multi-workload resilience
|
|
2
|
+
|
|
3
|
+
- Source: a byte-verified copy of the non-Git R60 development tree at `D:\Projects\deadbyte-mcp\development\deadbyte-mcp-0.15.38-r61`, retaining its three intentional LIVELOG edits. The old R60 path remains a compatibility dependency of the live 0.15.37 generation and is not an R61 edit target.
|
|
4
|
+
- Sealed predecessor: `v0.15.37-1cfecd7889419da7`; release manifest `1cfecd7889419da7800814e3a2a4ffa93d48dfdb0c344a5b7b91fe8d093230aa`; generation manifest `54842021c75f01bf7ecbd5b10ab8a482ecf107765b45c46f9d39b12bab65eac4`.
|
|
5
|
+
- Target: `deadbyte-mcp@0.15.38`, R61, unchanged 43-tool compact catalog and zero new authority scopes.
|
|
6
|
+
- Mechanism decisions and license observations: [r61-reference-evidence.md](r61-reference-evidence.md). No donor source was copied.
|
|
7
|
+
- RED: eight admitted `coding_search` jobs blocked `machine_ping` at the governor boundary; 12,000 filtered LIVELOG requests grew an unbounded identity map; a historical schema differential test referenced a moved external source despite byte-identical canonical reference content; the active 0.15.37 generation pinned Bridge source/dependency hashes to the mutable R60 development path, so the first R61 edits caused read-only controller status/doctor to fail.
|
|
8
|
+
- Fix: existing Bridge governor now separates bounded control/ordinary/bulk admission; LIVELOG presentation and filter identities are bounded and audit-sequence-aware; the historical schema test reads the canonical reference corpus and retains the exact pinned SHA-256 check. The R61 updater verifies the development Bridge input but binds the generated runtime config to the manifest-verified immutable release slot. The two trusted R60 Bridge files were restored byte-for-byte from the sealed 0.15.37 slot after R61 was copied to its own path; live status returned ONLINE without restart, revoke, or slot mutation.
|
|
9
|
+
- Performance evidence: `D:\Projects\deadbyte-mcp\testing\0.15.38\r61-ab-nine-rounds.json` (SHA-256 `3f10010654f08b4347c8e22e0f7ec3c521a69872878934770a0d2c0fd5b16ef7`) and 15-round 1/8 follow-up `r61-ab-single-and-eight.json` (SHA-256 `b16143ff7cb8aeced0e685352ffebeeeb74116d648d5b3509af2c66bd1f3b8a0a`). At 32-way mixed governor load, median throughput changed 790.1 → 903.75 ops/s, control p95 31.54 → 21.82 ms, and maximum observed queue depth 23 → 14. All 108 full-matrix runs had zero errors and unknown outcomes. At 1-way follow-up, throughput 244.78 → 246.82 ops/s and total p95 46.03 → 45.93 ms. This is a direct-governor/scratch-I/O benchmark, **not** full MCP transport, signed audit, or production-load proof.
|
|
10
|
+
- R61 focused gate after identity change: 47/47 PASS, 0 skip. Isolated Bridge/Core cold start, public MCP status, Core recovery and stop: PASS in one run; not a multi-workload transport benchmark.
|
|
11
|
+
- Final full regression, Windows gate, release manifest/doctor, package boundary after final bytes, registry, activation, rollback and restore remain separate required gates. This document is not a release PASS claim.
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# R61 reference-mechanism decisions
|
|
2
|
+
|
|
3
|
+
This is a source-inspection record, not authority to copy donor code. R61 uses
|
|
4
|
+
patterns reimplemented inside existing DEADBYTE components. No donor source
|
|
5
|
+
bytes or dependencies are imported.
|
|
6
|
+
|
|
7
|
+
| Reference | Inspected source | Mechanism and comparison with DEADBYTE | License/decision |
|
|
8
|
+
| --- | --- | --- | --- |
|
|
9
|
+
| Better Remote Commander | `references/better-remote-commander/packages/relay/src/device-hub.ts`, `mcp/invoke.ts`, `NOTICE` | Replaces stale sockets, correlates call/result and uses a pong watchdog. DEADBYTE already has a single guarded Bridge dispatch and bounded reconnect; test half-open detection and shared recovery, but do not add a fleet or new relay. | Root package declares MIT; NOTICE identifies derived Desktop Commander code. ADAPT watchdog tests only; KEEP current dispatch. |
|
|
10
|
+
| CUA | `references/cua/rfcs/3007-cua-driver-lifecycle-sessions.md`, `3682-typed-native-window-sdk.md`, `libs/cua-driver/rust/crates/cua-driver-core/tests/session_lifecycle.rs` | Accepted lifecycle sessions separate cleanup from authority; typed window actions distinguish snapshot target and post-action verification. DEADBYTE already has native Desktop and stale-frame controls. Add adversarial lifecycle/fresh-observation tests only if missing. RFC 2447 is superseded and not an architecture guide. | Top-level Python metadata declares MIT; component licenses must be checked before any copying. KEEP native/adapter split; ADAPT tests. |
|
|
11
|
+
| Desktop Commander | `references/desktop-commander/dist/utils/toolHistory.js`, process handlers | History caps entries, stored output bytes and file size. DEADBYTE already bounds process retained output via policy, repairs PATHEXT, supports offset reads, cancellation and bounded operation history. LIVELOG completed identity set is unbounded presentation state. | Package declares MIT. ADAPT LIVELOG retention; KEEP process runtime. |
|
|
12
|
+
| Open Remote MCP | `references/open-remote-mcp/docs/ARCHITECTURE.md`, `apps/agent/src/index.ts`, `NOTICE.md` | Relay policy narrows, never widens local device capability. DEADBYTE signed ledger and separate local planes are stronger; add a focused relay/local enforcement test, not a second permission system. | Root package has no license field in inspected metadata; no source copying. KEEP local authority; ADAPT test. |
|
|
13
|
+
| ReMCP | `references/remcp/docs/TOOL_SELECTION_EVAL.md`, `scripts/check-distribution.mjs`, `docs/DISTRIBUTION.md` | Golden positive/negative tool-selection cases and cross-distribution identity checks. DEADBYTE already has exact catalog, release manifest and npm closure; add a small golden routing test without a new runtime dependency. | Package declares MIT. ADAPT evaluation; KEEP release machinery. |
|
|
14
|
+
| Secure Host MCP | `references/secure-host-mcp/src/workspace.ts`, `src/executor.ts`, `test/workspace.test.ts` | Rejects broad workspace roots, resolves symlink parents and bounds executor time. DEADBYTE already has explicit roots, policy-pinned profiles and native containment. Probe equivalent boundary cases; do not expose generic shell or change root policy without RED evidence. | Package declares MIT. KEEP architecture; ADAPT adversarial cases if missing. |
|
|
15
|
+
| WinRemote MCP | `references/winremote-mcp/src/winremote/security.py`, `tiers.py`, `tests/test_security_hardening.py` | Capability tiers and URL/OAuth hardening. DEADBYTE authority planes are narrower and independently revocable; OCR/tier expansion would add scope. Compare URL and Windows privilege boundary tests where current interfaces overlap. | Python metadata declares MIT. KEEP planes; REJECT OCR and tier expansion. |
|
|
16
|
+
|
|
17
|
+
Acceptance remains based on DEADBYTE's observed behavior, not donor popularity.
|
|
18
|
+
Any newly found donor gap requires a focused RED and a narrow local fix.
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "deadbyte-mcp",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.39",
|
|
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-
|
|
45
|
+
"gate:windows": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gate-windows-r62-prepublish.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",
|
|
@@ -85,7 +85,9 @@
|
|
|
85
85
|
"r59:focused:test": "node --test --test-concurrency=1 test/capability-snapshot-r59.test.mjs test/capability-resolver.test.mjs test/runtime-plane-registry-r59.test.mjs test/optional-plane-degraded-r59.test.mjs test/bridge-runtime-r59.test.mjs test/controller-policy-preflight-r59.test.mjs test/r59-tool-surface-compat.test.mjs test/r58-controller-state-coherence.test.mjs",
|
|
86
86
|
"r59:release:test": "node --test --test-concurrency=1 test/r59-release-contract.test.mjs test/r59-tool-surface-compat.test.mjs test/bridge-runtime-r59.test.mjs test/controller-policy-preflight-r59.test.mjs",
|
|
87
87
|
"r60:focused:test": "node --test --test-concurrency=1 test/r60-authority-coherence.test.mjs test/r60-authority-enforcement.test.mjs test/r60-bridge-dispatch.test.mjs test/r60-clock-discipline.test.mjs test/r60-live-timeline.test.mjs test/r60-reconnect-errors.test.mjs test/r60-reconnect-jitter.test.mjs test/r60-remote-call-recovery.test.mjs test/r60-windows-log-decode.test.mjs test/r60-release-contract.test.mjs",
|
|
88
|
-
"r60:full:test": "node scripts/full-regression-r60.mjs"
|
|
88
|
+
"r60:full:test": "node scripts/full-regression-r60.mjs",
|
|
89
|
+
"r61:focused:test": "node --test --test-concurrency=1 test/r61-release-contract.test.mjs test/r61-release-bridge-binding.test.mjs test/r61-control-lane.test.mjs test/r61-live-timeline-bounds.test.mjs test/r61-npm-artifact-identity.test.mjs test/remote-live-log-r37.test.mjs test/bridge-runtime-r59.test.mjs test/commander-schema-differential-r48.test.mjs test/package-boundary.test.mjs test/r60-bridge-dispatch.test.mjs test/r60-authority-enforcement.test.mjs",
|
|
90
|
+
"r62:focused:test": "node --test --test-concurrency=1 test/r62-release-contract.test.mjs test/r62-doctor-transactions-reconcile.test.mjs test/r62-doctor-receipt-semantics.test.mjs test/r62-rollback-failure-receipt.test.mjs test/r58-doctor-transactions.test.mjs test/r58-completed-update-receipt.test.mjs test/runtime-self-update.test.mjs test/r56-rollback-launcher-restore.test.mjs"
|
|
89
91
|
},
|
|
90
92
|
"bundleDependencies": [
|
|
91
93
|
"@modelcontextprotocol/server",
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
param(
|
|
2
|
+
[ValidateSet('all','preflight','focused','full','manifest','doctor')]
|
|
3
|
+
[string]$Stage='all'
|
|
4
|
+
)
|
|
5
|
+
|
|
6
|
+
$ErrorActionPreference='Stop'
|
|
7
|
+
Set-StrictMode -Version 3.0
|
|
8
|
+
$root=Split-Path $PSScriptRoot -Parent
|
|
9
|
+
Set-Location -LiteralPath $root
|
|
10
|
+
|
|
11
|
+
function Invoke-Npm([string]$Name,[string[]]$NpmArgs){
|
|
12
|
+
Write-Host "==== $Name ===="
|
|
13
|
+
& npm.cmd @NpmArgs
|
|
14
|
+
if($LASTEXITCODE -ne 0){ throw "R61 prepublish gate failed at $Name exit=$LASTEXITCODE" }
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
$stateRoot=if(-not [string]::IsNullOrWhiteSpace($env:DEADBYTE_STATE_ROOT)){
|
|
18
|
+
[IO.Path]::GetFullPath($env:DEADBYTE_STATE_ROOT)
|
|
19
|
+
}else{ Join-Path $env:USERPROFILE '.deadbyte-mcp' }
|
|
20
|
+
$pointer=Join-Path $stateRoot 'active-release.json'
|
|
21
|
+
if(-not (Test-Path -LiteralPath $pointer -PathType Leaf)){ throw "R61 predecessor pointer missing: $pointer" }
|
|
22
|
+
$active=Get-Content -LiteralPath $pointer -Raw | ConvertFrom-Json
|
|
23
|
+
if($active.release_id -ne 'v0.15.37-1cfecd7889419da7'){ throw "R61 predecessor release mismatch: $($active.release_id)" }
|
|
24
|
+
if($active.manifest_sha256 -ne '1cfecd7889419da7800814e3a2a4ffa93d48dfdb0c344a5b7b91fe8d093230aa'){ throw 'R61 predecessor manifest mismatch' }
|
|
25
|
+
if($active.generation_manifest_sha256 -ne '54842021c75f01bf7ecbd5b10ab8a482ecf107765b45c46f9d39b12bab65eac4'){ throw 'R61 predecessor generation mismatch' }
|
|
26
|
+
if($Stage -eq 'preflight'){Write-Host '==== R61 WINDOWS GATE: PASS preflight ====';return}
|
|
27
|
+
|
|
28
|
+
if($Stage -eq 'all' -or $Stage -eq 'focused'){
|
|
29
|
+
Invoke-Npm 'r61-focused' @('run','r61:focused:test')
|
|
30
|
+
if($Stage -eq 'focused'){Write-Host '==== R61 WINDOWS GATE: PASS focused ====';return}
|
|
31
|
+
}
|
|
32
|
+
if($Stage -eq 'all' -or $Stage -eq 'full'){
|
|
33
|
+
Invoke-Npm 'full-regression' @('test')
|
|
34
|
+
if($Stage -eq 'full'){Write-Host '==== R61 WINDOWS GATE: PASS full ====';return}
|
|
35
|
+
}
|
|
36
|
+
if($Stage -eq 'all' -or $Stage -eq 'manifest'){
|
|
37
|
+
Invoke-Npm 'manifest-write' @('run','manifest:write')
|
|
38
|
+
Invoke-Npm 'manifest-verify' @('run','manifest:verify')
|
|
39
|
+
if($Stage -eq 'manifest'){Write-Host '==== R61 WINDOWS GATE: PASS manifest ====';return}
|
|
40
|
+
}
|
|
41
|
+
if($Stage -eq 'all' -or $Stage -eq 'doctor'){
|
|
42
|
+
Invoke-Npm 'doctor' @('run','doctor')
|
|
43
|
+
if($Stage -eq 'doctor'){Write-Host '==== R61 WINDOWS GATE: PASS doctor ====';return}
|
|
44
|
+
}
|
|
45
|
+
Write-Host '==== R61 PREPUBLISH WINDOWS GATE: PASS ===='
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
param(
|
|
2
|
+
[ValidateSet('all','preflight','focused','full','manifest','doctor')]
|
|
3
|
+
[string]$Stage='all'
|
|
4
|
+
)
|
|
5
|
+
|
|
6
|
+
$ErrorActionPreference='Stop'
|
|
7
|
+
Set-StrictMode -Version 3.0
|
|
8
|
+
$root=Split-Path $PSScriptRoot -Parent
|
|
9
|
+
Set-Location -LiteralPath $root
|
|
10
|
+
|
|
11
|
+
function Invoke-Npm([string]$Name,[string[]]$NpmArgs){
|
|
12
|
+
Write-Host "==== $Name ===="
|
|
13
|
+
& npm.cmd @NpmArgs
|
|
14
|
+
if($LASTEXITCODE -ne 0){ throw "R62 prepublish gate failed at $Name exit=$LASTEXITCODE" }
|
|
15
|
+
}
|
|
16
|
+
|
|
17
|
+
$stateRoot=if(-not [string]::IsNullOrWhiteSpace($env:DEADBYTE_STATE_ROOT)){
|
|
18
|
+
[IO.Path]::GetFullPath($env:DEADBYTE_STATE_ROOT)
|
|
19
|
+
}else{ Join-Path $env:USERPROFILE '.deadbyte-mcp' }
|
|
20
|
+
$pointer=Join-Path $stateRoot 'active-release.json'
|
|
21
|
+
if(-not (Test-Path -LiteralPath $pointer -PathType Leaf)){ throw "R62 predecessor pointer missing: $pointer" }
|
|
22
|
+
$active=Get-Content -LiteralPath $pointer -Raw | ConvertFrom-Json
|
|
23
|
+
if($active.release_id -ne 'v0.15.38-917901b3fcb2a77f'){ throw "R62 predecessor release mismatch: $($active.release_id)" }
|
|
24
|
+
if($active.manifest_sha256 -ne '917901b3fcb2a77f696fedc539bd97c567d9dc59345779906fc633d11ea4bcfb'){ throw 'R62 predecessor manifest mismatch' }
|
|
25
|
+
if($active.generation_manifest_sha256 -ne '9d320a8af1ba8e9e6a23552f35263da2670c00af1355464820552d849d9033c6'){ throw 'R62 predecessor generation mismatch' }
|
|
26
|
+
if($Stage -eq 'preflight'){Write-Host '==== R62 WINDOWS GATE: PASS preflight ====';return}
|
|
27
|
+
|
|
28
|
+
if($Stage -eq 'all' -or $Stage -eq 'focused'){
|
|
29
|
+
Invoke-Npm 'r62-focused' @('run','r62:focused:test')
|
|
30
|
+
if($Stage -eq 'focused'){Write-Host '==== R62 WINDOWS GATE: PASS focused ====';return}
|
|
31
|
+
}
|
|
32
|
+
if($Stage -eq 'all' -or $Stage -eq 'full'){
|
|
33
|
+
Invoke-Npm 'full-regression' @('test')
|
|
34
|
+
if($Stage -eq 'full'){Write-Host '==== R62 WINDOWS GATE: PASS full ====';return}
|
|
35
|
+
}
|
|
36
|
+
if($Stage -eq 'all' -or $Stage -eq 'manifest'){
|
|
37
|
+
Invoke-Npm 'manifest-write' @('run','manifest:write')
|
|
38
|
+
Invoke-Npm 'manifest-verify' @('run','manifest:verify')
|
|
39
|
+
if($Stage -eq 'manifest'){Write-Host '==== R62 WINDOWS GATE: PASS manifest ====';return}
|
|
40
|
+
}
|
|
41
|
+
if($Stage -eq 'all' -or $Stage -eq 'doctor'){
|
|
42
|
+
Invoke-Npm 'doctor' @('run','doctor')
|
|
43
|
+
if($Stage -eq 'doctor'){Write-Host '==== R62 WINDOWS GATE: PASS doctor ====';return}
|
|
44
|
+
}
|
|
45
|
+
Write-Host '==== R62 PREPUBLISH WINDOWS GATE: PASS ===='
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import {createHash} from 'node:crypto';
|
|
2
|
+
|
|
3
|
+
const digest=(name,bytes,encoding='hex')=>createHash(name).update(bytes).digest(encoding);
|
|
4
|
+
|
|
5
|
+
export function verifyPublishedTarballIdentity({version,localBytes,registryBytes,published,tags}){
|
|
6
|
+
if(typeof version!=='string'||!/^\d+\.\d+\.\d+$/.test(version)||!Buffer.isBuffer(localBytes)||!Buffer.isBuffer(registryBytes)){
|
|
7
|
+
throw new Error('npm artifact identity inputs invalid');
|
|
8
|
+
}
|
|
9
|
+
const tarballSha256=digest('sha256',localBytes);
|
|
10
|
+
const integrity='sha512-'+digest('sha512',localBytes,'base64');
|
|
11
|
+
const shasum=digest('sha1',localBytes);
|
|
12
|
+
const dist=published?.dist??published;
|
|
13
|
+
if(published?.version!==version||dist?.integrity!==integrity||dist?.shasum!==shasum||
|
|
14
|
+
dist?.tarball!==`https://registry.npmjs.org/deadbyte-mcp/-/deadbyte-mcp-${version}.tgz`){
|
|
15
|
+
throw new Error('published registry metadata does not match the exact local tarball');
|
|
16
|
+
}
|
|
17
|
+
if(tags?.latest!==version)throw new Error(`npm latest tag mismatch: expected ${version}, got ${tags?.latest??'<missing>'}`);
|
|
18
|
+
if(digest('sha256',registryBytes)!==tarballSha256||'sha512-'+digest('sha512',registryBytes,'base64')!==integrity){
|
|
19
|
+
throw new Error('registry tarball bytes differ from the exact published local artifact');
|
|
20
|
+
}
|
|
21
|
+
return Object.freeze({tarball_sha256:tarballSha256,npm_integrity:integrity,shasum});
|
|
22
|
+
}
|