deadbyte-mcp 0.10.0 β 0.11.0
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 +69 -55
- package/README.txt +13 -14
- package/bin/WORKER-REGISTRY.txt +3 -3
- package/bin/appcontainer-stage.exe +0 -0
- package/bin/appcontainer-stage.obj +0 -0
- package/bin/bootstrap-advapi32.exe +0 -0
- package/bin/bootstrap-advapi32.obj +0 -0
- package/bin/bootstrap-exitcode.exe +0 -0
- package/bin/bootstrap-exitcode.obj +0 -0
- package/bin/bootstrap-kernel32.exe +0 -0
- package/bin/bootstrap-kernel32.obj +0 -0
- package/bin/child-control-probe.exe +0 -0
- package/bin/child-control-probe.obj +0 -0
- package/bin/child-control-stage.exe +0 -0
- package/bin/child-control-stage.obj +0 -0
- package/bin/contained-reverse-worker.exe +0 -0
- package/bin/contained-reverse-worker.obj +0 -0
- package/bin/contained-transform-worker.exe +0 -0
- package/bin/contained-transform-worker.obj +0 -0
- package/bin/containment-probe.exe +0 -0
- package/bin/containment-probe.obj +0 -0
- package/bin/deadbyte-contain.exe +0 -0
- package/bin/deadbyte-contain.obj +0 -0
- package/bin/deadbyte-exec.exe +0 -0
- package/bin/deadbyte-exec.obj +0 -0
- package/bin/deadbyte-process-host.exe +0 -0
- package/bin/deadbyte-process-host.obj +0 -0
- package/bin/deadbyte-tunnel-host.exe +0 -0
- package/bin/deadbyte-tunnel-host.obj +0 -0
- package/controller/README.TXT +3 -3
- package/controller/deadbyte-controller.ps1 +1 -1
- package/controller/deadbyte-process-policy.json +1 -1
- package/docs/ARCHITECTURE.md +1 -1
- package/package.json +1 -1
- package/scripts/deferred-slot-operation.mjs +1 -1
- package/scripts/final-closure-r36.mjs +113 -0
- package/scripts/final-closure-verify-r36.mjs +208 -0
- package/scripts/final-closure-verify.mjs +48 -48
- package/scripts/final-closure.mjs +13 -13
- package/scripts/gate-windows-r36.ps1 +42 -0
- package/scripts/gate-windows.ps1 +3 -3
- package/scripts/release-parity-r36.mjs +200 -0
- package/scripts/release-parity-tests.ps1 +2 -2
- package/scripts/release-parity.mjs +37 -37
- package/scripts/windows-gate-evidence-r36.mjs +52 -0
- package/scripts/windows-gate-evidence.mjs +5 -5
- package/src/agent-memory-plane.mjs +98 -0
- package/src/autonomous-output-contracts.mjs +5 -2
- package/src/autonomous-runtime.mjs +155 -31
- package/src/autonomous-timeout-recovery.mjs +27 -0
- package/src/deadbyte-cli.mjs +37 -76
- package/src/effect-ledger.mjs +47 -0
- package/src/observation-lease.mjs +32 -0
- package/src/remote-live-log.mjs +59 -0
- package/src/remote-mcp-autonomous-smoke-client.mjs +15 -9
- package/src/version.mjs +1 -1
- package/src/worker-scheduler.mjs +53 -0
- package/test/autonomous-output-contract.test.mjs +1 -1
- package/test/core.test.mjs +1 -1
- package/test/production-docs.test.mjs +5 -5
- package/test/r33-closeout-regression.test.mjs +4 -4
- package/test/r33-finalization.test.mjs +6 -6
- package/test/r36-finalization.test.mjs +5 -5
- package/test/r36-release-identity.test.mjs +12 -19
- package/test/r37-agent-fabric.test.mjs +92 -0
- package/test/r37-autonomous-timeout-recovery.test.mjs +60 -0
- package/test/r37-finalization.test.mjs +74 -0
- package/test/release-version.test.mjs +42 -36
- package/test/remote-live-log-r37.test.mjs +47 -0
- package/test/remote-session-cli.test.mjs +27 -50
|
@@ -0,0 +1,74 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { readFile } from 'node:fs/promises';
|
|
4
|
+
import { validateParityEvidence, R36_PREDECESSOR_RELEASE_ID, R36_PREDECESSOR_MANIFEST } from '../scripts/release-parity.mjs';
|
|
5
|
+
import { verifyFinalClosureObject } from '../scripts/final-closure-verify.mjs';
|
|
6
|
+
|
|
7
|
+
const root=new URL('../',import.meta.url);
|
|
8
|
+
const text=rel=>readFile(new URL(rel,root),'utf8');
|
|
9
|
+
|
|
10
|
+
function parityFixture(){
|
|
11
|
+
const manifest='a'.repeat(64);
|
|
12
|
+
return {
|
|
13
|
+
schema:'deadbyte.r37-parity.v1',status:'passed',execution_provider:'deadbyte_mcp',rdc_operation_count:0,
|
|
14
|
+
candidate:{release_id:`v0.11.0-${manifest.slice(0,16)}`,version:'0.11.0',manifest_sha256:manifest},
|
|
15
|
+
immutable_slot:{protected:true,release_root:'C:/immutable/r37',development_root:'D:/Projects/deadbyte-mcp-r36-dev'},
|
|
16
|
+
local_full:{status:'passed',tool_count:76,strict_output_schemas:true},
|
|
17
|
+
public_compact:{status:'passed',tool_count:41,capability_closure:true,gateway_count:5},
|
|
18
|
+
autonomous:{status:'passed',signed_release_verified:true,observed_failure_before_replan:true},
|
|
19
|
+
before_rollback_disarmed:{status:'passed',capability_closure:true,coding_armed:false,autonomous_armed:false},
|
|
20
|
+
rollback:{state:'completed'},stage_restore:{status:'restored',manifest_sha256:manifest},restore:{state:'completed'},
|
|
21
|
+
predecessor:{release_id:R36_PREDECESSOR_RELEASE_ID,version:'0.10.0',manifest_sha256:R36_PREDECESSOR_MANIFEST},
|
|
22
|
+
predecessor_disarmed:{status:'passed',tool_count:41,capability_closure:true},
|
|
23
|
+
successor:{release_id:`v0.11.0-${manifest.slice(0,16)}`,version:'0.11.0',manifest_sha256:manifest},
|
|
24
|
+
successor_disarmed:{status:'passed',capability_closure:true,coding_armed:false,autonomous_armed:false},
|
|
25
|
+
requirements:Object.fromEntries(['tree_read','precondition_mutation','search','owned_process','observation','coding_loop','autonomy','interrupted_recovery','evidence_verification','compact_closure','full_surface'].map(key=>[key,true]))
|
|
26
|
+
};
|
|
27
|
+
}
|
|
28
|
+
|
|
29
|
+
test('R37 parity validator requires full-76, compact closure, exact R36 predecessor and immutable-slot separation',()=>{
|
|
30
|
+
const good=parityFixture();
|
|
31
|
+
assert.equal(validateParityEvidence(good),true);
|
|
32
|
+
assert.throws(()=>validateParityEvidence({...good,local_full:{...good.local_full,tool_count:75}}),/full 76/i);
|
|
33
|
+
assert.throws(()=>validateParityEvidence({...good,public_compact:{...good.public_compact,capability_closure:false}}),/compact closure/i);
|
|
34
|
+
assert.throws(()=>validateParityEvidence({...good,predecessor:{...good.predecessor,manifest_sha256:'b'.repeat(64)}}),/predecessor/i);
|
|
35
|
+
assert.throws(()=>validateParityEvidence({...good,immutable_slot:{...good.immutable_slot,development_root:good.immutable_slot.release_root}}),/immutable-slot/i);
|
|
36
|
+
assert.throws(()=>validateParityEvidence({...good,stage_restore:{status:'missing',manifest_sha256:good.candidate.manifest_sha256}}),/stage restore/i);
|
|
37
|
+
});
|
|
38
|
+
|
|
39
|
+
test('R37 parity captures R37 bridge, exact R36 predecessor, stage reseed and successor restore',async()=>{
|
|
40
|
+
const parity=await text('scripts/release-parity.mjs');
|
|
41
|
+
assert.match(parity,/R36_PREDECESSOR_RELEASE_ID='v0\.10\.0-8d1e5f09745e7647'/);
|
|
42
|
+
assert.match(parity,/8d1e5f09745e764796b60e0a8a0168be7334ed4bf834fad5974a80eba295b4e8/);
|
|
43
|
+
assert.match(parity,/const stageRestore=await restoreFrozenStage/);
|
|
44
|
+
assert.match(parity,/publicR36Disarmed/);
|
|
45
|
+
assert.match(parity,/scheduleDeferred\('activate',candidateManifest,\{bridgeRoot:successorBridge\.root,bridgeScriptSha256:successorBridge\.sha256\}\)/);
|
|
46
|
+
});
|
|
47
|
+
|
|
48
|
+
test('R37 current final closure writer and independent verifier bind R37 domains and R36 predecessor',async()=>{
|
|
49
|
+
const [writer,verifier]=await Promise.all([text('scripts/final-closure.mjs'),text('scripts/final-closure-verify.mjs')]);
|
|
50
|
+
assert.equal(typeof verifyFinalClosureObject,'function');
|
|
51
|
+
assert.match(writer,/DEADBYTE-R37-FINAL-CLOSURE-V1/);
|
|
52
|
+
assert.match(writer,/deadbyte\.r37-final-closure\.v1/);
|
|
53
|
+
assert.match(writer,/pointer\.version==='0\.11\.0'/);
|
|
54
|
+
assert.match(writer,/R37 FINAL MACHINE BASELINE/);
|
|
55
|
+
assert.match(writer,/deadbyte\.r37-parity\.v1/);
|
|
56
|
+
assert.match(writer,/deadbyte\.r37-windows-gate\.v1/);
|
|
57
|
+
assert.match(writer,/R36_PREDECESSOR_RELEASE_ID/);
|
|
58
|
+
assert.doesNotMatch(verifier,/from ['"]\.\.\/src\//);
|
|
59
|
+
assert.match(verifier,/DEADBYTE-R37-FINAL-CLOSURE-V1/);
|
|
60
|
+
assert.match(verifier,/deadbyte\.r37-final-closure\.v1/);
|
|
61
|
+
assert.match(verifier,/envelope\.body\.version==='0\.11\.0'/);
|
|
62
|
+
assert.match(verifier,/R37 FINAL MACHINE BASELINE/);
|
|
63
|
+
assert.match(verifier,/deadbyte\.r37-parity\.v1/);
|
|
64
|
+
assert.match(verifier,/deadbyte\.r37-windows-gate\.v1/);
|
|
65
|
+
assert.match(verifier,/8d1e5f09745e764796b60e0a8a0168be7334ed4bf834fad5974a80eba295b4e8/);
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test('R37 bounded public parity suite covers current release identity and agent fabric',async()=>{
|
|
69
|
+
const script=await text('scripts/release-parity-tests.ps1');
|
|
70
|
+
assert.match(script,/r37-finalization\.test\.mjs/);
|
|
71
|
+
assert.match(script,/release-version\.test\.mjs/);
|
|
72
|
+
assert.match(script,/r37-agent-fabric\.test\.mjs/);
|
|
73
|
+
assert.match(script,/remote-live-log-r37\.test\.mjs/);
|
|
74
|
+
});
|
|
@@ -3,43 +3,49 @@ import assert from 'node:assert/strict';
|
|
|
3
3
|
import { readFile } from 'node:fs/promises';
|
|
4
4
|
import { createHash } from 'node:crypto';
|
|
5
5
|
|
|
6
|
-
const root
|
|
7
|
-
const text
|
|
6
|
+
const root=new URL('../',import.meta.url);
|
|
7
|
+
const text=rel=>readFile(new URL(rel,root),'utf8');
|
|
8
|
+
const R36_RELEASE_ID='v0.10.0-8d1e5f09745e7647';
|
|
9
|
+
const R36_MANIFEST='8d1e5f09745e764796b60e0a8a0168be7334ed4bf834fad5974a80eba295b4e8';
|
|
8
10
|
|
|
9
|
-
test('
|
|
10
|
-
const pkg
|
|
11
|
-
const [version,
|
|
12
|
-
text('src/version.mjs'),
|
|
13
|
-
text('controller/
|
|
14
|
-
text('scripts/
|
|
15
|
-
text('
|
|
16
|
-
text('docs/ARCHITECTURE.md'),
|
|
17
|
-
text('controller/README.TXT'),
|
|
18
|
-
text('scripts/deferred-slot-operation.mjs'),
|
|
19
|
-
text('src/remote-mcp-r36-parity-client.mjs'),
|
|
20
|
-
text('scripts/final-closure.mjs'),
|
|
21
|
-
text('scripts/final-closure-verify.mjs'),
|
|
22
|
-
text('scripts/windows-gate-evidence.mjs'),
|
|
11
|
+
test('R37 successor release authority agrees on V0.11.0 / R37 and preserves exact public R36 predecessor',async()=>{
|
|
12
|
+
const pkg=JSON.parse(await text('package.json'));
|
|
13
|
+
const [version,controller,gate,readme,architecture,controllerReadme,deferred,parity,closure,closureVerify,windowsGate,semanticConfig]=await Promise.all([
|
|
14
|
+
text('src/version.mjs'),text('controller/deadbyte-controller.ps1'),text('scripts/gate-windows.ps1'),
|
|
15
|
+
text('README.txt'),text('docs/ARCHITECTURE.md'),text('controller/README.TXT'),
|
|
16
|
+
text('scripts/deferred-slot-operation.mjs'),text('scripts/release-parity.mjs'),text('scripts/final-closure.mjs'),
|
|
17
|
+
text('scripts/final-closure-verify.mjs'),text('scripts/windows-gate-evidence.mjs'),
|
|
23
18
|
text('controller/deadbyte-semantic-lsp-config.json')
|
|
24
19
|
]);
|
|
25
|
-
assert.equal(pkg.version,
|
|
26
|
-
assert.match(version
|
|
27
|
-
assert.match(controller
|
|
28
|
-
assert.match(gate
|
|
29
|
-
assert.match(readme
|
|
30
|
-
assert.match(architecture
|
|
31
|
-
assert.match(controllerReadme
|
|
32
|
-
assert.match(controllerReadme
|
|
33
|
-
assert.match(controllerReadme
|
|
34
|
-
assert.match(deferred
|
|
35
|
-
assert.match(parity
|
|
36
|
-
assert.match(parity
|
|
37
|
-
assert.match(parity,
|
|
38
|
-
assert.match(
|
|
39
|
-
assert.match(
|
|
40
|
-
assert.match(
|
|
41
|
-
assert.
|
|
42
|
-
assert.match(
|
|
43
|
-
assert.
|
|
44
|
-
|
|
20
|
+
assert.equal(pkg.version,'0.11.0');
|
|
21
|
+
assert.match(version,/DEADBYTE_VERSION = '0\.11\.0'/);
|
|
22
|
+
assert.match(controller,/CONTROLLER V0\.11\.0 \/ R37/);
|
|
23
|
+
assert.match(gate,/DEADBYTE V0\.11\.0 \/ R37 WINDOWS BATCH GATE: PASS/);
|
|
24
|
+
assert.match(readme,/^DEADBYTE MCP V0\.11\.0 \/ R37 PRODUCTION BASELINE$/m);
|
|
25
|
+
assert.match(architecture,/^# DEADBYTE MCP V0\.11\.0 \/ R37 ARCHITECTURE$/m);
|
|
26
|
+
assert.match(controllerReadme,/^DEADBYTE MCP V0\.11\.0 \/ R37 CONTROLLER$/m);
|
|
27
|
+
assert.match(controllerReadme,/full 76-tool (?:profile|catalog)/);
|
|
28
|
+
assert.match(controllerReadme,/compact capability profile[^\n]*<=42 tools/);
|
|
29
|
+
assert.match(deferred,/--expected-version','0\.11\.0'/);
|
|
30
|
+
assert.match(parity,/deadbyte\.r37-parity\.v1/);
|
|
31
|
+
assert.match(parity,/version==='0\.11\.0'|version:'0\.11\.0'/);
|
|
32
|
+
assert.match(parity,new RegExp(R36_RELEASE_ID.replaceAll('.','\\.')));
|
|
33
|
+
assert.match(parity,new RegExp(R36_MANIFEST));
|
|
34
|
+
assert.match(closure,/DEADBYTE-R37-FINAL-CLOSURE-V1/);
|
|
35
|
+
assert.match(closure,/version:'0\.11\.0'/);
|
|
36
|
+
assert.match(closureVerify,/DEADBYTE V0\.11\.0 \/ R37 WINDOWS BATCH GATE: PASS/);
|
|
37
|
+
assert.match(windowsGate,/schema:'deadbyte\.r37-windows-gate\.v1'/);
|
|
38
|
+
assert.equal(createHash('sha256').update(Buffer.from(semanticConfig,'utf8')).digest('hex'),'d274b099a298c1033fea8f1e8849751693bbc0448778d619400acb82d4f53a3b');
|
|
39
|
+
});
|
|
40
|
+
|
|
41
|
+
test('R37 keeps the R36 capability surface contract while adding internal agent fabric',async()=>{
|
|
42
|
+
const [parity,fabric,live]=await Promise.all([
|
|
43
|
+
text('src/remote-mcp-r36-parity-client.mjs'),
|
|
44
|
+
text('src/autonomous-runtime.mjs'),
|
|
45
|
+
text('src/remote-live-log.mjs')
|
|
46
|
+
]);
|
|
47
|
+
assert.match(parity,/R36_EXPECTED_TOOLS\.length !== 76/);
|
|
48
|
+
assert.match(parity,/R36_COMPACT_TOOL_LIMIT=42/);
|
|
49
|
+
for(const name of ['deriveAgentMemory','effectIdentity','createWorkerScheduler','issueObservationLease']) assert.match(fabric,new RegExp(name));
|
|
50
|
+
assert.match(live,/createLiveTimelineTracker/);
|
|
45
51
|
});
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { createLiveTimelineTracker } from '../src/remote-live-log.mjs';
|
|
4
|
+
|
|
5
|
+
test('R37 live timeline correlates RUN and result with stable short span id',()=>{
|
|
6
|
+
let now=1000;
|
|
7
|
+
const tracker=createLiveTimelineTracker({clock:()=>now});
|
|
8
|
+
const run=tracker.observe({event_type:'tool.request',tool:'coding_file_read',request_id:'abcdef1234567890',
|
|
9
|
+
args:{root_id:'projects',path:'src/a.mjs',content:'SECRET',token:'SECRET'}});
|
|
10
|
+
assert.equal(run,'βΆ [abcdef12] RUN coding_file_read root=projects path=src/a.mjs');
|
|
11
|
+
now=1250;
|
|
12
|
+
const done=tracker.observe({event_type:'tool.result',tool:'coding_file_read',request_id:'abcdef1234567890',
|
|
13
|
+
outcome:{is_error:false,duration_ms:250}});
|
|
14
|
+
assert.equal(done,'β [abcdef12] OK coding_file_read 250ms');
|
|
15
|
+
assert.deepEqual(tracker.pending(),[]);
|
|
16
|
+
assert.doesNotMatch(run+done,/SECRET/);
|
|
17
|
+
});
|
|
18
|
+
|
|
19
|
+
test('R37 live timeline distinguishes result whose request was outside live tail',()=>{
|
|
20
|
+
const tracker=createLiveTimelineTracker();
|
|
21
|
+
const line=tracker.observe({event_type:'tool.result',tool:'coding_tree',request_id:'old-request-12345678',
|
|
22
|
+
outcome:{is_error:false,duration_ms:15}});
|
|
23
|
+
assert.equal(line,'β© [old-requ] OK coding_tree 15ms (request before live window)');
|
|
24
|
+
});
|
|
25
|
+
|
|
26
|
+
test('R37 live timeline deduplicates terminal result and reports interrupted spans with ids',()=>{
|
|
27
|
+
const tracker=createLiveTimelineTracker();
|
|
28
|
+
tracker.observe({event_type:'tool.request',tool:'coding_command_run',request_id:'request-23456789',args:{command_id:'node_script'}});
|
|
29
|
+
const first=tracker.observe({event_type:'tool.result',tool:'coding_command_run',request_id:'request-23456789',outcome:{is_error:true,duration_ms:900}});
|
|
30
|
+
const duplicate=tracker.observe({event_type:'tool.result',tool:'coding_command_run',request_id:'request-23456789',outcome:{is_error:true,duration_ms:900}});
|
|
31
|
+
assert.equal(first,'β [request-] ERR coding_command_run 900ms');
|
|
32
|
+
assert.equal(duplicate,null);
|
|
33
|
+
|
|
34
|
+
tracker.observe({event_type:'tool.request',tool:'coding_file_read',request_id:'pending-12345678',args:{path:'src/a.mjs'}});
|
|
35
|
+
assert.deepEqual(tracker.reconcileInterrupted('recovery'),[
|
|
36
|
+
'β [pending-] INTERRUPTED coding_file_read β recovery ended before terminal result'
|
|
37
|
+
]);
|
|
38
|
+
});
|
|
39
|
+
|
|
40
|
+
test('R37 CLI uses timeline tracker for compact live mode while keeping legacy formatter API',async()=>{
|
|
41
|
+
const {readFile}=await import('node:fs/promises');
|
|
42
|
+
const src=await readFile(new URL('../src/deadbyte-cli.mjs',import.meta.url),'utf8');
|
|
43
|
+
assert.match(src,/createLiveTimelineTracker/);
|
|
44
|
+
assert.match(src,/const activityTracker=createLiveTimelineTracker\(\)/);
|
|
45
|
+
assert.doesNotMatch(src,/remote --verbose/);
|
|
46
|
+
assert.doesNotMatch(src,/args\[0\]==='--verbose'/);
|
|
47
|
+
});
|
|
@@ -65,7 +65,7 @@ async function collect(child){
|
|
|
65
65
|
|
|
66
66
|
const winTest=isWindows?test:test.skip;
|
|
67
67
|
|
|
68
|
-
winTest('bare remote uses
|
|
68
|
+
winTest('bare remote uses one unified live timeline, keeps authority semantics, then disarms and parks when the foreground session ends',async()=>{
|
|
69
69
|
const fx=await fixture();
|
|
70
70
|
let child=null;
|
|
71
71
|
try{
|
|
@@ -87,7 +87,7 @@ winTest('bare remote uses compact human logs by default, keeps authority semanti
|
|
|
87
87
|
assert.match(output.stdout,/\[OK\] ONLINE/);
|
|
88
88
|
assert.match(output.stdout,/β
\[READY\] DEADBYTE MCP online/);
|
|
89
89
|
assert.match(output.stdout,/π \[AUTH\] ARMED: process, coding, autonomous \| host DISARMED/);
|
|
90
|
-
assert.match(output.stdout,/\[LOG\]
|
|
90
|
+
assert.match(output.stdout,/\[LOG\] Unified live timeline\. Ctrl\+C disconnects and revokes authority\./);
|
|
91
91
|
assert.doesNotMatch(output.stdout,/Process plane\s*:/);
|
|
92
92
|
assert.doesNotMatch(output.stdout,/Coding plane\s*:/);
|
|
93
93
|
const auditDir=path.join(fx.state,'audit');
|
|
@@ -110,20 +110,23 @@ winTest('bare remote uses compact human logs by default, keeps authority semanti
|
|
|
110
110
|
'[TOOL OUT] 2026-09-16T00:00:00.002Z #000002 coding_file_read {"is_error":true}'
|
|
111
111
|
].join('\n')+'\n','utf8');
|
|
112
112
|
const logDeadline=Date.now()+3000;
|
|
113
|
-
while(Date.now()<logDeadline
|
|
114
|
-
assert.match(output.stdout,/βΆ RUN coding_tree root=projects path=src/);
|
|
115
|
-
assert.match(output.stdout
|
|
116
|
-
assert.match(output.stdout,/βΆ RUN coding_file_read root=projects path=src\/deadbyte-cli\.mjs/);
|
|
117
|
-
assert.match(output.stdout
|
|
118
|
-
assert.equal((output.stdout.match(
|
|
113
|
+
while(Date.now()<logDeadline&&!/β \[fedcba98\] ERR coding_file_read 1\.73s/.test(output.stdout)) await sleep(50);
|
|
114
|
+
assert.match(output.stdout,/βΆ \[abcdef12\] RUN coding_tree root=projects path=src/);
|
|
115
|
+
assert.match(output.stdout,/β \[abcdef12\] OK coding_tree 42ms \[cursor r1:[0-9a-f]{24}:1\]/);
|
|
116
|
+
assert.match(output.stdout,/βΆ \[fedcba98\] RUN coding_file_read root=projects path=src\/deadbyte-cli\.mjs/);
|
|
117
|
+
assert.match(output.stdout,/β \[fedcba98\] ERR coding_file_read 1\.73s \[cursor r1:[0-9a-f]{24}:2\]/);
|
|
118
|
+
assert.equal((output.stdout.match(/β \[abcdef12\] OK coding_tree 42ms/g)||[]).length,1,'duplicate terminal result must print once');
|
|
119
119
|
const resultJournal=JSON.parse(await readFile(path.join(fx.state,'runtime','remote-results',`${marker.result_session_id}.json`),'utf8'));
|
|
120
120
|
assert.deepEqual(resultJournal.events.map(event=>event.seq),[1,2]);
|
|
121
121
|
assert.equal(resultJournal.events[0].request_id,'abcdef1234567890');
|
|
122
122
|
assert.ok(resultJournal.events.every(event=>/^[0-9a-f]{64}$/.test(event.payload_sha256)));
|
|
123
123
|
assert.doesNotMatch(JSON.stringify(resultJournal),/TOOL IN|TOOL OUT|stdout_excerpt|stderr_excerpt/);
|
|
124
|
-
assert.
|
|
124
|
+
assert.match(output.stdout,/abcdef12/);
|
|
125
|
+
assert.match(output.stdout,/fedcba98/);
|
|
125
126
|
assert.doesNotMatch(output.stdout,/DO_NOT_PRINT_PAYLOAD|DO_NOT_PRINT_TOKEN/);
|
|
126
|
-
assert.
|
|
127
|
+
assert.match(output.stdout,/\[BRIDGE\.STDOUT\] IN coding_tree/);
|
|
128
|
+
assert.match(output.stdout,/\[BRIDGE\.STDOUT\] OUT coding_tree/);
|
|
129
|
+
assert.match(output.stdout,/\[BRIDGE\.STDOUT\] ERR coding_file_read/);
|
|
127
130
|
assert.doesNotMatch(output.stdout,/\[TOOL IN \]|\[TOOL OUT\]/);
|
|
128
131
|
assert.doesNotMatch(output.stdout,/payload bytes=/);
|
|
129
132
|
child.stdin.end();
|
|
@@ -132,7 +135,7 @@ winTest('bare remote uses compact human logs by default, keeps authority semanti
|
|
|
132
135
|
const commands=await traceCommands(fx.trace);
|
|
133
136
|
assert.deepEqual(commands.slice(-5),['disarmautonomous','disarmcoding','disarmprocess','disarmhost','park']);
|
|
134
137
|
assert.match(output.stdout,/^DEADBYTE MCP$/m);
|
|
135
|
-
assert.match(output.stdout,/
|
|
138
|
+
assert.match(output.stdout,/Unified live timeline/i);
|
|
136
139
|
assert.match(output.stdout,/π \[AUTH\] Revoking session authority/);
|
|
137
140
|
assert.doesNotMatch(output.stdout,/disarmautonomous OK|disarmcoding OK|disarmprocess OK|disarmhost OK|DEADBYTE MCP = PARKED/);
|
|
138
141
|
const withoutApprovedEmoji=output.stdout.replace(/[ππ₯π€β
ββ β»π‘βΆπππ]/gu,'');
|
|
@@ -151,17 +154,17 @@ winTest('remote --resume replays only terminal results after the cursor before s
|
|
|
151
154
|
const firstOutput=await collect(first);
|
|
152
155
|
await waitFor(fx.trace,commands=>commands.includes('hoststatus'));
|
|
153
156
|
const liveDeadline=Date.now()+3000;
|
|
154
|
-
while(Date.now()<liveDeadline&&!/\[LOG\]
|
|
157
|
+
while(Date.now()<liveDeadline&&!/\[LOG\] Unified live timeline/.test(firstOutput.stdout)) await sleep(50);
|
|
155
158
|
const auditDir=path.join(fx.state,'audit');await mkdir(auditDir,{recursive:true});
|
|
156
159
|
const auditFile=path.join(auditDir,'segment-00000001.jsonl');
|
|
157
160
|
await writeFile(auditFile,JSON.stringify({seq:1,event_type:'tool.result',tool:'coding_tree',request_id:'resume-request-1',outcome:{is_error:false}})+'\n','utf8');
|
|
158
161
|
let deadline=Date.now()+3000;
|
|
159
|
-
while(Date.now()<deadline&&!/coding_tree
|
|
160
|
-
const cursor1=firstOutput.stdout.match(/coding_tree
|
|
162
|
+
while(Date.now()<deadline&&!/coding_tree .*\[cursor r1:[0-9a-f]{24}:1\]/.test(firstOutput.stdout)) await sleep(50);
|
|
163
|
+
const cursor1=firstOutput.stdout.match(/coding_tree .*\[cursor (r1:[0-9a-f]{24}:1)\]/)?.[1];
|
|
161
164
|
assert.ok(cursor1,'first result cursor missing');
|
|
162
165
|
await writeFile(auditFile,JSON.stringify({seq:2,event_type:'tool.result',tool:'coding_file_read',request_id:'resume-request-2',outcome:{is_error:false}})+'\n',{encoding:'utf8',flag:'a'});
|
|
163
166
|
deadline=Date.now()+3000;
|
|
164
|
-
while(Date.now()<deadline&&!/coding_file_read
|
|
167
|
+
while(Date.now()<deadline&&!/coding_file_read .*\[cursor r1:[0-9a-f]{24}:2\]/.test(firstOutput.stdout)) await sleep(50);
|
|
165
168
|
first.stdin.end();
|
|
166
169
|
const firstEnded=await Promise.race([firstOutput.closed,sleep(6000).then(()=>({timeout:true}))]);
|
|
167
170
|
assert.equal(firstEnded.timeout,undefined);
|
|
@@ -170,12 +173,12 @@ winTest('remote --resume replays only terminal results after the cursor before s
|
|
|
170
173
|
const secondOutput=await collect(second);
|
|
171
174
|
deadline=Date.now()+5000;
|
|
172
175
|
while(Date.now()<deadline&&(!/\[REPLAY\] \[OK\] coding_file_read \[cursor r1:[0-9a-f]{24}:2\]/.test(secondOutput.stdout)||
|
|
173
|
-
!/\[LOG\]
|
|
176
|
+
!/\[LOG\] Unified live timeline/.test(secondOutput.stdout))) await sleep(50);
|
|
174
177
|
assert.match(secondOutput.stdout,/\[REPLAY\] \[OK\] coding_file_read \[cursor r1:[0-9a-f]{24}:2\]/);
|
|
175
178
|
assert.match(secondOutput.stdout,/β»οΈ \[SESSION\] Previous result stream replayed/);
|
|
176
179
|
assert.doesNotMatch(secondOutput.stdout,/\[REPLAY\] \[OK\] coding_tree/);
|
|
177
180
|
const replayIndex=secondOutput.stdout.indexOf('[REPLAY]');
|
|
178
|
-
const liveIndex=secondOutput.stdout.indexOf('[LOG]
|
|
181
|
+
const liveIndex=secondOutput.stdout.indexOf('[LOG] Unified live timeline');
|
|
179
182
|
assert.ok(replayIndex>=0&&liveIndex>replayIndex,'resume replay must happen before new live tail');
|
|
180
183
|
second.stdin.end();
|
|
181
184
|
const secondEnded=await Promise.race([secondOutput.closed,sleep(6000).then(()=>({timeout:true}))]);
|
|
@@ -187,43 +190,17 @@ winTest('remote --resume replays only terminal results after the cursor before s
|
|
|
187
190
|
}
|
|
188
191
|
});
|
|
189
192
|
|
|
190
|
-
winTest('remote --verbose
|
|
193
|
+
winTest('remote --verbose is rejected because R37 has one unified remote mode',async()=>{
|
|
191
194
|
const fx=await fixture();
|
|
192
|
-
let child=null;
|
|
193
195
|
try{
|
|
194
|
-
child=spawn(process.execPath,[cliPath,'remote','--verbose'],{env:fx.env,stdio:['
|
|
196
|
+
const child=spawn(process.execPath,[cliPath,'remote','--verbose'],{env:fx.env,stdio:['ignore','pipe','pipe'],windowsHide:true});
|
|
195
197
|
const output=await collect(child);
|
|
196
|
-
const ready=await waitFor(fx.trace,commands=>commands.slice(0,8).join(',')==='start,armprocess,armcoding,armautonomous,processstatus,codingstatus,autonomousstatus,hoststatus');
|
|
197
|
-
assert.equal(ready.length>=8,true);
|
|
198
|
-
const liveDeadline=Date.now()+3000;
|
|
199
|
-
while(Date.now()<liveDeadline&&!/Live logs active/.test(output.stdout)) await sleep(50);
|
|
200
|
-
assert.match(output.stdout,/Live logs active/);
|
|
201
|
-
const auditDir=path.join(fx.state,'audit');
|
|
202
|
-
const runtimeLogs=path.join(fx.state,'runtime','logs');
|
|
203
|
-
await mkdir(auditDir,{recursive:true});
|
|
204
|
-
await mkdir(runtimeLogs,{recursive:true});
|
|
205
|
-
await writeFile(path.join(auditDir,'segment-00000001.jsonl'),[
|
|
206
|
-
JSON.stringify({seq:1,event_type:'tool.request',tool:'coding_tree',request_id:'abcdef1234567890'}),
|
|
207
|
-
JSON.stringify({seq:2,event_type:'tool.result',tool:'coding_tree',request_id:'abcdef1234567890',outcome:{is_error:false}})
|
|
208
|
-
].join('\n')+'\n','utf8');
|
|
209
|
-
await writeFile(path.join(runtimeLogs,'bridge.stdout.log'),[
|
|
210
|
-
'[TOOL IN ] 2026-09-16T00:00:00.000Z #000001 coding_tree {}',
|
|
211
|
-
'[TOOL OUT] 2026-09-16T00:00:00.001Z #000001 coding_tree {"is_error":false}'
|
|
212
|
-
].join('\n')+'\n','utf8');
|
|
213
|
-
const deadline=Date.now()+3000;
|
|
214
|
-
while(Date.now()<deadline&&(!/\[AUDIT #2\] tool\.result coding_tree abcdef12/.test(output.stdout)||!/\[BRIDGE\.STDOUT\] \[TOOL OUT\].*coding_tree/.test(output.stdout))) await sleep(50);
|
|
215
|
-
assert.match(output.stdout,/\[AUDIT #1\] tool\.request coding_tree abcdef12/);
|
|
216
|
-
assert.match(output.stdout,/\[AUDIT #2\] tool\.result coding_tree abcdef12/);
|
|
217
|
-
assert.match(output.stdout,/\[BRIDGE\.STDOUT\] \[TOOL IN \].*coding_tree/);
|
|
218
|
-
assert.match(output.stdout,/\[BRIDGE\.STDOUT\] \[TOOL OUT\].*coding_tree/);
|
|
219
|
-
child.stdin.end();
|
|
220
198
|
const ended=await Promise.race([output.closed,sleep(6000).then(()=>({timeout:true}))]);
|
|
221
|
-
assert.equal(ended.timeout,undefined
|
|
222
|
-
assert.
|
|
223
|
-
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
}
|
|
199
|
+
assert.equal(ended.timeout,undefined);
|
|
200
|
+
assert.notEqual(ended.code,0);
|
|
201
|
+
assert.match(output.stderr,/unsupported remote command '--verbose'/i);
|
|
202
|
+
assert.deepEqual(await traceCommands(fx.trace),[],'rejected legacy flag must not touch runtime authority');
|
|
203
|
+
}finally{await rm(fx.dir,{recursive:true,force:true});}
|
|
227
204
|
});
|
|
228
205
|
|
|
229
206
|
winTest('detached guardian revokes authority, parks, and removes the session marker after the owner is hard-killed',async()=>{
|