docs: record send sent diagnostic intake
This commit is contained in:
@@ -59,7 +59,7 @@ N13/N14/N15 are pre-business validation results. They can help identify UI eleme
|
||||
|
||||
## Current loop
|
||||
|
||||
Current loop: `R10 receive-file download resolver v2 diagnostic complete`; next R11 receive-file download preview contract.
|
||||
Current loop: `R10a returned send-sent record diagnostic intake complete`; next R11 receive-file download preview contract.
|
||||
|
||||
Active continuous execution plan: `docs/superpowers/plans/2026-07-10-r6f-r14-continuous-execution-plan.md`.
|
||||
|
||||
@@ -240,7 +240,7 @@ Continuous execution plan R6f-R14 is approved and execution has started:
|
||||
- Plan file: `docs/superpowers/plans/2026-07-10-r6f-r14-continuous-execution-plan.md`.
|
||||
- Scope: 15 ordered rounds covering send-message connector/gate hardening, send-file preview/idempotency/package, receive-file download preview, receive-message reconciliation, end-to-end business smoke, and release-candidate report.
|
||||
- Execution rule after approval: one round at a time, status-card update, verification, commit, push, then continue automatically until an evidence-only blocker requires user action.
|
||||
- Last completed round: R10 receive-file download resolver v2 diagnostic.
|
||||
- Last completed round: R10a returned send-sent record diagnostic intake.
|
||||
- Next active round: R11 receive-file download preview contract.
|
||||
|
||||
R6g send audit and idempotency replay diagnostics is complete:
|
||||
@@ -334,4 +334,13 @@ R10 receive-file download resolver v2 diagnostic is complete:
|
||||
- Fixture result: `records_checked=3`, `cache_candidates_checked=4`, `accepted_matches=2`, `ambiguous_matches=0`, `score_100_matches=1`, `score_80_matches=1`, and `score_40_only_matches=1`.
|
||||
- Diagnostic output keeps `raw_paths_printed=false`, `file_contents_read=false`, and `file_paths_returned=false`.
|
||||
- Decision: resolver logic is proven, but real production file download remains blocked until a real cache mapping package produces accepted non-ambiguous matches.
|
||||
- Next node: R10a returned send-sent record diagnostic intake, because two new operator packages arrived.
|
||||
|
||||
R10a returned send-sent record diagnostic intake is complete:
|
||||
|
||||
- Added `scripts\validate-send-sent-record-diagnostic-package.ps1` and `scripts\test-validate-send-sent-record-diagnostic-package.ps1`.
|
||||
- Reviewed `send-sent-record-diagnostic-package1(1).zip` and `send-sent-record-diagnostic-package2(1).zip` from Downloads using safe summary output only.
|
||||
- Both packages report `operator_observed_success=true`, `do_not_send_second_time_confirmed=true`, and `content_sha256_matches_input=true`.
|
||||
- Both packages also report `exact_content_seen_after=false`, `content_sha256_seen_after=false`, `after_offline_blocked=true`, `strict_send_record_pass=false`, and `production_send_unlock_recommended=false`.
|
||||
- Decision: production `isphere_send_message` remains blocked; the packages are useful manual evidence but not enough to open the send gate.
|
||||
- Next node: R11 receive-file download preview contract.
|
||||
|
||||
@@ -0,0 +1,55 @@
|
||||
# Returned send-sent record diagnostic intake - 2026-07-10
|
||||
|
||||
## Inputs reviewed
|
||||
|
||||
- `send-sent-record-diagnostic-package1(1).zip`
|
||||
- `send-sent-record-diagnostic-package2(1).zip`
|
||||
|
||||
The raw packages stay outside the repository. This note records only safe summary fields.
|
||||
|
||||
## Validator
|
||||
|
||||
Added `scripts/validate-send-sent-record-diagnostic-package.ps1` for this package family. It outputs booleans and counts only; it does not print raw target id, raw message body, raw idempotency key, or local operator paths.
|
||||
|
||||
## Safe validation summaries
|
||||
|
||||
Package 1:
|
||||
|
||||
```json
|
||||
{"ok":true,"package_type":"send-sent-record-diagnostic","package_file_name":"send-sent-record-diagnostic-package1(1).zip","summary_json_present":false,"input_json_present":true,"content_sha256_matches_input":true,"before_run_count":1,"after_run_count":1,"exact_content_seen_after":false,"content_sha256_seen_after":false,"after_offline_blocked":true,"operator_observed_success":true,"do_not_send_second_time_confirmed":true,"production_send_enabled":false,"automatic_send_enabled":false,"strict_send_record_pass":false,"production_send_unlock_recommended":false,"decision":"manual_success_without_machine_sent_record"}
|
||||
```
|
||||
|
||||
Package 2:
|
||||
|
||||
```json
|
||||
{"ok":true,"package_type":"send-sent-record-diagnostic","package_file_name":"send-sent-record-diagnostic-package2(1).zip","summary_json_present":true,"input_json_present":true,"content_sha256_matches_input":true,"before_run_count":1,"after_run_count":1,"exact_content_seen_after":false,"content_sha256_seen_after":false,"after_offline_blocked":true,"latest_after_route_hints":["A_ROUTE_INCOMPLETE","A_ROUTE_OFFLINE_BLOCKED"],"operator_observed_success":true,"do_not_send_second_time_confirmed":true,"production_send_enabled":false,"automatic_send_enabled":false,"strict_send_record_pass":false,"production_send_unlock_recommended":false,"decision":"manual_success_without_machine_sent_record"}
|
||||
```
|
||||
|
||||
Strict mode was also checked against package 2 and failed, as expected, because `strict_send_record_pass=false`.
|
||||
|
||||
## Business interpretation
|
||||
|
||||
The two packages improve confidence that a human operator successfully sent the fixed sandbox message once. They do not prove that the bridge can safely enable production send, because the machine-verifiable sent-record evidence is still missing:
|
||||
|
||||
- `exact_content_seen_after=false`
|
||||
- `content_sha256_seen_after=false`
|
||||
- `after_offline_blocked=true`
|
||||
- package 2 after route hints include `A_ROUTE_INCOMPLETE` and `A_ROUTE_OFFLINE_BLOCKED`
|
||||
|
||||
## Decision
|
||||
|
||||
Production `isphere_send_message` remains blocked. Current usable state remains:
|
||||
|
||||
- send-message preview/dry-run: usable
|
||||
- audit and idempotency: usable
|
||||
- production send: blocked by missing strict machine sent-record evidence
|
||||
|
||||
## Next requirement for unlocking production send
|
||||
|
||||
A future online package must show all of the following without printing raw body/target/path values:
|
||||
|
||||
1. before and after recorder outputs are present;
|
||||
2. content hash or sent-record marker is visible after send;
|
||||
3. offline blocker is absent after send;
|
||||
4. operator confirms only one send was performed;
|
||||
5. strict validator returns `strict_send_record_pass=true` and `production_send_unlock_recommended=true`.
|
||||
@@ -752,6 +752,41 @@ git push gitea main
|
||||
|
||||
---
|
||||
|
||||
### R10a: Returned send-sent record diagnostic intake
|
||||
|
||||
**Purpose:** 用户在 R10 后提供了两个 `send-sent-record-diagnostic` 返回包。本插入轮次只做安全复核:判断是否能打开生产发消息门禁;不能则记录明确阻断。
|
||||
|
||||
**Files:**
|
||||
- Create: `scripts/validate-send-sent-record-diagnostic-package.ps1`
|
||||
- Create: `scripts/test-validate-send-sent-record-diagnostic-package.ps1`
|
||||
- Create: `docs/source-discovery/2026-07-10-returned-send-sent-record-diagnostic.md`
|
||||
- Modify: `docs/current-status-card.md`
|
||||
|
||||
- [x] **Step 1: Write validator test first**
|
||||
|
||||
Test covers a blocked fixture and a strict-pass fixture. Initial run failed before the validator existed.
|
||||
|
||||
- [x] **Step 2: Implement safe validator**
|
||||
|
||||
Validator accepts `-ZipPath`, emits booleans/counts only, and supports `-Strict` non-zero exit when strict sent-record evidence is missing.
|
||||
|
||||
- [x] **Step 3: Validate returned packages**
|
||||
|
||||
Both returned packages produced `decision="manual_success_without_machine_sent_record"` and `strict_send_record_pass=false`.
|
||||
|
||||
- [x] **Step 4: Document decision**
|
||||
|
||||
Created `docs/source-discovery/2026-07-10-returned-send-sent-record-diagnostic.md`. Production send remains blocked.
|
||||
|
||||
**R10a Result:**
|
||||
|
||||
- Package 1 and package 2 both have before/after runs and operator success.
|
||||
- Neither package has machine-verifiable after sent-record/content-hash evidence.
|
||||
- Both show `after_offline_blocked=true`.
|
||||
- `production_send_unlock_recommended=false`; default `isphere_send_message` remains production-blocked.
|
||||
|
||||
---
|
||||
|
||||
### R11: Receive-file download preview contract
|
||||
|
||||
**Purpose:** 即使真实下载还不能做,也让 `isphere_receive_files` 对 download 请求返回可机器解析的 preview/blocked 结果,而不是只有泛化拒绝。
|
||||
|
||||
137
scripts/test-validate-send-sent-record-diagnostic-package.ps1
Normal file
137
scripts/test-validate-send-sent-record-diagnostic-package.ps1
Normal file
@@ -0,0 +1,137 @@
|
||||
param()
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
Set-StrictMode -Version Latest
|
||||
|
||||
$repo = (Resolve-Path -LiteralPath (Join-Path $PSScriptRoot "..")).Path
|
||||
$validator = Join-Path $repo "scripts\validate-send-sent-record-diagnostic-package.ps1"
|
||||
$tempDir = Join-Path ([System.IO.Path]::GetTempPath()) ("isphere-send-sent-validator-test-" + [guid]::NewGuid().ToString("N"))
|
||||
|
||||
function Assert-True([bool]$Condition, [string]$Message) {
|
||||
if (-not $Condition) { throw $Message }
|
||||
}
|
||||
|
||||
function New-StringFromCodes([int[]]$Codes) {
|
||||
return -join ($Codes | ForEach-Object { [char]$_ })
|
||||
}
|
||||
|
||||
$inputFileName = New-StringFromCodes @(0x586B,0x5199,0x2D,0x53D1,0x9001,0x4FE1,0x606F,0x2E,0x6A,0x73,0x6F,0x6E)
|
||||
$summaryFileName = New-StringFromCodes @(0x53D1,0x9001,0x8BB0,0x5F55,0x8BCA,0x65AD,0x6458,0x8981,0x2E,0x6A,0x73,0x6F,0x6E)
|
||||
|
||||
function ConvertTo-Sha256Hex([string]$Text) {
|
||||
$bytes = [System.Text.Encoding]::UTF8.GetBytes($Text)
|
||||
$sha = [System.Security.Cryptography.SHA256]::Create()
|
||||
try {
|
||||
return -join ($sha.ComputeHash($bytes) | ForEach-Object { $_.ToString("x2") })
|
||||
}
|
||||
finally {
|
||||
$sha.Dispose()
|
||||
}
|
||||
}
|
||||
|
||||
function New-FixturePackage([string]$Name, [bool]$StrictPass) {
|
||||
$root = Join-Path $tempDir $Name
|
||||
New-Item -ItemType Directory -Force -Path $root | Out-Null
|
||||
$before = Join-Path $root "return-evidence\before\probe-before"
|
||||
$after = Join-Path $root "return-evidence\after\probe-after"
|
||||
New-Item -ItemType Directory -Force -Path $before | Out-Null
|
||||
New-Item -ItemType Directory -Force -Path $after | Out-Null
|
||||
|
||||
$content = "hello"
|
||||
$hash = ConvertTo-Sha256Hex $content
|
||||
[ordered]@{
|
||||
gate = "R6e sent-record diagnostic"
|
||||
generated_by_script = $true
|
||||
operator_language = "zh-CN"
|
||||
ONLINE_SANDBOX_REQUIRED = $true
|
||||
MANUAL_ONE_SEND_ONLY = $true
|
||||
DO_NOT_SEND_SECOND_TIME = $true
|
||||
production_send_enabled = $false
|
||||
automatic_send_enabled = $false
|
||||
sandbox_target_type = "direct"
|
||||
sandbox_target_id = "fixture-target"
|
||||
content_text_to_send = $content
|
||||
content_sha256 = $hash
|
||||
idempotency_key = ("fixture-" + $Name)
|
||||
manual_send_started_at_local = "2026-07-10T19:00:00+08:00"
|
||||
manual_send_finished_at_local = "2026-07-10T19:00:10+08:00"
|
||||
operator_observed_success = $true
|
||||
success_ack_or_sent_record = "fixture operator observed success"
|
||||
do_not_send_second_time_confirmed = $true
|
||||
} | ConvertTo-Json -Depth 5 | Set-Content -LiteralPath (Join-Path $root $inputFileName) -Encoding UTF8
|
||||
|
||||
[ordered]@{
|
||||
ok = $true
|
||||
package = "send-sent-record-diagnostic"
|
||||
operator_language = "zh-CN"
|
||||
production_send_enabled = $false
|
||||
automatic_send_enabled = $false
|
||||
content_sha256_matches_input = $true
|
||||
before_run_count = 1
|
||||
after_run_count = 1
|
||||
exact_content_seen_before = $false
|
||||
exact_content_seen_after = $StrictPass
|
||||
content_sha256_seen_before = $false
|
||||
content_sha256_seen_after = $StrictPass
|
||||
latest_before_route_hints = @("A_ROUTE_OFFLINE_BLOCKED")
|
||||
latest_after_route_hints = if ($StrictPass) { @("B_ROUTE_SENT_RECORD_SEEN") } else { @("A_ROUTE_OFFLINE_BLOCKED") }
|
||||
after_offline_blocked = -not $StrictPass
|
||||
operator_observed_success = $true
|
||||
do_not_send_second_time_confirmed = $true
|
||||
raw_message_body_written = $false
|
||||
raw_target_id_written = $false
|
||||
raw_idempotency_key_written = $false
|
||||
local_paths_written = $false
|
||||
} | ConvertTo-Json -Depth 5 | Set-Content -LiteralPath (Join-Path $root $summaryFileName) -Encoding UTF8
|
||||
|
||||
"[]" | Set-Content -LiteralPath (Join-Path $before "send_uia_controls_preflight.json") -Encoding UTF8
|
||||
"[]" | Set-Content -LiteralPath (Join-Path $after "send_uia_controls_preflight.json") -Encoding UTF8
|
||||
|
||||
$zip = Join-Path $tempDir ($Name + ".zip")
|
||||
Compress-Archive -LiteralPath $root -DestinationPath $zip -Force
|
||||
return $zip
|
||||
}
|
||||
|
||||
try {
|
||||
if (-not (Test-Path -LiteralPath $validator)) {
|
||||
throw "missing validator script: $validator"
|
||||
}
|
||||
|
||||
New-Item -ItemType Directory -Force -Path $tempDir | Out-Null
|
||||
$blockedZip = New-FixturePackage "blocked-package" $false
|
||||
$passZip = New-FixturePackage "pass-package" $true
|
||||
|
||||
$blockedOutput = & powershell -NoProfile -ExecutionPolicy Bypass -File $validator -ZipPath $blockedZip
|
||||
if ($LASTEXITCODE -ne 0) { throw "blocked fixture validator failed: $blockedOutput" }
|
||||
$blocked = ($blockedOutput | Select-Object -Last 1) | ConvertFrom-Json
|
||||
Assert-True ($blocked.ok -eq $true) "blocked ok should be true"
|
||||
Assert-True ($blocked.strict_send_record_pass -eq $false) "blocked strict pass should be false"
|
||||
Assert-True ($blocked.production_send_unlock_recommended -eq $false) "blocked should not unlock production send"
|
||||
Assert-True ($blocked.after_offline_blocked -eq $true) "blocked offline flag should be true"
|
||||
Assert-True ($blocked.raw_message_body_written -eq $false) "raw body must not be written"
|
||||
Assert-True ($blocked.raw_target_id_written -eq $false) "raw target must not be written"
|
||||
Assert-True ($blocked.local_paths_written -eq $false) "local paths must not be written"
|
||||
|
||||
$passOutput = & powershell -NoProfile -ExecutionPolicy Bypass -File $validator -ZipPath $passZip -Strict
|
||||
if ($LASTEXITCODE -ne 0) { throw "pass fixture strict validator failed: $passOutput" }
|
||||
$pass = ($passOutput | Select-Object -Last 1) | ConvertFrom-Json
|
||||
Assert-True ($pass.strict_send_record_pass -eq $true) "pass strict should be true"
|
||||
Assert-True ($pass.production_send_unlock_recommended -eq $true) "pass should unlock gated production path"
|
||||
|
||||
$strictBlocked = & powershell -NoProfile -ExecutionPolicy Bypass -File $validator -ZipPath $blockedZip -Strict
|
||||
if ($LASTEXITCODE -eq 0) {
|
||||
throw "Strict unexpectedly passed for blocked fixture: $strictBlocked"
|
||||
}
|
||||
|
||||
[ordered]@{
|
||||
ok = $true
|
||||
blocked_strict_send_record_pass = $blocked.strict_send_record_pass
|
||||
pass_strict_send_record_pass = $pass.strict_send_record_pass
|
||||
production_send_unlock_recommended = $pass.production_send_unlock_recommended
|
||||
} | ConvertTo-Json -Depth 4 -Compress
|
||||
}
|
||||
finally {
|
||||
if (Test-Path -LiteralPath $tempDir) {
|
||||
Remove-Item -LiteralPath $tempDir -Recurse -Force
|
||||
}
|
||||
}
|
||||
202
scripts/validate-send-sent-record-diagnostic-package.ps1
Normal file
202
scripts/validate-send-sent-record-diagnostic-package.ps1
Normal file
@@ -0,0 +1,202 @@
|
||||
param(
|
||||
[string]$PackagePath = "",
|
||||
[string]$ZipPath = "",
|
||||
[string]$WorkDir = "",
|
||||
[switch]$Strict
|
||||
)
|
||||
|
||||
$ErrorActionPreference = "Stop"
|
||||
Set-StrictMode -Version Latest
|
||||
|
||||
function New-StringFromCodes([int[]]$Codes) {
|
||||
return -join ($Codes | ForEach-Object { [char]$_ })
|
||||
}
|
||||
|
||||
$inputFileName = New-StringFromCodes @(0x586B,0x5199,0x2D,0x53D1,0x9001,0x4FE1,0x606F,0x2E,0x6A,0x73,0x6F,0x6E)
|
||||
$summaryFileName = New-StringFromCodes @(0x53D1,0x9001,0x8BB0,0x5F55,0x8BCA,0x65AD,0x6458,0x8981,0x2E,0x6A,0x73,0x6F,0x6E)
|
||||
|
||||
function ConvertTo-Sha256Hex([string]$Text) {
|
||||
$bytes = [System.Text.Encoding]::UTF8.GetBytes($Text)
|
||||
$sha = [System.Security.Cryptography.SHA256]::Create()
|
||||
try {
|
||||
return -join ($sha.ComputeHash($bytes) | ForEach-Object { $_.ToString("x2") })
|
||||
}
|
||||
finally {
|
||||
$sha.Dispose()
|
||||
}
|
||||
}
|
||||
|
||||
function Get-JsonPropertyValue($Object, [string]$Name, $Default = $null) {
|
||||
if ($null -eq $Object) { return $Default }
|
||||
$property = $Object.PSObject.Properties[$Name]
|
||||
if ($null -eq $property) { return $Default }
|
||||
return $property.Value
|
||||
}
|
||||
|
||||
function Test-NonEmptyString($Value) {
|
||||
if ($null -eq $Value) { return $false }
|
||||
return -not [string]::IsNullOrWhiteSpace([string]$Value)
|
||||
}
|
||||
|
||||
function ConvertTo-Bool($Value, [bool]$Default = $false) {
|
||||
if ($null -eq $Value) { return $Default }
|
||||
if ($Value -is [bool]) { return [bool]$Value }
|
||||
$text = ([string]$Value).Trim().ToLowerInvariant()
|
||||
if ($text -eq "true" -or $text -eq "1" -or $text -eq "yes") { return $true }
|
||||
if ($text -eq "false" -or $text -eq "0" -or $text -eq "no") { return $false }
|
||||
return $Default
|
||||
}
|
||||
|
||||
function Get-RunCountFromEvidence($AllFiles, [string]$Phase) {
|
||||
$pattern = "[\\/]return-evidence[\\/]$Phase[\\/]"
|
||||
$manifestDirs = @($AllFiles | Where-Object { $_.FullName -match $pattern -and $_.Name -eq "manifest.json" } | ForEach-Object { $_.DirectoryName } | Sort-Object -Unique)
|
||||
if ($manifestDirs.Count -gt 0) { return $manifestDirs.Count }
|
||||
$phaseFiles = @($AllFiles | Where-Object { $_.FullName -match $pattern })
|
||||
if ($phaseFiles.Count -gt 0) { return 1 }
|
||||
return 0
|
||||
}
|
||||
|
||||
function Test-AfterOfflineBlocked($AllFiles, $Summary) {
|
||||
$summaryValue = Get-JsonPropertyValue $Summary "after_offline_blocked" $null
|
||||
if ($null -ne $summaryValue) { return ConvertTo-Bool $summaryValue $false }
|
||||
$afterFiles = @($AllFiles | Where-Object { $_.FullName -match "[\\/]return-evidence[\\/]after[\\/]" -and $_.Name -eq "send_uia_controls_preflight.json" })
|
||||
foreach ($file in $afterFiles) {
|
||||
$text = Get-Content -LiteralPath $file.FullName -Raw
|
||||
if ($text.Contains("A_ROUTE_OFFLINE_BLOCKED") -or $text.Contains('"offline_blocker_visible":true')) {
|
||||
return $true
|
||||
}
|
||||
}
|
||||
return $false
|
||||
}
|
||||
|
||||
function Get-ArrayValue($Object, [string]$Name) {
|
||||
$value = Get-JsonPropertyValue $Object $Name @()
|
||||
if ($null -eq $value) { return @() }
|
||||
return @($value)
|
||||
}
|
||||
|
||||
if (-not [string]::IsNullOrWhiteSpace($ZipPath)) {
|
||||
$PackagePath = $ZipPath
|
||||
}
|
||||
if ([string]::IsNullOrWhiteSpace($PackagePath)) {
|
||||
throw "PackagePath or ZipPath is required"
|
||||
}
|
||||
if (-not (Test-Path -LiteralPath $PackagePath)) {
|
||||
throw "package not found"
|
||||
}
|
||||
|
||||
$resolvedPackage = (Resolve-Path -LiteralPath $PackagePath).Path
|
||||
$cleanup = $false
|
||||
if ([string]::IsNullOrWhiteSpace($WorkDir)) {
|
||||
$WorkDir = Join-Path ([System.IO.Path]::GetTempPath()) ("isphere-send-sent-diagnostic-" + [guid]::NewGuid().ToString("N"))
|
||||
$cleanup = $true
|
||||
}
|
||||
|
||||
if (Test-Path -LiteralPath $WorkDir) {
|
||||
Remove-Item -LiteralPath $WorkDir -Recurse -Force
|
||||
}
|
||||
New-Item -ItemType Directory -Force -Path $WorkDir | Out-Null
|
||||
|
||||
try {
|
||||
if ($resolvedPackage.EndsWith(".zip", [System.StringComparison]::OrdinalIgnoreCase)) {
|
||||
Expand-Archive -LiteralPath $resolvedPackage -DestinationPath $WorkDir -Force
|
||||
$root = $WorkDir
|
||||
}
|
||||
else {
|
||||
$root = $resolvedPackage
|
||||
}
|
||||
|
||||
$allFiles = @(Get-ChildItem -LiteralPath $root -Recurse -File)
|
||||
$summaryFile = $allFiles | Where-Object { $_.Name -eq $summaryFileName } | Sort-Object FullName | Select-Object -First 1
|
||||
$inputFile = $allFiles | Where-Object { $_.Name -eq $inputFileName } | Sort-Object FullName | Select-Object -First 1
|
||||
|
||||
$summaryJson = $null
|
||||
if ($summaryFile) {
|
||||
$summaryJson = Get-Content -LiteralPath $summaryFile.FullName -Raw | ConvertFrom-Json
|
||||
}
|
||||
$inputJson = $null
|
||||
if ($inputFile) {
|
||||
$inputJson = Get-Content -LiteralPath $inputFile.FullName -Raw | ConvertFrom-Json
|
||||
}
|
||||
|
||||
$contentHashMatches = ConvertTo-Bool (Get-JsonPropertyValue $summaryJson "content_sha256_matches_input" $null) $false
|
||||
if ($null -ne $inputJson -and (Test-NonEmptyString (Get-JsonPropertyValue $inputJson "content_text_to_send")) -and (Test-NonEmptyString (Get-JsonPropertyValue $inputJson "content_sha256"))) {
|
||||
$contentHashMatches = ((ConvertTo-Sha256Hex ([string](Get-JsonPropertyValue $inputJson "content_text_to_send"))) -eq ([string](Get-JsonPropertyValue $inputJson "content_sha256")))
|
||||
}
|
||||
|
||||
$beforeRunCount = [int](Get-JsonPropertyValue $summaryJson "before_run_count" (Get-RunCountFromEvidence $allFiles "before"))
|
||||
$afterRunCount = [int](Get-JsonPropertyValue $summaryJson "after_run_count" (Get-RunCountFromEvidence $allFiles "after"))
|
||||
$exactContentSeenAfter = ConvertTo-Bool (Get-JsonPropertyValue $summaryJson "exact_content_seen_after" $false) $false
|
||||
$contentShaSeenAfter = ConvertTo-Bool (Get-JsonPropertyValue $summaryJson "content_sha256_seen_after" $false) $false
|
||||
$afterOfflineBlocked = Test-AfterOfflineBlocked $allFiles $summaryJson
|
||||
$operatorObservedSuccess = ConvertTo-Bool (Get-JsonPropertyValue $summaryJson "operator_observed_success" (Get-JsonPropertyValue $inputJson "operator_observed_success" $false)) $false
|
||||
$noSecondSend = ConvertTo-Bool (Get-JsonPropertyValue $summaryJson "do_not_send_second_time_confirmed" (Get-JsonPropertyValue $inputJson "do_not_send_second_time_confirmed" $false)) $false
|
||||
$productionSendEnabled = ConvertTo-Bool (Get-JsonPropertyValue $summaryJson "production_send_enabled" (Get-JsonPropertyValue $inputJson "production_send_enabled" $false)) $false
|
||||
$automaticSendEnabled = ConvertTo-Bool (Get-JsonPropertyValue $summaryJson "automatic_send_enabled" (Get-JsonPropertyValue $inputJson "automatic_send_enabled" $false)) $false
|
||||
$rawBodyWritten = ConvertTo-Bool (Get-JsonPropertyValue $summaryJson "raw_message_body_written" $false) $false
|
||||
$rawTargetWritten = ConvertTo-Bool (Get-JsonPropertyValue $summaryJson "raw_target_id_written" $false) $false
|
||||
$rawIdemWritten = ConvertTo-Bool (Get-JsonPropertyValue $summaryJson "raw_idempotency_key_written" $false) $false
|
||||
$localPathsWritten = ConvertTo-Bool (Get-JsonPropertyValue $summaryJson "local_paths_written" $false) $false
|
||||
|
||||
$strictPass = (
|
||||
$contentHashMatches -and
|
||||
$beforeRunCount -ge 1 -and
|
||||
$afterRunCount -ge 1 -and
|
||||
($exactContentSeenAfter -or $contentShaSeenAfter) -and
|
||||
-not $afterOfflineBlocked -and
|
||||
$operatorObservedSuccess -and
|
||||
$noSecondSend -and
|
||||
-not $productionSendEnabled -and
|
||||
-not $automaticSendEnabled -and
|
||||
-not $rawBodyWritten -and
|
||||
-not $rawTargetWritten -and
|
||||
-not $rawIdemWritten -and
|
||||
-not $localPathsWritten
|
||||
)
|
||||
|
||||
$decision = "not_usable"
|
||||
if ($strictPass) {
|
||||
$decision = "strict_send_record_pass"
|
||||
}
|
||||
elseif ($operatorObservedSuccess -and $beforeRunCount -ge 1 -and $afterRunCount -ge 1 -and $contentHashMatches) {
|
||||
$decision = "manual_success_without_machine_sent_record"
|
||||
}
|
||||
elseif ($beforeRunCount -ge 1 -or $afterRunCount -ge 1) {
|
||||
$decision = "partial_probe_only"
|
||||
}
|
||||
|
||||
$summaryOut = [ordered]@{
|
||||
ok = $true
|
||||
package_type = "send-sent-record-diagnostic"
|
||||
package_file_name = [System.IO.Path]::GetFileName($resolvedPackage)
|
||||
summary_json_present = ($null -ne $summaryFile)
|
||||
input_json_present = ($null -ne $inputFile)
|
||||
content_sha256_matches_input = $contentHashMatches
|
||||
before_run_count = $beforeRunCount
|
||||
after_run_count = $afterRunCount
|
||||
exact_content_seen_after = $exactContentSeenAfter
|
||||
content_sha256_seen_after = $contentShaSeenAfter
|
||||
after_offline_blocked = $afterOfflineBlocked
|
||||
latest_after_route_hints = Get-ArrayValue $summaryJson "latest_after_route_hints"
|
||||
operator_observed_success = $operatorObservedSuccess
|
||||
do_not_send_second_time_confirmed = $noSecondSend
|
||||
production_send_enabled = $productionSendEnabled
|
||||
automatic_send_enabled = $automaticSendEnabled
|
||||
raw_message_body_written = $rawBodyWritten
|
||||
raw_target_id_written = $rawTargetWritten
|
||||
raw_idempotency_key_written = $rawIdemWritten
|
||||
local_paths_written = $localPathsWritten
|
||||
strict_send_record_pass = $strictPass
|
||||
production_send_unlock_recommended = $strictPass
|
||||
decision = $decision
|
||||
}
|
||||
$summaryOut | ConvertTo-Json -Depth 6 -Compress
|
||||
if ($Strict -and -not $strictPass) {
|
||||
exit 1
|
||||
}
|
||||
}
|
||||
finally {
|
||||
if ($cleanup -and (Test-Path -LiteralPath $WorkDir)) {
|
||||
Remove-Item -LiteralPath $WorkDir -Recurse -Force
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user