Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
123 changes: 123 additions & 0 deletions legacy/tools/compatibility/Get-FrozenManifestProjection.ps1
Original file line number Diff line number Diff line change
@@ -0,0 +1,123 @@
#requires -Version 7.2

<#
.SYNOPSIS
Shared frozen-source digest helpers for the compatibility retirement packets.

.DESCRIPTION
Every retirement packet freezes a set of source inputs and hashes them into a
snapshot identity. Both the generator (New-*RetirementPacket.ps1) and the
verifier (Test-*RetirementPacket.ps1) must compute that identity byte for byte
identically, so the computation lives here once and is dot-sourced by both.
Duplicating it in the mirror pair is what lets the two silently drift.

Why a projection instead of the whole registry file
---------------------------------------------------
Packets used to freeze the whole of orchestration/integrations.json. That file
also carries the toolchainDigests arrays, which are re-pinned whenever ANY
pinned Rust source file changes. So editing one unrelated Rust file invalidated
six packets at once and forced all of them to be regenerated in the same change
- 112 files, past the review-tool ceiling, which meant the governance mechanism
was blocking review of the very code it governs.

That coupling was never meaningful. A packet's staleness claim is about the
registry state of the capability it retires - is the replacement still declared,
with the same implementation, contract, effects and status - not about the
digests of source files it does not name. Freezing a projection over exactly
the integration entries the retirement concerns, plus the manifest's policy
header, keeps the claim the packet actually makes and drops the coupling it
never needed.

Canonicalisation
----------------
Deterministic by construction, and identical on both sides of the mirror:
1. Select the named integration entries. Missing or duplicated ids are a hard
error - an empty projection would be a silent governance hole.
2. Order them by id with an ordinal (culture-invariant) sort, so the digest
does not depend on the registry's file order or on the host locale.
3. Emit { schema, policy, integrations } via ConvertTo-Json -Depth 40
-Compress. Depth 40 matches the deepest packet writer; -Compress removes
insignificant whitespace so formatting-only edits to the registry do not
move the digest.
4. SHA-256 over the UTF8 bytes, lowercase hex - the same shape as the
Get-FileHash digests it sits beside in a frozen set.

Frozen-set entries
------------------
An entry is either a repository-relative file path, or a projection token:

manifest-projection:<manifest path>#<integration id>[,<integration id>...]

Root resolution is shared too: crates/ and orchestration/ paths resolve against
the pipeline repository root, everything else against the PowerShell root
(legacy/).
#>

Set-StrictMode -Version Latest

function Get-FrozenDigestSha256 {
param([Parameter(Mandatory = $true)][AllowEmptyString()][string]$Text)
return ([Convert]::ToHexString([Security.Cryptography.SHA256]::HashData([Text.Encoding]::UTF8.GetBytes($Text)))).ToLowerInvariant()
}

function Resolve-FrozenSourcePath {
param(
[Parameter(Mandatory = $true)][string]$Relative,
[Parameter(Mandatory = $true)][string]$RepoRoot,
[Parameter(Mandatory = $true)][string]$PipelineRepoRoot
)
$root = if ($Relative.StartsWith('crates/') -or $Relative.StartsWith('orchestration/')) { $PipelineRepoRoot } else { $RepoRoot }
return (Join-Path $root $Relative)
}

function Get-FrozenManifestProjection {
param(
[Parameter(Mandatory = $true)][string]$ManifestPath,
[Parameter(Mandatory = $true)][string[]]$IntegrationIds
)
if ($IntegrationIds.Count -eq 0) { throw "manifest projection requires at least one integration id" }
$manifest = Get-Content -LiteralPath $ManifestPath -Raw | ConvertFrom-Json
$ordered = [string[]]@($IntegrationIds)
[Array]::Sort($ordered, [StringComparer]::Ordinal)
$selected = @(foreach ($id in $ordered) {
$matched = @($manifest.integrations | Where-Object { $_.id -eq $id })
if ($matched.Count -ne 1) {
throw "manifest projection requires exactly one '$id' integration in $ManifestPath (found $($matched.Count))"
}
$matched[0]
})
$projection = [ordered]@{
schema = "code-intel-frozen-manifest-projection.v1"
policy = $manifest.policy
integrations = $selected
}
return Get-FrozenDigestSha256 (ConvertTo-Json -InputObject $projection -Depth 40 -Compress)
}

