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.
Files changed (129) hide show
  1. package/MANIFEST.SHA256 +128 -67
  2. package/PROVENANCE.json +23 -12
  3. package/README.txt +18 -18
  4. package/RELEASE.json +28 -14
  5. package/SBOM.cdx.json +14 -2
  6. package/TEST-MATRIX.json +41 -10
  7. package/bin/appcontainer-stage.obj +0 -0
  8. package/bin/bootstrap-advapi32.obj +0 -0
  9. package/bin/bootstrap-exitcode.obj +0 -0
  10. package/bin/bootstrap-kernel32.obj +0 -0
  11. package/bin/child-control-probe.obj +0 -0
  12. package/bin/child-control-stage.obj +0 -0
  13. package/bin/contained-reverse-worker.obj +0 -0
  14. package/bin/contained-transform-worker.obj +0 -0
  15. package/bin/containment-probe.obj +0 -0
  16. package/bin/deadbyte-contain.obj +0 -0
  17. package/bin/deadbyte-desktop-input-r40.obj +0 -0
  18. package/bin/deadbyte-desktop-observer-r40.obj +0 -0
  19. package/bin/deadbyte-desktop-uia-r40.obj +0 -0
  20. package/bin/deadbyte-exec.obj +0 -0
  21. package/bin/deadbyte-hardware-observer-r45.obj +0 -0
  22. package/bin/deadbyte-native-inspect-r67.exe +0 -0
  23. package/bin/deadbyte-native-inspect-r67.obj +0 -0
  24. package/bin/deadbyte-process-host.obj +0 -0
  25. package/bin/deadbyte-tunnel-host.obj +0 -0
  26. package/bridge/package.json +1 -1
  27. package/controller/deadbyte-desktop-policy.json +5 -5
  28. package/controller/deadbyte-process-policy.json +4 -4
  29. package/docs/R67-ALPHA-REFERENCE-DIFFERENTIAL.md +42 -0
  30. package/docs/R67-ALPHA-STATIC-COMPARISON.json +205 -0
  31. package/docs/R67-CANDIDATE-PARENT.json +10 -0
  32. package/docs/R67-EVIDENCE-RECONCILE-CLOSEOUT-20261011.md +64 -0
  33. package/docs/R67-FULL-REGRESSION-UNKNOWN.json +27 -0
  34. package/docs/R67-NATIVE-INSPECT-BINARY.json +11 -0
  35. package/docs/R67-NPM-EXDEV-PRESERVATION-20261011.md +39 -0
  36. package/docs/R67-OBSERVATION-TRUTH.md +82 -0
  37. package/docs/R67-REFERENCE-GAP-MATRIX.json +57 -0
  38. package/docs/R67-REGRESSION-CLOSURE-20261011.md +24 -0
  39. package/native/deadbyte-native-inspect-r67.cpp +252 -0
  40. package/package.json +6 -3
  41. package/proof/CONTAINMENT-BUILD.txt +6 -6
  42. package/scripts/build-native-inspector-r67.ps1 +28 -0
  43. package/scripts/gate-windows-r67.ps1 +56 -0
  44. package/scripts/npm-preserve-artifact-r67.mjs +99 -0
  45. package/scripts/npm-release-r48.mjs +10 -2
  46. package/scripts/npm-release-readiness-r67.mjs +26 -0
  47. package/scripts/r67-acquire-alpha-reference.mjs +95 -0
  48. package/scripts/r67-audit-nonpass-source.mjs +39 -0
  49. package/scripts/r67-compare-desktop-alpha.mjs +48 -0
  50. package/scripts/r67-diagnose-failed-shard.mjs +23 -0
  51. package/scripts/r67-durable-batch.mjs +42 -0
  52. package/scripts/r67-focused-gate.mjs +58 -0
  53. package/scripts/r67-full-regression.mjs +28 -0
  54. package/scripts/r67-independent-observation-verify.mjs +36 -0
  55. package/scripts/r67-independent-runtime-observation-verify.mjs +63 -0
  56. package/scripts/r67-nonpass-adjudicate.mjs +20 -0
  57. package/scripts/r67-publish-boundary-audit.mjs +32 -0
  58. package/scripts/r67-regression-reconcile.mjs +10 -0
  59. package/scripts/r67-regression-shard-run.mjs +70 -0
  60. package/scripts/r67-run-shard-batch.mjs +18 -0
  61. package/scripts/r67-stage-candidate.mjs +30 -0
  62. package/scripts/r67-verify-parent-ping.mjs +22 -0
  63. package/scripts/release-manifest.mjs +1 -0
  64. package/src/activation-continuity-engine-r65.mjs +2 -1
  65. package/src/autonomous-runtime.mjs +1 -1
  66. package/src/deadbyte-cli.mjs +33 -1
  67. package/src/machine-fs-smoke-client.mjs +13 -5
  68. package/src/machine-identity.mjs +59 -2
  69. package/src/machine-mcp-tools.mjs +8 -0
  70. package/src/mcp-server.mjs +11 -2
  71. package/src/native-inspector-r67.mjs +66 -0
  72. package/src/r67-diagnostic-export.mjs +118 -0
  73. package/src/r67-diagnostics-verify.mjs +82 -0
  74. package/src/r67-evidence-reconcile.mjs +128 -0
  75. package/src/r67-native-observation-authority.mjs +45 -0
  76. package/src/r67-observation-receipt.mjs +43 -0
  77. package/src/r67-regression-shards.mjs +176 -0
  78. package/src/remote-live-log.mjs +14 -10
  79. package/src/tool-audit.mjs +1 -1
  80. package/src/version.mjs +1 -1
  81. package/test/agent-runtime.test.mjs +1 -1
  82. package/test/autonomous-loop.test.mjs +11 -6
  83. package/test/autonomous-runtime.test.mjs +1 -1
  84. package/test/coding-plane.test.mjs +1 -1
  85. package/test/full-max-catalog-r46.test.mjs +1 -1
  86. package/test/output-schema.test.mjs +1 -1
  87. package/test/r51-live-log-polling.test.mjs +12 -0
  88. package/test/r53-release-contract.test.mjs +1 -1
  89. package/test/r54-release-contract.test.mjs +1 -1
  90. package/test/r55-release-contract.test.mjs +1 -1
  91. package/test/r56-release-contract.test.mjs +1 -1
  92. package/test/r57-release-contract.test.mjs +1 -1
  93. package/test/r58-bundled-bridge.test.mjs +1 -1
  94. package/test/r58-release-contract.test.mjs +2 -2
  95. package/test/r58-windows-gate.test.mjs +1 -1
  96. package/test/r59-tool-surface-compat.test.mjs +1 -1
  97. package/test/r60-release-contract.test.mjs +3 -3
  98. package/test/r61-release-contract.test.mjs +1 -1
  99. package/test/r62-release-contract.test.mjs +1 -1
  100. package/test/r63-release-contract.test.mjs +1 -1
  101. package/test/r64-release-contract.test.mjs +1 -1
  102. package/test/r65-epoch-native-activation-integration.test.mjs +4 -4
  103. package/test/r65-release-contract.test.mjs +1 -1
  104. package/test/r66-release-contract.test.mjs +2 -1
  105. package/test/r67-cli-integration.test.mjs +41 -0
  106. package/test/r67-diagnostics-cli.test.mjs +60 -0
  107. package/test/r67-diagnostics-verify.test.mjs +49 -0
  108. package/test/r67-diagnostics-zip-oracle.test.mjs +38 -0
  109. package/test/r67-diagnostics.test.mjs +60 -0
  110. package/test/r67-evidence-reconcile.test.mjs +186 -0
  111. package/test/r67-isolated-slot-rollback-restore.test.mjs +62 -0
  112. package/test/r67-live-log-secret-canary.test.mjs +44 -0
  113. package/test/r67-machine-fs-smoke-epoch.test.mjs +22 -0
  114. package/test/r67-native-inspector.test.mjs +131 -0
  115. package/test/r67-native-observation-authority.test.mjs +49 -0
  116. package/test/r67-npm-cross-volume.test.mjs +74 -0
  117. package/test/r67-npm-publish-gate.test.mjs +38 -0
  118. package/test/r67-regression-shards.test.mjs +184 -0
  119. package/test/r67-release-contract.test.mjs +44 -0
  120. package/test/r67-runtime-observation-binding.test.mjs +86 -0
  121. package/test/r67-server-observation-wiring.test.mjs +12 -0
  122. package/test/r67-signed-receipt.test.mjs +66 -0
  123. package/test/r67-skip-rationale.test.mjs +31 -0
  124. package/test/r67-tool-annotations.test.mjs +21 -0
  125. package/test/r67-windows-gate-argv.test.mjs +13 -0
  126. package/test/release-version.test.mjs +1 -1
  127. package/test/remote-live-log-r36.test.mjs +10 -0
  128. package/test/remote-live-log-r37.test.mjs +29 -0
  129. package/test/semantic-multilang.test.mjs +1 -1
