deadbyte-mcp 0.15.45 → 0.15.46
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 +34 -24
- package/PROVENANCE.json +260 -257
- package/README.txt +22 -21
- package/RELEASE.json +367 -346
- package/SBOM.cdx.json +2 -2
- package/TEST-MATRIX.json +501 -503
- package/bridge/package.json +1 -1
- package/controller/deadbyte-controller.ps1 +20 -6
- package/controller/deadbyte-process-policy.json +4 -4
- package/package.json +2 -2
- package/scripts/gate-windows-r72.ps1 +76 -0
- package/scripts/npm-release-r48.mjs +2 -0
- package/scripts/npm-release-readiness-r72.mjs +76 -0
- package/src/deadbyte-cli.mjs +722 -721
- package/src/launcher-isolation.mjs +58 -0
- package/src/remote-authority.mjs +75 -75
- package/src/remote-mcp-machine-smoke-client.mjs +84 -84
- package/src/runtime-update.mjs +2056 -2008
- package/src/staging-input-isolation.mjs +79 -0
- package/src/version.mjs +1 -1
- package/test/deferred-slot-operation-behavior.test.mjs +2 -2
- package/test/r58-cleanup-retention.test.mjs +3 -3
- package/test/r58-concurrent-recovery.test.mjs +3 -3
- package/test/r58-stale-owner.test.mjs +1 -1
- package/test/r59-tool-surface-compat.test.mjs +2 -2
- package/test/r60-authority-coherence.test.mjs +10 -2
- package/test/r71-isolated-slot-rollback-restore.test.mjs +11 -11
- package/test/r71-release-identity.test.mjs +12 -10
- package/test/r72-launcher-isolation.test.mjs +99 -0
- package/test/r72-publication-fence.test.mjs +56 -0
- package/test/r72-publication-output-integrity.test.mjs +110 -0
- package/test/r72-remote-safe-contract.test.mjs +101 -0
- package/test/r72-staging-input-isolation.test.mjs +87 -0
- package/test/r72-staging-workspace-isolation.test.mjs +114 -0
- package/test/remote-session-cli.test.mjs +110 -64
package/bridge/package.json
CHANGED
|
@@ -1346,15 +1346,29 @@ function Arm-Autonomous($Cfg) {
|
|
|
1346
1346
|
Write-Host 'AUTONOMOUS PLANE ENABLED UNTIL EXPLICIT REVOKE'
|
|
1347
1347
|
}
|
|
1348
1348
|
|
|
1349
|
+
function Get-AutonomousRevocationLeaseFile($Cfg) {
|
|
1350
|
+
if ([string]::IsNullOrWhiteSpace([string]$Cfg.AutonomousPolicyFile)) { return $null }
|
|
1351
|
+
# Revocation may not depend on approval/root checks used only for issuing grants.
|
|
1352
|
+
# The source remains the bound policy snapshot, never a caller-supplied path.
|
|
1353
|
+
$snapshot = Read-ControllerPolicySnapshot ([string]$Cfg.AutonomousPolicyFile) 'autonomous'
|
|
1354
|
+
$policy = $snapshot.Policy
|
|
1355
|
+
if ($policy.schema -ne 'deadbyte.autonomous-policy.v1' -or $policy.enabled -ne $true) { Fail 'autonomous policy schema/enabled mismatch' }
|
|
1356
|
+
if ([string]::IsNullOrWhiteSpace([string]$policy.lease_file)) { Fail 'autonomous policy lease_file missing' }
|
|
1357
|
+
$leaseFile = [System.IO.Path]::GetFullPath([string]$policy.lease_file)
|
|
1358
|
+
$runtimeReal = [System.IO.Path]::GetFullPath($RuntimeDir).TrimEnd('\') + '\'
|
|
1359
|
+
if (-not $leaseFile.StartsWith($runtimeReal, [System.StringComparison]::OrdinalIgnoreCase)) { Fail 'autonomous policy lease_file must live under controller runtime directory' }
|
|
1360
|
+
return $leaseFile
|
|
1361
|
+
}
|
|
1362
|
+
|
|
1349
1363
|
function Disarm-Autonomous($Cfg, [switch]$Quiet) {
|
|
1350
1364
|
if ([string]::IsNullOrWhiteSpace([string]$Cfg.AutonomousPolicyFile)) { return }
|
|
1351
|
-
$
|
|
1365
|
+
$leaseFile = Get-AutonomousRevocationLeaseFile $Cfg
|
|
1352
1366
|
$epochError = $null
|
|
1353
|
-
if (Test-Path -LiteralPath $
|
|
1354
|
-
try { Invoke-AuthorityEpochCommand $Cfg 'autonomous' 'user-revoke' $
|
|
1355
|
-
Remove-Item -LiteralPath $
|
|
1367
|
+
if (Test-Path -LiteralPath $leaseFile -PathType Leaf) {
|
|
1368
|
+
try { Invoke-AuthorityEpochCommand $Cfg 'autonomous' 'user-revoke' $leaseFile | Out-Null } catch { $epochError = $_.Exception }
|
|
1369
|
+
Remove-Item -LiteralPath $leaseFile -Force -ErrorAction SilentlyContinue
|
|
1356
1370
|
}
|
|
1357
|
-
if (Test-Path -LiteralPath $
|
|
1371
|
+
if (Test-Path -LiteralPath $leaseFile) { throw 'Autonomous authority revocation failed: grant remains present' }
|
|
1358
1372
|
if ($null -ne $epochError) { throw $epochError }
|
|
1359
1373
|
if (-not $Quiet) { Write-Host 'AUTONOMOUS PLANE DISARMED' }
|
|
1360
1374
|
}
|
|
@@ -1642,7 +1656,7 @@ function Invoke-MachineSmoke($Cfg) {
|
|
|
1642
1656
|
Wait-PublicDnsReady $Cfg $url
|
|
1643
1657
|
$probeArgs = @($url)
|
|
1644
1658
|
if (-not [string]::IsNullOrWhiteSpace([string]$env:DEADBYTE_REMOTE_PROBE_MODE)) {
|
|
1645
|
-
if ([string]$env:DEADBYTE_REMOTE_PROBE_MODE -notin @('default','desktop','host','full','revoked')) { Fail 'invalid remote enforcement probe mode' }
|
|
1659
|
+
if ([string]$env:DEADBYTE_REMOTE_PROBE_MODE -notin @('default','operator','desktop','host','full','revoked')) { Fail 'invalid remote enforcement probe mode' }
|
|
1646
1660
|
$probeArgs += [string]$env:DEADBYTE_REMOTE_PROBE_MODE
|
|
1647
1661
|
}
|
|
1648
1662
|
Invoke-CoreGate $Cfg 'remote-mcp-machine-smoke-client.mjs' $probeArgs
|
|
@@ -1,15 +1,15 @@
|
|
|
1
1
|
{
|
|
2
2
|
"schema": "deadbyte.process-policy.v1",
|
|
3
3
|
"enabled": true,
|
|
4
|
-
"grant_file": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.
|
|
5
|
-
"state_dir": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.
|
|
4
|
+
"grant_file": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.46-r72\\controller\\runtime\\process-grant.json",
|
|
5
|
+
"state_dir": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.46-r72\\controller\\runtime\\process-state",
|
|
6
6
|
"native_host": {
|
|
7
|
-
"path": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.
|
|
7
|
+
"path": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.46-r72\\bin\\deadbyte-process-host.exe",
|
|
8
8
|
"sha256": "daf9cfb371bee88cafbf5597eaa507fec504dbe0b0ddd40d0c3c2e02817f49e4"
|
|
9
9
|
},
|
|
10
10
|
"roots": {
|
|
11
11
|
"core": {
|
|
12
|
-
"path": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.
|
|
12
|
+
"path": "D:\\Projects\\deadbyte-mcp\\development\\deadbyte-mcp-0.15.46-r72",
|
|
13
13
|
"deny_paths": [
|
|
14
14
|
"node_modules",
|
|
15
15
|
"controller/runtime",
|
package/package.json
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
{
|
|
2
2
|
"name": "deadbyte-mcp",
|
|
3
|
-
"version": "0.15.
|
|
3
|
+
"version": "0.15.46",
|
|
4
4
|
"private": false,
|
|
5
5
|
"type": "module",
|
|
6
6
|
"description": "Authenticated MCP agentic runtime with signed skills, persistent model backends, identity-bound remote devices, durable job supervision, immutable release slots, and separately revocable machine authority.",
|
|
@@ -42,7 +42,7 @@
|
|
|
42
42
|
"contained:run": "node src/contained-cli.mjs workspaces/demo input.txt",
|
|
43
43
|
"contained:smoke": "node src/contained-smoke.mjs",
|
|
44
44
|
"mcp:contained:smoke": "node src/mcp-contained-smoke-client.mjs",
|
|
45
|
-
"gate:windows": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gate-windows-
|
|
45
|
+
"gate:windows": "powershell -NoProfile -ExecutionPolicy Bypass -File scripts/gate-windows-r72.ps1",
|
|
46
46
|
"authority:smoke": "node src/authority-smoke.mjs",
|
|
47
47
|
"mcp:remote:smoke": "node src/remote-mcp-smoke-client.mjs",
|
|
48
48
|
"mcp:host:smoke": "node src/mcp-host-smoke-client.mjs",
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
#requires -Version 5.1
|
|
2
|
+
[CmdletBinding()]
|
|
3
|
+
param([ValidateSet('preflight','focused','full','manifest','doctor','all')][string]$Stage='preflight')
|
|
4
|
+
Set-StrictMode -Version Latest
|
|
5
|
+
$ErrorActionPreference='Stop'
|
|
6
|
+
$repo=Split-Path -Parent $PSScriptRoot
|
|
7
|
+
$state=Join-Path $env:USERPROFILE '.deadbyte-mcp'
|
|
8
|
+
$parentId='v0.15.45-34aa8d1241cfb8bf'
|
|
9
|
+
$parentSha='34aa8d1241cfb8bf0b5ba303bf3c06e0e9e1bf01f64457bca659d6dd4d634fdc'
|
|
10
|
+
$parentGen='ff2b73410062688651abd7bc2dd7b2b8c87810a28e3808bfe1f4352a25b0e6e4'
|
|
11
|
+
function Sha([string]$file){
|
|
12
|
+
$sha=[System.Security.Cryptography.SHA256]::Create()
|
|
13
|
+
try {
|
|
14
|
+
$stream=[System.IO.File]::OpenRead($file)
|
|
15
|
+
try {return ([BitConverter]::ToString($sha.ComputeHash($stream))).Replace('-','').ToLowerInvariant()}
|
|
16
|
+
finally {$stream.Dispose()}
|
|
17
|
+
} finally {$sha.Dispose()}
|
|
18
|
+
}
|
|
19
|
+
function Run-Node([string]$label,[string[]]$nodeArgs) {
|
|
20
|
+
Write-Output "R72_STAGE_START=$label"
|
|
21
|
+
& node @nodeArgs
|
|
22
|
+
if($LASTEXITCODE -ne 0){throw "R72_${label}_FAILED exit=$LASTEXITCODE"}
|
|
23
|
+
Write-Output "R72_STAGE_PASS=$label"
|
|
24
|
+
}
|
|
25
|
+
Push-Location $repo
|
|
26
|
+
try {
|
|
27
|
+
$pkg=Get-Content -LiteralPath 'package.json' -Raw | ConvertFrom-Json
|
|
28
|
+
$release=Get-Content -LiteralPath 'RELEASE.json' -Raw | ConvertFrom-Json
|
|
29
|
+
if($pkg.version -ne '0.15.46' -or $release.version -ne '0.15.46' -or $release.train -ne 'R72'){
|
|
30
|
+
throw 'R72_CANDIDATE_VERSION_DRIFT'
|
|
31
|
+
}
|
|
32
|
+
if($release.parent.release_id -ne $parentId -or $release.parent.manifest_sha256 -ne $parentSha -or
|
|
33
|
+
$release.parent.generation_manifest_sha256 -ne $parentGen){throw 'R72_PARENT_IDENTITY_DRIFT'}
|
|
34
|
+
$parentRoot=Join-Path $state "releases\$parentId"
|
|
35
|
+
if(-not (Test-Path -LiteralPath $parentRoot -PathType Container)){throw 'R72_PARENT_SLOT_MISSING'}
|
|
36
|
+
if((Sha (Join-Path $parentRoot 'MANIFEST.SHA256')) -ne $parentSha){throw 'R72_PARENT_MANIFEST_MISMATCH'}
|
|
37
|
+
$active=Get-Content -LiteralPath (Join-Path $state 'active-release.json') -Raw | ConvertFrom-Json
|
|
38
|
+
if($active.version -ne '0.15.45' -or $active.release_id -ne $parentId -or
|
|
39
|
+
$active.manifest_sha256 -ne $parentSha -or $active.generation_manifest_sha256 -ne $parentGen){
|
|
40
|
+
throw 'R72_PRODUCTION_PREDECESSOR_DRIFT'
|
|
41
|
+
}
|
|
42
|
+
Write-Output 'R72_PREDECESSOR_PREFLIGHT=PASS'
|
|
43
|
+
if($Stage -eq 'preflight'){return}
|
|
44
|
+
if($Stage -in @('focused','all')){
|
|
45
|
+
Run-Node -label 'focused' -nodeArgs @('--test','--test-concurrency=1',
|
|
46
|
+
'test/r72-remote-safe-contract.test.mjs','test/r72-publication-fence.test.mjs',
|
|
47
|
+
'test/r60-authority-coherence.test.mjs','test/r58-cleanup-retention.test.mjs',
|
|
48
|
+
'test/remote-session-cli.test.mjs','test/r70-controller-autonomous-root.test.mjs',
|
|
49
|
+
'test/r70-controller-owner-issue-boundary.test.mjs','test/r71-release-identity.test.mjs',
|
|
50
|
+
'test/r71-isolated-slot-rollback-restore.test.mjs','test/r59-tool-surface-compat.test.mjs')
|
|
51
|
+
if($Stage -eq 'focused'){return}
|
|
52
|
+
}
|
|
53
|
+
if($Stage -in @('full','all')){
|
|
54
|
+
& powershell -NoLogo -NoProfile -ExecutionPolicy Bypass -File (Join-Path $repo 'scripts\verify-r70-full-regression.ps1')
|
|
55
|
+
if($LASTEXITCODE -ne 0){throw "R72_FULL_REGRESSION_FAILED exit=$LASTEXITCODE"}
|
|
56
|
+
Write-Output 'R72_FULL_REGRESSION_PASS'
|
|
57
|
+
if($Stage -eq 'full'){return}
|
|
58
|
+
}
|
|
59
|
+
if($Stage -in @('manifest','all')){
|
|
60
|
+
Run-Node -label 'manifest' -nodeArgs @('scripts/release-manifest.mjs','verify')
|
|
61
|
+
if($Stage -eq 'manifest'){return}
|
|
62
|
+
}
|
|
63
|
+
if($Stage -in @('doctor','all')){
|
|
64
|
+
$previous=$env:DEADBYTE_STATE_ROOT
|
|
65
|
+
$isolated=Join-Path $env:TEMP ('deadbyte-r72-doctor-'+[guid]::NewGuid().ToString('N'))
|
|
66
|
+
try{
|
|
67
|
+
New-Item -ItemType Directory -Path $isolated -Force | Out-Null
|
|
68
|
+
$env:DEADBYTE_STATE_ROOT=$isolated
|
|
69
|
+
Run-Node -label 'isolated_doctor' -nodeArgs @('src/deadbyte-cli.mjs','doctor')
|
|
70
|
+
}finally{
|
|
71
|
+
$env:DEADBYTE_STATE_ROOT=$previous
|
|
72
|
+
Remove-Item -LiteralPath $isolated -Recurse -Force -ErrorAction SilentlyContinue
|
|
73
|
+
}
|
|
74
|
+
}
|
|
75
|
+
Write-Output 'R72_WINDOWS_CANDIDATE_GATE=PASS_PREPUBLICATION'
|
|
76
|
+
}finally{Pop-Location}
|
|
@@ -5,6 +5,7 @@ import { mkdtemp, readFile, rm, unlink, mkdir } from 'node:fs/promises';
|
|
|
5
5
|
import {preserveNpmTarball,assertVacantPackDestination} from './npm-preserve-artifact-r67.mjs';
|
|
6
6
|
import {assertR67NpmPublishReady} from './npm-release-readiness-r67.mjs';
|
|
7
7
|
import {assertR71NpmPublishReady} from './npm-release-readiness-r71.mjs';
|
|
8
|
+
import {assertR72NpmPublishReady} from './npm-release-readiness-r72.mjs';
|
|
8
9
|
import { existsSync } from 'node:fs';
|
|
9
10
|
import { resolveStateRoot } from '../src/state-root.mjs';
|
|
10
11
|
import path from 'node:path';
|
|
@@ -91,6 +92,7 @@ async function main() {
|
|
|
91
92
|
}
|
|
92
93
|
if (!isVerifyOnly && version==='0.15.44') assertR67NpmPublishReady(release);
|
|
93
94
|
if (!isVerifyOnly && version==='0.15.45') assertR71NpmPublishReady(release);
|
|
95
|
+
if (!isVerifyOnly && version==='0.15.46') await assertR72NpmPublishReady(release,{root});
|
|
94
96
|
if (release.parent?.release_id !== provenance.parent_release_id ||
|
|
95
97
|
release.parent?.manifest_sha256 !== provenance.parent_manifest_sha256 ||
|
|
96
98
|
release.parent?.generation_manifest_sha256 !== provenance.parent_generation_manifest_sha256) {
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
/** R72 publication fence: exact v0.15.45 parent, final manifest and external gate evidence.
|
|
2
|
+
* This deliberately does NOT generate, sign or upgrade release evidence. */
|
|
3
|
+
import {createHash} from 'node:crypto';
|
|
4
|
+
import {readFile,lstat} from 'node:fs/promises';
|
|
5
|
+
import path from 'node:path';
|
|
6
|
+
|
|
7
|
+
const HEX64=/^[0-9a-f]{64}$/;
|
|
8
|
+
const expectedParent=Object.freeze({
|
|
9
|
+
version:'0.15.45',
|
|
10
|
+
release_id:'v0.15.45-34aa8d1241cfb8bf',
|
|
11
|
+
manifest_sha256:'34aa8d1241cfb8bf0b5ba303bf3c06e0e9e1bf01f64457bca659d6dd4d634fdc',
|
|
12
|
+
generation_manifest_sha256:'ff2b73410062688651abd7bc2dd7b2b8c87810a28e3808bfe1f4352a25b0e6e4'
|
|
13
|
+
});
|
|
14
|
+
const evidenceGates=['full_regression','windows_lifecycle','package_acceptance','independent_judge'];
|
|
15
|
+
const sha=bytes=>createHash('sha256').update(bytes).digest('hex');
|
|
16
|
+
function reject(reason){throw new Error(`PUBLISH_BLOCKED R72 ${reason}`);}
|
|
17
|
+
function exactParent(subject){return expectedParent.version===subject?.version&&
|
|
18
|
+
expectedParent.release_id===subject?.release_id&&
|
|
19
|
+
expectedParent.manifest_sha256===subject?.manifest_sha256&&
|
|
20
|
+
expectedParent.generation_manifest_sha256===subject?.generation_manifest_sha256;}
|
|
21
|
+
|
|
22
|
+
export async function assertR72NpmPublishReady(release,{root}={}){
|
|
23
|
+
if(release?.version!=='0.15.46'||release?.train!=='R72'||
|
|
24
|
+
release?.name!=='deadbyte-mcp'||!exactParent(release?.parent)||
|
|
25
|
+
!exactParent(release?.runtime_predecessor))reject('release identity or predecessor mismatch');
|
|
26
|
+
const status=release.r72_hotfix;
|
|
27
|
+
for(const [name,value] of Object.entries({
|
|
28
|
+
status:'CANDIDATE_SEALED',windows_regression:'PASS',package_acceptance:'PASS',
|
|
29
|
+
manifest:'PASS',remote_lifecycle:'PASS',security_gate:'PASS',independent_judge:'PASS'
|
|
30
|
+
}))if(status?.[name]!==value)reject(`${name}=${String(status?.[name]??'MISSING')}; require ${value}`);
|
|
31
|
+
if(!root||!path.isAbsolute(root))reject('candidate root missing');
|
|
32
|
+
const manifest=await readFile(path.join(root,'MANIFEST.SHA256')).catch(()=>reject('candidate manifest unavailable'));
|
|
33
|
+
const manifestSha256=sha(manifest);
|
|
34
|
+
const evidenceRoot=path.join(root,'testing','r72-release-evidence');
|
|
35
|
+
// Evidence and transcript storage must not be junctions/symlinks to another tree.
|
|
36
|
+
for(const dir of [evidenceRoot,path.join(evidenceRoot,'outputs')]){
|
|
37
|
+
const info=await lstat(dir).catch(()=>reject('evidence/output directory missing'));
|
|
38
|
+
if(!info.isDirectory()||info.isSymbolicLink())reject('evidence/output directory is not a real directory');
|
|
39
|
+
}
|
|
40
|
+
let ready;
|
|
41
|
+
try{ready=JSON.parse(await readFile(path.join(evidenceRoot,'ready.json'),'utf8'));}
|
|
42
|
+
catch{reject('independent release evidence index missing/invalid');}
|
|
43
|
+
if(ready?.schema!=='deadbyte.r72-release-evidence-index.v1'||ready?.version!=='0.15.46'||
|
|
44
|
+
ready?.manifest_sha256!==manifestSha256||!exactParent(ready?.parent))reject('evidence index subject mismatch');
|
|
45
|
+
for(const gate of evidenceGates){
|
|
46
|
+
const hash=ready?.gate_sha256?.[gate];
|
|
47
|
+
if(!HEX64.test(String(hash??'')))reject(`${gate} receipt identity missing`);
|
|
48
|
+
let bytes,receipt;
|
|
49
|
+
try{bytes=await readFile(path.join(evidenceRoot,`${gate}.json`));receipt=JSON.parse(bytes.toString('utf8'));}
|
|
50
|
+
catch{reject(`${gate} receipt missing/invalid`);}
|
|
51
|
+
if(sha(bytes)!==hash||receipt?.schema!=='deadbyte.r72-gate-result.v1'||
|
|
52
|
+
receipt?.gate!==gate||receipt?.version!=='0.15.46'||
|
|
53
|
+
receipt?.manifest_sha256!==manifestSha256||
|
|
54
|
+
receipt?.status!=='PASS'||receipt?.exit_code!==0)reject(`${gate} receipt tamper or failed gate`);
|
|
55
|
+
if(!HEX64.test(String(receipt.output_sha256??'')))reject(`${gate} missing bound command output`);
|
|
56
|
+
// Exact, gate-specific transcript path: a self-declared digest alone is not evidence.
|
|
57
|
+
const relativeOutput=`outputs/${gate}.log`;
|
|
58
|
+
if(receipt.output_file!==relativeOutput)reject(`${gate} output path identity mismatch`);
|
|
59
|
+
const outputPath=path.join(evidenceRoot,'outputs',`${gate}.log`);
|
|
60
|
+
const outputInfo=await lstat(outputPath).catch(()=>reject(`${gate} output missing/unavailable`));
|
|
61
|
+
if(!outputInfo.isFile()||outputInfo.isSymbolicLink())reject(`${gate} output must be a regular non-symlink file`);
|
|
62
|
+
if(outputInfo.size<1||outputInfo.size>64*1024*1024)reject(`${gate} output size invalid`);
|
|
63
|
+
const output=await readFile(outputPath).catch(()=>reject(`${gate} output unavailable`));
|
|
64
|
+
if(sha(output)!==receipt.output_sha256)reject(`${gate} output hash mismatch`);
|
|
65
|
+
if(gate==='full_regression'&&(!Number.isSafeInteger(receipt.pass_count)||receipt.pass_count<1||receipt.fail_count!==0))
|
|
66
|
+
reject('full regression count contract invalid');
|
|
67
|
+
if(gate==='windows_lifecycle'&&(
|
|
68
|
+
receipt.safe_default_arm_count!==0||receipt.operator_owner_consent_enforced!==true||
|
|
69
|
+
receipt.stale_owner_recovery_verified!==true||receipt.signed_epoch_fail_closed!==true))
|
|
70
|
+
reject('Windows lifecycle or R70 owner authority verification missing');
|
|
71
|
+
if(gate==='independent_judge'&&receipt.independent_verification!=='PASS')
|
|
72
|
+
reject('independent judge verdict unavailable');
|
|
73
|
+
}
|
|
74
|
+
return Object.freeze({status:'R72_RELEASE_READY_EVIDENCE_BOUND',version:'0.15.46',
|
|
75
|
+
manifest_sha256:manifestSha256,evidence_count:evidenceGates.length});
|
|
76
|
+
}
|