function Get-FrozenSourceDigest {
param(
[Parameter(Mandatory = $true)][string]$Entry,
[Parameter(Mandatory = $true)][string]$RepoRoot,
[Parameter(Mandatory = $true)][string]$PipelineRepoRoot
)
if ($Entry.StartsWith('manifest-projection:')) {
$spec = $Entry.Substring('manifest-projection:'.Length)
$parts = @($spec -split '#', 2)
if ($parts.Count -ne 2) { throw "malformed frozen projection entry: $Entry" }
$ids = @($parts[1] -split ',' | ForEach-Object { $_.Trim() } | Where-Object { $_.Length -gt 0 })
if ([string]::IsNullOrWhiteSpace($parts[0]) -or $ids.Count -eq 0) { throw "malformed frozen projection entry: $Entry" }
return Get-FrozenManifestProjection -ManifestPath (Resolve-FrozenSourcePath $parts[0] $RepoRoot $PipelineRepoRoot) -IntegrationIds $ids
}
return (Get-FileHash -LiteralPath (Resolve-FrozenSourcePath $Entry $RepoRoot $PipelineRepoRoot) -Algorithm SHA256).Hash.ToLowerInvariant()
}

function Get-FrozenSourceIdentity {
param(
[Parameter(Mandatory = $true)][string[]]$FrozenSet,
[Parameter(Mandatory = $true)][string]$RepoRoot,
[Parameter(Mandatory = $true)][string]$PipelineRepoRoot
)
return Get-FrozenDigestSha256 ((@($FrozenSet | ForEach-Object {
Get-FrozenSourceDigest -Entry $_ -RepoRoot $RepoRoot -PipelineRepoRoot $PipelineRepoRoot
})) -join "`n")
}
20 changes: 15 additions & 5 deletions legacy/tools/compatibility/New-CodeNexusDirectRetirementPacket.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -76,14 +76,24 @@ foreach ($testName in $b05Tests) {
if ($LASTEXITCODE -ne 0) { throw "B05 targeted fallback test failed: $testName" }
}

