deadbyte-mcp 0.15.74 → 0.15.76

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 (109) hide show
  1. package/MANIFEST.SHA256 +108 -42
  2. package/PROVENANCE.json +20 -22
  3. package/README.txt +23 -18
  4. package/RELEASE.json +69 -18
  5. package/SBOM.cdx.json +2 -2
  6. package/TEST-MATRIX.json +32 -2
  7. package/bin/deadbyte-desktop-uia-r199-fixed.exe +0 -0
  8. package/bin/deadbyte-desktop-uia-r199-fixed.obj +0 -0
  9. package/bin/deadbyte-desktop-uia-r199.exe +0 -0
  10. package/bin/deadbyte-desktop-uia-r199.obj +0 -0
  11. package/bin/deadbyte-fs-read-r197-fixed.exe +0 -0
  12. package/bin/deadbyte-fs-read-r198.exe +0 -0
  13. package/bin/deadbyte-fs-read-r198.obj +0 -0
  14. package/bin/deadbyte-root-relative-probe-r197.exe +0 -0
  15. package/bridge/package.json +1 -1
  16. package/controller/deadbyte-process-policy.json +4 -4
  17. package/docs/R184-package-lock.json +2 -8
  18. package/native/deadbyte-desktop-uia-r199.cpp +345 -0
  19. package/native/deadbyte-fs-read-r197.cpp +174 -0
  20. package/native/deadbyte-fs-read-r198.cpp +181 -0
  21. package/native/deadbyte-root-relative-probe-r197.cpp +97 -0
  22. package/package.json +5 -2
  23. package/scripts/build-native-desktop-uia-r199-fixed.ps1 +28 -0
  24. package/scripts/build-native-desktop-uia-r199.ps1 +28 -0
  25. package/scripts/build-native-fs-read-r197-fixed.ps1 +28 -0
  26. package/scripts/build-native-fs-read-r197.ps1 +28 -0
  27. package/scripts/build-native-fs-read-r198.ps1 +28 -0
  28. package/scripts/build-native-root-probe-r197.ps1 +28 -0
  29. package/scripts/gate-windows-r195.ps1 +114 -0
  30. package/scripts/gate-windows-r206.ps1 +116 -0
  31. package/scripts/gate-windows-r207.ps1 +104 -0
  32. package/scripts/init-desktop-policy-r199.ps1 +85 -0
  33. package/scripts/npm-release-r48.mjs +27 -0
  34. package/scripts/npm-release-readiness-r195.mjs +72 -0
  35. package/scripts/npm-release-readiness-r206.mjs +76 -0
  36. package/scripts/npm-release-readiness-r207.mjs +76 -0
  37. package/scripts/r193-owner-request-live.mjs +8 -7
  38. package/scripts/r193-owner-uac-broker.mjs +6 -5
  39. package/scripts/r205-candidate-selection.mjs +22 -0
  40. package/src/candidate-selection-evidence-r206.mjs +71 -0
  41. package/src/candidate-selection-r205.mjs +96 -0
  42. package/src/desktop-postcondition-r196.mjs +30 -0
  43. package/src/desktop-runtime-r40.mjs +44 -7
  44. package/src/desktop-uia-identity-r199.mjs +51 -0
  45. package/src/desktop-uia-r40.mjs +9 -1
  46. package/src/machine-fs-handle-read-r196.mjs +43 -0
  47. package/src/machine-fs-native-read-r197.mjs +73 -0
  48. package/src/machine-fs-native-read-r198.mjs +76 -0
  49. package/src/machine-fs-read-worker.mjs +5 -25
  50. package/src/machine-fs.mjs +31 -16
  51. package/src/r195-canonical-owner-observation.mjs +15 -0
  52. package/src/r207-owner-enrollment-io.mjs +30 -0
  53. package/src/remote-destination-journal-r202.mjs +120 -0
  54. package/src/remote-device-r44.mjs +89 -14
  55. package/src/remote-payload-boundary-r201.mjs +71 -0
  56. package/src/remote-terminal-evidence-r200.mjs +60 -0
  57. package/src/version.mjs +1 -1
  58. package/test/desktop-runtime-r40.test.mjs +111 -0
  59. package/test/desktop-uia-r40.test.mjs +15 -0
  60. package/test/fixtures/r197-junction-swap-worker.mjs +21 -0
  61. package/test/fixtures/r203-journal-writer.mjs +6 -0
  62. package/test/process-policy-refresh.test.mjs +4 -4
  63. package/test/r130-release-security-contract.test.mjs +8 -8
  64. package/test/r132-release-identity.test.mjs +7 -7
  65. package/test/r153-prepublish-identity.test.mjs +1 -1
  66. package/test/r160-release-contract.test.mjs +3 -3
  67. package/test/r165-live-cli-skew.test.mjs +1 -1
  68. package/test/r167-release-contract.test.mjs +11 -11
  69. package/test/r168-release-contract.test.mjs +4 -4
  70. package/test/r172-release-contract.test.mjs +6 -6
  71. package/test/r173-release-contract.test.mjs +16 -16
  72. package/test/r179-release-contract.test.mjs +12 -12
  73. package/test/r190-release-contract.test.mjs +10 -10
  74. package/test/r191-release-contract.test.mjs +12 -12
  75. package/test/r192-release-identity.test.mjs +9 -9
  76. package/test/r193-release-identity.test.mjs +24 -22
  77. package/test/r193-release-readiness.test.mjs +2 -2
  78. package/test/r193-windows-gate.test.mjs +10 -10
  79. package/test/r194-release-identity.test.mjs +19 -15
  80. package/test/r194-release-readiness.test.mjs +3 -3
  81. package/test/r194-windows-gate.test.mjs +9 -8
  82. package/test/r195-canonical-owner-observation.test.mjs +32 -0
  83. package/test/r195-release-readiness.test.mjs +22 -0
  84. package/test/r196-desktop-postcondition.test.mjs +53 -0
  85. package/test/r196-handle-bound-read.test.mjs +99 -0
  86. package/test/r196-remote-outcome.test.mjs +94 -0
  87. package/test/r197-namespace-race.test.mjs +41 -0
  88. package/test/r197-native-dispatch-race.test.mjs +49 -0
  89. package/test/r197-native-file-read.test.mjs +60 -0
  90. package/test/r197-native-root-open.test.mjs +61 -0
  91. package/test/r198-root-identity.test.mjs +88 -0
  92. package/test/r199-native-uia-worker.test.mjs +28 -0
  93. package/test/r199-uia-identity.test.mjs +43 -0
  94. package/test/r200-remote-reconcile.test.mjs +106 -0
  95. package/test/r201-payload-boundary.test.mjs +78 -0
  96. package/test/r201-payload-fuzz.test.mjs +37 -0
  97. package/test/r201-tool-boundary-fuzz.test.mjs +120 -0
  98. package/test/r202-destination-journal.test.mjs +92 -0
  99. package/test/r203-atomic-journal.test.mjs +86 -0
  100. package/test/r205-candidate-selection-cli.test.mjs +31 -0
  101. package/test/r205-candidate-selection.test.mjs +83 -0
  102. package/test/r206-candidate-evidence.test.mjs +64 -0
  103. package/test/r206-release-contract.test.mjs +42 -0
  104. package/test/r206-release-readiness.test.mjs +23 -0
  105. package/test/r207-owner-enrollment-io.test.mjs +37 -0
  106. package/test/r207-release-contract.test.mjs +51 -0
  107. package/test/r207-release-readiness.test.mjs +23 -0
  108. package/test/r59-tool-surface-compat.test.mjs +1 -1
  109. package/test/r64-machine-fs-large-read.test.mjs +26 -12