@@ -39,7 +39,7 @@ deadbyte-process-host.cpp
39
39
  exit_code=0
40
40
  ==== probe-dependencies ====
41
41
 
42
- Dump of file D:\Projects\deadbyte-mcp\development\deadbyte-mcp-0.15.30-stabilization\bin\containment-probe.exe
42
+ Dump of file D:\Projects\deadbyte-mcp\development\deadbyte-mcp-0.15.44-r67\bin\containment-probe.exe
43
43
 
44
44
  File Type: EXECUTABLE IMAGE
45
45
 
@@ -59,7 +59,7 @@ File Type: EXECUTABLE IMAGE
59
59
  exit_code=0
60
60
  ==== contained-launcher-dependencies ====
61
61
 
62
- Dump of file D:\Projects\deadbyte-mcp\development\deadbyte-mcp-0.15.30-stabilization\bin\deadbyte-exec.exe
62
+ Dump of file D:\Projects\deadbyte-mcp\development\deadbyte-mcp-0.15.44-r67\bin\deadbyte-exec.exe
63
63
 
64
64
  File Type: EXECUTABLE IMAGE
65
65
 
@@ -83,7 +83,7 @@ File Type: EXECUTABLE IMAGE
83
83
  exit_code=0
84
84
  ==== contained-worker-dependencies ====
85
85
 
86
- Dump of file D:\Projects\deadbyte-mcp\development\deadbyte-mcp-0.15.30-stabilization\bin\contained-transform-worker.exe
86
+ Dump of file D:\Projects\deadbyte-mcp\development\deadbyte-mcp-0.15.44-r67\bin\contained-transform-worker.exe
87
87
 
88
88
  File Type: EXECUTABLE IMAGE
89
89
 
@@ -104,7 +104,7 @@ File Type: EXECUTABLE IMAGE
104
104
  exit_code=0
105
105
  ==== contained-reverse-worker-dependencies ====
106
106
 
107
- Dump of file D:\Projects\deadbyte-mcp\development\deadbyte-mcp-0.15.30-stabilization\bin\contained-reverse-worker.exe
107
+ Dump of file D:\Projects\deadbyte-mcp\development\deadbyte-mcp-0.15.44-r67\bin\contained-reverse-worker.exe
108
108
 
109
109
  File Type: EXECUTABLE IMAGE
110
110
 
@@ -125,7 +125,7 @@ File Type: EXECUTABLE IMAGE
125
125
  exit_code=0
126
126
  ==== named-tunnel-host-dependencies ====
127
127
 
128
- Dump of file D:\Projects\deadbyte-mcp\development\deadbyte-mcp-0.15.30-stabilization\bin\deadbyte-tunnel-host.exe
128
+ Dump of file D:\Projects\deadbyte-mcp\development\deadbyte-mcp-0.15.44-r67\bin\deadbyte-tunnel-host.exe
129
129
 
130
130
  File Type: EXECUTABLE IMAGE
131
131
 
@@ -144,7 +144,7 @@ File Type: EXECUTABLE IMAGE
144
144
  exit_code=0
145
145
  ==== process-host-dependencies ====
146
146
 
147
- Dump of file D:\Projects\deadbyte-mcp\development\deadbyte-mcp-0.15.30-stabilization\bin\deadbyte-process-host.exe
147
+ Dump of file D:\Projects\deadbyte-mcp\development\deadbyte-mcp-0.15.44-r67\bin\deadbyte-process-host.exe
148
148
 
149
149
  File Type: EXECUTABLE IMAGE
150
150
 