# Frozen source set. Test-CodeNexusDirectRetirementPacket.ps1 repeats this list
# and both sides hash it through the same dot-sourced helper, so the mirror pair
# cannot drift.
#
# The registry input is a canonical projection over exactly the integrations
# this retirement concerns - localization.codenexus-lite, the participant being
# retired, and provider.codenexus-adapt, the replacement - plus the manifest
# policy header, not the whole of orchestration/integrations.json. E04's
# staleness claim is about the registry state of the capability it retires; it
# is not about the toolchainDigests of unrelated Rust sources that happen to be
# pinned in the same file, which are re-pinned on every routine source edit.
. (Join-Path $PSScriptRoot "Get-FrozenManifestProjection.ps1")
$snapshotInputs = @(
"run-code-intel.ps1", "Invoke-CodeNexusLite.ps1", "crates/code-intel-cli/src/codenexus_adapter.rs",
"crates/code-intel-cli/src/survival_scan.rs", "orchestration/integrations.json"
"crates/code-intel-cli/src/survival_scan.rs",
"manifest-projection:orchestration/integrations.json#localization.codenexus-lite,provider.codenexus-adapt"
)
$snapshotIdentity = Get-Sha256Text (($snapshotInputs | ForEach-Object {
$root = if ($_.StartsWith('crates/') -or $_.StartsWith('orchestration/')) { $PipelineRepoRoot } else { $RepoRoot }
(Get-FileHash -LiteralPath (Join-Path $root $_) -Algorithm SHA256).Hash.ToLowerInvariant()
}) -join "`n")
$snapshotIdentity = Get-FrozenSourceIdentity -FrozenSet $snapshotInputs -RepoRoot $RepoRoot -PipelineRepoRoot $PipelineRepoRoot
$retirementId = "retire-codenexus-direct-branch"
$branchId = "run-code-intel.codenexus-lite.direct"
$replacementId = "provider.codenexus-adapt"
Expand Down
14 changes: 12 additions & 2 deletions legacy/tools/compatibility/New-HospitalRetirementPacket.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,17 @@ function W([string]$p,[object]$v){[IO.File]::WriteAllText($p,($v|ConvertTo-Json
$tests=@('provider_quota_precedes_missing_current_graph_and_is_replay_stable','precedence_matrix_matches_the_legacy_stable_diagnoses_and_fails_closed','missing_or_non_admitted_authority_is_rejected_and_enrichment_never_overrides_it','conflicting_or_provider_injected_modalities_fail_closed_independent_of_input_order','markdown_is_a_rebuildable_view_and_cannot_change_the_machine_verdict','a09_seeded_path_executes_hospital_through_a01_and_rejects_snapshot_mismatch','legacy_facade_and_rust_execute_the_same_fixture_with_stable_machine_parity');foreach($n in $tests){& cargo test -q -p code-intel --test hospital_diagnosis $n -- --exact|Out-Null;if($LASTEXITCODE-ne0){throw "B09 test failed $n"}}
$boundary=& pwsh -NoLogo -NoProfile -File (Join-Path $RepoRoot "tools\compatibility\Test-HospitalRetirementBoundary.ps1")|ConvertFrom-Json;$runPath=Join-Path $RepoRoot "run-code-intel.ps1";$run=[IO.File]::ReadAllText($runPath);$base=$run.Replace("`r`n","`n").Replace("`r","`n")
$functions='(?s)function New-HospitalProtocol \{.*?(?=\nfunction Get-CodeIntelSentruxStep)';$call='(?s)\$hospitalReport = New-CodeIntelHospitalReport .*?Convert-HospitalReportToMarkdown \$hospitalReport \| Set-Content -LiteralPath \$hospitalMarkdownPath -Encoding UTF8\n';$matches=@([regex]::Match($base,$functions),[regex]::Match($base,$call))|Sort-Object Index;if($matches.Where({-not$_.Success}).Count){throw "bounded E08 branch absent"}
$frozen=@('run-code-intel.ps1','crates/code-intel-cli/src/hospital_diagnosis.rs','orchestration/integrations.json','crates/code-intel-cli/src/run_commit.rs','crates/code-intel-cli/src/artifact_index.rs','crates/code-intel-cli/src/doctor_adapter.rs');$digests=@{};foreach($p in $frozen){$digests[$p]=(Get-FileHash (Join-Path $(if($p.StartsWith('crates/')-or$p.StartsWith('orchestration/')){$PipelineRepoRoot}else{$RepoRoot}) $p) -Algorithm SHA256).Hash.ToLowerInvariant()};$snapshot=S (($frozen|ForEach-Object{$digests[$_]})-join"`n")
# Frozen source set. Test-HospitalRetirementPacket.ps1 repeats this list and both
# sides hash it through the same dot-sourced helper, so the mirror pair cannot
# drift. The registry input is a canonical projection over exactly the
# integration this retirement concerns - diagnosis.hospital, the replacement
# capability and the registry participant - plus the manifest policy header, not
# the whole of orchestration/integrations.json. E08's staleness claim is about
# the registry state of the capability it retires; it is not about the
# toolchainDigests of unrelated Rust sources that happen to be pinned in the
# same file, which are re-pinned on every routine source edit.
. (Join-Path $PSScriptRoot "Get-FrozenManifestProjection.ps1")
$frozen=@('run-code-intel.ps1','crates/code-intel-cli/src/hospital_diagnosis.rs','manifest-projection:orchestration/integrations.json#diagnosis.hospital','crates/code-intel-cli/src/run_commit.rs','crates/code-intel-cli/src/artifact_index.rs','crates/code-intel-cli/src/doctor_adapter.rs');$digests=@{};foreach($p in $frozen){$digests[$p]=Get-FrozenSourceDigest -Entry $p -RepoRoot $RepoRoot -PipelineRepoRoot $PipelineRepoRoot};$snapshot=S (($frozen|ForEach-Object{$digests[$_]})-join"`n")
$rid="retire-hospital-branch";$bid="run-code-intel.hospital.embedded-diagnosis-render";$rep="diagnosis.hospital";$callPath="run-code-intel.ps1::$bid";$expiry=$EvaluatedAt+2592000
function E([string]$n,[string]$c,[object]$d){$v=[ordered]@{schema="code-intel-compatibility-retirement-evidence.v1";snapshotIdentity=$snapshot;id="e08.$n";evidenceClass=$c;retirementId=$rid;legacyBranchId=$bid;replacementCapabilityId=$rep;details=$d};$r="evidence/$n.json";W (Join-Path $OutDir $r) $v;Ref "code-intel-compatibility-retirement-evidence.v1" "compatibility.retirement-evidence" $r}
$atom=E "replacement-atom" "replacement_atom" ([ordered]@{outcome="blocked";status="pending_facade_route";capability=$rep;b09RegistryAvailable=$true;normalFacadeUsesB09=$boundary.normalFacadeUsesB09;blocker="normal facade still executes embedded Hospital authority"})
Expand Down Expand Up @@ -35,5 +45,5 @@ $ticket=[ordered]@{schema="code-intel-compatibility-retirement-ticket-template.v
W (Join-Path $OutDir "compatibility-retirement-ticket.json") $ticket;& $CodeIntel compatibility retirement-ticket lint --ticket (Join-Path $OutDir "compatibility-retirement-ticket.json") --evaluated-at $EvaluatedAt|Out-Null;if($LASTEXITCODE-ne0){throw "E01 lint failed"};$ticketRef=Ref "code-intel-compatibility-retirement-ticket-template.v1" "compatibility.retirement-ticket-template" "compatibility-retirement-ticket.json";$ticketDecl=($registryJson.integrations|Where-Object id -eq "compatibility.retirement-ticket-template").capabilityDeclaration
$e01=[ordered]@{schema="code-intel-capability-request.v1";capability="compatibility.retirement-ticket-template";contractVersion=1;implementation=$ticketDecl.implementation;snapshot=$gate.snapshot;options=[ordered]@{evaluatedAt=$EvaluatedAt};inputs=@($ticketRef,$manifestRef,$decisionRef,$diffRef);effectPolicy=[ordered]@{allowedEffects=$ticketDecl.allowedEffects}};W (Join-Path $OutDir "e01-request.json") $e01
$o=@(& $CodeIntel capability exec compatibility.retirement-ticket-template --request (Join-Path $OutDir "e01-request.json") --out (Join-Path $OutDir "e01-out") --artifact-root $OutDir 2>&1);$x=$LASTEXITCODE;$txt=$o-join"`n";[IO.File]::WriteAllText((Join-Path $OutDir "e01-stderr.txt"),$txt,[Text.UTF8Encoding]::new($false));if($x-ne65-or$txt-notmatch"ticket requires an approved E00 decision"){throw "E01 must validate patch then reject blocked E00: $x $txt"}
foreach($p in $frozen){if((Get-FileHash (Join-Path $(if($p.StartsWith('crates/')-or$p.StartsWith('orchestration/')){$PipelineRepoRoot}else{$RepoRoot}) $p) -Algorithm SHA256).Hash.ToLowerInvariant()-ne$digests[$p]){throw "E08 changed frozen path: $p"}}
foreach($p in $frozen){if((Get-FrozenSourceDigest -Entry $p -RepoRoot $RepoRoot -PipelineRepoRoot $PipelineRepoRoot)-ne$digests[$p]){throw "E08 changed frozen path: $p"}}
$status=[ordered]@{schema="code-intel-compatibility-retirement-execution-status.v1";retirementId=$rid;decision="blocked";deletionExecuted=$false;retired=$false;liveEmbeddedAuthority=$true;normalFacadeUsesB09=$false;blockers=@($decision.blockers);gainLedgerProjection=$decision.gainLedgerProjection;boundary="B09 is registered but the normal facade still executes embedded Hospital authority; E08 has no deletion authority and excludes publication, index, and doctor."};W (Join-Path $OutDir "status.json") $status;$status|ConvertTo-Json -Depth 10 -Compress
Loading
Loading