deadbyte-mcp 0.11.3 → 0.13.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 +126 -54
- package/R41-PARENT.json +15 -0
- package/README.txt +5 -4
- package/acceptance/r40/desktop-live-drift.mjs +106 -0
- package/acceptance/r40/desktop-live-ground.mjs +110 -0
- package/acceptance/r40/desktop-live-input.mjs +128 -0
- package/acceptance/r40/desktop-live-observe.mjs +100 -0
- package/acceptance/r40/desktop-live-uia.mjs +121 -0
- package/bin/appcontainer-stage.obj +0 -0
- package/bin/bootstrap-advapi32.obj +0 -0
- package/bin/bootstrap-exitcode.obj +0 -0
- package/bin/bootstrap-kernel32.obj +0 -0
- package/bin/child-control-probe.obj +0 -0
- package/bin/child-control-stage.obj +0 -0
- package/bin/contained-reverse-worker.obj +0 -0
- package/bin/contained-transform-worker.obj +0 -0
- package/bin/containment-probe.obj +0 -0
- package/bin/deadbyte-contain.obj +0 -0
- package/bin/deadbyte-desktop-input-r40.exe +0 -0
- package/bin/deadbyte-desktop-input-r40.obj +0 -0
- package/bin/deadbyte-desktop-observer-r40.exe +0 -0
- package/bin/deadbyte-desktop-observer-r40.obj +0 -0
- package/bin/deadbyte-desktop-uia-r40.exe +0 -0
- package/bin/deadbyte-desktop-uia-r40.obj +0 -0
- package/bin/deadbyte-exec.obj +0 -0
- package/bin/deadbyte-process-host.obj +0 -0
- package/bin/deadbyte-tunnel-host.obj +0 -0
- package/controller/README.TXT +7 -5
- package/controller/deadbyte-controller.config.psd1.example +3 -0
- package/controller/deadbyte-controller.ps1 +149 -4
- package/controller/deadbyte-desktop-policy.json +41 -0
- package/controller/deadbyte-process-policy.json +4 -4
- package/docs/ARCHITECTURE.md +6 -1
- package/docs/superpowers/specs/2026-09-19-r40-desktop-computer-use-design.md +214 -0
- package/docs/superpowers/specs/2026-09-20-r41-deterministic-memory-design.md +132 -0
- package/native/deadbyte-desktop-input.cpp +455 -0
- package/native/deadbyte-desktop-observer.cpp +253 -0
- package/native/deadbyte-desktop-uia.cpp +307 -0
- package/package.json +12 -8
- package/proof/CONTAINMENT-BUILD.txt +6 -6
- package/scripts/build-containment.ps1 +24 -14
- package/scripts/build-desktop-r40.ps1 +112 -0
- package/scripts/deferred-slot-operation-r40.mjs +126 -0
- package/scripts/deferred-slot-operation-r41.mjs +127 -0
- package/scripts/final-closure-r40.mjs +114 -0
- package/scripts/final-closure-r41.mjs +116 -0
- package/scripts/final-closure-verify-r40.mjs +212 -0
- package/scripts/final-closure-verify-r41.mjs +215 -0
- package/scripts/gate-windows-r40.ps1 +43 -0
- package/scripts/gate-windows-r41.ps1 +48 -0
- package/scripts/init-desktop-policy-r40.ps1 +85 -0
- package/scripts/r40-compact-ledger-probe.mjs +4 -0
- package/scripts/release-parity-r40.mjs +212 -0
- package/scripts/release-parity-r41.mjs +221 -0
- package/scripts/release-parity-tests-r40.ps1 +9 -0
- package/scripts/release-parity-tests-r41.ps1 +9 -0
- package/scripts/verify-memory-r41.mjs +88 -0
- package/scripts/verify-r41-parent.mjs +61 -0
- package/scripts/windows-gate-evidence-r40.mjs +52 -0
- package/scripts/windows-gate-evidence-r41.mjs +53 -0
- package/src/autonomous-context-engine.mjs +3 -1
- package/src/autonomous-planner-contracts.mjs +19 -1
- package/src/autonomous-planner.mjs +24 -0
- package/src/autonomous-runtime.mjs +164 -25
- package/src/capability-ledger.mjs +6 -1
- package/src/compact-gateway-mcp-tools.mjs +14 -2
- package/src/deadbyte-cli.mjs +72 -44
- package/src/desktop-contract.mjs +263 -0
- package/src/desktop-input-r40.mjs +148 -0
- package/src/desktop-mcp-tools-r40.mjs +126 -0
- package/src/desktop-memory-r40.mjs +272 -0
- package/src/desktop-observer-r40.mjs +231 -0
- package/src/desktop-policy-r40.mjs +110 -0
- package/src/desktop-runtime-r40.mjs +318 -0
- package/src/desktop-uia-r40.mjs +123 -0
- package/src/mcp-server.mjs +87 -19
- package/src/memory-r41.mjs +692 -0
- package/src/r40-compact-disarmed-probe.mjs +71 -0
- package/src/r40-full-surface-probe.mjs +34 -0
- package/src/release-generation.mjs +38 -5
- package/src/remote-console.mjs +41 -0
- package/src/remote-live-log.mjs +208 -45
- package/src/remote-mcp-desktop-r40-smoke-client.mjs +70 -0
- package/src/remote-mcp-r40-parity-client.mjs +200 -0
- package/src/remote-mcp-smoke-client.mjs +20 -6
- package/src/remote-result-journal.mjs +10 -2
- package/src/runtime-update.mjs +55 -17
- package/src/tool-audit.mjs +29 -2
- package/src/version.mjs +1 -1
- package/test/autonomous-capability-r36.test.mjs +43 -1
- package/test/autonomous-desktop-r40.test.mjs +188 -0
- package/test/capability-ledger-r36.test.mjs +1 -0
- package/test/cli-entrypoint.test.mjs +1 -1
- package/test/compact-catalog-r36.test.mjs +2 -2
- package/test/compact-gateway-r36.test.mjs +56 -4
- package/test/compact-max-catalog-r40.test.mjs +95 -0
- package/test/controller-desktop-r40.test.mjs +86 -0
- package/test/core.test.mjs +1 -1
- package/test/desktop-adversarial-r40.test.mjs +62 -0
- package/test/desktop-contract-r40.test.mjs +200 -0
- package/test/desktop-input-r40.test.mjs +63 -0
- package/test/desktop-mcp-tools-r40.test.mjs +61 -0
- package/test/desktop-memory-r40.test.mjs +141 -0
- package/test/desktop-observer-r40.test.mjs +119 -0
- package/test/desktop-policy-r40.test.mjs +111 -0
- package/test/desktop-runtime-r40.test.mjs +278 -0
- package/test/desktop-uia-r40.test.mjs +42 -0
- package/test/full-max-catalog-r40.test.mjs +91 -0
- package/test/helpers/autonomous-r34-fixture.mjs +3 -3
- package/test/memory-autonomous-integration-r41.test.mjs +31 -0
- package/test/memory-history-r41.test.mjs +126 -0
- package/test/memory-projections-r41.test.mjs +92 -0
- package/test/memory-retrieval-r41.test.mjs +124 -0
- package/test/memory-snapshot-r41.test.mjs +106 -0
- package/test/r33-closeout-regression.test.mjs +7 -7
- package/test/r33-finalization.test.mjs +15 -15
- package/test/r37-remote-tool-call-timeline.test.mjs +6 -5
- package/test/r40-finalization.test.mjs +118 -0
- package/test/r41-finalization.test.mjs +38 -0
- package/test/release-generation.test.mjs +41 -9
- package/test/release-version.test.mjs +20 -61
- package/test/remote-console-r40.test.mjs +38 -0
- package/test/remote-live-log-r37.test.mjs +89 -32
- package/test/remote-r24-catalog.test.mjs +12 -3
- package/test/remote-result-journal.test.mjs +15 -0
- package/test/remote-session-cli.test.mjs +69 -46
- package/test/runtime-self-update.test.mjs +44 -0
|
@@ -0,0 +1,126 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { createHash,generateKeyPairSync,sign as cryptoSign } from 'node:crypto';
|
|
4
|
+
import { mkdir,mkdtemp,rm,writeFile } from 'node:fs/promises';
|
|
5
|
+
import os from 'node:os';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { canonicalJson } from '../src/canonical-json.mjs';
|
|
8
|
+
import { createR41MemoryProvider } from '../src/memory-r41.mjs';
|
|
9
|
+
import { verifyR41Memory } from '../scripts/verify-memory-r41.mjs';
|
|
10
|
+
|
|
11
|
+
const EVENT_DOMAIN=Buffer.from('DEADBYTE-AUTONOMOUS-EVENT-V1\0');
|
|
12
|
+
const GOAL_DOMAIN=Buffer.from('DEADBYTE-AUTONOMOUS-GOAL-V1\0');
|
|
13
|
+
const ZERO='0'.repeat(64);
|
|
14
|
+
const sha=value=>createHash('sha256').update(Buffer.from(typeof value==='string'?value:canonicalJson(value),'utf8')).digest('hex');
|
|
15
|
+
const {privateKey,publicKey}=generateKeyPairSync('ed25519');
|
|
16
|
+
const keyId=createHash('sha256').update(Buffer.from(publicKey.export({type:'spki',format:'der'}))).digest('hex');
|
|
17
|
+
const manifest=sha('r41-history-release');
|
|
18
|
+
|
|
19
|
+
function eventJournal(goalId,items){
|
|
20
|
+
const events=[];
|
|
21
|
+
for(const [index,[type,payload]] of items.entries()){
|
|
22
|
+
const body={schema:'deadbyte.autonomous-event.v1',seq:index+1,goal_id:goalId,
|
|
23
|
+
created_at_utc:`2026-09-20T08:00:${String(index).padStart(2,'0')}.000Z`,prev_sha256:events.at(-1)?.event_sha256??ZERO,type,payload};
|
|
24
|
+
const event_sha256=sha(body);const signed={...body,event_sha256};
|
|
25
|
+
events.push({...signed,attestation:{algorithm:'ed25519',key_id:keyId,
|
|
26
|
+
signature_base64:cryptoSign(null,Buffer.concat([EVENT_DOMAIN,Buffer.from(canonicalJson(signed),'utf8')]),privateKey).toString('base64')}});
|
|
27
|
+
}
|
|
28
|
+
return events;
|
|
29
|
+
}
|
|
30
|
+
function signedGoal(goalId,title){
|
|
31
|
+
const identity={schema:'deadbyte.autonomous-goal.v1',policy_sha256:sha('policy'),root_id:'core',submission_id:title,
|
|
32
|
+
title,goal:`repair ${title}`,acceptance:'tests pass',max_iterations:8};
|
|
33
|
+
const body={...identity,goal_sha256:sha(identity),goal_id:goalId};
|
|
34
|
+
return {...body,attestation:{algorithm:'ed25519',key_id:keyId,
|
|
35
|
+
signature_base64:cryptoSign(null,Buffer.concat([GOAL_DOMAIN,Buffer.from(canonicalJson(body),'utf8')]),privateKey).toString('base64')}};
|
|
36
|
+
}
|
|
37
|
+
async function writeHistory(root,goal,events){
|
|
38
|
+
const dir=path.join(root,goal.goal_id);await mkdir(path.join(dir,'events'),{recursive:true});
|
|
39
|
+
await writeFile(path.join(dir,'goal.json'),`${canonicalJson(goal)}\n`);
|
|
40
|
+
for(const event of events)await writeFile(path.join(dir,'events',`${String(event.seq).padStart(6,'0')}.json`),`${canonicalJson(event)}\n`);
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
test('R41 provider retrieves verified prior-goal memory and excludes cross-release journals',async()=>{
|
|
44
|
+
const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r41-history-'));
|
|
45
|
+
try{
|
|
46
|
+
const journalRoot=path.join(root,'goals');const memoryRoot=path.join(root,'memory');
|
|
47
|
+
const priorId=sha('prior-goal');const priorGoal=signedGoal(priorId,'ParserSymbol timeout');
|
|
48
|
+
const priorEvents=eventJournal(priorId,[
|
|
49
|
+
['goal_created',{source_release_manifest:manifest}],
|
|
50
|
+
['profile_completed',{profile_id:'test',passed:false,diagnostic_codes:['ERR_PARSER_TIMEOUT'],symbols:['ParserSymbol']}]
|
|
51
|
+
]);
|
|
52
|
+
await writeHistory(journalRoot,priorGoal,priorEvents);
|
|
53
|
+
const foreignId=sha('foreign-goal');const foreignGoal=signedGoal(foreignId,'ParserSymbol foreign');
|
|
54
|
+
await writeHistory(journalRoot,foreignGoal,eventJournal(foreignId,[['goal_created',{source_release_manifest:sha('other-release')}]]));
|
|
55
|
+
const currentId=sha('current-goal');const signedCurrent=signedGoal(currentId,'ParserSymbol regression');
|
|
56
|
+
await writeHistory(journalRoot,signedCurrent,eventJournal(currentId,[['goal_created',{source_release_manifest:manifest}]]));
|
|
57
|
+
const currentGoal={...signedCurrent};delete currentGoal.attestation;
|
|
58
|
+
const currentEvents=eventJournal(currentId,[['goal_created',{source_release_manifest:manifest}]]);
|
|
59
|
+
const provider=createR41MemoryProvider({memoryRoot,journalRoot,sourceReleaseManifest:manifest,privateKey,publicKey,keyId,byteBudget:32768});
|
|
60
|
+
const result=await provider.refresh({goal:currentGoal,events:currentEvents,currentSymbols:['ParserSymbol']});
|
|
61
|
+
assert.equal(result.historical_goal_count,1);
|
|
62
|
+
assert.ok(result.planner_context.historical_memory.length>=1);
|
|
63
|
+
assert.equal(result.planner_context.historical_memory.some(item=>item.goal?.goal_id===foreignId||item.goal_id===foreignId),false);
|
|
64
|
+
assert.equal(result.planner_context.historical_archive_sha256,result.historical_archive_sha256);
|
|
65
|
+
const grownPriorEvents=eventJournal(priorId,[
|
|
66
|
+
['goal_created',{source_release_manifest:manifest}],
|
|
67
|
+
['profile_completed',{profile_id:'test',passed:false,diagnostic_codes:['ERR_PARSER_TIMEOUT'],symbols:['ParserSymbol']}],
|
|
68
|
+
['planner_decision',{decision:{summary:'retry parser',action:'run_profile'}}],
|
|
69
|
+
['profile_completed',{profile_id:'test',passed:true,symbols:['ParserSymbol']}],
|
|
70
|
+
['release_completed',{receipt_sha256:sha('prior-release-grown')}]
|
|
71
|
+
]);
|
|
72
|
+
await rm(path.join(journalRoot,priorId),{recursive:true,force:true});
|
|
73
|
+
await writeHistory(journalRoot,priorGoal,grownPriorEvents);
|
|
74
|
+
const refreshed=await provider.refresh({goal:currentGoal,events:currentEvents,currentSymbols:['ParserSymbol']});
|
|
75
|
+
assert.notEqual(refreshed.historical_archive_sha256,result.historical_archive_sha256);
|
|
76
|
+
const publicKeyPath=path.join(root,'public.pem');await writeFile(publicKeyPath,publicKey.export({type:'spki',format:'pem'}));
|
|
77
|
+
const verified=await verifyR41Memory({memoryRoot,journalRoot,sourceReleaseManifest:manifest,publicKeyPath});
|
|
78
|
+
assert.equal(verified.status,'passed');assert.equal(verified.goal_count,1);assert.equal(verified.archive_count,2);
|
|
79
|
+
}finally{await rm(root,{recursive:true,force:true});}
|
|
80
|
+
});
|
|
81
|
+
|
|
82
|
+
test('R41 provider fails closed on a poisoned same-release historical chain',async()=>{
|
|
83
|
+
const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r41-history-poison-'));
|
|
84
|
+
try{
|
|
85
|
+
const journalRoot=path.join(root,'goals');const goalId=sha('poisoned-goal');const historical=signedGoal(goalId,'poisoned');
|
|
86
|
+
const events=eventJournal(goalId,[['goal_created',{source_release_manifest:manifest}],['release_completed',{}]]);
|
|
87
|
+
events[1].prev_sha256=sha('forged');
|
|
88
|
+
await writeHistory(journalRoot,historical,events);
|
|
89
|
+
const currentId=sha('current-poison-check');const current={...signedGoal(currentId,'current')};delete current.attestation;
|
|
90
|
+
const provider=createR41MemoryProvider({memoryRoot:path.join(root,'memory'),journalRoot,sourceReleaseManifest:manifest,privateKey,publicKey,keyId});
|
|
91
|
+
await assert.rejects(provider.refresh({goal:current,events:eventJournal(currentId,[['goal_created',{source_release_manifest:manifest}]])}),/predecessor mismatch|hash mismatch/);
|
|
92
|
+
}finally{await rm(root,{recursive:true,force:true});}
|
|
93
|
+
});
|
|
94
|
+
|
|
95
|
+
|
|
96
|
+
test('R41 verifier accepts content-addressed indexes from earlier verified snapshot prefixes',async()=>{
|
|
97
|
+
const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r41-history-prefix-index-'));
|
|
98
|
+
try{
|
|
99
|
+
const journalRoot=path.join(root,'goals');const memoryRoot=path.join(root,'memory');
|
|
100
|
+
const goalId=sha('growing-goal');const signed=signedGoal(goalId,'growing journal');const goal={...signed};delete goal.attestation;
|
|
101
|
+
const firstEvents=eventJournal(goalId,[
|
|
102
|
+
['goal_created',{source_release_manifest:manifest}],
|
|
103
|
+
['profile_completed',{profile_id:'test',passed:false,diagnostic_codes:['ERR_FIRST']}]
|
|
104
|
+
]);
|
|
105
|
+
await writeHistory(journalRoot,signed,firstEvents);
|
|
106
|
+
const provider=createR41MemoryProvider({memoryRoot,journalRoot,sourceReleaseManifest:manifest,privateKey,publicKey,keyId,byteBudget:32768});
|
|
107
|
+
const first=await provider.refresh({goal,events:firstEvents});
|
|
108
|
+
const grownEvents=eventJournal(goalId,[
|
|
109
|
+
['goal_created',{source_release_manifest:manifest}],
|
|
110
|
+
['profile_completed',{profile_id:'test',passed:false,diagnostic_codes:['ERR_FIRST']}],
|
|
111
|
+
['planner_decision',{decision:{summary:'retry safely',action:'run_profile'}}],
|
|
112
|
+
['profile_completed',{profile_id:'test',passed:true}],
|
|
113
|
+
['release_completed',{receipt_sha256:sha('grown-release')}]
|
|
114
|
+
]);
|
|
115
|
+
await rm(path.join(journalRoot,goalId),{recursive:true,force:true});
|
|
116
|
+
await writeHistory(journalRoot,signed,grownEvents);
|
|
117
|
+
const grown=await provider.refresh({goal,events:grownEvents});
|
|
118
|
+
assert.notEqual(first.memory_sha256,grown.memory_sha256);
|
|
119
|
+
assert.notEqual(first.index_sha256,grown.index_sha256);
|
|
120
|
+
const publicKeyPath=path.join(root,'public.pem');await writeFile(publicKeyPath,publicKey.export({type:'spki',format:'pem'}));
|
|
121
|
+
const verified=await verifyR41Memory({memoryRoot,journalRoot,sourceReleaseManifest:manifest,publicKeyPath});
|
|
122
|
+
assert.equal(verified.status,'passed');
|
|
123
|
+
assert.equal(verified.snapshot_count,2);
|
|
124
|
+
assert.equal(verified.index_count,2);
|
|
125
|
+
}finally{await rm(root,{recursive:true,force:true});}
|
|
126
|
+
});
|
|
@@ -0,0 +1,92 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { createHash, generateKeyPairSync, sign as cryptoSign } from 'node:crypto';
|
|
4
|
+
import { canonicalJson } from '../src/canonical-json.mjs';
|
|
5
|
+
import {
|
|
6
|
+
deriveEpisodicMemory,verifyEpisode,
|
|
7
|
+
deriveDecisionMemory,verifyDecisionMemory,
|
|
8
|
+
deriveIncidentMemory,verifyIncidentMemory
|
|
9
|
+
} from '../src/memory-r41.mjs';
|
|
10
|
+
|
|
11
|
+
const DOMAIN=Buffer.from('DEADBYTE-AUTONOMOUS-EVENT-V1\0');
|
|
12
|
+
const ZERO='0'.repeat(64);
|
|
13
|
+
const sha=value=>createHash('sha256').update(Buffer.from(typeof value==='string'?value:canonicalJson(value),'utf8')).digest('hex');
|
|
14
|
+
const {privateKey,publicKey}=generateKeyPairSync('ed25519');
|
|
15
|
+
const keyId=sha(Buffer.from(publicKey.export({type:'spki',format:'der'})));
|
|
16
|
+
const goalId=sha('projection-goal');
|
|
17
|
+
const goal={schema:'deadbyte.autonomous-goal.v1',goal_id:goalId,goal_sha256:sha('projection-body'),root_id:'core',
|
|
18
|
+
title:'repair linker',goal:'repair LNK2019',acceptance:'build and tests pass'};
|
|
19
|
+
|
|
20
|
+
function appendJournal(out,type,payload){
|
|
21
|
+
const index=out.length;
|
|
22
|
+
const body={schema:'deadbyte.autonomous-event.v1',seq:index+1,goal_id:goalId,
|
|
23
|
+
created_at_utc:`2026-09-20T02:00:${String(index).padStart(2,'0')}.000Z`,prev_sha256:out.at(-1)?.event_sha256??ZERO,type,payload};
|
|
24
|
+
const event_sha256=sha(body);const signed={...body,event_sha256};
|
|
25
|
+
const signature_base64=cryptoSign(null,Buffer.concat([DOMAIN,Buffer.from(canonicalJson(signed),'utf8')]),privateKey).toString('base64');
|
|
26
|
+
out.push({...signed,attestation:{algorithm:'ed25519',key_id:keyId,signature_base64}});
|
|
27
|
+
}
|
|
28
|
+
function journal(items){
|
|
29
|
+
const out=[];
|
|
30
|
+
for(const [type,payload] of items)appendJournal(out,type,payload);
|
|
31
|
+
return out;
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
const base=journal([
|
|
35
|
+
['goal_created',{submission_id:'incident-1',acceptance:'build and tests pass'}],
|
|
36
|
+
['planner_decision',{planner_round:1,decision:{action:'inspect',summary:'inspect linker output'}}],
|
|
37
|
+
['profile_completed',{profile_id:'build',passed:false,tool:'msbuild',operation:'build',platform:'win32',architecture:'x64',
|
|
38
|
+
exit_code:1,diagnostic_codes:['LNK2019'],stderr_sha256:sha('stderr'),target:'release',symbols:['FooBar'],receipt_sha256:sha('build-fail')}],
|
|
39
|
+
['planner_decision',{planner_round:2,decision:{action:'patch',summary:'add missing FooBar definition'}}],
|
|
40
|
+
['native_diff_committed',{paths:['src/foo.cpp'],diff_receipt_sha256:sha('diff'),artifact_sha256:sha('foo-obj')}],
|
|
41
|
+
['profile_completed',{profile_id:'build',passed:true,receipt_sha256:sha('build-pass')}],
|
|
42
|
+
['release_completed',{receipt_sha256:sha('release')}]
|
|
43
|
+
]);
|
|
44
|
+
|
|
45
|
+
test('R41 episodic memory contains only canonical journal references and rejects nonexistent events',()=>{
|
|
46
|
+
const episode=deriveEpisodicMemory(goal,base,{publicKey,keyId});
|
|
47
|
+
assert.equal(episode.schema,'deadbyte.episode.v1');
|
|
48
|
+
assert.equal(episode.outcome,'succeeded');
|
|
49
|
+
assert.deepEqual(episode.event_range,{first_seq:1,last_seq:7,journal_head_sha256:base.at(-1).event_sha256});
|
|
50
|
+
assert.ok(episode.observations.every(item=>item.event_ref?.event_sha256));
|
|
51
|
+
assert.ok(episode.decisions.every(item=>item.event_ref?.event_sha256));
|
|
52
|
+
assert.ok(episode.receipt_refs.includes(sha('release')));
|
|
53
|
+
assert.equal(verifyEpisode(episode,{goal,events:base,publicKey,keyId}).ok,true);
|
|
54
|
+
const forged=structuredClone(episode);forged.actions[0].event_ref.event_sha256=sha('nonexistent');
|
|
55
|
+
assert.equal(verifyEpisode(forged,{goal,events:base,publicKey,keyId}).ok,false);
|
|
56
|
+
});
|
|
57
|
+
|
|
58
|
+
test('R41 decision memory preserves supersession edges and rejects cycles',()=>{
|
|
59
|
+
const events=journal([
|
|
60
|
+
['goal_created',{submission_id:'decisions'}],
|
|
61
|
+
['planner_decision',{planner_round:1,decision:{action:'inspect',summary:'inspect first'}}]
|
|
62
|
+
]);
|
|
63
|
+
const firstId=sha({schema:'deadbyte.decision-id.v1',goal_id:goalId,event_sha256:events[1].event_sha256});
|
|
64
|
+
appendJournal(events,'planner_decision',{planner_round:2,decision:{action:'patch',summary:'patch after evidence',supersedes:firstId}});
|
|
65
|
+
const memory=deriveDecisionMemory(goal,events,{publicKey,keyId});
|
|
66
|
+
assert.equal(memory.decisions.length,2);
|
|
67
|
+
assert.equal(memory.decisions[0].status,'superseded');
|
|
68
|
+
assert.equal(memory.decisions[1].status,'active');
|
|
69
|
+
assert.equal(memory.decisions[1].supersedes,memory.decisions[0].decision_id);
|
|
70
|
+
assert.equal(memory.decisions[0].superseded_by,memory.decisions[1].decision_id);
|
|
71
|
+
assert.equal(verifyDecisionMemory(memory,{goal,events,publicKey,keyId}).ok,true);
|
|
72
|
+
|
|
73
|
+
const cyclic=structuredClone(memory);
|
|
74
|
+
cyclic.decisions[0].supersedes=cyclic.decisions[1].decision_id;
|
|
75
|
+
cyclic.decisions[1].superseded_by=cyclic.decisions[0].decision_id;
|
|
76
|
+
assert.equal(verifyDecisionMemory(cyclic,{goal,events,publicKey,keyId}).ok,false);
|
|
77
|
+
});
|
|
78
|
+
|
|
79
|
+
test('R41 incidents use deterministic structured fingerprints and reject spoofing',()=>{
|
|
80
|
+
const memory=deriveIncidentMemory(goal,base,{publicKey,keyId});
|
|
81
|
+
assert.equal(memory.schema,'deadbyte.incident-memory.v1');
|
|
82
|
+
assert.equal(memory.incidents.length,1);
|
|
83
|
+
const incident=memory.incidents[0];
|
|
84
|
+
assert.equal(incident.fingerprint.tool,'msbuild');
|
|
85
|
+
assert.deepEqual(incident.fingerprint.diagnostic_codes,['LNK2019']);
|
|
86
|
+
assert.deepEqual(incident.fingerprint.symbols,['FooBar']);
|
|
87
|
+
assert.equal(incident.status,'resolved');
|
|
88
|
+
assert.ok(incident.successful_fix.some(ref=>ref.event_sha256===base[4].event_sha256));
|
|
89
|
+
assert.equal(verifyIncidentMemory(memory,{goal,events:base,publicKey,keyId}).ok,true);
|
|
90
|
+
const forged=structuredClone(memory);forged.incidents[0].fingerprint.exit_code=0;
|
|
91
|
+
assert.equal(verifyIncidentMemory(forged,{goal,events:base,publicKey,keyId}).ok,false);
|
|
92
|
+
});
|
|
@@ -0,0 +1,124 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { createHash, generateKeyPairSync, sign as cryptoSign } from 'node:crypto';
|
|
4
|
+
import { mkdtemp,readFile,rm } from 'node:fs/promises';
|
|
5
|
+
import os from 'node:os';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { canonicalJson } from '../src/canonical-json.mjs';
|
|
8
|
+
import {
|
|
9
|
+
buildMemoryCorpus,buildRetrievalIndex,verifyRetrievalIndex,queryMemoryIndex,
|
|
10
|
+
buildWorkingMemory,verifyWorkingMemory,createSemanticMemoryAdapter,createR41MemoryProvider
|
|
11
|
+
} from '../src/memory-r41.mjs';
|
|
12
|
+
|
|
13
|
+
const DOMAIN=Buffer.from('DEADBYTE-AUTONOMOUS-EVENT-V1\0');
|
|
14
|
+
const ZERO='0'.repeat(64);
|
|
15
|
+
const sha=value=>createHash('sha256').update(Buffer.from(typeof value==='string'?value:canonicalJson(value),'utf8')).digest('hex');
|
|
16
|
+
const {privateKey,publicKey}=generateKeyPairSync('ed25519');
|
|
17
|
+
const keyId=sha(Buffer.from(publicKey.export({type:'spki',format:'der'})));
|
|
18
|
+
const goalId=sha('retrieval-goal');
|
|
19
|
+
const manifest=sha('r41-release');
|
|
20
|
+
const goal={schema:'deadbyte.autonomous-goal.v1',goal_id:goalId,goal_sha256:sha('retrieval-body'),root_id:'core',
|
|
21
|
+
title:'repair parser',goal:'repair ParserSymbol timeout',acceptance:'build and tests pass'};
|
|
22
|
+
|
|
23
|
+
function journal(items){
|
|
24
|
+
const out=[];
|
|
25
|
+
for(const [index,[type,payload]] of items.entries()){
|
|
26
|
+
const body={schema:'deadbyte.autonomous-event.v1',seq:index+1,goal_id:goalId,
|
|
27
|
+
created_at_utc:`2026-09-20T04:00:${String(index).padStart(2,'0')}.000Z`,prev_sha256:out.at(-1)?.event_sha256??ZERO,type,payload};
|
|
28
|
+
const event_sha256=sha(body);const signed={...body,event_sha256};
|
|
29
|
+
const signature_base64=cryptoSign(null,Buffer.concat([DOMAIN,Buffer.from(canonicalJson(signed),'utf8')]),privateKey).toString('base64');
|
|
30
|
+
out.push({...signed,attestation:{algorithm:'ed25519',key_id:keyId,signature_base64}});
|
|
31
|
+
}
|
|
32
|
+
return out;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
const events=journal([
|
|
36
|
+
['goal_created',{submission_id:'retrieval',acceptance:'build and tests pass'}],
|
|
37
|
+
['planner_decision',{planner_round:1,decision:{action:'inspect',summary:'inspect ParserSymbol timeout'}}],
|
|
38
|
+
['profile_completed',{profile_id:'test',passed:false,tool:'node',operation:'test',platform:'win32',architecture:'x64',
|
|
39
|
+
timeout_state:'expired',diagnostic_codes:['ERR_TEST_TIMEOUT'],stderr_sha256:sha('stderr'),symbols:['ParserSymbol'],receipt_sha256:sha('failed')}],
|
|
40
|
+
['native_diff_committed',{paths:['src/parser.mjs'],diff_receipt_sha256:sha('diff'),artifact_sha256:sha('artifact')}],
|
|
41
|
+
['profile_completed',{profile_id:'test',passed:true,receipt_sha256:sha('passed')}],
|
|
42
|
+
['release_completed',{receipt_sha256:sha('release')}]
|
|
43
|
+
]);
|
|
44
|
+
|
|
45
|
+
function fixture(){
|
|
46
|
+
const corpus=buildMemoryCorpus({goal,events,publicKey,keyId,sourceReleaseManifest:manifest});
|
|
47
|
+
const index=buildRetrievalIndex(corpus,{sourceReleaseManifest:manifest});
|
|
48
|
+
return {corpus,index};
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
test('R41 retrieval indexes rebuild byte-identically and support exact token symbol artifact and incident lookup',()=>{
|
|
52
|
+
const {corpus,index}=fixture();
|
|
53
|
+
const rebuilt=buildRetrievalIndex(corpus,{sourceReleaseManifest:manifest});
|
|
54
|
+
assert.equal(canonicalJson(index),canonicalJson(rebuilt));
|
|
55
|
+
assert.equal(verifyRetrievalIndex(index,{corpus,sourceReleaseManifest:manifest}).ok,true);
|
|
56
|
+
assert.ok(queryMemoryIndex(index,{query:'ParserSymbol timeout',limit:8}).candidate_ids.length>=1);
|
|
57
|
+
assert.ok(queryMemoryIndex(index,{symbol:'ParserSymbol',limit:8}).candidate_ids.length>=1);
|
|
58
|
+
assert.ok(queryMemoryIndex(index,{artifact_sha256:sha('artifact'),limit:8}).candidate_ids.length>=1);
|
|
59
|
+
assert.ok(queryMemoryIndex(index,{incident_fingerprint:corpus.incidents.incidents[0].fingerprint_sha256,limit:8}).candidate_ids.includes(corpus.incidents.incidents[0].incident_id));
|
|
60
|
+
assert.deepEqual(queryMemoryIndex(index,{id:corpus.episode.episode_id,limit:1}).candidate_ids,[corpus.episode.episode_id]);
|
|
61
|
+
});
|
|
62
|
+
|
|
63
|
+
test('R41 poisoned or cross-release indexes fail closed',()=>{
|
|
64
|
+
const {corpus,index}=fixture();
|
|
65
|
+
const poisoned=structuredClone(index);
|
|
66
|
+
poisoned.token_index.timeout=[sha('forged-document')];
|
|
67
|
+
assert.equal(verifyRetrievalIndex(poisoned,{corpus,sourceReleaseManifest:manifest}).ok,false);
|
|
68
|
+
assert.equal(verifyRetrievalIndex(index,{corpus,sourceReleaseManifest:sha('other-release')}).ok,false);
|
|
69
|
+
});
|
|
70
|
+
|
|
71
|
+
test('R41 working memory is bounded provenance-bearing disposable state and rejects staleness',()=>{
|
|
72
|
+
const {corpus,index}=fixture();
|
|
73
|
+
const args={goal,events,corpus,index,publicKey,keyId,sourceReleaseManifest:manifest,byteBudget:16384,
|
|
74
|
+
currentPlan:{step:'verify'},currentFiles:[{path:'src/parser.mjs',sha256:sha('parser'),source_event_sha256:events[3].event_sha256}],
|
|
75
|
+
currentSymbols:['ParserSymbol'],currentAuthority:{coding:{armed:true,reason:'standing-grant',instance_nonce:sha('secret')}}};
|
|
76
|
+
const working=buildWorkingMemory(args);
|
|
77
|
+
assert.ok(Buffer.byteLength(canonicalJson(working),'utf8')<=16384);
|
|
78
|
+
assert.equal(working.source_release_manifest,manifest);
|
|
79
|
+
assert.equal(working.journal_head_sha256,events.at(-1).event_sha256);
|
|
80
|
+
assert.equal(working.current_authority.authorizes_execution,false);
|
|
81
|
+
assert.equal(JSON.stringify(working).includes('instance_nonce'),false);
|
|
82
|
+
assert.ok(working.relevant_incidents[0].source_event_ids.length>=1);
|
|
83
|
+
assert.equal(verifyWorkingMemory(working,args).ok,true);
|
|
84
|
+
const staleArgs={...args,events:events.slice(0,-1)};
|
|
85
|
+
assert.equal(verifyWorkingMemory(working,staleArgs).ok,false);
|
|
86
|
+
assert.equal(verifyWorkingMemory(working,{...args,sourceReleaseManifest:sha('wrong-release')}).ok,false);
|
|
87
|
+
});
|
|
88
|
+
|
|
89
|
+
test('R41 semantic retrieval is disabled by default and verifies candidate IDs against canonical memory',async()=>{
|
|
90
|
+
const {corpus,index}=fixture();
|
|
91
|
+
const disabled=createSemanticMemoryAdapter();
|
|
92
|
+
await assert.rejects(disabled.query({query:'parser',corpus,index,sourceReleaseManifest:manifest}),/disabled/);
|
|
93
|
+
|
|
94
|
+
const validId=corpus.incidents.incidents[0].incident_id;
|
|
95
|
+
const enabled=createSemanticMemoryAdapter({enabled:true,retrieveCandidates:async()=>[validId]});
|
|
96
|
+
const resolved=await enabled.query({query:'parser timeout',corpus,index,sourceReleaseManifest:manifest});
|
|
97
|
+
assert.deepEqual(resolved.candidate_ids,[validId]);
|
|
98
|
+
assert.equal(resolved.records[0].incident_id,validId);
|
|
99
|
+
|
|
100
|
+
const poisoned=createSemanticMemoryAdapter({enabled:true,retrieveCandidates:async()=>[sha('not-canonical')]});
|
|
101
|
+
await assert.rejects(poisoned.query({query:'parser',corpus,index,sourceReleaseManifest:manifest}),/canonical candidate/);
|
|
102
|
+
});
|
|
103
|
+
|
|
104
|
+
test('R41 content-addressed projections survive deletion and rebuild byte-identically',async()=>{
|
|
105
|
+
const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r41-provider-'));
|
|
106
|
+
try{
|
|
107
|
+
const provider=createR41MemoryProvider({memoryRoot:root,sourceReleaseManifest:manifest,writerVersion:'0.13.0',
|
|
108
|
+
privateKey,publicKey,keyId,byteBudget:16384});
|
|
109
|
+
const input={goal,events,currentPlan:null,currentFiles:[],currentSymbols:['ParserSymbol'],currentAuthority:{}};
|
|
110
|
+
const first=await provider.refresh(input);
|
|
111
|
+
assert.equal(first.replay_mode,'full-replay');
|
|
112
|
+
const snapshotBytes=await readFile(first.snapshot_path);
|
|
113
|
+
const indexBytes=await readFile(first.index_path);
|
|
114
|
+
await rm(first.index_path);
|
|
115
|
+
const rebuilt=await provider.refresh(input);
|
|
116
|
+
assert.equal(rebuilt.replay_mode,'snapshot-suffix');
|
|
117
|
+
assert.equal(rebuilt.snapshot_sha256,first.snapshot_sha256);
|
|
118
|
+
assert.equal(rebuilt.index_sha256,first.index_sha256);
|
|
119
|
+
assert.deepEqual(await readFile(rebuilt.snapshot_path),snapshotBytes);
|
|
120
|
+
assert.deepEqual(await readFile(rebuilt.index_path),indexBytes);
|
|
121
|
+
assert.equal(provider.semantic_enabled,false);
|
|
122
|
+
assert.equal(Object.hasOwn(provider,'arm'),false);
|
|
123
|
+
}finally{await rm(root,{recursive:true,force:true});}
|
|
124
|
+
});
|
|
@@ -0,0 +1,106 @@
|
|
|
1
|
+
import test from 'node:test';
|
|
2
|
+
import assert from 'node:assert/strict';
|
|
3
|
+
import { createHash, generateKeyPairSync, sign as cryptoSign } from 'node:crypto';
|
|
4
|
+
import { mkdtemp, readFile, writeFile } from 'node:fs/promises';
|
|
5
|
+
import os from 'node:os';
|
|
6
|
+
import path from 'node:path';
|
|
7
|
+
import { canonicalJson } from '../src/canonical-json.mjs';
|
|
8
|
+
import {
|
|
9
|
+
deriveMemoryState,
|
|
10
|
+
createMemorySnapshot,
|
|
11
|
+
verifyMemorySnapshot,
|
|
12
|
+
replayFromMemorySnapshot,
|
|
13
|
+
loadMemoryState,
|
|
14
|
+
writeMemorySnapshot
|
|
15
|
+
} from '../src/memory-r41.mjs';
|
|
16
|
+
|
|
17
|
+
const EVENT_DOMAIN=Buffer.from('DEADBYTE-AUTONOMOUS-EVENT-V1\0');
|
|
18
|
+
const ZERO='0'.repeat(64);
|
|
19
|
+
const sha=value=>createHash('sha256').update(Buffer.from(canonicalJson(value),'utf8')).digest('hex');
|
|
20
|
+
const {privateKey,publicKey}=generateKeyPairSync('ed25519');
|
|
21
|
+
const keyId=sha(Buffer.from(publicKey.export({type:'spki',format:'der'})));
|
|
22
|
+
const goalId=sha('goal');
|
|
23
|
+
const manifest=sha('r41-manifest');
|
|
24
|
+
const goal={schema:'deadbyte.autonomous-goal.v1',goal_id:goalId,goal_sha256:sha('goal-body'),title:'repair',goal:'repair source',acceptance:'tests pass'};
|
|
25
|
+
|
|
26
|
+
function journal(types){
|
|
27
|
+
const events=[];
|
|
28
|
+
for(const [index,[type,payload]] of types.entries()){
|
|
29
|
+
const body={schema:'deadbyte.autonomous-event.v1',seq:index+1,goal_id:goalId,
|
|
30
|
+
created_at_utc:`2026-09-20T00:00:${String(index).padStart(2,'0')}.000Z`,
|
|
31
|
+
prev_sha256:events.at(-1)?.event_sha256??ZERO,type,payload};
|
|
32
|
+
const event_sha256=sha(body);
|
|
33
|
+
const signed={...body,event_sha256};
|
|
34
|
+
const signature_base64=cryptoSign(null,Buffer.concat([EVENT_DOMAIN,Buffer.from(canonicalJson(signed),'utf8')]),privateKey).toString('base64');
|
|
35
|
+
events.push({...signed,attestation:{algorithm:'ed25519',key_id:keyId,signature_base64}});
|
|
36
|
+
}
|
|
37
|
+
return events;
|
|
38
|
+
}
|
|
39
|
+
|
|
40
|
+
const events=journal([
|
|
41
|
+
['goal_created',{submission_id:'r41',acceptance:'tests pass'}],
|
|
42
|
+
['planner_decision',{planner_round:1,decision:{action:'inspect',summary:'inspect source'}}],
|
|
43
|
+
['inspect_completed',{contexts:[{path:'src/a.mjs',sha256:sha('a'),bytes:1}]}],
|
|
44
|
+
['profile_completed',{profile_id:'test',passed:false,receipt_sha256:sha('failed')}],
|
|
45
|
+
['planner_decision',{planner_round:2,decision:{action:'patch',summary:'apply exact fix'}}],
|
|
46
|
+
['native_diff_committed',{paths:['src/a.mjs'],mutation_epoch:1,diff_receipt_sha256:sha('diff')}],
|
|
47
|
+
['profile_completed',{profile_id:'test',passed:true,receipt_sha256:sha('passed')}],
|
|
48
|
+
['release_completed',{receipt_sha256:sha('release')}]
|
|
49
|
+
]);
|
|
50
|
+
|
|
51
|
+
function makeSnapshot(prefix=events.slice(0,5)){
|
|
52
|
+
return createMemorySnapshot({goal,events:prefix,snapshotSequence:1,sourceReleaseManifest:manifest,
|
|
53
|
+
writerVersion:'0.13.0',createdAtUtc:'2026-09-20T01:00:00.000Z',privateKey,keyId,publicKey});
|
|
54
|
+
}
|
|
55
|
+
|
|
56
|
+
test('R41 snapshot plus verified suffix is byte-equivalent to full replay',()=>{
|
|
57
|
+
const snapshot=makeSnapshot();
|
|
58
|
+
assert.equal(snapshot.schema,'deadbyte.memory-snapshot.v1');
|
|
59
|
+
assert.equal(snapshot.schema_version,1);
|
|
60
|
+
assert.equal(snapshot.last_event_seq,5);
|
|
61
|
+
assert.equal(snapshot.journal_prefix_hash,events[4].event_sha256);
|
|
62
|
+
assert.equal(snapshot.source_release_manifest,manifest);
|
|
63
|
+
assert.equal(verifyMemorySnapshot(snapshot,{goal,events,publicKey,keyId,sourceReleaseManifest:manifest}).ok,true);
|
|
64
|
+
const resumed=replayFromMemorySnapshot(snapshot,{goal,events,publicKey,keyId,sourceReleaseManifest:manifest});
|
|
65
|
+
assert.equal(canonicalJson(resumed),canonicalJson(deriveMemoryState(goal,events,{publicKey,keyId})));
|
|
66
|
+
});
|
|
67
|
+
|
|
68
|
+
test('R41 snapshot tampering fails closed for schema sequence prefix state hash and signature',()=>{
|
|
69
|
+
const base=makeSnapshot();
|
|
70
|
+
const mutations=[
|
|
71
|
+
value=>{value.schema='deadbyte.memory-snapshot.v0';},
|
|
72
|
+
value=>{value.snapshot_sequence=0;},
|
|
73
|
+
value=>{value.last_event_seq=6;},
|
|
74
|
+
value=>{value.journal_prefix_hash=sha('wrong-prefix');},
|
|
75
|
+
value=>{value.state.last_event_seq=4;},
|
|
76
|
+
value=>{value.state_hash=sha('wrong-state');},
|
|
77
|
+
value=>{value.attestation.signature_base64=Buffer.alloc(64).toString('base64');}
|
|
78
|
+
];
|
|
79
|
+
for(const mutate of mutations){
|
|
80
|
+
const candidate=structuredClone(base);mutate(candidate);
|
|
81
|
+
const proof=verifyMemorySnapshot(candidate,{goal,events,publicKey,keyId,sourceReleaseManifest:manifest});
|
|
82
|
+
assert.equal(proof.ok,false,JSON.stringify(candidate));
|
|
83
|
+
}
|
|
84
|
+
});
|
|
85
|
+
|
|
86
|
+
test('R41 missing or corrupt snapshot falls back explicitly to full verified replay',async()=>{
|
|
87
|
+
const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r41-snapshot-'));
|
|
88
|
+
const file=path.join(root,'memory.snapshot.json');
|
|
89
|
+
const missing=await loadMemoryState({snapshotPath:file,goal,events,publicKey,keyId,sourceReleaseManifest:manifest});
|
|
90
|
+
assert.equal(missing.mode,'full-replay');
|
|
91
|
+
assert.equal(missing.snapshot_reason,'missing');
|
|
92
|
+
assert.equal(canonicalJson(missing.state),canonicalJson(deriveMemoryState(goal,events,{publicKey,keyId})));
|
|
93
|
+
|
|
94
|
+
await writeFile(file,'{"broken":true}\n');
|
|
95
|
+
const corrupt=await loadMemoryState({snapshotPath:file,goal,events,publicKey,keyId,sourceReleaseManifest:manifest});
|
|
96
|
+
assert.equal(corrupt.mode,'full-replay');
|
|
97
|
+
assert.match(corrupt.snapshot_reason,/snapshot/i);
|
|
98
|
+
|
|
99
|
+
const snapshot=makeSnapshot();
|
|
100
|
+
await writeMemorySnapshot(file,snapshot);
|
|
101
|
+
const disk=JSON.parse(await readFile(file,'utf8'));
|
|
102
|
+
assert.equal(disk.snapshot_sha256,snapshot.snapshot_sha256);
|
|
103
|
+
const resumed=await loadMemoryState({snapshotPath:file,goal,events,publicKey,keyId,sourceReleaseManifest:manifest});
|
|
104
|
+
assert.equal(resumed.mode,'snapshot-suffix');
|
|
105
|
+
assert.equal(canonicalJson(resumed.state),canonicalJson(deriveMemoryState(goal,events,{publicKey,keyId})));
|
|
106
|
+
});
|
|
@@ -86,12 +86,12 @@ test('audit restart reconciles an orphan request with an explicit interrupted re
|
|
|
86
86
|
}finally{await rm(stateRoot,{recursive:true,force:true});}
|
|
87
87
|
});
|
|
88
88
|
|
|
89
|
-
test('Windows
|
|
89
|
+
test('Windows current R41 gate emits manifest-bound machine-readable evidence outside the candidate tree', async()=>{
|
|
90
90
|
const stateRoot=await temp('deadbyte-r33-windows-evidence-');
|
|
91
91
|
try{
|
|
92
|
-
const gate=await readFile(path.join(root,'scripts','gate-windows-
|
|
93
|
-
assert.match(gate,/windows-gate-evidence-
|
|
94
|
-
const result=await run(process.execPath,[path.join(root,'scripts','windows-gate-evidence-
|
|
92
|
+
const gate=await readFile(path.join(root,'scripts','gate-windows-r41.ps1'),'utf8');
|
|
93
|
+
assert.match(gate,/windows-gate-evidence-r41\.mjs/,'gate-windows-r41.ps1 must invoke the evidence writer');
|
|
94
|
+
const result=await run(process.execPath,[path.join(root,'scripts','windows-gate-evidence-r41.mjs')],{
|
|
95
95
|
cwd:root,env:{...process.env,DEADBYTE_STATE_ROOT:stateRoot}
|
|
96
96
|
});
|
|
97
97
|
assert.equal(result.code,0,result.stderr||result.stdout);
|
|
@@ -99,12 +99,12 @@ test('Windows R39 gate emits manifest-bound machine-readable evidence outside th
|
|
|
99
99
|
assert.equal(summary.status,'written');
|
|
100
100
|
const evidence=JSON.parse(await readFile(summary.path,'utf8'));
|
|
101
101
|
const manifestSha=sha256(await readFile(path.join(root,'MANIFEST.SHA256')));
|
|
102
|
-
assert.equal(evidence.schema,'deadbyte.
|
|
102
|
+
assert.equal(evidence.schema,'deadbyte.r41-windows-gate.v1');
|
|
103
103
|
assert.equal(evidence.status,'passed');
|
|
104
104
|
assert.equal(evidence.exit_code,0);
|
|
105
|
-
assert.equal(evidence.version,'0.
|
|
105
|
+
assert.equal(evidence.version,'0.13.0');
|
|
106
106
|
assert.equal(evidence.manifest_sha256,manifestSha);
|
|
107
|
-
assert.equal(evidence.marker,'DEADBYTE V0.
|
|
107
|
+
assert.equal(evidence.marker,'DEADBYTE V0.13.0 / R41 WINDOWS BATCH GATE: PASS');
|
|
108
108
|
assert.ok(summary.path.startsWith(path.join(stateRoot,'evidence','release')));
|
|
109
109
|
}finally{await rm(stateRoot,{recursive:true,force:true});}
|
|
110
110
|
});
|
|
@@ -2,8 +2,8 @@ import test from 'node:test';
|
|
|
2
2
|
import assert from 'node:assert/strict';
|
|
3
3
|
import { readFile } from 'node:fs/promises';
|
|
4
4
|
import { R34_EXPECTED_TOOLS } from '../src/remote-mcp-r34-parity-client.mjs';
|
|
5
|
-
import { validateParityEvidence } from '../scripts/release-parity-
|
|
6
|
-
import { verifyFinalClosureObject } from '../scripts/final-closure-verify-
|
|
5
|
+
import { validateParityEvidence } from '../scripts/release-parity-r40.mjs';
|
|
6
|
+
import { verifyFinalClosureObject } from '../scripts/final-closure-verify-r40.mjs';
|
|
7
7
|
|
|
8
8
|
const root = new URL('../', import.meta.url);
|
|
9
9
|
const text = rel => readFile(new URL(rel, root), 'utf8');
|
|
@@ -19,28 +19,28 @@ test('R34 public parity catalog is exact, unique, and includes production coding
|
|
|
19
19
|
|
|
20
20
|
test('release parity and final verifier are package entry points', async () => {
|
|
21
21
|
const pkg = JSON.parse(await text('package.json'));
|
|
22
|
-
assert.equal(pkg.scripts['release:parity'], 'node scripts/release-parity-
|
|
23
|
-
assert.equal(pkg.scripts['release:final:write'], 'node scripts/final-closure-
|
|
24
|
-
assert.equal(pkg.scripts['release:final:verify'], 'node scripts/final-closure-verify-
|
|
22
|
+
assert.equal(pkg.scripts['release:parity'], 'node scripts/release-parity-r41.mjs');
|
|
23
|
+
assert.equal(pkg.scripts['release:final:write'], 'node scripts/final-closure-r41.mjs');
|
|
24
|
+
assert.equal(pkg.scripts['release:final:verify'], 'node scripts/final-closure-verify-r41.mjs');
|
|
25
25
|
assert.equal(typeof validateParityEvidence, 'function');
|
|
26
26
|
assert.equal(typeof verifyFinalClosureObject, 'function');
|
|
27
27
|
});
|
|
28
28
|
|
|
29
|
-
test('
|
|
30
|
-
const verifier = await text('scripts/final-closure-verify-
|
|
31
|
-
const writer = await text('scripts/final-closure-
|
|
29
|
+
test('R40 final closure verifier is implementation-independent from production helpers', async () => {
|
|
30
|
+
const verifier = await text('scripts/final-closure-verify-r40.mjs');
|
|
31
|
+
const writer = await text('scripts/final-closure-r40.mjs');
|
|
32
32
|
assert.doesNotMatch(verifier, /from ['"]\.\.\/src\//);
|
|
33
33
|
assert.match(verifier, /DEADBYTE-R27-SLOT-UPDATE-V1/);
|
|
34
34
|
assert.match(verifier, /DEADBYTE-MACHINE-PING-V1/);
|
|
35
|
-
assert.match(verifier, /DEADBYTE-
|
|
36
|
-
assert.match(writer, /pointer\.version==='0\.
|
|
37
|
-
assert.match(verifier, /envelope\.body\.version==='0\.
|
|
38
|
-
assert.match(verifier, /release_label==='
|
|
39
|
-
assert.match(verifier, /
|
|
35
|
+
assert.match(verifier, /DEADBYTE-R40-FINAL-CLOSURE-V1/);
|
|
36
|
+
assert.match(writer, /pointer\.version==='0\.12\.0'/);
|
|
37
|
+
assert.match(verifier, /envelope\.body\.version==='0\.12\.0'/);
|
|
38
|
+
assert.match(verifier, /release_label==='R40 FINAL MACHINE BASELINE'/);
|
|
39
|
+
assert.match(verifier, /ce761dd6e014d42eddb635855038e0ce049c63c6e3af7e63c3005bbe198bcf7b/);
|
|
40
40
|
});
|
|
41
41
|
|
|
42
42
|
test('final closure verifier canonicalizes traversal order before exact-tree comparison', async () => {
|
|
43
|
-
const verifier = await text('scripts/final-closure-verify-
|
|
43
|
+
const verifier = await text('scripts/final-closure-verify-r40.mjs');
|
|
44
44
|
assert.match(verifier, /const actual=\(await walk\(root\)\)\.filter\(rel=>rel!==manifestName\)\.sort\(\(a,b\)=>a\.localeCompare\(b,'en'\)\);/);
|
|
45
45
|
assert.match(verifier, /const expected=\[\.\.\.entries\.keys\(\)\]\.sort\(\(a,b\)=>a\.localeCompare\(b,'en'\)\);/);
|
|
46
46
|
});
|
|
@@ -72,4 +72,4 @@ test('R34 parity isolates scratch mutation and search from the core release tree
|
|
|
72
72
|
assert.match(parity, /machine_search_start[\s\S]*?root_id:scratchRoot/);
|
|
73
73
|
assert.match(parity, /machine_fs_delete[\s\S]*?root_id:scratchRoot/);
|
|
74
74
|
assert.doesNotMatch(parity, /machine_fs_(?:write|read|edit_exact|stat|delete)'[^\n]*root_id:'core'/);
|
|
75
|
-
});
|
|
75
|
+
});
|
|
@@ -32,15 +32,16 @@ test('R37 unified timeline renders one sanitized tool-call line with ISO timesta
|
|
|
32
32
|
assert.doesNotMatch(line,/TOP_SECRET_PAYLOAD|TOP_SECRET_TOKEN|Bearer abc\.def\.ghi/);
|
|
33
33
|
});
|
|
34
34
|
|
|
35
|
-
test('
|
|
35
|
+
test('R40 default live tracker keeps legacy formatter separate and emits one compact result line',()=>{
|
|
36
36
|
let now=Date.parse('2026-09-18T16:24:30.125Z');
|
|
37
37
|
const tracker=createLiveTimelineTracker({clock:()=>now});
|
|
38
38
|
const call=tracker.observe({event_type:'tool.request',request_id:'abcdef1234567890',tool:'coding_tree',
|
|
39
|
-
created_at_utc:'2026-09-18T16:24:30.125Z',args:{root_id:'projects',path:'src'}});
|
|
40
|
-
assert.
|
|
39
|
+
created_at_utc:'2026-09-18T16:24:30.125Z',args:{root_id:'projects',path:'src'}},{sequence:1});
|
|
40
|
+
assert.equal(call,null);
|
|
41
41
|
now+=250;
|
|
42
|
-
|
|
43
|
-
outcome:{is_error:false,duration_ms:250}}
|
|
42
|
+
const done=tracker.observe({event_type:'tool.result',request_id:'abcdef1234567890',tool:'coding_tree',
|
|
43
|
+
observed_at_utc:'2026-09-18T16:24:30.375Z',outcome:{is_error:false,duration_ms:250}},{sequence:2});
|
|
44
|
+
assert.match(done,/^🔍 23:24:30\.375 #2 \[abcdef12\] coding_tree projects:src 250ms ✓$/);
|
|
44
45
|
});
|
|
45
46
|
|
|
46
47
|
test('R37 remote result journal persists sanitized tool-call and result in one monotonic cursor stream',async()=>{
|