@@ -0,0 +1,28 @@
1
+ param([Parameter(Mandatory=$true)][ValidatePattern('^[0-9a-f]{64}$')][string]$SourceSha256)
2
+ $ErrorActionPreference='Stop'
3
+ Set-StrictMode -Version Latest
4
+ $root=Split-Path -Parent $PSScriptRoot
5
+ $src=Join-Path $root 'native\deadbyte-native-inspect-r67.cpp'
6
+ $observed=(Get-FileHash -LiteralPath $src -Algorithm SHA256).Hash.ToLowerInvariant()
7
+ if($observed -ne $SourceSha256){throw "R67 source SHA mismatch; refusing build"}
8
+ Write-Output "R67_SOURCE_SHA256=$observed"
9
+ $bin=Join-Path $root 'bin'
10
+ $exe=Join-Path $bin 'deadbyte-native-inspect-r67.exe'
11
+ $obj=Join-Path $bin 'deadbyte-native-inspect-r67.obj'
12
+ $vswhere='C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe'
13
+ if(!(Test-Path -LiteralPath $vswhere)){throw 'vswhere missing'}
14
+ $install=(& $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath | Select-Object -First 1)
15
+ if(!$install){throw 'MSVC x64 C++ toolchain missing'}
16
+ $dev=Join-Path $install 'Common7\Tools\VsDevCmd.bat'
17
+ $cmd=if($env:ComSpec){$env:ComSpec}else{Join-Path $env:SystemRoot 'System32\cmd.exe'}
18
+ New-Item -ItemType Directory -Path $bin -Force | Out-Null
19
+ $common='/nologo /std:c++17 /permissive- /W4 /WX /O2 /MT /EHsc /guard:cf /diagnostics:caret /utf-8 /Brepro /DUNICODE /D_UNICODE /D_WIN32_WINNT=0x0A00'
20
+ $compile='cl {0} "{1}" /Fo:"{2}" /Fe:"{3}" /link bcrypt.lib /Brepro /INCREMENTAL:NO' -f $common,$src,$obj,$exe
21
+ $line='call "{0}" -no_logo -arch=x64 -host_arch=x64 && {1}' -f $dev,$compile
22
+ $output=& $cmd /d /s /c $line 2>&1
23
+ $rc=$LASTEXITCODE
24
+ $output | ForEach-Object { Write-Output ([string]$_) }
25
+ if($rc -ne 0){throw "R67 native build failed exit=$rc"}
26
+ if(!(Test-Path -LiteralPath $exe -PathType Leaf)){throw 'R67 native exe missing'}
27
+ $sha=(Get-FileHash -LiteralPath $exe -Algorithm SHA256).Hash.ToLowerInvariant()
28
+ Write-Output "R67_NATIVE_BUILD_PASS sha256=$sha path=$exe"
@@ -0,0 +1,56 @@
1
+ param(
2
+ [ValidateSet('preflight','focused','evidence','manifest','doctor','all')]
3
+ [string]$Stage='preflight',
4
+ [string]$OperationId=''
5
+ )
6
+ $ErrorActionPreference='Stop'
7
+ Set-StrictMode -Version Latest
8
+ $root=Split-Path -Parent $PSScriptRoot
9
+ $parent='D:\Projects\deadbyte-mcp\development\deadbyte-mcp-0.15.43-r66'
10
+ $expected='4c4a64a4c8e9f5a6e9eecce85fd0007ebcac99121b29c07f1a1fc81d1643cd33'
11
+ $expectedGen='ef3b041e2a87c2e143d4733a98a52d9db80cd16ad7007e112fcb5202e70c77c3'
12
+ $expectedRelease='v0.15.43-4c4a64a4c8e9f5a6'
13
+ if(!(Test-Path -LiteralPath $parent -PathType Container)){throw 'R67 predecessor source missing'}
14
+ $prev=(Get-FileHash -LiteralPath (Join-Path $parent 'MANIFEST.SHA256') -Algorithm SHA256).Hash.ToLowerInvariant()
15
+ if($prev -ne $expected){throw 'R67 predecessor manifest not exact'}
16
+ $stateRoot=Join-Path $env:USERPROFILE '.deadbyte-mcp'
17
+ $pointerPath=Join-Path $stateRoot 'active-release.json'
18
+ if(!(Test-Path -LiteralPath $pointerPath -PathType Leaf)){throw 'R67 active predecessor pointer missing'}
19
+ $pointer=Get-Content -LiteralPath $pointerPath -Raw | ConvertFrom-Json
20
+ if($pointer.release_id -ne $expectedRelease -or $pointer.manifest_sha256 -ne $expected -or
21
+ $pointer.generation_manifest_sha256 -ne $expectedGen){throw 'R67 active predecessor binding mismatch'}
22
+ $pkg=Get-Content -LiteralPath (Join-Path $root 'package.json') -Raw | ConvertFrom-Json
23
+ if($pkg.version -ne '0.15.44'){throw 'R67 package candidate version mismatch'}
24
+ Write-Output 'R67_PREDECESSOR_PREFLIGHT=PASS'
25
+ if($Stage -eq 'preflight'){return}
26
+ function Invoke-Node([string]$Label,[string[]]$NodeArgs){
27
+ Write-Output "R67_STAGE_START=$Label"
28
+ & node @NodeArgs
29
+ if($LASTEXITCODE -ne 0){throw "R67 stage $Label exit=$LASTEXITCODE"}
30
+ Write-Output "R67_STAGE_PASS=$Label"
31
+ }
32
+ if($Stage -eq 'all' -or $Stage -eq 'focused'){
33
+ Invoke-Node 'focused' @('scripts/r67-focused-gate.mjs')
34
+ Invoke-Node 'machine-fs-smoke' @('src/machine-fs-smoke-client.mjs')
35
+ if($Stage -eq 'focused'){return}
36
+ }
37
+ if($Stage -eq 'all' -or $Stage -eq 'evidence'){
38
+ if($OperationId -notmatch '^[a-z0-9][a-z0-9._-]{5,63}$'){throw 'R67 full evidence operation ID required'}
39
+ Invoke-Node 'evidence' @('scripts/r67-regression-reconcile.mjs',$OperationId)
40
+ if($Stage -eq 'evidence'){return}
41
+ }
42
+ if($Stage -eq 'all' -or $Stage -eq 'manifest'){
43
+ Invoke-Node 'manifest-verify' @('scripts/release-manifest.mjs','verify')
44
+ if($Stage -eq 'manifest'){return}
45
+ }
46
+ if($Stage -eq 'all' -or $Stage -eq 'doctor'){
47
+ $prior=$env:DEADBYTE_STATE_ROOT
48
+ $isolated='D:\Projects\deadbyte-mcp\testing\0.15.44-r67\doctor-isolated-empty'
49
+ if(Test-Path -LiteralPath (Join-Path $isolated 'active-release.json')){throw 'isolated doctor root unexpectedly has active release pointer'}
50
+ try{
51
+ $env:DEADBYTE_STATE_ROOT=$isolated
52
+ Invoke-Node 'isolated-doctor' @('src/deadbyte-cli.mjs','doctor')
53
+ }finally{$env:DEADBYTE_STATE_ROOT=$prior}
54
+ if($Stage -eq 'doctor'){return}
55
+ }
56
+ Write-Output 'R67_WINDOWS_GATE=PASS_PREDEPLOY_CANDIDATE'
@@ -0,0 +1,99 @@
1
+ import {createHash,randomBytes} from 'node:crypto';
2
+ import {lstat,readFile,open,link,unlink} from 'node:fs/promises';
3
+ import path from 'node:path';
4
+
5
+ function sha256(bytes){return createHash('sha256').update(bytes).digest('hex');}
6
+ function integrity(bytes){return 'sha512-'+createHash('sha512').update(bytes).digest('base64');}
7
+ async function regular(pathname,label){
8
+ const stat=await lstat(pathname);
9
+ if(!stat.isFile()||stat.isSymbolicLink())throw new Error(label+' must be a regular non-symlink file');
10
+ return stat;
11
+ }
12
+ function assertSameIdentity(before,after){
13
+ if(before.dev!==after.dev||before.ino!==after.ino||before.size!==after.size)
14
+ throw new Error('source artifact identity changed during preservation; do not remove original');
15
+ }
16
+
17
+ /**
18
+ * Preserve an npm-packed immutable tarball across Windows volumes.
19
+ * Uses an exclusive staging file ON THE DESTINATION VOLUME, syncs complete
20
+ * verified bytes, and publishes with a same-volume, no-clobber hard link.
21
+ * No rename(D: -> C:), no partial destination visibility, no npm publish.
22
+ * Preserving exact bytes is NOT permission to send them to npm.
23
+ */
24
+ export async function preserveNpmTarball({source,destination,expectedIntegrity,expectedShasum}={}){
25
+ if(typeof source!=='string'||typeof destination!=='string'||
26
+ !path.isAbsolute(source)||!path.isAbsolute(destination)||
27
+ path.resolve(source)===path.resolve(destination))throw new Error('absolute distinct source and destination required');
28
+ if(typeof expectedIntegrity!=='string'||!/^sha512-[A-Za-z0-9+/]+=*$/.test(expectedIntegrity))
29
+ throw new Error('npm SHA-512 integrity precondition required');
30
+ if(expectedShasum!==undefined&&!/^[a-f0-9]{40}$/.test(expectedShasum))
31
+ throw new Error('invalid npm packed artifact SHA-1 precondition');
32
+
33
+ const original=await regular(source,'source artifact');
34
+ if(original.size===0||original.size>128*1024*1024)throw new Error('npm artifact size outside permitted budget');
35
+ const bytes=await readFile(source);
36
+ assertSameIdentity(original,await regular(source,'source artifact'));
37
+ if(bytes.length!==original.size||integrity(bytes)!==expectedIntegrity)
38
+ throw new Error('npm packed artifact integrity mismatch; original retained');
39
+ if(expectedShasum!==undefined&&createHash('sha1').update(bytes).digest('hex')!==expectedShasum)
40
+ throw new Error('npm packed artifact shasum mismatch; original retained');
41
+ const hash=sha256(bytes);
42
+ let committed=false;
43
+ try{
44
+ const existing=await regular(destination,'preserved artifact');
45
+ const preserved=await readFile(destination);
46
+ if(existing.size!==bytes.length||sha256(preserved)!==hash||integrity(preserved)!==expectedIntegrity)
47
+ throw new Error('existing preserved artifact differs; manual conflict reconciliation required');
48
+ committed=true;
49
+ }catch(error){
50
+ if(error?.code!=='ENOENT')throw error;
51
+ }
52
+ let staging=null;
53
+ if(!committed){
54
+ staging=path.join(path.dirname(destination),'.'+path.basename(destination)+'.stage-'+process.pid+'-'+randomBytes(8).toString('hex'));
55
+ try{
56
+ const handle=await open(staging,'wx',0o600);
57
+ try{
58
+ await handle.writeFile(bytes);
59
+ await handle.sync();
60
+ }finally{await handle.close();}
61
+ const staged=await readFile(staging);
62
+ if(staged.length!==bytes.length||sha256(staged)!==hash||integrity(staged)!==expectedIntegrity)
63
+ throw new Error('staged artifact integrity mismatch; original retained');
64
+ // Atomic visibility of already-fsynced bytes, exclusively on the destination volume.
65
+ try{await link(staging,destination);}
66
+ catch(error){
67
+ if(error?.code!=='EEXIST')throw error;
68
+ const existing=await regular(destination,'preserved artifact');
69
+ const preserved=await readFile(destination);
70
+ if(existing.size!==bytes.length||sha256(preserved)!==hash||integrity(preserved)!==expectedIntegrity)
71
+ throw new Error('concurrent preserved artifact conflict; original retained');
72
+ }
73
+ committed=true;
74
+ }finally{
75
+ if(staging)await unlink(staging).catch(e=>{if(e?.code!=='ENOENT')throw e;});
76
+ }
77
+ }
78
+ // Final post-commit verification before relinquishing the source artifact.
79
+ const final=await regular(destination,'preserved artifact');
80
+ const preserved=await readFile(destination);
81
+ if(final.size!==bytes.length||sha256(preserved)!==hash||integrity(preserved)!==expectedIntegrity)
82
+ throw new Error('preserved artifact changed after commit; original retained');
83
+ const current=await regular(source,'source artifact');
84
+ assertSameIdentity(original,current);
85
+ if(sha256(await readFile(source))!==hash)throw new Error('source bytes changed after commit; retain for reconciliation');
86
+ await unlink(source);
87
+ return {status:staging?'VERIFIED_PRESERVED':'VERIFIED_ALREADY_PRESERVED',
88
+ sha256:hash,bytes:bytes.length,integrity:expectedIntegrity};
89
+ }
90
+
91
+ export async function assertVacantPackDestination({root,filename}={}){
92
+ if(typeof root!=='string'||!path.isAbsolute(root)||typeof filename!=='string'||
93
+ !/^[A-Za-z0-9][A-Za-z0-9._-]*\.tgz$/.test(filename)||filename!==path.basename(filename))
94
+ throw new Error('invalid npm pack target');
95
+ const target=path.join(root,filename);
96
+ try{await lstat(target);}
97
+ catch(error){if(error?.code==='ENOENT')return target;throw error;}
98
+ throw new Error('PACK_BLOCKED existing npm tarball must be archived and reconciled before npm pack: '+target);
99
+ }
@@ -1,7 +1,9 @@
1
1
  import { spawnSync } from 'node:child_process';
