deadbyte-mcp 0.15.43 → 0.15.44
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 +128 -67
- package/PROVENANCE.json +23 -12
- package/README.txt +18 -18
- package/RELEASE.json +28 -14
- package/SBOM.cdx.json +14 -2
- package/TEST-MATRIX.json +41 -10
- 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.obj +0 -0
- package/bin/deadbyte-desktop-observer-r40.obj +0 -0
- package/bin/deadbyte-desktop-uia-r40.obj +0 -0
- package/bin/deadbyte-exec.obj +0 -0
- package/bin/deadbyte-hardware-observer-r45.obj +0 -0
- package/bin/deadbyte-native-inspect-r67.exe +0 -0
- package/bin/deadbyte-native-inspect-r67.obj +0 -0
- package/bin/deadbyte-process-host.obj +0 -0
- package/bin/deadbyte-tunnel-host.obj +0 -0
- package/bridge/package.json +1 -1
- package/controller/deadbyte-desktop-policy.json +5 -5
- package/controller/deadbyte-process-policy.json +4 -4
- package/docs/R67-ALPHA-REFERENCE-DIFFERENTIAL.md +42 -0
- package/docs/R67-ALPHA-STATIC-COMPARISON.json +205 -0
- package/docs/R67-CANDIDATE-PARENT.json +10 -0
- package/docs/R67-EVIDENCE-RECONCILE-CLOSEOUT-20261011.md +64 -0
- package/docs/R67-FULL-REGRESSION-UNKNOWN.json +27 -0
- package/docs/R67-NATIVE-INSPECT-BINARY.json +11 -0
- package/docs/R67-NPM-EXDEV-PRESERVATION-20261011.md +39 -0
- package/docs/R67-OBSERVATION-TRUTH.md +82 -0
- package/docs/R67-REFERENCE-GAP-MATRIX.json +57 -0
- package/docs/R67-REGRESSION-CLOSURE-20261011.md +24 -0
- package/native/deadbyte-native-inspect-r67.cpp +252 -0
- package/package.json +6 -3
- package/proof/CONTAINMENT-BUILD.txt +6 -6
- package/scripts/build-native-inspector-r67.ps1 +28 -0
- package/scripts/gate-windows-r67.ps1 +56 -0
- package/scripts/npm-preserve-artifact-r67.mjs +99 -0
- package/scripts/npm-release-r48.mjs +10 -2
- package/scripts/npm-release-readiness-r67.mjs +26 -0
- package/scripts/r67-acquire-alpha-reference.mjs +95 -0
- package/scripts/r67-audit-nonpass-source.mjs +39 -0
- package/scripts/r67-compare-desktop-alpha.mjs +48 -0
- package/scripts/r67-diagnose-failed-shard.mjs +23 -0
- package/scripts/r67-durable-batch.mjs +42 -0
- package/scripts/r67-focused-gate.mjs +58 -0
- package/scripts/r67-full-regression.mjs +28 -0
- package/scripts/r67-independent-observation-verify.mjs +36 -0
- package/scripts/r67-independent-runtime-observation-verify.mjs +63 -0
- package/scripts/r67-nonpass-adjudicate.mjs +20 -0
- package/scripts/r67-publish-boundary-audit.mjs +32 -0
- package/scripts/r67-regression-reconcile.mjs +10 -0
- package/scripts/r67-regression-shard-run.mjs +70 -0
- package/scripts/r67-run-shard-batch.mjs +18 -0
- package/scripts/r67-stage-candidate.mjs +30 -0
- package/scripts/r67-verify-parent-ping.mjs +22 -0
- package/scripts/release-manifest.mjs +1 -0
- package/src/activation-continuity-engine-r65.mjs +2 -1
- package/src/autonomous-runtime.mjs +1 -1
- package/src/deadbyte-cli.mjs +33 -1
- package/src/machine-fs-smoke-client.mjs +13 -5
- package/src/machine-identity.mjs +59 -2
- package/src/machine-mcp-tools.mjs +8 -0
- package/src/mcp-server.mjs +11 -2
- package/src/native-inspector-r67.mjs +66 -0
- package/src/r67-diagnostic-export.mjs +118 -0
- package/src/r67-diagnostics-verify.mjs +82 -0
- package/src/r67-evidence-reconcile.mjs +128 -0
- package/src/r67-native-observation-authority.mjs +45 -0
- package/src/r67-observation-receipt.mjs +43 -0
- package/src/r67-regression-shards.mjs +176 -0
- package/src/remote-live-log.mjs +14 -10
- package/src/tool-audit.mjs +1 -1
- package/src/version.mjs +1 -1
- package/test/agent-runtime.test.mjs +1 -1
- package/test/autonomous-loop.test.mjs +11 -6
- package/test/autonomous-runtime.test.mjs +1 -1
- package/test/coding-plane.test.mjs +1 -1
- package/test/full-max-catalog-r46.test.mjs +1 -1
- package/test/output-schema.test.mjs +1 -1
- package/test/r51-live-log-polling.test.mjs +12 -0
- package/test/r53-release-contract.test.mjs +1 -1
- package/test/r54-release-contract.test.mjs +1 -1
- package/test/r55-release-contract.test.mjs +1 -1
- package/test/r56-release-contract.test.mjs +1 -1
- package/test/r57-release-contract.test.mjs +1 -1
- package/test/r58-bundled-bridge.test.mjs +1 -1
- package/test/r58-release-contract.test.mjs +2 -2
- package/test/r58-windows-gate.test.mjs +1 -1
- package/test/r59-tool-surface-compat.test.mjs +1 -1
- package/test/r60-release-contract.test.mjs +3 -3
- package/test/r61-release-contract.test.mjs +1 -1
- package/test/r62-release-contract.test.mjs +1 -1
- package/test/r63-release-contract.test.mjs +1 -1
- package/test/r64-release-contract.test.mjs +1 -1
- package/test/r65-epoch-native-activation-integration.test.mjs +4 -4
- package/test/r65-release-contract.test.mjs +1 -1
- package/test/r66-release-contract.test.mjs +2 -1
- package/test/r67-cli-integration.test.mjs +41 -0
- package/test/r67-diagnostics-cli.test.mjs +60 -0
- package/test/r67-diagnostics-verify.test.mjs +49 -0
- package/test/r67-diagnostics-zip-oracle.test.mjs +38 -0
- package/test/r67-diagnostics.test.mjs +60 -0
- package/test/r67-evidence-reconcile.test.mjs +186 -0
- package/test/r67-isolated-slot-rollback-restore.test.mjs +62 -0
- package/test/r67-live-log-secret-canary.test.mjs +44 -0
- package/test/r67-machine-fs-smoke-epoch.test.mjs +22 -0
- package/test/r67-native-inspector.test.mjs +131 -0
- package/test/r67-native-observation-authority.test.mjs +49 -0
- package/test/r67-npm-cross-volume.test.mjs +74 -0
- package/test/r67-npm-publish-gate.test.mjs +38 -0
- package/test/r67-regression-shards.test.mjs +184 -0
- package/test/r67-release-contract.test.mjs +44 -0
- package/test/r67-runtime-observation-binding.test.mjs +86 -0
- package/test/r67-server-observation-wiring.test.mjs +12 -0
- package/test/r67-signed-receipt.test.mjs +66 -0
- package/test/r67-skip-rationale.test.mjs +31 -0
- package/test/r67-tool-annotations.test.mjs +21 -0
- package/test/r67-windows-gate-argv.test.mjs +13 -0
- package/test/release-version.test.mjs +1 -1
- package/test/remote-live-log-r36.test.mjs +10 -0
- package/test/remote-live-log-r37.test.mjs +29 -0
- package/test/semantic-multilang.test.mjs +1 -1
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
import {createHash} from 'node:crypto';
|
|
2
|
+
import {lstat,readdir,readFile} from 'node:fs/promises';
|
|
3
|
+
import path from 'node:path';
|
|
4
|
+
const sha=value=>createHash('sha256').update(Buffer.from(JSON.stringify(value),'utf8')).digest('hex');
|
|
5
|
+
|
|
6
|
+
export function createR67ShardPlan(filenames,shardCount=32){
|
|
7
|
+
if(!Array.isArray(filenames)||!Number.isInteger(shardCount)||shardCount<1||shardCount>64)throw new Error('invalid shard plan');
|
|
8
|
+
if(!filenames.length||filenames.length<shardCount)throw new Error('insufficient regression files');
|
|
9
|
+
const sorted=[...filenames].sort();
|
|
10
|
+
if(sorted.some((n,i)=>typeof n!=='string'||!/^test\/[a-z0-9._-]+\.test\.mjs$/.test(n)||(i>0&&n===sorted[i-1])))
|
|
11
|
+
throw new Error('invalid or duplicate test filename');
|
|
12
|
+
// Measured on Windows: 53.2s controller lifecycle and 110.4s remote lifecycle.
|
|
13
|
+
// Assign both to standalone tail shards; smaller shard counts reserve at least one normal shard.
|
|
14
|
+
const measured=['test/r58-controller-live-local.test.mjs','test/remote-session-cli.test.mjs'];
|
|
15
|
+
const present=measured.filter(name=>sorted.includes(name));
|
|
16
|
+
const isolated=present.slice(-Math.min(present.length,shardCount-1));
|
|
17
|
+
const isolatedSet=new Set(isolated);
|
|
18
|
+
const normal=sorted.filter(name=>!isolatedSet.has(name));
|
|
19
|
+
const normalShardCount=shardCount-isolated.length;
|
|
20
|
+
const shards=Array.from({length:shardCount},(_,index)=>({index,files:[]}));
|
|
21
|
+
normal.forEach((name,index)=>shards[index%normalShardCount].files.push(name));
|
|
22
|
+
isolated.forEach((name,index)=>shards[normalShardCount+index].files.push(name));
|
|
23
|
+
const plan_sha256=sha({schema:'deadbyte.r67-shard-plan.v1',shardCount,files:sorted,
|
|
24
|
+
assignment:'measured-slow-suites-isolation-v2',isolated});
|
|
25
|
+
return {schema:'deadbyte.r67-shard-plan.v1',plan_sha256,file_count:sorted.length,
|
|
26
|
+
shards:shards.map(s=>({...s,files_sha256:sha(s.files)}))};
|
|
27
|
+
}
|
|
28
|
+
export function r67ShardTimeoutMs(shard){
|
|
29
|
+
if(!shard||!Array.isArray(shard.files))throw new Error('invalid shard');
|
|
30
|
+
if(shard.files.length===1&&shard.files[0]==='test/remote-session-cli.test.mjs')return 165000;
|
|
31
|
+
if(shard.files.length===1&&shard.files[0]==='test/r58-controller-live-local.test.mjs')return 120000;
|
|
32
|
+
return 58000;
|
|
33
|
+
}
|
|
34
|
+
export function reconcileR67Shards(plan,receipts){
|
|
35
|
+
if(!plan||plan.schema!=='deadbyte.r67-shard-plan.v1'||!Array.isArray(plan.shards)||!Array.isArray(receipts))throw new Error('invalid shard proof input');
|
|
36
|
+
const seen=new Map();
|
|
37
|
+
for(const r of receipts){
|
|
38
|
+
if(!Number.isInteger(r?.shard_index)||r.shard_index<0||r.shard_index>=plan.shards.length)throw new Error('out-of-plan shard');
|
|
39
|
+
if(seen.has(r.shard_index))throw new Error('duplicate shard receipt');
|
|
40
|
+
seen.set(r.shard_index,r);
|
|
41
|
+
}
|
|
42
|
+
const missing=plan.shards.filter(s=>!seen.has(s.index)).map(s=>s.index);
|
|
43
|
+
let tampered=false,failed=false,unknown=false,passed=0,failureCount=0,testCount=0;
|
|
44
|
+
for(const shard of plan.shards){
|
|
45
|
+
const r=seen.get(shard.index);if(!r)continue;
|
|
46
|
+
const missingCounts=r.status==='OUTCOME_UNKNOWN'&&r.test_count===null&&r.passed===null&&r.failed===null;
|
|
47
|
+
const validCounts=Number.isInteger(r.test_count)&&r.test_count>=0&&
|
|
48
|
+
Number.isInteger(r.passed)&&r.passed>=0&&Number.isInteger(r.failed)&&r.failed>=0&&
|
|
49
|
+
r.passed+r.failed<=r.test_count;
|
|
50
|
+
if(r.plan_sha256!==plan.plan_sha256||r.files_sha256!==shard.files_sha256||
|
|
51
|
+
!['PASS','FAILED','OUTCOME_UNKNOWN'].includes(r.status)||!(missingCounts||validCounts)){tampered=true;continue;}
|
|
52
|
+
if(r.schema==='deadbyte.r67-shard-result.v2'){
|
|
53
|
+
const unknownWithoutCounts=r.status==='OUTCOME_UNKNOWN'&&missingCounts&&r.skipped===null&&r.cancelled===null&&r.todo===null;
|
|
54
|
+
const complete=validCounts&&Number.isInteger(r.skipped)&&r.skipped>=0&&
|
|
55
|
+
Number.isInteger(r.cancelled)&&r.cancelled===0&&Number.isInteger(r.todo)&&r.todo===0&&
|
|
56
|
+
r.passed+r.failed+r.skipped+r.cancelled+r.todo===r.test_count;
|
|
57
|
+
if(!(unknownWithoutCounts||complete)){tampered=true;continue;}
|
|
58
|
+
}
|
|
59
|
+
if(r.status==='PASS'&&(r.exit_code!==0||r.failed!==0||r.test_count<shard.files.length))tampered=true;
|
|
60
|
+
if(r.status==='FAILED'||r.exit_code!==0&&r.status!=='OUTCOME_UNKNOWN'||r.failed>0)failed=true;
|
|
61
|
+
if(r.status==='OUTCOME_UNKNOWN')unknown=true;
|
|
62
|
+
passed+=r.passed;failureCount+=r.failed;testCount+=r.test_count;
|
|
63
|
+
}
|
|
64
|
+
const status=tampered||failed?'FAILED':missing.length?'BLOCKED':unknown?'OUTCOME_UNKNOWN':'PASS';
|
|
65
|
+
return {schema:'deadbyte.r67-shard-reconciliation.v1',status,plan_sha256:plan.plan_sha256,
|
|
66
|
+
file_count:plan.file_count,shards_expected:plan.shards.length,shards_observed:seen.size,
|
|
67
|
+
missing,test_count:testCount,passed,failed:failureCount,integrity_failed:tampered};
|
|
68
|
+
}
|
|
69
|
+
|
|
70
|
+
/** Bind regression evidence to executable SOURCE bytes, not just test filenames. */
|
|
71
|
+
export async function r67RegressionTreeHash(root,{roots=['src','test','scripts','controller','bridge','native','docs'],
|
|
72
|
+
topLevel=['package.json','package-lock.json'],extra=['bin/deadbyte-native-inspect-r67.exe']}={}){
|
|
73
|
+
if(typeof root!=='string'||!root)throw new Error('regression source root required');
|
|
74
|
+
const seeds=[...roots,...topLevel,...extra];
|
|
75
|
+
if(!seeds.length||seeds.some(n=>typeof n!=='string'||!n||n.includes('\\')||n.split('/').some(part=>!part||part==='.'||part==='..')))
|
|
76
|
+
throw new Error('invalid regression source scope');
|
|
77
|
+
const entries=[];
|
|
78
|
+
let total=0;
|
|
79
|
+
const seen=new Set();
|
|
80
|
+
async function visit(rel){
|
|
81
|
+
if(seen.has(rel))throw new Error('duplicate regression source path');
|
|
82
|
+
seen.add(rel);
|
|
83
|
+
const file=path.join(root,...rel.split('/'));
|
|
84
|
+
const info=await lstat(file);
|
|
85
|
+
if(info.isSymbolicLink())throw new Error('symlink forbidden in regression source tree: '+rel);
|
|
86
|
+
if(info.isDirectory()){
|
|
87
|
+
const children=(await readdir(file)).sort();
|
|
88
|
+
for(const child of children)await visit(rel+'/'+child);
|
|
89
|
+
return;
|
|
90
|
+
}
|
|
91
|
+
if(!info.isFile()||info.size>8*1024*1024)throw new Error('non-file/oversized regression source: '+rel);
|
|
92
|
+
if(entries.length>=5000||total+info.size>128*1024*1024)throw new Error('regression source budget exceeded');
|
|
93
|
+
const bytes=await readFile(file);
|
|
94
|
+
if(bytes.length!==info.size)throw new Error('regression source changed during read: '+rel);
|
|
95
|
+
total+=bytes.length;
|
|
96
|
+
entries.push([rel,bytes.length,createHash('sha256').update(bytes).digest('hex')]);
|
|
97
|
+
}
|
|
98
|
+
for(const seed of seeds)await visit(seed);
|
|
99
|
+
entries.sort((a,b)=>a[0].localeCompare(b[0],'en'));
|
|
100
|
+
return {schema:'deadbyte.r67-source-tree.v1',
|
|
101
|
+
sha256:sha({schema:'deadbyte.r67-source-tree.v1',files:entries}),
|
|
102
|
+
file_count:entries.length,bytes_total:total};
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
/** Parse complete Node TAP totals without treating missing or cancelled output as success. */
|
|
106
|
+
export function parseR67TapSummary(output){
|
|
107
|
+
if(typeof output!=='string')return null;
|
|
108
|
+
const counts=Object.create(null);
|
|
109
|
+
const keys=['tests','pass','fail','cancelled','skipped','todo'];
|
|
110
|
+
for(const raw of output.split(/\r?\n/)){
|
|
111
|
+
const line=raw.trim();
|
|
112
|
+
const match=/^(?:#|ℹ)\s+(tests|pass|fail|cancelled|skipped|todo)\s+(\d+)$/u.exec(line);
|
|
113
|
+
if(!match)continue;
|
|
114
|
+
if(Object.hasOwn(counts,match[1]))return null;
|
|
115
|
+
const n=Number(match[2]);
|
|
116
|
+
if(!Number.isSafeInteger(n))return null;
|
|
117
|
+
counts[match[1]]=n;
|
|
118
|
+
}
|
|
119
|
+
if(keys.some(k=>!Number.isSafeInteger(counts[k])))return null;
|
|
120
|
+
if(counts.tests!==counts.pass+counts.fail+counts.skipped+counts.cancelled+counts.todo)return null;
|
|
121
|
+
if(counts.cancelled!==0||counts.todo!==0)return null;
|
|
122
|
+
return Object.fromEntries(keys.map(k=>[k,counts[k]]));
|
|
123
|
+
}
|
|
124
|
+
|
|
125
|
+
export function parseR67NonpassCases(output){
|
|
126
|
+
if(typeof output!=='string'||output.length>16*1024*1024)throw new Error('bounded TAP text required');
|
|
127
|
+
const keys=['tests','pass','fail','cancelled','skipped','todo'];
|
|
128
|
+
const totals=Object.create(null);
|
|
129
|
+
for(const raw of output.split(/\r?\n/)){
|
|
130
|
+
const line=raw.trim();
|
|
131
|
+
const m=/^(?:#|ℹ)\s+(tests|pass|fail|cancelled|skipped|todo)\s+(\d+)$/u.exec(line);
|
|
132
|
+
if(!m)continue;
|
|
133
|
+
if(Object.hasOwn(totals,m[1]))return null;
|
|
134
|
+
totals[m[1]]=Number(m[2]);
|
|
135
|
+
}
|
|
136
|
+
if(keys.some(k=>!Number.isSafeInteger(totals[k])))return null;
|
|
137
|
+
if(totals.tests!==totals.pass+totals.fail+totals.cancelled+totals.skipped+totals.todo)return null;
|
|
138
|
+
const summary=totals;
|
|
139
|
+
const cases=[];
|
|
140
|
+
const RX=/^\s*(?:ok|not ok)\s+\d+\s+-\s+(.+?)\s+#\s+(SKIP|TODO)(?:\s+(.*\S))?\s*$/u;
|
|
141
|
+
for(const line of output.split(/\r?\n/)){
|
|
142
|
+
const match=RX.exec(line);
|
|
143
|
+
if(!match)continue;
|
|
144
|
+
const name=match[1].trim(),reason=match[3]?.trim()||null;
|
|
145
|
+
cases.push({kind:match[2],name,reason});
|
|
146
|
+
if(cases.length>10000)throw new Error('case ledger budget exceeded');
|
|
147
|
+
}
|
|
148
|
+
const expected=summary.skipped+summary.todo;
|
|
149
|
+
const actual=cases.filter(c=>c.kind==='SKIP').length+cases.filter(c=>c.kind==='TODO').length;
|
|
150
|
+
const unclassified=cases.filter(c=>!c.name||!c.reason).length+Math.max(0,expected-actual);
|
|
151
|
+
const countersMatch=summary.skipped===cases.filter(c=>c.kind==='SKIP').length&&
|
|
152
|
+
summary.todo===cases.filter(c=>c.kind==='TODO').length;
|
|
153
|
+
return {cases,expected_nonpass:expected,fully_classified:countersMatch&&unclassified===0,
|
|
154
|
+
unclassified_count:unclassified,counters_match:countersMatch};
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
|
|
158
|
+
/** Diagnostic-only FAILED TAP case identities. Never export stack traces or raw assertion messages. */
|
|
159
|
+
export function parseR67FailedCases(output){
|
|
160
|
+
if(typeof output!=='string'||output.length>16*1024*1024)throw new Error('bounded TAP text required');
|
|
161
|
+
const tap=parseR67TapSummary(output);
|
|
162
|
+
if(!tap)return {cases:[],count:0,complete:false,expected:null};
|
|
163
|
+
const cases=[];
|
|
164
|
+
for(const line of output.split(/\r?\n/)){
|
|
165
|
+
const match=/^\s*not ok\s+\d+\s+-\s+(.+?)\s*(?:#.*)?$/u.exec(line);
|
|
166
|
+
if(!match)continue;
|
|
167
|
+
const name=match[1].trim();
|
|
168
|
+
if(!name)continue;
|
|
169
|
+
const sensitive=/sk-(?:proj|test|live|[a-z]{10})-|bearer\s+|authorization|password\s*[:=]|(?:[A-Z]:\\Users\\|\/home\/)[^\s]+/i.test(name);
|
|
170
|
+
const printable=!/[\x00-\x1f\x7f-\x9f]/u.test(name)&&name.length<=256;
|
|
171
|
+
cases.push({name:sensitive||!printable?'[redacted]':name,
|
|
172
|
+
name_sha256:createHash('sha256').update(Buffer.from(name,'utf8')).digest('hex')});
|
|
173
|
+
if(cases.length>128)throw new Error('failed-case ledger budget exceeded');
|
|
174
|
+
}
|
|
175
|
+
return {cases,count:cases.length,expected:tap.fail,complete:tap.fail===cases.length};
|
|
176
|
+
}
|
package/src/remote-live-log.mjs
CHANGED
|
@@ -25,7 +25,7 @@ const LIFECYCLE_ASCII=Object.freeze({
|
|
|
25
25
|
|
|
26
26
|
function safeAtom(value){
|
|
27
27
|
if(typeof value==='string'){
|
|
28
|
-
if(value.length<1||value.length>160||/[\
|
|
28
|
+
if(value.length<1||value.length>160||/[\x00-\x1f\x7f-\x9f]/u.test(value)) return null;
|
|
29
29
|
return value;
|
|
30
30
|
}
|
|
31
31
|
if(typeof value==='number'&&Number.isFinite(value)) return String(value);
|
|
@@ -55,8 +55,10 @@ const START_VISIBLE_PATTERNS=[/(?:^|_)file_write$/,/text_replace$/,/symbol_repla
|
|
|
55
55
|
|
|
56
56
|
export function selectLiveLogNames({auditNames=[],runtimeNames=[]}={}){
|
|
57
57
|
if(!Array.isArray(auditNames)||!Array.isArray(runtimeNames)) throw new Error('live log names must be arrays');
|
|
58
|
-
const audit=auditNames.filter(name=>typeof name==='string'&&/^segment-\d{8}\.jsonl$/.test(name)).sort().slice(-2);
|
|
59
|
-
|
|
58
|
+
const audit=[...new Set(auditNames.filter(name=>typeof name==='string'&&/^segment-\d{8}\.jsonl$/.test(name)))].sort().slice(-2);
|
|
59
|
+
// Runtime filenames come from discovery, but never trust caller-supplied path components.
|
|
60
|
+
// Bound number of active readers to prevent log-file flooding from exhausting handles.
|
|
61
|
+
const runtime=[...new Set(runtimeNames.filter(name=>typeof name==='string'&&/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}\.log$/.test(name)))].sort().slice(-64);
|
|
60
62
|
return Object.freeze({audit:Object.freeze(audit),runtime:Object.freeze(runtime)});
|
|
61
63
|
}
|
|
62
64
|
|
|
@@ -72,7 +74,7 @@ export function truncateUtf8(value,maxBytes,{ellipsis='…'}={}){
|
|
|
72
74
|
}
|
|
73
75
|
function clipped(value,max=72){
|
|
74
76
|
if(typeof value!=='string') return '';
|
|
75
|
-
const one=value.replace(/[\
|
|
77
|
+
const one=value.replace(/[\x00-\x1f\x7f-\x9f]+/gu,' ').replace(/\s{2,}/g,' ').trim();
|
|
76
78
|
return truncateUtf8(one,max);
|
|
77
79
|
}
|
|
78
80
|
function shortValue(value,max=12){
|
|
@@ -83,7 +85,7 @@ function payloadByteCount(value){
|
|
|
83
85
|
return value&&typeof value==='object'&&value.redacted===true&&Number.isFinite(Number(value.byte_count))?Number(value.byte_count):null;
|
|
84
86
|
}
|
|
85
87
|
function safePathAtom(value){
|
|
86
|
-
if(typeof value!=='string'||value.length<1||value.length>2048||/[\
|
|
88
|
+
if(typeof value!=='string'||value.length<1||value.length>2048||/[\x00-\x1f\x7f-\x9f]/u.test(value)) return null;
|
|
87
89
|
return value;
|
|
88
90
|
}
|
|
89
91
|
function rootedPath(args,key='path',rootPaths={}){
|
|
@@ -172,7 +174,7 @@ function displayClock(ms){
|
|
|
172
174
|
|
|
173
175
|
export function formatRemoteToolCall(event,{clock=()=>Date.now(),displayMode='unicode'}={}){
|
|
174
176
|
if(!event||typeof event!=='object'||Array.isArray(event)||event.event_type!=='tool.request'||
|
|
175
|
-
typeof event.tool!=='string'
|
|
177
|
+
typeof event.tool!=='string'||!/^[A-Za-z][A-Za-z0-9_.-]{0,127}$/.test(event.tool)) return null;
|
|
176
178
|
if(typeof clock!=='function') throw new Error('remote tool-call clock must be a function');
|
|
177
179
|
const args=sanitizeAuditArgs(event.args??{});
|
|
178
180
|
return remoteDisplayText(`${eventTimestamp(event,clock)} | ${event.tool.padEnd(TOOL_COLUMN_WIDTH)} | Arguments: ${canonicalJson(args)}`,displayMode);
|
|
@@ -186,8 +188,8 @@ function formatDuration(ms){
|
|
|
186
188
|
}
|
|
187
189
|
|
|
188
190
|
export function formatCompactAuditEvent(event){
|
|
189
|
-
if(!event||typeof event!=='object'||Array.isArray(event)||typeof event.tool!=='string'
|
|
190
|
-
if(event.event_type==='tool.request') return `▶ RUN ${event.tool}${summarizeArgs(event.args)}`;
|
|
191
|
+
if(!event||typeof event!=='object'||Array.isArray(event)||typeof event.tool!=='string'||!/^[A-Za-z][A-Za-z0-9_.-]{0,127}$/.test(event.tool)) return null;
|
|
192
|
+
if(event.event_type==='tool.request') return `▶ RUN ${event.tool}${summarizeArgs(sanitizeAuditArgs(event.args??{}))}`;
|
|
191
193
|
if(event.event_type==='tool.result'){
|
|
192
194
|
const marker=event.outcome?.is_error===true?'❌ ERR':'✅ OK';
|
|
193
195
|
const duration=formatDuration(event.outcome?.duration_ms);
|
|
@@ -361,7 +363,9 @@ export function createLiveTimelineTracker({clock=()=>Date.now(),verbose=false,fo
|
|
|
361
363
|
const summary=span?.summary||'';
|
|
362
364
|
const rawReason=typeof event.outcome?.reason==='string'&&event.outcome.reason?event.outcome.reason:
|
|
363
365
|
(unknown&&typeof event.outcome?.recovery?.reason==='string'?event.outcome.recovery.reason:'');
|
|
364
|
-
const
|
|
366
|
+
const screenedReason=typeof rawReason==='string'?sanitizeAuditArgs(rawReason):null;
|
|
367
|
+
const sensitiveReason=typeof rawReason==='string'&&typeof screenedReason!=='string';
|
|
368
|
+
const reason=sensitiveReason?'[REDACTED_SENSITIVE_REASON]':rawReason?clipped(rawReason,180):(unknown?'terminal result unavailable; inspect state before retry':'');
|
|
365
369
|
const category=categoryForTool(displayTool);
|
|
366
370
|
const receipt=Array.isArray(event.outcome?.receipt_sha256s)&&typeof event.outcome.receipt_sha256s[0]==='string'
|
|
367
371
|
?shortValue(event.outcome.receipt_sha256s[0],8):'';
|
|
@@ -414,7 +418,7 @@ export function createLiveTimelineTracker({clock=()=>Date.now(),verbose=false,fo
|
|
|
414
418
|
lastSourceSequence=sourceSequence;
|
|
415
419
|
}
|
|
416
420
|
const requestId=typeof event.request_id==='string'&&event.request_id?event.request_id:null;
|
|
417
|
-
const tool=typeof event.tool==='string'
|
|
421
|
+
const tool=typeof event.tool==='string'&&/^[A-Za-z][A-Za-z0-9_.-]{0,127}$/.test(event.tool)?event.tool:null;
|
|
418
422
|
if(event.event_type==='tool.request'&&requestId&&tool){
|
|
419
423
|
if(pending.has(requestId)||completed.has(requestId)) return null;
|
|
420
424
|
const args=event.args??{};
|
package/src/tool-audit.mjs
CHANGED
|
@@ -21,7 +21,7 @@ const secretExactKeys=new Set([
|
|
|
21
21
|
]);
|
|
22
22
|
const secretSuffixes=['_password','_passwd','_secret','_token','_credential','_credentials','_cookie','_cookies','_private_key','_recovery_code','_api_key'];
|
|
23
23
|
const payloadKeys=new Set(['content','file_text','text','body','new_string','old_string','raw_input','raw_text','data_base64']);
|
|
24
|
-
const secretValuePattern=/(?:^|[^a-z])(bearer\s+\S+|(?:api[-_]?key|access[-_]?token|refresh[-_]?token|token|password|secret)\s*[=:]\s*\S
|
|
24
|
+
const secretValuePattern=/(?:^|[^a-z])(bearer\s+\S+|(?:api[-_]?key|access[-_]?token|refresh[-_]?token|token|password|secret)\s*[=:]\s*\S+|sk-(?:proj-|svcacct-|admin-)?[A-Za-z0-9_-]{12,}|gh[pousr]_[A-Za-z0-9_]{12,}|github_pat_[A-Za-z0-9_]{12,}|-----BEGIN [^-]*PRIVATE KEY-----)/i;
|
|
25
25
|
const sha256=bytes=>createHash('sha256').update(bytes).digest('hex');
|
|
26
26
|
const utf8Bytes=value=>Buffer.from(typeof value==='string'?value:canonicalJson(value),'utf8');
|
|
27
27
|
const byteCount=value=>utf8Bytes(value).length;
|
package/src/version.mjs
CHANGED
|
@@ -69,7 +69,7 @@ async function cleanup(f, client) {
|
|
|
69
69
|
await rm(f.trust, { recursive: true, force: true }).catch(() => {});
|
|
70
70
|
}
|
|
71
71
|
|
|
72
|
-
test
|
|
72
|
+
test('R44 historical agent catalog contract is frozen; current R47 runtime supersedes its base surface',{skip:'Historical R44 13-tool catalog deliberately superseded by R47; not applicable to current release'}, async () => {
|
|
73
73
|
const f = await fixture();
|
|
74
74
|
let client;
|
|
75
75
|
try {
|
|
@@ -123,7 +123,7 @@ test('R24 autonomous goal diagnoses a failing test, replans with native diff, be
|
|
|
123
123
|
maxIterations:10 });
|
|
124
124
|
assert.equal(submitted.status,'accepted');
|
|
125
125
|
const result = await f.runtime.run({ goalId:submitted.goal_id, maxCycles:16 });
|
|
126
|
-
assert.equal(result.status,'completed');
|
|
126
|
+
assert.equal(result.status,'completed',JSON.stringify({status:result.status,reason:result.reason??null,loop_phase:result.loop?.phase??null}));
|
|
127
127
|
assert.equal(await readFile(f.program,'utf8'),"export const value = 'fixed';\n");
|
|
128
128
|
const status = await f.runtime.status({ goalId:submitted.goal_id });
|
|
129
129
|
assert.equal(status.state,'succeeded');
|
|
@@ -154,7 +154,7 @@ test('historical autonomous release verification survives source drift and disar
|
|
|
154
154
|
title:'repair program', goal:'make exported value equal fixed', acceptance:'release evidence must remain verifiable',
|
|
155
155
|
maxIterations:10 });
|
|
156
156
|
const result = await f.runtime.run({ goalId:submitted.goal_id, maxCycles:16 });
|
|
157
|
-
assert.equal(result.status,'completed');
|
|
157
|
+
assert.equal(result.status,'completed',JSON.stringify({status:result.status,reason:result.reason??null,loop_phase:result.loop?.phase??null}));
|
|
158
158
|
assert.equal((await f.runtime.verify({ goalId:submitted.goal_id })).ok,true);
|
|
159
159
|
|
|
160
160
|
await writeFile(f.program,"export const value = 'rolled-back';\n");
|
|
@@ -196,7 +196,7 @@ test('autonomous profile execution is capped by the absolute autonomous lease wi
|
|
|
196
196
|
title:'deadline-bound profiles',goal:'make exported value equal fixed',
|
|
197
197
|
acceptance:'build, test, and benchmark must pass',maxIterations:10});
|
|
198
198
|
const result=await f.runtime.run({goalId:submitted.goal_id,maxCycles:16});
|
|
199
|
-
assert.equal(result.status,'completed');
|
|
199
|
+
assert.equal(result.status,'completed',JSON.stringify({status:result.status,reason:result.reason??null,loop_phase:result.loop?.phase??null}));
|
|
200
200
|
assert.ok(calls.length>=3);
|
|
201
201
|
assert.ok(calls.every(call=>typeof call.deadline==='string'&&Number.isFinite(Date.parse(call.deadline))));
|
|
202
202
|
assert.ok(calls.every(call=>call.has_precheck===true));
|
|
@@ -239,7 +239,12 @@ test('autonomous profile nonce rotation immediately before spawn fails closed wi
|
|
|
239
239
|
const started=journal.events.find(event=>event.type==='profile_started'&&event.payload?.profile_id==='build');
|
|
240
240
|
assert.ok(started);
|
|
241
241
|
assert.match(started.payload.authority_instance_nonce,/^[0-9a-f]{64}$/);
|
|
242
|
-
|
|
242
|
+
const pause=journal.events.find(event=>event.type==='goal_paused'&&event.payload?.reason==='profile_execution_without_receipt');
|
|
243
|
+
assert.ok(pause);
|
|
244
|
+
assert.equal(pause.payload.receipt_id,started.payload.receipt_id);
|
|
245
|
+
assert.equal(pause.payload.request_sha256,started.payload.request_sha256);
|
|
246
|
+
assert.equal(typeof pause.payload.detail,'string');
|
|
247
|
+
assert.ok(pause.payload.detail.length>0&&pause.payload.detail.length<=512);
|
|
243
248
|
assert.equal(journal.events.some(event=>event.type==='profile_completed'&&event.payload?.profile_id==='build'),false);
|
|
244
249
|
assert.equal((await f.codingRuntime.verifyReceiptDetailed(started.payload.receipt_id)).ok,false);
|
|
245
250
|
} finally {
|
|
@@ -255,7 +260,7 @@ test('provider planner repairs an invalid structured decision inside the same ru
|
|
|
255
260
|
title:'repair after planner contract error', goal:'make exported value equal fixed',
|
|
256
261
|
acceptance:'build, test, and benchmark must pass', maxIterations:10 });
|
|
257
262
|
const result = await f.runtime.run({ goalId:submitted.goal_id, maxCycles:16 });
|
|
258
|
-
assert.equal(result.status,'completed');
|
|
263
|
+
assert.equal(result.status,'completed',JSON.stringify({status:result.status,reason:result.reason??null,loop_phase:result.loop?.phase??null}));
|
|
259
264
|
assert.equal(await readFile(f.program,'utf8'),"export const value = 'fixed';\n");
|
|
260
265
|
assert.equal(f.planner.prompts.length,6);
|
|
261
266
|
assert.match(f.planner.prompts[1],/PREVIOUS_RESPONSE_REJECTED/);
|
|
@@ -337,7 +342,7 @@ test('provider supervisor adopts an OPEN circuit after restart and resumes only
|
|
|
337
342
|
if(status.state==='cancelled') throw new Error('provider circuit supervisor cancelled goal');
|
|
338
343
|
await new Promise(resolve=>setTimeout(resolve,25));
|
|
339
344
|
} while(Date.now()<deadline);
|
|
340
|
-
assert.equal(status.state,'succeeded');
|
|
345
|
+
assert.equal(status.state,'succeeded',JSON.stringify({state:status.state,reason:status.reason??null,loop_phase:status.loop?.phase??null}));
|
|
341
346
|
assert.ok(f.planner.prompts.length>3);
|
|
342
347
|
const journal=await f.runtime.events({goalId:submitted.goal_id,fromSeq:1,limit:200});
|
|
343
348
|
assert.equal(journal.events.filter(event=>event.type==='provider_probe_started').length,1);
|
|
@@ -76,7 +76,7 @@ async function fixture() {
|
|
|
76
76
|
return { root, client, transport };
|
|
77
77
|
}
|
|
78
78
|
|
|
79
|
-
test
|
|
79
|
+
test('R44 historical hermetic autonomous catalog is frozen at 50; current R47 runtime supersedes it',{skip:'Historical R44 autonomous catalog frozen at 50; current R47+ has a different catalog'}, async () => {
|
|
80
80
|
const f = await fixture();
|
|
81
81
|
try {
|
|
82
82
|
await f.client.connect(f.transport);
|
|
@@ -70,7 +70,7 @@ async function fixture() {
|
|
|
70
70
|
return { root, client, transport };
|
|
71
71
|
}
|
|
72
72
|
|
|
73
|
-
test
|
|
73
|
+
test('R44 historical hermetic coding catalog is frozen at 38; current R47 runtime supersedes it',{skip:'Historical R44 coding catalog frozen at 38; current R47+ supersedes it'}, async () => {
|
|
74
74
|
const f = await fixture();
|
|
75
75
|
try {
|
|
76
76
|
await f.client.connect(f.transport);
|
|
@@ -15,7 +15,7 @@ const desktopPolicyPath=path.join(repoRoot,'controller','deadbyte-desktop-policy
|
|
|
15
15
|
const sha=bytes=>createHash('sha256').update(bytes).digest('hex');
|
|
16
16
|
const absent=async p=>{try{await access(p);return false;}catch(e){if(e?.code==='ENOENT')return true;throw e;}};
|
|
17
17
|
|
|
18
|
-
test
|
|
18
|
+
test('R46 historical max-runtime full stdio catalog contract is frozen at 84; current R47 runtime intentionally supersedes it',{skip:'Historical R46 max-runtime catalog frozen at 84; current R47+ intentionally supersedes it'},async()=>{
|
|
19
19
|
const f=await createR34Fixture({authority:'disarmed'});
|
|
20
20
|
const processPolicyPath=path.join(f.root,'process-policy.json');
|
|
21
21
|
const processGrant=path.join(f.root,'process-grant.json');
|
|
@@ -48,7 +48,7 @@ async function fixture() {
|
|
|
48
48
|
return { trust, client, transport };
|
|
49
49
|
}
|
|
50
50
|
|
|
51
|
-
test
|
|
51
|
+
test('R44 historical base-plus-agent catalog is frozen at 13; current R47 runtime supersedes it',{skip:'Historical R44 base-plus-agent catalog frozen at 13; current R47+ supersedes it'}, async () => {
|
|
52
52
|
const f = await fixture();
|
|
53
53
|
try {
|
|
54
54
|
await f.client.connect(f.transport);
|
|
@@ -26,3 +26,15 @@ test('R51 live tail parses each audit line once and reuses the decoded event',as
|
|
|
26
26
|
assert.match(cli,/auditTimelineRecord\(file,line,auditEvent\)/);
|
|
27
27
|
assert.match(cli,/formatLogLine\(file,line,\{auditEvent,/);
|
|
28
28
|
});
|
|
29
|
+
|
|
30
|
+
test('R67 live log selection is bounded, deduplicated and rejects path traversal/drive prefixes',()=>{
|
|
31
|
+
const runtimeNames=['bridge.stdout.log','bridge.stdout.log','../private.log','..\\private.log','C:\\token.log','.hidden.log',
|
|
32
|
+
...Array.from({length:180},(_,i)=>'remote-'+String(i).padStart(3,'0')+'.log')];
|
|
33
|
+
const auditNames=['segment-00000001.jsonl','segment-00000002.jsonl','segment-00000002.jsonl','segment-00000003.jsonl'];
|
|
34
|
+
const selected=selectLiveLogNames({auditNames,runtimeNames});
|
|
35
|
+
assert.deepEqual(selected.audit,['segment-00000002.jsonl','segment-00000003.jsonl']);
|
|
36
|
+
assert.ok(selected.runtime.length<=64,'cap runtime readers to a finite budget');
|
|
37
|
+
assert.equal(new Set(selected.runtime).size,selected.runtime.length);
|
|
38
|
+
assert.ok(selected.runtime.every(name=>/^[A-Za-z0-9][A-Za-z0-9._-]{0,127}\.log$/.test(name)));
|
|
39
|
+
assert.ok(selected.runtime.includes('remote-179.log'));
|
|
40
|
+
});
|
|
@@ -6,7 +6,7 @@ const root=new URL('../',import.meta.url);
|
|
|
6
6
|
const read=rel=>readFile(new URL(rel,root),'utf8');
|
|
7
7
|
const json=rel=>read(rel).then(JSON.parse);
|
|
8
8
|
const currentPackage=await json('package.json');
|
|
9
|
-
const r53test=currentPackage.version==='0.15.30'?test:test.
|
|
9
|
+
const r53test=currentPackage.version==='0.15.30'?test:(name,fn)=>test(name,{skip:'Historical R53 release contract requires 0.15.30; current '+currentPackage.version},fn);
|
|
10
10
|
|
|
11
11
|
r53test('R53 current release identity is coherent across package lock source metadata SBOM and gate',async()=>{
|
|
12
12
|
const [pkg,lock,release,provenance,matrix,sbom,versionSource]=await Promise.all([
|
|
@@ -6,7 +6,7 @@ const root=new URL('../',import.meta.url);
|
|
|
6
6
|
const read=rel=>readFile(new URL(rel,root),'utf8');
|
|
7
7
|
const json=rel=>read(rel).then(JSON.parse);
|
|
8
8
|
const currentPackage=await json('package.json');
|
|
9
|
-
const r54test=currentPackage.version==='0.15.31'?test:test.
|
|
9
|
+
const r54test=currentPackage.version==='0.15.31'?test:(name,fn)=>test(name,{skip:'Historical R54 release contract requires 0.15.31; current '+currentPackage.version},fn);
|
|
10
10
|
|
|
11
11
|
r54test('R54 release identity is coherent across package lock source metadata SBOM and gate',async()=>{
|
|
12
12
|
const [pkg,lock,release,provenance,matrix,sbom,versionSource]=await Promise.all([
|
|
@@ -6,7 +6,7 @@ const root=new URL('../',import.meta.url);
|
|
|
6
6
|
const read=rel=>readFile(new URL(rel,root),'utf8');
|
|
7
7
|
const json=rel=>read(rel).then(JSON.parse);
|
|
8
8
|
const currentPackage=await json('package.json');
|
|
9
|
-
const r55test=currentPackage.version==='0.15.32'?test:test.
|
|
9
|
+
const r55test=currentPackage.version==='0.15.32'?test:(name,fn)=>test(name,{skip:'Historical R55 release contract requires 0.15.32; current '+currentPackage.version},fn);
|
|
10
10
|
|
|
11
11
|
r55test('R55 release identity is coherent across package lock source metadata SBOM and gate',async()=>{
|
|
12
12
|
const [pkg,lock,release,provenance,matrix,sbom,versionSource]=await Promise.all([
|
|
@@ -6,7 +6,7 @@ const root=new URL('../',import.meta.url);
|
|
|
6
6
|
const read=rel=>readFile(new URL(rel,root),'utf8');
|
|
7
7
|
const json=rel=>read(rel).then(JSON.parse);
|
|
8
8
|
const currentPackage=await json('package.json');
|
|
9
|
-
const r56test=currentPackage.version==='0.15.33'?test:test.
|
|
9
|
+
const r56test=currentPackage.version==='0.15.33'?test:(name,fn)=>test(name,{skip:'Historical R56 release contract requires 0.15.33; current '+currentPackage.version},fn);
|
|
10
10
|
|
|
11
11
|
r56test('R56 release identity is coherent across package lock source metadata SBOM and gate',async()=>{
|
|
12
12
|
const [pkg,lock,release,provenance,matrix,sbom,versionSource]=await Promise.all([
|
|
@@ -6,7 +6,7 @@ const root=new URL('../',import.meta.url);
|
|
|
6
6
|
const read=rel=>readFile(new URL(rel,root),'utf8');
|
|
7
7
|
const json=rel=>read(rel).then(JSON.parse);
|
|
8
8
|
const currentPackage=await json('package.json');
|
|
9
|
-
const r57test=currentPackage.version==='0.15.34'?test:test.
|
|
9
|
+
const r57test=currentPackage.version==='0.15.34'?test:(name,fn)=>test(name,{skip:'Historical R57 release contract requires 0.15.34; current '+currentPackage.version},fn);
|
|
10
10
|
|
|
11
11
|
r57test('R57 release identity is coherent across package lock source metadata SBOM and gate',async()=>{
|
|
12
12
|
const [pkg,lock,release,provenance,matrix,sbom,versionSource]=await Promise.all([
|
|
@@ -11,7 +11,7 @@ test('R58 deployment activates the bridge bundled inside the candidate release,
|
|
|
11
11
|
assert.match(deploy,/const bridgeScript=path\.join\(bridgeRoot,'src','bridge\.mjs'\)/);
|
|
12
12
|
});
|
|
13
13
|
|
|
14
|
-
test('R58 bundled bridge package is present and version-bound to 0.15.35',{skip:currentPackage.version!=='0.15.35'},async()=>{
|
|
14
|
+
test('R58 bundled bridge package is present and version-bound to 0.15.35',{skip:currentPackage.version!=='0.15.35' ? 'Historical R58 bridge artifact requires 0.15.35; current '+currentPackage.version : false},async()=>{
|
|
15
15
|
const [pkg,bridgePkg,bridge]=await Promise.all([
|
|
16
16
|
readFile(new URL('../package.json',import.meta.url),'utf8').then(JSON.parse),
|
|
17
17
|
readFile(new URL('../bridge/package.json',import.meta.url),'utf8').then(JSON.parse),
|
|
@@ -6,7 +6,7 @@ const read=rel=>readFile(new URL('../'+rel,import.meta.url),'utf8');
|
|
|
6
6
|
const json=rel=>read(rel).then(JSON.parse);
|
|
7
7
|
const currentPackage=await json('package.json');
|
|
8
8
|
|
|
9
|
-
test('R58 identity is coherent and parent is exact production-accepted 0.15.34',{skip:currentPackage.version!=='0.15.35'},async()=>{
|
|
9
|
+
test('R58 identity is coherent and parent is exact production-accepted 0.15.34',{skip:currentPackage.version!=='0.15.35' ? 'Historical R58 release contract requires 0.15.35; current '+currentPackage.version : false},async()=>{
|
|
10
10
|
const [pkg,lock,release,prov,matrix,sbom,version,bridgePkg]=await Promise.all([
|
|
11
11
|
json('package.json'),json('package-lock.json'),json('RELEASE.json'),json('PROVENANCE.json'),json('TEST-MATRIX.json'),json('SBOM.cdx.json'),read('src/version.mjs'),json('bridge/package.json')
|
|
12
12
|
]);
|
|
@@ -29,7 +29,7 @@ test('R58 identity is coherent and parent is exact production-accepted 0.15.34',
|
|
|
29
29
|
assert.equal(release.parent.tarball_sha256,'a6f7b21faf34793ca17dfb6d0e9ec03320f1468d011e75d8349098df82fc2639');
|
|
30
30
|
});
|
|
31
31
|
|
|
32
|
-
test('R58 consolidation evidence preserves fail-closed and non-final claims',{skip:currentPackage.version!=='0.15.35'},async()=>{
|
|
32
|
+
test('R58 consolidation evidence preserves fail-closed and non-final claims',{skip:currentPackage.version!=='0.15.35' ? 'Historical R58 release contract requires 0.15.35; current '+currentPackage.version : false},async()=>{
|
|
33
33
|
const [release,prov,matrix]=await Promise.all([json('RELEASE.json'),json('PROVENANCE.json'),json('TEST-MATRIX.json')]);
|
|
34
34
|
assert.equal(release.consolidation.bridge_bundled_inside_release,true);
|
|
35
35
|
assert.equal(release.consolidation.bridge_recursive_local_dependency_binding,true);
|
|
@@ -5,7 +5,7 @@ import {readFile} from 'node:fs/promises';
|
|
|
5
5
|
const read=rel=>readFile(new URL('../'+rel,import.meta.url),'utf8');
|
|
6
6
|
const currentPackage=JSON.parse(await read('package.json'));
|
|
7
7
|
|
|
8
|
-
test('R58 canonical Windows gate is final-candidate bound and leaves historical gates immutable',{skip:currentPackage.version!=='0.15.35'},async()=>{
|
|
8
|
+
test('R58 canonical Windows gate is final-candidate bound and leaves historical gates immutable',{skip:currentPackage.version!=='0.15.35' ? 'Historical R58 Windows gate requires 0.15.35; current '+currentPackage.version : false},async()=>{
|
|
9
9
|
const [pkgText,gate,evidence,r57Gate,r57Evidence]=await Promise.all([
|
|
10
10
|
read('package.json'),read('scripts/gate-windows-r58.ps1'),read('scripts/windows-gate-evidence-r58.mjs'),
|
|
11
11
|
read('scripts/gate-windows-r57.ps1'),read('scripts/windows-gate-evidence-r57.mjs')
|
|
@@ -83,7 +83,7 @@ test('R59 compact baseline changes only at the explicitly authorized R64 read-of
|
|
|
83
83
|
assert.deepEqual(diff.added,[]);
|
|
84
84
|
assert.deepEqual(diff.removed,[]);
|
|
85
85
|
const packageVersion=JSON.parse(await readFile(path.join(repoRoot,'package.json'),'utf8')).version;
|
|
86
|
-
if(['0.15.41','0.15.42','0.15.43'].includes(packageVersion)){
|
|
86
|
+
if(['0.15.41','0.15.42','0.15.43','0.15.44'].includes(packageVersion)){
|
|
87
87
|
assert.deepEqual(diff.schema_changed,['machine_fs']);
|
|
88
88
|
assert.equal(diff.unchanged.length,42);
|
|
89
89
|
const prior=baseline.tools.find(tool=>tool.name==='machine_fs');
|
|
@@ -13,7 +13,7 @@ const PARENT=Object.freeze({
|
|
|
13
13
|
generation_manifest_sha256:'6134f9f26b680e13ed545da4ab5f3020f411ea2569062fb9c154c8a7e036c9dc'
|
|
14
14
|
});
|
|
15
15
|
|
|
16
|
-
test('R60 identity is coherent and binds the exact production-accepted 0.15.36 predecessor',{skip:currentPackage.version!=='0.15.37'},async()=>{
|
|
16
|
+
test('R60 identity is coherent and binds the exact production-accepted 0.15.36 predecessor',{skip:currentPackage.version!=='0.15.37' ? 'Historical R60 release contract requires 0.15.37; current '+currentPackage.version : false},async()=>{
|
|
17
17
|
const [pkg,lock,release,prov,matrix,sbom,version,bridgePkg,contract]=await Promise.all([
|
|
18
18
|
json('package.json'),json('package-lock.json'),json('RELEASE.json'),json('PROVENANCE.json'),
|
|
19
19
|
json('TEST-MATRIX.json'),json('SBOM.cdx.json'),read('src/version.mjs'),json('bridge/package.json'),
|
|
@@ -47,7 +47,7 @@ test('R60 identity is coherent and binds the exact production-accepted 0.15.36 p
|
|
|
47
47
|
assert.match(contract,/0\.15\.37/);
|
|
48
48
|
});
|
|
49
49
|
|
|
50
|
-
test('R60 release contract exposes the proven remote truth semantics without widening dependencies',{skip:currentPackage.version!=='0.15.37'},async()=>{
|
|
50
|
+
test('R60 release contract exposes the proven remote truth semantics without widening dependencies',{skip:currentPackage.version!=='0.15.37' ? 'Historical R60 release contract requires 0.15.37; current '+currentPackage.version : false},async()=>{
|
|
51
51
|
const [pkg,release,matrix]=await Promise.all([json('package.json'),json('RELEASE.json'),json('TEST-MATRIX.json')]);
|
|
52
52
|
assert.equal(Object.keys(pkg.dependencies??{}).length,4);
|
|
53
53
|
assert.equal(release.r60_remote_hardening.authority_truth_coherence,true);
|
|
@@ -70,7 +70,7 @@ test('R60 release contract exposes the proven remote truth semantics without wid
|
|
|
70
70
|
assert.equal(matrix.observed_pre_release_evidence.r60_package.status,'PASS_VERIFY_ONLY_PRE_FINAL_SEAL');
|
|
71
71
|
});
|
|
72
72
|
|
|
73
|
-
test('R60 package scripts bind the new focused, full-regression and Windows-gate entrypoints',{skip:currentPackage.version!=='0.15.37'},async()=>{
|
|
73
|
+
test('R60 package scripts bind the new focused, full-regression and Windows-gate entrypoints',{skip:currentPackage.version!=='0.15.37' ? 'Historical R60 release contract requires 0.15.37; current '+currentPackage.version : false},async()=>{
|
|
74
74
|
const [pkg,gate]=await Promise.all([json('package.json'),read('scripts/gate-windows-r60-prepublish.ps1')]);
|
|
75
75
|
assert.match(pkg.scripts['r60:focused:test'],/r60-authority-coherence\.test\.mjs/);
|
|
76
76
|
assert.match(pkg.scripts['r60:focused:test'],/r60-remote-call-recovery\.test\.mjs/);
|
|
@@ -11,7 +11,7 @@ const PARENT={
|
|
|
11
11
|
generation_manifest_sha256:'54842021c75f01bf7ecbd5b10ab8a482ecf107765b45c46f9d39b12bab65eac4'
|
|
12
12
|
};
|
|
13
13
|
|
|
14
|
-
test('R61 identity binds exact sealed 0.15.37 predecessor without a public surface expansion',{skip:currentPackage.version!=='0.15.38'},async()=>{
|
|
14
|
+
test('R61 identity binds exact sealed 0.15.37 predecessor without a public surface expansion',{skip:currentPackage.version!=='0.15.38' ? 'Historical R61 release contract requires 0.15.38; current '+currentPackage.version : false},async()=>{
|
|
15
15
|
const [pkg,lock,bridge,release,provenance,matrix,sbom,version,gate]=await Promise.all([
|
|
16
16
|
json('package.json'),json('package-lock.json'),json('bridge/package.json'),json('RELEASE.json'),
|
|
17
17
|
json('PROVENANCE.json'),json('TEST-MATRIX.json'),json('SBOM.cdx.json'),read('src/version.mjs'),
|
|
@@ -12,7 +12,7 @@ const PARENT={
|
|
|
12
12
|
generation_manifest_sha256:'9d320a8af1ba8e9e6a23552f35263da2670c00af1355464820552d849d9033c6'
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
-
test('R62 identity binds exact sealed 0.15.38 parent and transaction reconciliation scope',{skip:currentPackage.version!=='0.15.39'},async()=>{
|
|
15
|
+
test('R62 identity binds exact sealed 0.15.38 parent and transaction reconciliation scope',{skip:currentPackage.version!=='0.15.39' ? 'Historical R62 release contract requires 0.15.39; current '+currentPackage.version : false},async()=>{
|
|
16
16
|
const [pkg,lock,bridge,release,provenance,matrix,sbom,version,gate]=await Promise.all([
|
|
17
17
|
json('package.json'),json('package-lock.json'),json('bridge/package.json'),json('RELEASE.json'),
|
|
18
18
|
json('PROVENANCE.json'),json('TEST-MATRIX.json'),json('SBOM.cdx.json'),read('src/version.mjs'),
|
|
@@ -12,7 +12,7 @@ const PARENT={
|
|
|
12
12
|
generation_manifest_sha256:'f47cb96083679e764725df1bde6eda53169a39f55772c173ab22f89a1dfaa7ab'
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
-
test('R63 identity binds exact active 0.15.39 parent and one-shot runtime coherence repair',{skip:currentPackage.version!=='0.15.40'},async()=>{
|
|
15
|
+
test('R63 identity binds exact active 0.15.39 parent and one-shot runtime coherence repair',{skip:currentPackage.version!=='0.15.40' ? 'Historical R63 release contract requires 0.15.40; current '+currentPackage.version : false},async()=>{
|
|
16
16
|
const pkg=await json('package.json');
|
|
17
17
|
assert.equal(pkg.version,'0.15.40');
|
|
18
18
|
assert.match(pkg.scripts['r63:focused:test'],/r63-one-shot-coherence\.test\.mjs/);
|
|
@@ -12,7 +12,7 @@ const runtime={
|
|
|
12
12
|
generation_manifest_sha256:'f47cb96083679e764725df1bde6eda53169a39f55772c173ab22f89a1dfaa7ab'
|
|
13
13
|
};
|
|
14
14
|
|
|
15
|
-
test('R64 release identity distinguishes unsealed source predecessor from active runtime predecessor',{skip:currentPackage.version!=='0.15.41'},async()=>{
|
|
15
|
+
test('R64 release identity distinguishes unsealed source predecessor from active runtime predecessor',{skip:currentPackage.version!=='0.15.41' ? 'Historical R64 release contract requires 0.15.41; current '+currentPackage.version : false},async()=>{
|
|
16
16
|
const [pkg,lock,bridge,release,provenance,matrix,sbom,scope,gaps,version,gate]=await Promise.all([
|
|
17
17
|
json('package.json'),json('package-lock.json'),json('bridge/package.json'),json('RELEASE.json'),
|
|
18
18
|
json('PROVENANCE.json'),json('TEST-MATRIX.json'),json('SBOM.cdx.json'),json('docs/R64-SCOPE.json'),
|
|
@@ -16,7 +16,7 @@ const dummy={coding:'2'.repeat(64),autonomous:'3'.repeat(64),desktop:'4'.repeat(
|
|
|
16
16
|
|
|
17
17
|
async function optional(file){try{return await readFile(file);}catch(error){if(error?.code==='ENOENT')return null;throw error;}}
|
|
18
18
|
|
|
19
|
-
test('epoch-native orchestrator
|
|
19
|
+
test('epoch-native orchestrator handles BOM-encoded process grant with transaction continuity engine',async()=>{
|
|
20
20
|
const root=await mkdtemp(path.join(os.tmpdir(),'deadbyte-r65-epoch-activation-'));
|
|
21
21
|
try{
|
|
22
22
|
const state=path.join(root,'state'),runtime=path.join(state,'runtime'),trust=path.join(state,'trust'),policies=path.join(root,'policies');
|
|
@@ -33,7 +33,7 @@ test('epoch-native orchestrator uses transaction continuity engine instead of ge
|
|
|
33
33
|
await writeFile(beforePath,policyBytes);await writeFile(afterPath,policyBytes);
|
|
34
34
|
const oldGrant={schema:'deadbyte.process-grant.v1',policy_sha256:sha(policyBytes),instance_nonce:'8'.repeat(64),
|
|
35
35
|
profile_ids:['safe'],root_ids:['core'],granted_at_utc:'2026-10-07T00:00:00Z'};
|
|
36
|
-
const oldBytes=Buffer.from(JSON.stringify(oldGrant));await writeFile(grantFile,oldBytes);
|
|
36
|
+
const oldBytes=Buffer.concat([Buffer.from([0xef,0xbb,0xbf]),Buffer.from(JSON.stringify(oldGrant))]);await writeFile(grantFile,oldBytes);
|
|
37
37
|
const store=createAuthorityEpochStore({runtimeDir:runtime,policyBytes});
|
|
38
38
|
await store.append({plane:'process',action:'grant',grantBytes:oldBytes,grantInstanceNonce:oldGrant.instance_nonce});
|
|
39
39
|
let switched=false;
|
|
@@ -41,7 +41,7 @@ test('epoch-native orchestrator uses transaction continuity engine instead of ge
|
|
|
41
41
|
const bytes=await optional(grantFile),head=await store.readHead({plane:'process'});
|
|
42
42
|
let armed=false;
|
|
43
43
|
if(bytes){
|
|
44
|
-
const grant=JSON.parse(bytes);
|
|
44
|
+
const grant=JSON.parse(new TextDecoder('utf-8',{fatal:true}).decode(bytes));
|
|
45
45
|
armed=(await store.verifyGrant({plane:'process',grantBytes:bytes,grantInstanceNonce:grant.instance_nonce,policyBytes})).trusted;
|
|
46
46
|
}
|
|
47
47
|
return {state:'ONLINE',local_ready:true,...ids,supervisor:{running:true},authority:{
|
|
@@ -104,7 +104,7 @@ test('epoch-native explicit user revoke after transaction revoke wins over orche
|
|
|
104
104
|
const bytes=await optional(grantFile),head=await store.readHead({plane:'process'});
|
|
105
105
|
let armed=false;
|
|
106
106
|
if(bytes){
|
|
107
|
-
const grant=JSON.parse(bytes);
|
|
107
|
+
const grant=JSON.parse(new TextDecoder('utf-8',{fatal:true}).decode(bytes));
|
|
108
108
|
armed=(await store.verifyGrant({plane:'process',grantBytes:bytes,grantInstanceNonce:grant.instance_nonce,policyBytes})).trusted;
|
|
109
109
|
}
|
|
110
110
|
return {state:'ONLINE',local_ready:true,...ids,supervisor:{running:true},authority:{
|