@@ -0,0 +1,28 @@
1
+ #requires -Version 5.1
2
+ [CmdletBinding()]
3
+ param([Parameter(Mandatory=$true)][ValidatePattern('^[0-9a-f]{64}$')][string]$SourceSha256)
4
+ Set-StrictMode -Version Latest
5
+ $ErrorActionPreference='Stop'
6
+ $repo=Split-Path -Parent $PSScriptRoot
7
+ $src=Join-Path $repo 'native\deadbyte-root-relative-probe-r197.cpp'
8
+ $actual=(Get-FileHash -LiteralPath $src -Algorithm SHA256).Hash.ToLowerInvariant()
9
+ if($actual -cne $SourceSha256){throw 'R197_NATIVE_SOURCE_HASH_DRIFT'}
10
+ $vswhere='C:\Program Files (x86)\Microsoft Visual Studio\Installer\vswhere.exe'
11
+ if(!(Test-Path -LiteralPath $vswhere)){throw 'R197_MSVC_UNAVAILABLE'}
12
+ $install=(& $vswhere -latest -products * -requires Microsoft.VisualStudio.Component.VC.Tools.x86.x64 -property installationPath | Select-Object -First 1)
13
+ if(!$install){throw 'R197_MSVC_TOOLCHAIN_MISSING'}
14
+ $dev=Join-Path $install 'Common7\Tools\VsDevCmd.bat'
15
+ $bin=Join-Path $repo 'bin'
16
+ $exe=Join-Path $bin 'deadbyte-root-relative-probe-r197.exe'
17
+ $obj=Join-Path $bin 'deadbyte-root-relative-probe-r197.obj'
18
+ if(Test-Path -LiteralPath $exe){throw 'R197_NATIVE_OUTPUT_EXISTS'}
19
+ if(Test-Path -LiteralPath $obj){throw 'R197_NATIVE_OBJECT_EXISTS'}
20
+ $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'
21
+ $compile='cl {0} "{1}" /Fo:"{2}" /Fe:"{3}" /link /Brepro /INCREMENTAL:NO' -f $common,$src,$obj,$exe
22
+ $cmd=Join-Path $env:SystemRoot 'System32\cmd.exe'
23
+ $line='call "{0}" -no_logo -arch=x64 -host_arch=x64 && {1}' -f $dev,$compile
24
+ & $cmd /d /s /c $line
25
+ if($LASTEXITCODE -ne 0){throw ('R197_NATIVE_COMPILATION_FAIL exit='+$LASTEXITCODE)}
26
+ if(!(Test-Path -LiteralPath $exe -PathType Leaf)){throw 'R197_NATIVE_OUTPUT_MISSING'}
27
+ $hash=(Get-FileHash -LiteralPath $exe -Algorithm SHA256).Hash.ToLowerInvariant()
28
+ Write-Output ('R197_NATIVE_BUILD_PASS exe_sha256='+$hash)
@@ -0,0 +1,114 @@
1
+ #requires -Version 5.1
2
+ [CmdletBinding()]
3
+ param(
4
+ [ValidateSet('preflight','focused','full','manifest','doctor','all')][string]$Stage='preflight'
5
+ )
6
+ Set-StrictMode -Version Latest
7
+ $ErrorActionPreference='Stop'
8
+ $repo=Split-Path -Parent $PSScriptRoot
9
+ $productionState=Join-Path $env:USERPROFILE '.deadbyte-mcp'
10
+ $parentId='v0.15.74-e84bf4eed16e9443'
11
+ $parentSha='e84bf4eed16e9443fbd0bf9f0f562e26b01db778647aefcc8b12fd7f48636b47'
12
+ $parentGen='598f896be9ce65e6b0c618e8c8f6eaa2a9d91617a76a146bf3deb385a56d19e7'
13
+ $parentTarball='5da436a3f8068107e74caf6da58ff1e211d4a62f94266853136b601762f36f0c'
14
+ $nativeNode='C:\Program Files\nodejs\node.exe'
15
+ $node=if(Test-Path -LiteralPath $nativeNode -PathType Leaf){$nativeNode}else{(Get-Command node -ErrorAction Stop).Source}
16
+ function Sha([string]$file){
17
+ $sha=[Security.Cryptography.SHA256]::Create()
18
+ try{$stream=[IO.File]::OpenRead($file);try{return ([BitConverter]::ToString($sha.ComputeHash($stream))).Replace('-','').ToLowerInvariant()}finally{$stream.Dispose()}}finally{$sha.Dispose()}
19
+ }
20
+ function Need([bool]$condition,[string]$message){if(-not $condition){throw $message}}
21
+ function Run-Node([string]$label,[string[]]$nodeArgs){
22
+ Need ($null -ne $nodeArgs -and $nodeArgs.Count -gt 0) "R195_${label}_NO_NODE_ARGUMENTS"
23
+ Write-Output "R195_STAGE_START=$label"
24
+ $global:LASTEXITCODE=0
25
+ & $node @nodeArgs
26
+ $exit=$global:LASTEXITCODE
27
+ if($exit -ne 0){throw "R195_${label}_FAILED exit=$exit"}
28
+ Write-Output "R195_STAGE_PASS=$label"
29
+ }
30
+ Push-Location $repo
31
+ $previousExpectedDevelopmentRoot=$env:DEADBYTE_EXPECTED_DEVELOPMENT_ROOT
32
+ try{
33
+ $pkg=Get-Content -LiteralPath 'package.json' -Raw | ConvertFrom-Json
34
+ $release=Get-Content -LiteralPath 'RELEASE.json' -Raw | ConvertFrom-Json
35
+ Need (-not [string]::IsNullOrWhiteSpace([string]$release.r195.development_policy_root)) 'R195_DEVELOPMENT_PROVENANCE_ROOT_MISSING'
36
+ $env:DEADBYTE_EXPECTED_DEVELOPMENT_ROOT=[IO.Path]::GetFullPath([string]$release.r195.development_policy_root)
37
+ Need ($pkg.version -eq '0.15.75' -and $release.version -eq '0.15.75' -and $release.train -eq 'R195') 'R195_CANDIDATE_VERSION_DRIFT'
38
+ Need ($release.source_predecessor.version -eq '0.15.74' -and $release.source_predecessor.train -eq 'R194') 'R195_SOURCE_PREDECESSOR_VERSION_DRIFT'
39
+ Need ($release.source_predecessor.manifest_sha256 -eq $parentSha -and $release.source_predecessor.tarball_sha256 -eq $parentTarball) 'R195_SOURCE_PREDECESSOR_IDENTITY_DRIFT'
40
+ Need ($release.runtime_predecessor.release_id -eq $parentId -and $release.runtime_predecessor.manifest_sha256 -eq $parentSha -and $release.runtime_predecessor.generation_manifest_sha256 -eq $parentGen) 'R195_RUNTIME_PREDECESSOR_IDENTITY_DRIFT'
41
+ $active=Get-Content -LiteralPath (Join-Path $productionState 'active-release.json') -Raw | ConvertFrom-Json
42
+ Need ($active.version -eq '0.15.74' -and $active.release_id -eq $parentId -and $active.manifest_sha256 -eq $parentSha -and $active.generation_manifest_sha256 -eq $parentGen) 'R195_ACTIVE_RUNTIME_DRIFT'
43
+ Need ((Sha (Join-Path $active.release_root 'MANIFEST.SHA256')) -eq $parentSha) 'R195_ACTIVE_MANIFEST_MISMATCH'
44
+ Write-Output 'R195_PREDECESSOR_PREFLIGHT=PASS'
45
+ if($Stage -eq 'preflight'){return}
46
+ if($Stage -in @('focused','all')){
47
+ $focused=@(
48
+ 'test/r70-owner-approval.test.mjs',
49
+ 'test/r89-privileged-install-boundary.test.mjs',
50
+ 'test/r186-controller-owner-grant.test.mjs',
51
+ 'test/r186-owner-consent-preflight.test.mjs',
52
+ 'test/r186-owner-enrollment.test.mjs',
53
+ 'test/r186-owner-grant-broker.test.mjs',
54
+ 'test/r186-owner-local-signing.test.mjs',
55
+ 'test/r186-owner-request.test.mjs',
56
+ 'test/r186-owner-review-export.test.mjs',
57
+ 'test/r188-owner-uac.test.mjs',
58
+ 'test/r188-uac-boundary.test.mjs',
59
+ 'test/r193-limited-migration-contract.test.mjs',
60
+ 'test/r193-live-owner-subject.test.mjs',
61
+ 'test/r193-native-process-observer.test.mjs',
62
+ 'test/r193-native-token.test.mjs',
63
+ 'test/r193-owner-enrollment-entrypoint.test.mjs',
64
+ 'test/r193-owner-secret-acl.test.mjs',
65
+ 'test/r193-owner-uac-broker.test.mjs',
66
+ 'test/r193-owner-uac-entrypoint.test.mjs',
67
+ 'test/r193-release-readiness.test.mjs',
68
+ 'test/r193-release-identity.test.mjs',
69
+ 'test/r194-release-identity.test.mjs',
70
+ 'test/r194-release-readiness.test.mjs',
71
+ 'test/r193-uac-r70-bridge.test.mjs',
72
+ 'test/r194-windows-gate.test.mjs',
73
+ 'test/r194-npm-auth-recovery.test.mjs',
74
+ 'test/r194-npm-preauth.test.mjs'
75
+ 'test/r195-canonical-owner-observation.test.mjs'
76
+ 'test/r195-release-readiness.test.mjs'
77
+ )
78
+ Run-Node -label 'focused' -nodeArgs (@('--test','--test-reporter=tap','--test-concurrency=1')+$focused)
79
+ if($Stage -eq 'focused'){return}
80
+ }
81
+ if($Stage -in @('full','all')){
82
+ $previousCrossVolume=$env:DEADBYTE_TEST_CROSS_VOLUME_ROOT
83
+ $tempDrive=[IO.Path]::GetPathRoot([IO.Path]::GetFullPath($env:TEMP))
84
+ $scratchDrive=if($tempDrive -ieq 'D:\'){'C:\'}else{'D:\'}
85
+ Need (Test-Path -LiteralPath $scratchDrive -PathType Container) 'R195_CROSS_VOLUME_DRIVE_UNAVAILABLE'
86
+ $crossVolume=Join-Path $scratchDrive 'DEADBYTE-R195-CrossVolume'
87
+ try{
88
+ [IO.Directory]::CreateDirectory($crossVolume)|Out-Null
89
+ $env:DEADBYTE_TEST_CROSS_VOLUME_ROOT=$crossVolume
90
+ Run-Node -label 'full' -nodeArgs @('--test','--test-reporter=tap','--test-concurrency=4','test/*.test.mjs')
91
+ }finally{$env:DEADBYTE_TEST_CROSS_VOLUME_ROOT=$previousCrossVolume}
92
+ if($Stage -eq 'full'){return}
93
+ }
94
+ if($Stage -in @('manifest','all')){
95
+ Run-Node -label 'manifest' -nodeArgs @('scripts/release-manifest.mjs','verify')
96
+ if($Stage -eq 'manifest'){return}
97
+ }
98
+ if($Stage -in @('doctor','all')){
99
+ $previousStateRoot=$env:DEADBYTE_STATE_ROOT
100
+ $isolated=Join-Path $env:TEMP ('deadbyte-r195-doctor-'+[guid]::NewGuid().ToString('N'))
101
+ try{
102
+ [IO.Directory]::CreateDirectory($isolated)|Out-Null
103
+ $env:DEADBYTE_STATE_ROOT=$isolated
104
+ Run-Node -label 'isolated_doctor' -nodeArgs @('src/deadbyte-cli.mjs','doctor')
105
+ }finally{
106
+ $env:DEADBYTE_STATE_ROOT=$previousStateRoot
107
+ Remove-Item -LiteralPath $isolated -Recurse -Force -ErrorAction SilentlyContinue
108
+ }
109
+ }
110
+ Write-Output 'R195_WINDOWS_CANDIDATE_GATE=PASS_PREPUBLICATION'
111
+ }finally{
112
+ $env:DEADBYTE_EXPECTED_DEVELOPMENT_ROOT=$previousExpectedDevelopmentRoot
113
+ Pop-Location
114
+ }
@@ -0,0 +1,116 @@
1
+ #requires -Version 5.1
2
+ [CmdletBinding()]
3
+ param(
4
+ [ValidateSet('preflight','focused','full','manifest','doctor','all')][string]$Stage='preflight'
5
+ )
6
+ Set-StrictMode -Version Latest
7
+ $ErrorActionPreference='Stop'
8
+ $repo=Split-Path -Parent $PSScriptRoot
9
+ $productionState=Join-Path $env:USERPROFILE '.deadbyte-mcp'
10
+ $parentId='v0.15.74-e84bf4eed16e9443'
11
+ $parentSha='e84bf4eed16e9443fbd0bf9f0f562e26b01db778647aefcc8b12fd7f48636b47'
12
+ $parentGen='598f896be9ce65e6b0c618e8c8f6eaa2a9d91617a76a146bf3deb385a56d19e7'
13
+ $parentTarball='5da436a3f8068107e74caf6da58ff1e211d4a62f94266853136b601762f36f0c'
14
+ $nativeNode='C:\Program Files\nodejs\node.exe'
15
+ $node=if(Test-Path -LiteralPath $nativeNode -PathType Leaf){$nativeNode}else{(Get-Command node -ErrorAction Stop).Source}
16
+ function Sha([string]$file){
17
+ $sha=[Security.Cryptography.SHA256]::Create()
18
+ try{$stream=[IO.File]::OpenRead($file);try{return ([BitConverter]::ToString($sha.ComputeHash($stream))).Replace('-','').ToLowerInvariant()}finally{$stream.Dispose()}}finally{$sha.Dispose()}
19
+ }
20
+ function Need([bool]$condition,[string]$message){if(-not $condition){throw $message}}
21
+ function Run-Node([string]$label,[string[]]$nodeArgs){
22
+ Need ($null -ne $nodeArgs -and $nodeArgs.Count -gt 0) "R206_${label}_NO_NODE_ARGUMENTS"
23
+ Write-Output "R206_STAGE_START=$label"
24
+ $global:LASTEXITCODE=0
25
+ & $node @nodeArgs
26
+ $exit=$global:LASTEXITCODE
27
+ if($exit -ne 0){throw "R206_${label}_FAILED exit=$exit"}
28
+ Write-Output "R206_STAGE_PASS=$label"
29
+ }
30
+ Push-Location $repo
31
+ $previousExpectedDevelopmentRoot=$env:DEADBYTE_EXPECTED_DEVELOPMENT_ROOT
32
+ try{
33
+ $pkg=Get-Content -LiteralPath 'package.json' -Raw | ConvertFrom-Json
34
+ $release=Get-Content -LiteralPath 'RELEASE.json' -Raw | ConvertFrom-Json
35
+ Need (-not [string]::IsNullOrWhiteSpace([string]$release.r206.development_policy_root)) 'R206_DEVELOPMENT_PROVENANCE_ROOT_MISSING'
36
+ $env:DEADBYTE_EXPECTED_DEVELOPMENT_ROOT=[IO.Path]::GetFullPath([string]$release.r206.development_policy_root)
37
+ Need ($pkg.version -eq '0.15.75' -and $release.version -eq '0.15.75' -and $release.train -eq 'R206') 'R206_CANDIDATE_VERSION_DRIFT'
38
+ Need ($release.source_predecessor.version -eq '0.15.75' -and $release.source_predecessor.train -eq 'R205') 'R206_SOURCE_PREDECESSOR_VERSION_DRIFT'
39
+ Need ($release.source_predecessor.manifest_sha256 -eq '166eebde18d53a9ec46f738383c289733f9cd37918b3572b7515d1ab9b122c92' -and $null -eq $release.source_predecessor.tarball_sha256) 'R206_SOURCE_PREDECESSOR_IDENTITY_DRIFT'
40
+ Need ($release.runtime_predecessor.release_id -eq $parentId -and $release.runtime_predecessor.manifest_sha256 -eq $parentSha -and $release.runtime_predecessor.generation_manifest_sha256 -eq $parentGen) 'R206_RUNTIME_PREDECESSOR_IDENTITY_DRIFT'
41
+ $active=Get-Content -LiteralPath (Join-Path $productionState 'active-release.json') -Raw | ConvertFrom-Json
42
+ Need ($active.version -eq '0.15.74' -and $active.release_id -eq $parentId -and $active.manifest_sha256 -eq $parentSha -and $active.generation_manifest_sha256 -eq $parentGen) 'R206_ACTIVE_RUNTIME_DRIFT'
43
+ Need ((Sha (Join-Path $active.release_root 'MANIFEST.SHA256')) -eq $parentSha) 'R206_ACTIVE_MANIFEST_MISMATCH'
44
+ Write-Output 'R206_PREDECESSOR_PREFLIGHT=PASS'
45
+ if($Stage -eq 'preflight'){return}
46
+ if($Stage -in @('focused','all')){
47
+ $focused=@(
48
+ 'test/r70-owner-approval.test.mjs',
49
+ 'test/r89-privileged-install-boundary.test.mjs',
50
+ 'test/r186-controller-owner-grant.test.mjs',
51
+ 'test/r186-owner-consent-preflight.test.mjs',
52
+ 'test/r186-owner-enrollment.test.mjs',
53
+ 'test/r186-owner-grant-broker.test.mjs',
54
+ 'test/r186-owner-local-signing.test.mjs',
55
+ 'test/r186-owner-request.test.mjs',
56
+ 'test/r186-owner-review-export.test.mjs',
57
+ 'test/r188-owner-uac.test.mjs',
58
+ 'test/r188-uac-boundary.test.mjs',
59
+ 'test/r193-limited-migration-contract.test.mjs',
60
+ 'test/r193-live-owner-subject.test.mjs',
61
+ 'test/r193-native-process-observer.test.mjs',
62
+ 'test/r193-native-token.test.mjs',
63
+ 'test/r193-owner-enrollment-entrypoint.test.mjs',
64
+ 'test/r193-owner-secret-acl.test.mjs',
65
+ 'test/r193-owner-uac-broker.test.mjs',
66
+ 'test/r193-owner-uac-entrypoint.test.mjs',
67
+ 'test/r193-release-readiness.test.mjs',
68
+ 'test/r193-release-identity.test.mjs',
69
+ 'test/r194-release-identity.test.mjs',
70
+ 'test/r194-release-readiness.test.mjs',
71
+ 'test/r193-uac-r70-bridge.test.mjs',
72
+ 'test/r194-windows-gate.test.mjs',
73
+ 'test/r194-npm-auth-recovery.test.mjs',
74
+ 'test/r194-npm-preauth.test.mjs'
75
+ 'test/r195-canonical-owner-observation.test.mjs'
76
+ 'test/r206-candidate-evidence.test.mjs'
77
+ 'test/r206-release-contract.test.mjs'
78
+ 'test/r206-release-readiness.test.mjs'
79
+ )
80
+ Run-Node -label 'focused' -nodeArgs (@('--test','--test-reporter=tap','--test-concurrency=1')+$focused)
81
+ if($Stage -eq 'focused'){return}
82
+ }
83
+ if($Stage -in @('full','all')){
84
+ $previousCrossVolume=$env:DEADBYTE_TEST_CROSS_VOLUME_ROOT
85
+ $tempDrive=[IO.Path]::GetPathRoot([IO.Path]::GetFullPath($env:TEMP))
86
+ $scratchDrive=if($tempDrive -ieq 'D:\'){'C:\'}else{'D:\'}
87
+ Need (Test-Path -LiteralPath $scratchDrive -PathType Container) 'R206_CROSS_VOLUME_DRIVE_UNAVAILABLE'
88
+ $crossVolume=Join-Path $scratchDrive 'DEADBYTE-R206-CrossVolume'
89
+ try{
90
+ [IO.Directory]::CreateDirectory($crossVolume)|Out-Null
91
+ $env:DEADBYTE_TEST_CROSS_VOLUME_ROOT=$crossVolume
92
+ Run-Node -label 'full' -nodeArgs @('--test','--test-reporter=tap','--test-concurrency=4','test/*.test.mjs')
93
+ }finally{$env:DEADBYTE_TEST_CROSS_VOLUME_ROOT=$previousCrossVolume}
94
+ if($Stage -eq 'full'){return}
95
+ }
96
+ if($Stage -in @('manifest','all')){
97
+ Run-Node -label 'manifest' -nodeArgs @('scripts/release-manifest.mjs','verify')
98
+ if($Stage -eq 'manifest'){return}
99
+ }
100
+ if($Stage -in @('doctor','all')){
101
+ $previousStateRoot=$env:DEADBYTE_STATE_ROOT
102
+ $isolated=Join-Path $env:TEMP ('deadbyte-r206-doctor-'+[guid]::NewGuid().ToString('N'))
103
+ try{
104
+ [IO.Directory]::CreateDirectory($isolated)|Out-Null
105
+ $env:DEADBYTE_STATE_ROOT=$isolated
106
+ Run-Node -label 'isolated_doctor' -nodeArgs @('src/deadbyte-cli.mjs','doctor')
107
+ }finally{
108
+ $env:DEADBYTE_STATE_ROOT=$previousStateRoot
109
+ Remove-Item -LiteralPath $isolated -Recurse -Force -ErrorAction SilentlyContinue
110
+ }
111
+ }
112
+ Write-Output 'R206_WINDOWS_CANDIDATE_GATE=PASS_PREPUBLICATION'
113
+ }finally{
114
+ $env:DEADBYTE_EXPECTED_DEVELOPMENT_ROOT=$previousExpectedDevelopmentRoot
115
+ Pop-Location
116
+ }
@@ -0,0 +1,104 @@
1
+ #requires -Version 5.1
2
+ [CmdletBinding()]
3
+ param(
4
+ [ValidateSet('preflight','focused','full','manifest','doctor','all')][string]$Stage='preflight'
5
+ )
6
+ Set-StrictMode -Version Latest
7
+ $ErrorActionPreference='Stop'
8
+ $repo=Split-Path -Parent $PSScriptRoot
9
+ $productionState=Join-Path $env:USERPROFILE '.deadbyte-mcp'
10
+ $parentId='v0.15.75-9039fff265696091'
11
+ $parentSha='9039fff265696091f9217ba4f19526c6c74a967f9ff48b75ac6e340b5f431248'
12
+ $parentGen='83a212e01173c73f78cff2a6d26e6f3f50f476a8c0ea3cbbf592a466071909e9'
13
+ $parentTarball='c2ebb079e7725f3a2f2c7d8f98ef42059e94e51f402d99c1825f46e020237ee9'
14
+ $nativeNode='C:\Program Files\nodejs\node.exe'
15
+ $node=if(Test-Path -LiteralPath $nativeNode -PathType Leaf){$nativeNode}else{(Get-Command node -ErrorAction Stop).Source}
16
+ function Sha([string]$file){
17
+ $sha=[Security.Cryptography.SHA256]::Create()
18
+ try{$stream=[IO.File]::OpenRead($file);try{return ([BitConverter]::ToString($sha.ComputeHash($stream))).Replace('-','').ToLowerInvariant()}finally{$stream.Dispose()}}finally{$sha.Dispose()}
19
+ }
20
+ function Need([bool]$condition,[string]$message){if(-not $condition){throw $message}}
21
+ function Run-Node([string]$label,[string[]]$nodeArgs){
22
+ Need ($null -ne $nodeArgs -and $nodeArgs.Count -gt 0) "R207_${label}_NO_NODE_ARGUMENTS"
23
+ Write-Output "R207_STAGE_START=$label"
24
+ $global:LASTEXITCODE=0
25
+ & $node @nodeArgs
26
+ $exit=$global:LASTEXITCODE
27
+ if($exit -ne 0){throw "R207_${label}_FAILED exit=$exit"}
28
+ Write-Output "R207_STAGE_PASS=$label"
29
+ }
30
+ Push-Location $repo
31
+ $previousExpectedDevelopmentRoot=$env:DEADBYTE_EXPECTED_DEVELOPMENT_ROOT
32
+ try{
33
+ $pkg=Get-Content -LiteralPath 'package.json' -Raw | ConvertFrom-Json
34
+ $release=Get-Content -LiteralPath 'RELEASE.json' -Raw | ConvertFrom-Json
35
+ Need (-not [string]::IsNullOrWhiteSpace([string]$release.r207.development_policy_root)) 'R207_DEVELOPMENT_PROVENANCE_ROOT_MISSING'
36
+ $env:DEADBYTE_EXPECTED_DEVELOPMENT_ROOT=[IO.Path]::GetFullPath([string]$release.r207.development_policy_root)
37
+ Need ($pkg.version -eq '0.15.76' -and $release.version -eq '0.15.76' -and $release.train -eq 'R207') 'R207_CANDIDATE_VERSION_DRIFT'
38
+ Need ($release.source_predecessor.version -eq '0.15.75' -and $release.source_predecessor.train -eq 'R206') 'R207_SOURCE_PREDECESSOR_VERSION_DRIFT'
39
+ Need ($release.source_predecessor.manifest_sha256 -eq $parentSha -and $release.source_predecessor.tarball_sha256 -eq $parentTarball) 'R207_SOURCE_PREDECESSOR_IDENTITY_DRIFT'
40
+ Need ($release.runtime_predecessor.release_id -eq $parentId -and $release.runtime_predecessor.manifest_sha256 -eq $parentSha -and $release.runtime_predecessor.generation_manifest_sha256 -eq $parentGen) 'R207_RUNTIME_PREDECESSOR_IDENTITY_DRIFT'
41
+ $active=Get-Content -LiteralPath (Join-Path $productionState 'active-release.json') -Raw | ConvertFrom-Json
42
+ Need ($active.version -eq '0.15.75' -and $active.release_id -eq $parentId -and $active.manifest_sha256 -eq $parentSha -and $active.generation_manifest_sha256 -eq $parentGen) 'R207_ACTIVE_RUNTIME_DRIFT'
43
+ Need ((Sha (Join-Path $active.release_root 'MANIFEST.SHA256')) -eq $parentSha) 'R207_ACTIVE_MANIFEST_MISMATCH'
44
+ Write-Output 'R207_PREDECESSOR_PREFLIGHT=PASS'
45
+ if($Stage -eq 'preflight'){return}
46
+ if($Stage -in @('focused','all')){
47
+ $focused=@(
48
+ 'test/r70-owner-approval.test.mjs',
49
+ 'test/r89-privileged-install-boundary.test.mjs',
50
+ 'test/r186-controller-owner-grant.test.mjs',
51
+ 'test/r186-owner-consent-preflight.test.mjs',
52
+ 'test/r186-owner-enrollment.test.mjs',
53
+ 'test/r186-owner-grant-broker.test.mjs',
54
+ 'test/r186-owner-local-signing.test.mjs',
55
+ 'test/r186-owner-request.test.mjs',
56
+ 'test/r186-owner-review-export.test.mjs',
57
+ 'test/r188-owner-uac.test.mjs',
58
+ 'test/r188-uac-boundary.test.mjs',
59
+ 'test/r193-live-owner-subject.test.mjs',
60
+ 'test/r193-owner-enrollment-entrypoint.test.mjs',
61
+ 'test/r193-owner-secret-acl.test.mjs',
62
+ 'test/r193-owner-uac-broker.test.mjs',
63
+ 'test/r193-owner-uac-entrypoint.test.mjs',
64
+ 'test/r195-canonical-owner-observation.test.mjs',
65
+ 'test/r207-owner-enrollment-io.test.mjs',
66
+ 'test/r207-release-contract.test.mjs'
67
+ )
68
+ Run-Node -label 'focused' -nodeArgs (@('--test','--test-reporter=tap','--test-concurrency=1')+$focused)
69
+ if($Stage -eq 'focused'){return}
70
+ }
71
+ if($Stage -in @('full','all')){
72
+ $previousCrossVolume=$env:DEADBYTE_TEST_CROSS_VOLUME_ROOT
73
+ $tempDrive=[IO.Path]::GetPathRoot([IO.Path]::GetFullPath($env:TEMP))
74
+ $scratchDrive=if($tempDrive -ieq 'D:\'){'C:\'}else{'D:\'}
75
+ Need (Test-Path -LiteralPath $scratchDrive -PathType Container) 'R207_CROSS_VOLUME_DRIVE_UNAVAILABLE'
76
+ $crossVolume=Join-Path $scratchDrive 'DEADBYTE-R207-CrossVolume'
77
+ try{
78
+ [IO.Directory]::CreateDirectory($crossVolume)|Out-Null
79
+ $env:DEADBYTE_TEST_CROSS_VOLUME_ROOT=$crossVolume
80
+ Run-Node -label 'full' -nodeArgs @('--test','--test-reporter=tap','--test-concurrency=4','test/*.test.mjs')
81
+ }finally{$env:DEADBYTE_TEST_CROSS_VOLUME_ROOT=$previousCrossVolume}
82
+ if($Stage -eq 'full'){return}
83
+ }
84
+ if($Stage -in @('manifest','all')){
85
+ Run-Node -label 'manifest' -nodeArgs @('scripts/release-manifest.mjs','verify')
86
+ if($Stage -eq 'manifest'){return}
87
+ }
88
+ if($Stage -in @('doctor','all')){
89
+ $previousStateRoot=$env:DEADBYTE_STATE_ROOT
90
+ $isolated=Join-Path $env:TEMP ('deadbyte-r207-doctor-'+[guid]::NewGuid().ToString('N'))
91
+ try{
92
+ [IO.Directory]::CreateDirectory($isolated)|Out-Null
93
+ $env:DEADBYTE_STATE_ROOT=$isolated
94
+ Run-Node -label 'isolated_doctor' -nodeArgs @('src/deadbyte-cli.mjs','doctor')
95
+ }finally{
96
+ $env:DEADBYTE_STATE_ROOT=$previousStateRoot
97
+ Remove-Item -LiteralPath $isolated -Recurse -Force -ErrorAction SilentlyContinue
98
+ }
99
+ }
100
+ Write-Output 'R207_WINDOWS_CANDIDATE_GATE=PASS_PREPUBLICATION'
101
+ }finally{
102
+ $env:DEADBYTE_EXPECTED_DEVELOPMENT_ROOT=$previousExpectedDevelopmentRoot
103
+ Pop-Location
104
+ }
@@ -0,0 +1,85 @@
1
+ [CmdletBinding()]
2
+ param(
3
+ [string]$RuntimeRoot = '',
4
+ [string]$OutputPath = '',
5
+ [string[]]$AllowedActions = @('pointer_move','click_primary','click_secondary','double_click_primary','scroll','key_chord','text_input')
6
+ )
7
+ $ErrorActionPreference='Stop'
8
+ Set-StrictMode -Version Latest
9
+ function Get-Sha256Hex {
10
+ param([Parameter(Mandatory=$true)][string]$Path)
11
+ $Stream=[System.IO.File]::OpenRead([System.IO.Path]::GetFullPath($Path))
12
+ try{$Hasher=[System.Security.Cryptography.SHA256]::Create();try{return ([System.BitConverter]::ToString($Hasher.ComputeHash($Stream))).Replace('-','').ToLowerInvariant()}finally{$Hasher.Dispose()}}
13
+ finally{$Stream.Dispose()}
14
+ }
15
+
16
+ $Root=Split-Path -Parent $PSScriptRoot
17
+ $Controller=Join-Path $Root 'controller'
18
+ if([string]::IsNullOrWhiteSpace($RuntimeRoot)){ $RuntimeRoot=Join-Path $Controller 'runtime' }
19
+ if([string]::IsNullOrWhiteSpace($OutputPath)){ $OutputPath=Join-Path $Controller 'deadbyte-desktop-policy.json' }
20
+ $RuntimeRoot=[System.IO.Path]::GetFullPath($RuntimeRoot)
21
+ $OutputPath=[System.IO.Path]::GetFullPath($OutputPath)
22
+ $Observer=[System.IO.Path]::GetFullPath((Join-Path $Root 'bin\deadbyte-desktop-observer-r40.exe'))
23
+ $Input=[System.IO.Path]::GetFullPath((Join-Path $Root 'bin\deadbyte-desktop-input-r40.exe'))
24
+ $Grounder=[System.IO.Path]::GetFullPath((Join-Path $Root 'bin\deadbyte-desktop-uia-r199-fixed.exe'))
25
+ if(-not (Test-Path -LiteralPath $Observer -PathType Leaf)){throw "observer binary missing: $Observer"}
26
+ if(-not (Test-Path -LiteralPath $Input -PathType Leaf)){throw "input binary missing: $Input"}
27
+ if(-not (Test-Path -LiteralPath $Grounder -PathType Leaf)){throw "UIA grounder binary missing: $Grounder"}
28
+ $Known=@('pointer_move','click_primary','click_secondary','double_click_primary','scroll','key_chord','text_input')
29
+ if($AllowedActions.Count -lt 1){throw 'AllowedActions cannot be empty'}
30
+ $Unique=@($AllowedActions | Sort-Object -Unique)
31
+ if($Unique.Count -ne $AllowedActions.Count -or @($AllowedActions | Where-Object { $_ -notin $Known }).Count -gt 0){throw 'AllowedActions invalid'}
32
+ New-Item -ItemType Directory -Force -Path $RuntimeRoot | Out-Null
33
+ $Evidence=Join-Path $RuntimeRoot 'desktop-evidence'
34
+ New-Item -ItemType Directory -Force -Path $Evidence | Out-Null
35
+ $Grant=Join-Path $RuntimeRoot 'desktop-grant.json'
36
+ Remove-Item -LiteralPath $Grant -Force -ErrorAction SilentlyContinue
37
+ $Policy=[ordered]@{
38
+ schema='deadbyte.desktop-policy.v1'
39
+ enabled=$true
40
+ grant_file=$Grant
41
+ evidence_dir=$Evidence
42
+ observer=[ordered]@{
43
+ executable=$Observer
44
+ sha256=Get-Sha256Hex -Path $Observer
45
+ backend='gdi-bitblt-fallback'
46
+ }
47
+ input=[ordered]@{
48
+ executable=$Input
49
+ sha256=Get-Sha256Hex -Path $Input
50
+ }
51
+ grounder=[ordered]@{
52
+ executable=$Grounder
53
+ sha256=Get-Sha256Hex -Path $Grounder
54
+ }
55
+ allowed_input_desktops=@('Default')
56
+ allowed_actions=@($AllowedActions)
57
+ limits=[ordered]@{
58
+ max_frame_age_ms=2000
59
+ max_frame_bytes=134217728
60
+ capture_timeout_ms=10000
61
+ input_timeout_ms=5000
62
+ ground_timeout_ms=5000
63
+ post_observe_timeout_ms=10000
64
+ max_preview_bytes=1048576
65
+ max_text_bytes=4096
66
+ }
67
+ }
68
+ $Parent=Split-Path -Parent $OutputPath
69
+ New-Item -ItemType Directory -Force -Path $Parent | Out-Null
70
+ $Json=$Policy | ConvertTo-Json -Depth 8
71
+ $Utf8=New-Object System.Text.UTF8Encoding($false)
72
+ $Tmp=$OutputPath+'.tmp'
73
+ [System.IO.File]::WriteAllText($Tmp,$Json,$Utf8)
74
+ Move-Item -LiteralPath $Tmp -Destination $OutputPath -Force
75
+ [pscustomobject]@{
76
+ status='created'
77
+ policy_path=$OutputPath
78
+ policy_sha256=Get-Sha256Hex -Path $OutputPath
79
+ observer_sha256=$Policy.observer.sha256
80
+ input_sha256=$Policy.input.sha256
81
+ grounder_sha256=$Policy.grounder.sha256
82
+ grant_file=$Grant
83
+ grant_state='DISARMED'
84
+ action_kinds=@($AllowedActions)
85
+ }|ConvertTo-Json -Depth 6
@@ -15,6 +15,9 @@ import {assertR167NpmPublishReady,assertR167PackedIdentity} from './npm-release-
15
15
  import {assertR168NpmPublishReady,assertR168PackedIdentity} from './npm-release-readiness-r168.mjs';
16
16
  import {assertR193NpmPublishReady,assertR193PackedIdentity} from './npm-release-readiness-r193.mjs';
17
17
  import {assertR194NpmPublishReady,assertR194PackedIdentity} from './npm-release-readiness-r194.mjs';
18
+ import {assertR195NpmPublishReady,assertR195PackedIdentity} from './npm-release-readiness-r195.mjs';
19
+ import {assertR206NpmPublishReady,assertR206PackedIdentity} from './npm-release-readiness-r206.mjs';
20
+ import {assertR207NpmPublishReady,assertR207PackedIdentity} from './npm-release-readiness-r207.mjs';
18
21
  import {resumePackRecord} from '../src/npm-publication-resume-r168.mjs';
19
22
  import { existsSync,mkdtempSync,readdirSync,readFileSync,rmSync } from 'node:fs';
20
23
  import { resolveStateRoot } from '../src/state-root.mjs';
@@ -157,6 +160,18 @@ async function main() {
157
160
  if (!publishOnly) throw new Error('PUBLISH_BLOCKED R194 requires --publish-only; activation remains separately authorized');
158
161
  r194Readiness=await assertR194NpmPublishReady(release,{root});
159
162
  }
163
+ let r195Readiness=null;
164
+ let r206Readiness=null;
165
+ if (!isVerifyOnly && version==='0.15.75') {
166
+ if (!publishOnly) throw new Error('PUBLISH_BLOCKED R206 requires --publish-only; owner enrollment and activation remain separate');
167
+ if(release.train==='R206')r206Readiness=await assertR206NpmPublishReady(release,{root});
168
+ else r195Readiness=await assertR195NpmPublishReady(release,{root});
169
+ }
170
+ let r207Readiness=null;
171
+ if (!isVerifyOnly && version==='0.15.76') {
172
+ if (!publishOnly) throw new Error('PUBLISH_BLOCKED R207 requires --publish-only; owner enrollment and activation remain separate');
173
+ r207Readiness=await assertR207NpmPublishReady(release,{root});
174
+ }
160
175
  if (release.parent?.release_id !== provenance.parent_release_id ||
161
176
  release.parent?.manifest_sha256 !== provenance.parent_manifest_sha256 ||
162
177
  release.parent?.generation_manifest_sha256 !== provenance.parent_generation_manifest_sha256) {
@@ -304,7 +319,19 @@ async function main() {
304
319
  ...r194Readiness,observedSha256:createHash('sha256').update(localBytes).digest('hex'),
305
320
  observedIntegrity:localIntegrity,observedShasum:packRecord.shasum
306
321
  });
322
+ if(r195Readiness)assertR195PackedIdentity({
323
+ ...r195Readiness,observedSha256:createHash('sha256').update(localBytes).digest('hex'),
324
+ observedIntegrity:localIntegrity,observedShasum:packRecord.shasum
325
+ });
326
+ if(r206Readiness)assertR206PackedIdentity({
327
+ ...r206Readiness,observedSha256:createHash('sha256').update(localBytes).digest('hex'),
328
+ observedIntegrity:localIntegrity,observedShasum:packRecord.shasum
329
+ });
307
330
 
331
+ if(r207Readiness)assertR207PackedIdentity({
332
+ ...r207Readiness,observedSha256:createHash('sha256').update(localBytes).digest('hex'),
333
+ observedIntegrity:localIntegrity,observedShasum:packRecord.shasum
334
+ });
308
335
  console.log('[6/7] Publishing artifact to npm registry...');
309
336
  publishAttempted = true;
310
337
  const ownerAuth=async subject=>
@@ -0,0 +1,72 @@
1
+ import {createHash} from 'node:crypto';
2
+ import {lstat,readFile} from 'node:fs/promises';
3
+ import path from 'node:path';
4
+
5
+ const sha256=bytes=>createHash('sha256').update(bytes).digest('hex');
6
+ const hex64=value=>typeof value==='string'&&/^[0-9a-f]{64}$/.test(value);
7
+ const fail=message=>{throw new Error(`PUBLISH_BLOCKED R195 ${message}`);};
8
+ const required=(value,message)=>{if(!value)fail(message);};
9
+
10
+ async function checkedFile(file,expected,{maxBytes=64*1024*1024}={}){
11
+ required(hex64(expected),'evidence digest missing');
12
+ let info;try{info=await lstat(file);}catch{fail('evidence file absent');}
13
+ required(info.isFile()&&!info.isSymbolicLink()&&info.size>0&&info.size<=maxBytes,'evidence file invalid');
14
+ const bytes=await readFile(file);
15
+ required(sha256(bytes)===expected,'evidence digest differs');
16
+ return bytes;
17
+ }
18
+
19
+ function tapSummary(text,label){
20
+ const summaries=[...text.matchAll(/^# tests (\d+)\s*\r?\n# suites (\d+)\s*\r?\n# pass (\d+)\s*\r?\n# fail (\d+)\s*\r?\n# cancelled (\d+)\s*\r?\n# skipped (\d+)/gm)];
21
+ required(summaries.length>0,`${label} TAP summary absent`);
22
+ const last=summaries.at(-1);
23
+ return {tests:Number(last[1]),passes:Number(last[3]),fails:Number(last[4]),cancelled:Number(last[5]),skips:Number(last[6])};
24
+ }
25
+
26
+ export function assertR195PackedIdentity({tarball_sha256,tarball_integrity,tarball_shasum,observedSha256,observedIntegrity,observedShasum}={}){
27
+ required(hex64(tarball_sha256)&&typeof tarball_integrity==='string'&&tarball_integrity.startsWith('sha512-')&&
28
+ typeof tarball_shasum==='string'&&/^[0-9a-f]{40}$/.test(tarball_shasum),'verified tarball identity invalid');
29
+ required(observedSha256===tarball_sha256&&observedIntegrity===tarball_integrity&&observedShasum===tarball_shasum,
30
+ 'repacked tarball differs from verified closure bytes');
31
+ return true;
32
+ }
33
+
34
+ export async function assertR195NpmPublishReady(release,{root,closureRoot=process.env.DEADBYTE_R195_CLOSURE_ROOT}={}){
35
+ required(release?.version==='0.15.75'&&release?.train==='R195'&&
36
+ release?.r195?.scope==='CANONICAL_PROTECTED_OWNER_OBSERVATION','candidate metadata invalid');
37
+ required(release?.r195?.public_tool_delta===0&&release?.r195?.authority_scope_delta===0,'public authority surface widened');
38
+ required(release?.parent?.version==='0.15.74'&&release?.parent?.release_id==='v0.15.74-e84bf4eed16e9443'&&
39
+ release?.parent?.manifest_sha256==='e84bf4eed16e9443fbd0bf9f0f562e26b01db778647aefcc8b12fd7f48636b47'&&
40
+ release?.parent?.generation_manifest_sha256==='598f896be9ce65e6b0c618e8c8f6eaa2a9d91617a76a146bf3deb385a56d19e7','lineage mismatch');
41
+ required(root&&path.isAbsolute(root)&&closureRoot&&path.isAbsolute(closureRoot),'closure root absent');
42
+ const expected=path.resolve(root,'..','..','testing','r195-final-closure');
43
+ required(path.resolve(closureRoot).toLowerCase()===expected.toLowerCase(),'closure root outside scoped testing folder');
44
+ let closure;try{closure=JSON.parse(await readFile(path.join(closureRoot,'closure.json'),'utf8'));}catch{fail('closure unreadable');}
45
+ required(closure?.schema==='deadbyte.r195-release-closure.v1'&&closure.status==='RELEASE_READY'&&
46
+ closure.version==='0.15.75'&&closure.train==='R195','closure status mismatch');
47
+ required(closure.production_release_id===release.parent.release_id&&closure.production_manifest_sha256===release.parent.manifest_sha256&&
48
+ closure.production_generation_manifest_sha256===release.parent.generation_manifest_sha256,'production predecessor mismatch');
49
+ required(hex64(closure.manifest_sha256)&&closure.manifest_sha256===sha256(await readFile(path.join(root,'MANIFEST.SHA256'))),'final manifest drift');
50
+ required(closure.compact_tools===43&&closure.full_tools===117,'catalog count mismatch');
51
+ required(closure.owner_enrollment==='NOT_RUN'&&closure.production_activation==='NOT_RUN','prepublication closure crossed authority boundary');
52
+ const receipt=JSON.parse((await checkedFile(path.join(closureRoot,'protected-install-receipt.json'),closure.protected_receipt_sha256)).toString('utf8'));
53
+ required(receipt?.status==='PASS'&&receipt.package_version==='0.15.75'&&receipt.source_manifest_sha256===closure.manifest_sha256&&
54
+ receipt.protected_manifest_sha256===closure.manifest_sha256,'protected exact-byte receipt mismatch');
55
+ const focused=(await checkedFile(path.join(closureRoot,'windows-focused.stdout.log'),closure.focused_stdout_sha256)).toString('utf8');
56
+ const full=(await checkedFile(path.join(closureRoot,'windows-full.stdout.log'),closure.full_stdout_sha256)).toString('utf8');
57
+ const verify=(await checkedFile(path.join(closureRoot,'npm-verify.stdout.log'),closure.verify_stdout_sha256)).toString('utf8');
58
+ required(focused.includes('R195_STAGE_PASS=focused'),'focused protected gate incomplete');
59
+ const focusedSummary=tapSummary(focused,'focused');
60
+ required(focusedSummary.fails===0&&focusedSummary.cancelled===0&&focusedSummary.passes>=70&&focusedSummary.skips<=3,'focused regression count mismatch');
61
+ required(full.includes('R195_STAGE_PASS=full'),'full protected gate incomplete');
62
+ const summary=tapSummary(full,'full');
63
+ required(summary.tests>=2200&&summary.passes>=2100&&summary.fails===0&&summary.cancelled===0&&summary.skips<=70&&summary.passes+summary.skips===summary.tests,'full regression count mismatch');
64
+ required(verify.includes('VERIFY-ONLY PIPELINE PASS')&&verify.includes('Artifact isolation gate PASS')&&verify.includes('VERIFIED_TARBALL '),'npm exact-artifact verification incomplete');
65
+ const line=verify.split(/\r?\n/).find(value=>value.startsWith('VERIFIED_TARBALL '));
66
+ let artifact;try{artifact=JSON.parse(line.slice('VERIFIED_TARBALL '.length));}catch{fail('tarball evidence malformed');}
67
+ required(artifact.filename==='deadbyte-mcp-0.15.75.tgz'&&artifact.bytes>0&&artifact.sha256===closure.tarball_sha256&&
68
+ artifact.integrity===closure.tarball_integrity&&artifact.shasum===closure.tarball_shasum,'tarball identity mismatch');
69
+ return Object.freeze({status:'R195_RELEASE_READY_EVIDENCE_BOUND',manifest_sha256:closure.manifest_sha256,
70
+ tarball_sha256:artifact.sha256,tarball_integrity:artifact.integrity,tarball_shasum:artifact.shasum,
71
+ tests:summary.tests,passes:summary.passes,skips:summary.skips});
72
+ }