2
2
  import { createHash } from 'node:crypto';
3
3
  import { reconcileNpmPublication } from './npm-publication-r65.mjs';
4
- import { mkdtemp, readFile, rm, unlink, mkdir, rename } from 'node:fs/promises';
4
+ import { mkdtemp, readFile, rm, unlink, mkdir } from 'node:fs/promises';
5
+ import {preserveNpmTarball,assertVacantPackDestination} from './npm-preserve-artifact-r67.mjs';
6
+ import {assertR67NpmPublishReady} from './npm-release-readiness-r67.mjs';
5
7
  import { existsSync } from 'node:fs';
6
8
  import { resolveStateRoot } from '../src/state-root.mjs';
7
9
  import path from 'node:path';
@@ -86,6 +88,7 @@ async function main() {
86
88
  if (provenance.version !== version) {
87
89
  throw new Error(`PROVENANCE.json version mismatch: package=${version} provenance=${provenance.version}`);
88
90
  }
91
+ if (!isVerifyOnly && version==='0.15.44') assertR67NpmPublishReady(release);
89
92
  if (release.parent?.release_id !== provenance.parent_release_id ||
90
93
  release.parent?.manifest_sha256 !== provenance.parent_manifest_sha256 ||
91
94
  release.parent?.generation_manifest_sha256 !== provenance.parent_generation_manifest_sha256) {
@@ -113,6 +116,7 @@ async function main() {
113
116
  if(publicationDir)await mkdir(publicationDir,{recursive:true});
114
117
  if(resuming&&!existsSync(preservedTarball))throw new Error('immutable npm publication claim exists but exact local tarball is missing; manual artifact reconciliation required');
115
118
  if(!resuming&&preservedTarball&&existsSync(preservedTarball))throw new Error('unclaimed preserved npm tarball exists; inspect artifact evidence before another pack');
119
+ if(!resuming)await assertVacantPackDestination({root,filename:`deadbyte-mcp-${version}.tgz`});
116
120
  const packed=resuming?null:parseJson(runNpm(['pack', '--json'], { timeout: 180000 }));
117
121
  const packRecord=resuming?{filename:path.basename(preservedTarball)}:(Array.isArray(packed) ? packed[0] : packed?.[pkg.name]);
118
122
  const filename = packRecord?.filename;
@@ -196,7 +200,11 @@ async function main() {
196
200
  return;
197
201
  }
198
202
 
199
- if(!resuming)await rename(tarball,preservedTarball);
203
+ if(!resuming){
204
+ const preserved=await preserveNpmTarball({source:tarball,destination:preservedTarball,
205
+ expectedIntegrity:packRecord.integrity,expectedShasum:packRecord.shasum});
206
+ console.log('Immutable cross-volume artifact preservation verified: '+JSON.stringify(preserved));
207
+ }
200
208
  const publishTarball=preservedTarball;
201
209
  const localBytes = await readFile(publishTarball);
202
210
  const localIntegrity=`sha512-${createHash('sha512').update(localBytes).digest('base64')}`;
@@ -0,0 +1,26 @@
1
+ /**
2
+ * R67 npm publish fence. Does not prove Windows release readiness by itself:
3
+ * only the independent release verifier may change these metadata gates.
4
+ * The package publisher must never interpret focused or package-only PASS as
5
+ * authority to make an immutable public release.
6
+ */
7
+ export function assertR67NpmPublishReady(release){
8
+ if(release?.version!=='0.15.44'||release?.train!=='R67')
9
+ throw new Error('PUBLISH_BLOCKED R67 release identity does not match candidate');
10
+ const state=release.r67_native_observation;
11
+ const gates={
12
+ status:'CANDIDATE_SEALED',
13
+ full_release_gate:'PASS',
14
+ current_source_full_shards:'PASS',
15
+ native_fault_injection:'PASS',
16
+ protocol_parity:'PASS',
17
+ isolated_activation_rollback_restore:'PASS',
18
+ independent_machine_observation:'PASS'
19
+ };
20
+ for(const [key,expected] of Object.entries(gates)){
21
+ if(state?.[key]!==expected)
22
+ throw new Error('PUBLISH_BLOCKED R67 '+key+' '+String(state?.[key]??'MISSING')+
23
+ '; require independently verified gate '+expected+' before npm publication');
24
+ }
25
+ return {status:'R67_METADATA_GATES_MATCH',policy:'PUBLISH_REQUIRES_INDEPENDENT_RELEASE_EVIDENCE'};
26
+ }
@@ -0,0 +1,95 @@
1
+ import https from 'node:https';
2
+ import {createHash} from 'node:crypto';
3
+ import {gunzipSync} from 'node:zlib';
4
+ import {mkdir,open,writeFile,readFile} from 'node:fs/promises';
5
+ import path from 'node:path';
6
+ import {fileURLToPath} from 'node:url';
7
+ const root=path.dirname(path.dirname(fileURLToPath(import.meta.url)));
8
+ const ref=path.resolve(root,'..','..','references','desktop-commander-0.3.1-alpha.2');
9
+ const version='0.3.1-alpha.2';
10
+ const packageName='@wonderwhy-er/desktop-commander';
11
+ const url='https://registry.npmjs.org/@wonderwhy-er%2fdesktop-commander/'+version;
12
+ const hash=(b,algo='sha256')=>createHash(algo).update(b).digest('hex');
13
+ async function fetchBounded(url,maxSize){
14
+ const parsed=new URL(url);
15
+ if(parsed.protocol!=='https:'||parsed.hostname!=='registry.npmjs.org'||parsed.username||parsed.password||parsed.port)throw new Error('untrusted npm endpoint');
16
+ return await new Promise((resolve,reject)=>{
17
+ const req=https.get(parsed,{timeout:20000,headers:{'Accept':'application/json','User-Agent':'deadbyte-reference-verifier/1.0'}},res=>{
18
+ if(res.statusCode!==200){res.resume();reject(new Error('npm GET HTTP '+res.statusCode));return;}
19
+ const parts=[];let size=0;
20
+ res.on('data',b=>{size+=b.length;if(size>maxSize){req.destroy(new Error('download exceeded declared safety cap'));return;}parts.push(b);});
21
+ res.on('end',()=>resolve(Buffer.concat(parts)));
22
+ res.on('error',reject);
23
+ });
24
+ req.on('timeout',()=>req.destroy(new Error('npm request timeout')));
25
+ req.on('error',reject);
26
+ });
27
+ }
28
+ async function saveNew(file,data){
29
+ const h=await open(file,'wx',0o600);
30
+ try{await h.writeFile(data);await h.sync();}finally{await h.close();}
31
+ }
32
+ const metadata=JSON.parse((await fetchBounded(url,1024*1024)).toString('utf8'));
33
+ if(metadata.name!==packageName||metadata.version!==version)throw new Error('npm metadata identity mismatch');
34
+ const tarball=metadata.dist?.tarball;
35
+ const expected='https://registry.npmjs.org/@wonderwhy-er/desktop-commander/-/desktop-commander-'+version+'.tgz';
36
+ if(tarball!==expected)throw new Error('registry tarball URL is not exact pinned package');
37
+ if(!/^sha512-[A-Za-z0-9+/]+=*$/.test(metadata.dist.integrity??''))throw new Error('missing registry SHA512 integrity');
38
+ const tar=await fetchBounded(tarball,32*1024*1024);
39
+ const integrity='sha512-'+createHash('sha512').update(tar).digest('base64');
40
+ if(integrity!==metadata.dist.integrity)throw new Error('npm SHA512 integrity mismatch');
41
+ if(metadata.dist.shasum&&hash(tar,'sha1')!==metadata.dist.shasum)throw new Error('npm SHA1 mismatch');
42
+ const expanded=gunzipSync(tar,{maxOutputLength:128*1024*1024});
43
+ const files=[];let offset=0,total=0;
44
+ const selected=[];
45
+ const names=new Set();
46
+ function cstr(b){return b.toString('utf8').split('\0')[0];}
47
+ while(offset+512<=expanded.length){
48
+ const header=expanded.subarray(offset,offset+512);
49
+ if(header.every(v=>v===0))break;
50
+ const filename=cstr(header.subarray(0,100));
51
+ const prefix=cstr(header.subarray(345,500));
52
+ const name=prefix?prefix+'/'+filename:filename;
53
+ const szText=cstr(header.subarray(124,136)).trim();
54
+ if(!/^[0-7]*$/.test(szText))throw new Error('non-octal tar entry size');
55
+ const size=parseInt(szText||'0',8);
56
+ const type=header[156];
57
+ if(!Number.isSafeInteger(size)||size<0||offset+512+size>expanded.length)throw new Error('corrupt archive boundary');
58
+ if(type===50||type===49)throw new Error('tar link entry denied');
59
+ if(type===0||type===48){
60
+ if(!name.startsWith('package/')||name.includes('\\')||name.includes(':')||
61
+ name.split('/').some(c=>!c||c==='.'||c==='..')||names.has(name))throw new Error('unsafe tar entry '+name);
62
+ names.add(name);files.push({path:name,size});total+=size;
63
+ if(files.length>1000||total>128*1024*1024)throw new Error('tar inventory budget exceeded');
64
+ const rel=name.slice('package/'.length);
65
+ if(/^(?:package\.json|README\.md|LICENSE|LICENCE|dist\/[a-zA-Z0-9_./-]+\.(?:js|mjs|cjs|json|map))$/.test(rel)&&size<=8*1024*1024)
66
+ selected.push({rel,content:Buffer.from(expanded.subarray(offset+512,offset+512+size))});
67
+ }else if(![53,120,103].includes(type))throw new Error('unsupported tar type '+type+' for '+name);
68
+ offset+=512+Math.ceil(size/512)*512;
69
+ }
70
+ const packageEntry=selected.find(e=>e.rel==='package.json');
71
+ if(!packageEntry)throw new Error('tarball has no package.json');
72
+ const packaged=JSON.parse(packageEntry.content.toString('utf8'));
73
+ if(packaged.name!==packageName||packaged.version!==version)throw new Error('tarball package version disagrees with registry metadata');
74
+ await mkdir(path.join(ref,'static'),{recursive:true});
75
+ const archivePath=path.join(ref,'desktop-commander-'+version+'.tgz');
76
+ await saveNew(archivePath,tar);
77
+ let selectedBytes=0;
78
+ for(const e of selected){
79
+ const target=path.join(ref,'static',...e.rel.split('/'));
80
+ await mkdir(path.dirname(target),{recursive:true});
81
+ await saveNew(target,e.content);selectedBytes+=e.content.length;
82
+ }
83
+ const receipt={
84
+ schema:'deadbyte.competitor-reference-acquisition.v1',status:'VERIFIED_STATIC_ONLY',
85
+ package:packageName,version,metadata_source:url,
86
+ source_archive:archivePath,archive_bytes:tar.length,archive_sha256:hash(tar),
87
+ archive_sha512_integrity:integrity,registry_shasum_sha1:metadata.dist.shasum??null,
88
+ files_total:files.length,files_size_bytes:total,files_selected: selected.length,selected_bytes:selectedBytes,
89
+ has_lifecycle_scripts:Boolean(packaged.scripts&&(packaged.scripts.preinstall||packaged.scripts.install||packaged.scripts.postinstall)),
90
+ lifecycle_scripts_executed:false,dependencies_installed:false,remote_started:false,network_action:'registry_https_download_only',
91
+ selected_files_sha256:selected.map(e=>({path:e.rel,sha256:hash(e.content)})),
92
+ full_archive_inventory_sha256:hash(Buffer.from(JSON.stringify(files)))
93
+ };
94
+ await saveNew(path.join(ref,'ACQUISITION.json'),JSON.stringify(receipt,null,2)+'\n');
95
+ console.log(JSON.stringify({status:receipt.status,version,archive_sha256:receipt.archive_sha256,archive_bytes:tar.length,files_total:files.length,files_selected:selected.length,lifecycle_scripts_executed:false,reference_path:ref,source:metadata.dist.tarball},null,2));
@@ -0,0 +1,39 @@
1
+ import {readFile,readdir,open,mkdir} from 'node:fs/promises';
2
+ import {createHash} from 'node:crypto';
3
+ import path from 'node:path';
4
+ import {fileURLToPath} from 'node:url';
5
+ const root=path.resolve(fileURLToPath(new URL('..',import.meta.url)));
6
+ const evidence=path.resolve(root,'..','..','testing','0.15.44-r67','regression-shards');
7
+ const operation='r67audit-20261011c';
8
+ const cases=[];
9
+ const files=(await readdir(path.join(root,'test'))).filter(n=>n.endsWith('.test.mjs'));
10
+ const texts=new Map();for(const file of files)texts.set(file,(await readFile(path.join(root,'test',file),'utf8')).split(/\r?\n/));
11
+ const fileSha=b=>createHash('sha256').update(b).digest('hex');
12
+ for(let index=0;index<32;index++){
13
+ const p=path.join(evidence,operation+'-shard-'+String(index).padStart(2,'0'),'result.json');
14
+ const r=JSON.parse(await readFile(p,'utf8'));
15
+ for(const c of r.nonpass_cases??[]){
16
+ const name=c.name;
17
+ const matches=[];
18
+ for(const [file,lines] of texts){
19
+ for(let line=0;line<lines.length;line++){
20
+ const hay=lines[line];
21
+ const short=name.replace(/^R\d+ /,'').slice(0,40);
22
+ if(hay.includes(name)||hay.includes(short)){
23
+ matches.push({file,line:line+1,context:lines.slice(Math.max(0,line-3),Math.min(lines.length,line+4)).join(' ').slice(0,780)});
24
+ if(matches.length>=5)break;
25
+ }
26
+ }
27
+ if(matches.length>=5)break;
28
+ }
29
+ cases.push({shard:index,name,reason:c.reason,source_matches:matches});
30
+ }
31
+ }
32
+ const summary={schema:'deadbyte.r67-nonpass-source-audit.v1',operation,
33
+ count:cases.length,with_reason:cases.filter(c=>c.reason).length,
34
+ without_reason:cases.filter(c=>!c.reason).length,unmatched:cases.filter(c=>!c.source_matches.length).length,
35
+ cases};
36
+ const out=path.resolve(root,'..','..','testing','0.15.44-r67','R67-NONPASS-SOURCE-AUDIT-20261011.json');
37
+ const h=await open(out,'wx',0o600);try{await h.writeFile(JSON.stringify(summary,null,2)+'\n');await h.sync();}finally{await h.close();}
38
+ console.log(JSON.stringify({count:summary.count,with_reason:summary.with_reason,without_reason:summary.without_reason,
39
+ unmatched:summary.unmatched,findings:cases.filter(c=>!c.reason).map(c=>({shard:c.shard,name:c.name,matches:c.source_matches}))},null,2));
@@ -0,0 +1,48 @@
1
+ import {readdir,readFile,writeFile,mkdir,open} from 'node:fs/promises';
2
+ import {createHash} from 'node:crypto';
3
+ import path from 'node:path';
4
+ import {fileURLToPath} from 'node:url';
5
+ const root=path.resolve(path.dirname(fileURLToPath(import.meta.url)),'..','..','..');
6
+ const refs=path.join(root,'references');
7
+ const stable=path.join(refs,'desktop-commander','dist');
8
+ const alpha=path.join(refs,'desktop-commander-0.3.1-alpha.2','static','dist');
9
+ const output=path.resolve(path.dirname(fileURLToPath(import.meta.url)),'..','docs','R67-ALPHA-STATIC-COMPARISON.json');
10
+ const sha=b=>createHash('sha256').update(b).digest('hex');
11
+ async function inventory(dir,prefix=''){
12
+ const items=await readdir(path.join(dir,prefix),{withFileTypes:true});
13
+ const out=[];
14
+ for(const x of items){
15
+ const sub=[prefix,x.name].filter(Boolean).join('/');
16
+ if(x.isDirectory())out.push(...await inventory(dir,sub));
17
+ else if(x.isFile()&&/\.(?:js|mjs|cjs|json)$/.test(sub)){
18
+ const b=await readFile(path.join(dir,sub));
19
+ out.push({path:sub,sha256:sha(b),bytes:b.length});
20
+ }
21
+ }
22
+ return out;
23
+ }
24
+ const older=await inventory(stable),newer=await inventory(alpha);
25
+ const map=new Map(older.map(f=>[f.path,f]));
26
+ const changes=[];
27
+ for(const f of newer){
28
+ const old=map.get(f.path);
29
+ changes.push({path:f.path,status:!old?'ADDED':old.sha256===f.sha256?'UNCHANGED':'CHANGED',
30
+ stable_sha256:old?.sha256??null,alpha_sha256:f.sha256,delta_bytes:old?f.bytes-old.bytes:null});
31
+ }
32
+ const relevant=changes.filter(x=>/diagnostic|remote-device|annotations|schema|mcp|pdf|process|reconnect|terminal/i.test(x.path));
33
+ const report={
34
+ schema:'deadbyte.r67-competitor-static-compare.v1',
35
+ scope:'static npm archives only; do not execute or install competitor',
36
+ stable_version:'0.2.52',alpha_version:'0.3.1-alpha.2',
37
+ alpha_tarball_sha256:'faaf3f34f114589c0630ce4eaa7114ecc628ce2030822dfe67feac0e17fedc4b',
38
+ stable_compared_files:older.length,alpha_selected_compared_files:newer.length,
39
+ added:changes.filter(x=>x.status==='ADDED').length,
40
+ changed:changes.filter(x=>x.status==='CHANGED').length,
41
+ unchanged:changes.filter(x=>x.status==='UNCHANGED').length,
42
+ removed_from_selected_scope:0,
43
+ relevant_changes:relevant,
44
+ caveat:'Alpha was selectively extracted; do not treat missing alpha inventory as deleted without checking full archive.'
45
+ };
46
+ const handle=await open(output,'wx');
47
+ try{await handle.writeFile(JSON.stringify(report,null,2)+'\n');await handle.sync();}finally{await handle.close();}
48
+ console.log(JSON.stringify({status:'STATIC_DIFFERENTIAL_PASS',stable_files:report.stable_compared_files,alpha_files:report.alpha_selected_compared_files,added:report.added,changed:report.changed,unchanged:report.unchanged,relevant:relevant.filter(x=>x.status!=='UNCHANGED').map(x=>({path:x.path,status:x.status,delta:x.delta_bytes})).slice(0,60)},null,2));
@@ -0,0 +1,23 @@
1
+ import {readFile} from 'node:fs/promises';
2
+ import {spawnSync} from 'node:child_process';
3
+ import path from 'node:path';
4
+ import {fileURLToPath} from 'node:url';
5
+ const root=path.dirname(path.dirname(fileURLToPath(import.meta.url)));
6
+ const op=process.argv[2],shard=process.argv[3];
7
+ if(!/^[a-z0-9._-]{6,64}$/.test(op??'')||!/^(0|[1-9]\d?)$/.test(shard??''))throw new Error('operation and shard required');
8
+ const file=path.resolve(root,'..','..','testing','0.15.44-r67','regression-shards',op+'-shard-'+String(shard).padStart(2,'0'),'intent.json');
9
+ const intent=JSON.parse(await readFile(file,'utf8'));
10
+ if(intent.operation!==op||intent.shard_index!==Number(shard))throw new Error('historical intent mismatch');
11
+ const r=spawnSync(process.execPath,['--test','--test-reporter=tap','--test-concurrency=2',...intent.files],{
12
+ cwd:root,encoding:'utf8',windowsHide:true,shell:false,timeout:60000,maxBuffer:8*1024*1024,
13
+ env:Object.fromEntries(Object.entries(process.env).filter(([k])=>k!=='NODE_TEST_CONTEXT'))
14
+ });
15
+ const output=String(r.stdout??'');
16
+ const lines=output.split(/\r?\n/);
17
+ const failures=[];
18
+ for(let i=0;i<lines.length;i++){
19
+ if(/^(?:not ok |# (?:error|failure)|✖ )/.test(lines[i]))failures.push(lines.slice(Math.max(0,i-1),Math.min(lines.length,i+28)).join('\n').slice(0,4200));
20
+ }
21
+ console.log(JSON.stringify({schema:'deadbyte.r67-diagnostic-replay.v1',role:'NON_RELEASE_TEST_DIAGNOSIS_ONLY',
22
+ from_historical_operation:op,shard:Number(shard),exit_code:r.status,child_error:r.error?.code??null,
23
+ failures:failures.slice(0,20),tail:output.slice(-1800),stderr:String(r.stderr??'').slice(-1000)},null,2));
@@ -0,0 +1,42 @@
1
+ import {readdir,mkdir,open,readFile,rename} from 'node:fs/promises';
2
+ import {spawnSync} from 'node:child_process';
3
+ import {createHash} from 'node:crypto';
4
+ import path from 'node:path';
5
+ import {fileURLToPath} from 'node:url';
6
+ const root=path.dirname(path.dirname(fileURLToPath(import.meta.url)));
7
+ const evidence=path.resolve(root,'../../testing/0.15.44-r67/full-batches');
8
+ const tests=(await readdir(path.join(root,'test'))).filter(n=>n.endsWith('.test.mjs')).sort();
9
+ const size=27;
10
+ const indexRaw=process.argv[2];
11
+ if(!/^(?:0|[1-9]\d*)$/.test(indexRaw??''))throw new Error('batch index required');
12
+ const index=Number(indexRaw);
13
+ const total=Math.ceil(tests.length/size);
14
+ if(!Number.isInteger(index)||index<0||index>=total)throw new Error('batch index out of range');
15
+ await mkdir(evidence,{recursive:true});
16
+ const attempt=process.argv[3]??'initial';
17
+ if(!/^[a-zA-Z0-9_-]{1,24}$/.test(attempt))throw new Error('invalid attempt label');
18
+ const suffix=attempt==='initial'?'':'-'+attempt;
19
+ const file=path.join(evidence,'batch-'+String(index).padStart(2,'0')+suffix+'.json');
20
+ const start=new Date().toISOString();
21
+ const mode=process.argv[4]??'all';
22
+ if(!['all','core','remote'].includes(mode)||(mode!=='all'&&index!==10))throw new Error('invalid batch split mode');
23
+ const window=tests.slice(index*size,(index+1)*size);
24
+ const selected=mode==='core'?window.filter(n=>n!=='remote-session-cli.test.mjs'):mode==='remote'?window.filter(n=>n==='remote-session-cli.test.mjs'):window;
25
+ if(selected.length===0)throw new Error('batch split is empty');
26
+ const sha=s=>createHash('sha256').update(s).digest('hex');
27
+ const identity={schema:'deadbyte.r67-durable-test-batch.v1',batch_index:index,batch_count:total,total_test_files:tests.length,test_files:selected,split_mode:mode,candidate_root:root,started_at_utc:start};
28
+ const staged=await open(file,'wx',0o600);
29
+ try{await staged.writeFile(JSON.stringify({...identity,status:'RUNNING'})+'\n');await staged.sync();}finally{await staged.close();}
30
+ const cmd=['--test','--test-concurrency=4',...selected.map(f=>'test/'+f)];
31
+ const result=spawnSync(process.execPath,cmd,{cwd:root,shell:false,windowsHide:true,encoding:'utf8',timeout:mode==='remote'?180000:90000,maxBuffer:24*1024*1024});
32
+ const output=String(result.stdout??''),error=String(result.stderr??'');
33
+ const count=k=>{const matches=[...output.matchAll(new RegExp('(?:^|\n)[#ℹ ]*'+k+'\\s+(\\d+(?:\\.\\d+)?)','g'))];return matches.length?Number(matches[matches.length-1][1]):null;};
34
+ const testsCount=count('tests'),pass=count('pass'),fail=count('fail'),skip=count('skipped');
35
+ const status=result.status===0&&result.error===undefined&&testsCount!==null&&pass!==null&&fail===0?'PASS':(result.error?.code==='ETIMEDOUT'?'TIMED_OUT':'FAIL');
36
+ const completed={...identity,status,finished_at_utc:new Date().toISOString(),exit_code:result.status,timed_out:result.error?.code==='ETIMEDOUT',observed_test_count:testsCount,passed:pass,failed:fail,skipped:skip,stdout_sha256:sha(Buffer.from(output)),stderr_sha256:sha(Buffer.from(error)),...(status==='PASS'?{}:{failure_tail:(output+'\n'+error).slice(-3500)})};
37
+ const tmp=file+'.finished-'+process.pid;
38
+ const handle=await open(tmp,'wx',0o600);
39
+ try{await handle.writeFile(JSON.stringify(completed,null,2)+'\n');await handle.sync();}finally{await handle.close();}
40
+ await rename(tmp,file);
41
+ console.log(JSON.stringify({batch_index:index,batch_count:total,test_files:selected.length,status,passed:pass,failed:fail,skipped:skip,exit_code:result.status,evidence_path:file},null,2));
42
+ if(status!=='PASS')process.exitCode=1;
@@ -0,0 +1,58 @@
1
+ import {createHash} from 'node:crypto';
2
+ import {readFile,lstat} from 'node:fs/promises';
3
+ import {spawnSync} from 'node:child_process';
4
+ import path from 'node:path';
5
+ import {fileURLToPath} from 'node:url';
6
+ import {parseR67TapSummary} from '../src/r67-regression-shards.mjs';
7
+ const root=path.dirname(path.dirname(fileURLToPath(import.meta.url)));
8
+ const hash=b=>createHash('sha256').update(b).digest('hex');
9
+ const manifest=JSON.parse(await readFile(path.join(root,'docs','R67-NATIVE-INSPECT-BINARY.json'),'utf8'));
10
+ const binary=path.join(root,manifest.exe);
11
+ const info=await lstat(binary);
12
+ if(manifest.schema!=='deadbyte.r67-native-inspector-binary.v1'||!info.isFile()||info.isSymbolicLink()||hash(await readFile(binary))!==manifest.sha256)throw new Error('R67 native observer hash pin invalid');
13
+ const specs=[
14
+ 'test/r67-native-inspector.test.mjs',
15
+ 'test/r67-signed-receipt.test.mjs',
16
+ 'test/r67-cli-integration.test.mjs',
17
+ 'test/r67-diagnostics.test.mjs',
18
+ 'test/r67-diagnostics-cli.test.mjs',
19
+ 'test/r67-diagnostics-zip-oracle.test.mjs',
20
+ 'test/r67-diagnostics-verify.test.mjs',
21
+ 'test/r67-regression-shards.test.mjs',
22
+ 'test/r67-evidence-reconcile.test.mjs',
23
+ 'test/r67-skip-rationale.test.mjs',
24
+ 'test/r67-runtime-observation-binding.test.mjs',
25
+ 'test/r67-native-observation-authority.test.mjs',
26
+ 'test/r67-server-observation-wiring.test.mjs',
27
+ 'test/r67-machine-fs-smoke-epoch.test.mjs',
28
+ 'test/r67-isolated-slot-rollback-restore.test.mjs',
29
+ 'test/r65-epoch-native-activation-integration.test.mjs',
30
+ 'test/machine-identity.test.mjs',
31
+ 'test/r67-tool-annotations.test.mjs',
32
+ 'test/remote-live-log-r36.test.mjs',
33
+ 'test/remote-live-log-r37.test.mjs',
34
+ 'test/r67-live-log-secret-canary.test.mjs',
35
+ 'test/r51-live-log-polling.test.mjs',
36
+ 'test/cli-entrypoint.test.mjs',
37
+ 'test/observation-runtime.test.mjs',
38
+ 'test/observation-mcp-tools.test.mjs',
39
+ 'test/windows-observation-r48.test.mjs',
40
+ 'test/r67-release-contract.test.mjs',
41
+ 'test/r67-npm-cross-volume.test.mjs',
42
+ 'test/r67-npm-publish-gate.test.mjs',
43
+ 'test/r65-npm-publication.test.mjs'
44
+ ];
45
+ const args=['--test','--test-concurrency=1',...specs];
46
+ const result=spawnSync(process.execPath,args,{cwd:root,encoding:'utf8',windowsHide:true,shell:false,timeout:180000,maxBuffer:16*1024*1024});
47
+ const stdout=String(result.stdout??'');
48
+ const stderr=String(result.stderr??'');
49
+ const tap=parseR67TapSummary(stdout);
50
+ const counts=tap?{tests:tap.tests,pass:tap.pass,fail:tap.fail,skipped:tap.skipped,cancelled:tap.cancelled,todo:tap.todo}:null;
51
+ const complete=Boolean(tap&&tap.tests>=specs.length&&tap.fail===0&&tap.skipped===0&&tap.cancelled===0&&tap.todo===0&&result.status===0&&!result.error);
52
+ const receipt={schema:'deadbyte.r67-focused-gate.v1',status:complete?'pass':'fail',
53
+ candidate_version:'0.15.44-draft',predecessor_manifest_sha256:'4c4a64a4c8e9f5a6e9eecce85fd0007ebcac99121b29c07f1a1fc81d1643cd33',
54
+ native_exe_sha256:manifest.sha256,tests:specs,summary:counts,exit_code:result.status,timed_out:result.error?.code==='ETIMEDOUT',
55
+ stdout_sha256:hash(Buffer.from(stdout,'utf8')),stderr_sha256:hash(Buffer.from(stderr,'utf8'))};
56
+ console.log(JSON.stringify(receipt,null,2));
57
+ if(result.status!==0){console.error('TEST_OUTPUT_TAIL\n'+stdout.slice(-15000));console.error('TEST_ERROR_TAIL\n'+stderr.slice(-4000));}
58
+ if(!complete)process.exitCode=1;