完成70%
This commit is contained in:
@@ -3,16 +3,11 @@ $ErrorActionPreference = 'Stop'
|
||||
$root = Split-Path -Parent $PSScriptRoot
|
||||
$issues = New-Object System.Collections.Generic.List[string]
|
||||
|
||||
function Add-Issue {
|
||||
param([string]$Message)
|
||||
$script:issues.Add($Message)
|
||||
}
|
||||
|
||||
function Read-RequiredFile {
|
||||
param([string]$RelativePath)
|
||||
$path = Join-Path $root $RelativePath
|
||||
if (-not (Test-Path -LiteralPath $path -PathType Leaf)) {
|
||||
Add-Issue "missing required client owner: $RelativePath"
|
||||
$script:issues.Add("missing required G03 file: $RelativePath")
|
||||
return ''
|
||||
}
|
||||
return Get-Content -Raw -Encoding UTF8 -LiteralPath $path
|
||||
@@ -21,134 +16,46 @@ function Read-RequiredFile {
|
||||
function Assert-Contains {
|
||||
param([string]$Content, [string]$Label, [string]$Expected)
|
||||
if (-not $Content.Contains($Expected)) {
|
||||
Add-Issue "$Label missing production ownership marker: $Expected"
|
||||
$script:issues.Add("$Label missing: $Expected")
|
||||
}
|
||||
}
|
||||
|
||||
function Assert-DoesNotContain {
|
||||
param([string]$Content, [string]$Label, [string]$Forbidden)
|
||||
if ($Content.Contains($Forbidden)) {
|
||||
Add-Issue "$Label retains retired preview/legacy owner: $Forbidden"
|
||||
$script:issues.Add("$Label must not claim unsupported remote ownership: $Forbidden")
|
||||
}
|
||||
}
|
||||
|
||||
$page = Read-RequiredFile 'pages/genealogy/g03-create-genealogy.vue'
|
||||
$api = Read-RequiredFile 'utils/api.js'
|
||||
$coordinator = Read-RequiredFile 'utils/genealogy-bootstrap.js'
|
||||
$accessContract = Read-RequiredFile 'utils/genealogy-contracts.js'
|
||||
$mock = Read-RequiredFile 'data/mock.js'
|
||||
$staticContract = Read-RequiredFile 'tests/g03-create-flow-contract.ps1'
|
||||
$legacyRuntimeSmoke = Read-RequiredFile 'tests/g03-create-flow-runtime-smoke.js'
|
||||
$runtimePath = Join-Path $root 'tests/g03-bootstrap-runtime-smoke.js'
|
||||
$flowContract = Read-RequiredFile 'tests/g03-create-flow-contract.ps1'
|
||||
$flowRuntime = Read-RequiredFile 'tests/g03-create-flow-runtime-smoke.js'
|
||||
|
||||
# Keep only durable public ownership checks here. Internal helper names, cache strategy,
|
||||
# debounce timers, and test titles are intentionally left to executable behavior tests.
|
||||
Assert-Contains $page 'G03 page' '@/utils/genealogy-bootstrap.js'
|
||||
Assert-Contains $page 'G03 page' 'createGenealogyBootstrapCoordinator'
|
||||
Assert-Contains $api 'utils/api.js' '/genealogy/app/genealogies'
|
||||
Assert-Contains $api 'utils/api.js' '/genealogy/app/genealogy-bootstrap-operations/'
|
||||
Assert-Contains $api 'utils/api.js' '/genealogy/app/region/search'
|
||||
Assert-Contains $api 'utils/api.js' 'Idempotency-Key'
|
||||
Assert-Contains $coordinator 'utils/genealogy-bootstrap.js' 'createGenealogyBootstrapCoordinator'
|
||||
# Apifox only declares two independent writes. There is no recoverable atomic
|
||||
# bootstrap or result-query operation, so G03 remains an explicit local preview.
|
||||
Assert-Contains $page 'G03 page' 'flow-success-dialog__copy'
|
||||
Assert-Contains $page 'G03 page' 'createLocalGenealogyPreview'
|
||||
Assert-Contains $page 'G03 page' 'updateLocalGenealogyPreviewAncestor'
|
||||
Assert-Contains $page 'G03 page' 'removeLocalGenealogyPreview'
|
||||
Assert-Contains $flowContract 'G03 flow contract' 'createLocalGenealogyPreview'
|
||||
Assert-Contains $flowRuntime 'G03 runtime smoke' 'local-created-'
|
||||
|
||||
foreach ($entry in @(
|
||||
[pscustomobject]@{ Content = $page; Label = 'G03 page' },
|
||||
[pscustomobject]@{ Content = $mock; Label = 'data/mock.js' },
|
||||
[pscustomobject]@{ Content = $staticContract; Label = 'G03 static flow contract' },
|
||||
[pscustomobject]@{ Content = $legacyRuntimeSmoke; Label = 'G03 legacy runtime smoke' }
|
||||
foreach ($forbidden in @(
|
||||
'createGenealogyBootstrapCoordinator',
|
||||
'genealogy-bootstrap-operations',
|
||||
'Idempotency-Key',
|
||||
'/genealogy/app/region/search',
|
||||
'requestStrict(',
|
||||
'appApi.'
|
||||
)) {
|
||||
foreach ($retiredOwner in @(
|
||||
'createLocalGenealogyPreview',
|
||||
'updateLocalGenealogyPreview',
|
||||
'updateLocalGenealogyPreviewAncestor',
|
||||
'removeLocalGenealogyPreview',
|
||||
'local-created-'
|
||||
)) {
|
||||
Assert-DoesNotContain $entry.Content $entry.Label $retiredOwner
|
||||
}
|
||||
}
|
||||
|
||||
foreach ($retiredApiOwner in @('async createGenealogy(', 'genealogies.unshift(created)')) {
|
||||
Assert-DoesNotContain $api 'utils/api.js' $retiredApiOwner
|
||||
}
|
||||
foreach ($retiredAccessOwner in @(
|
||||
'visibility:',
|
||||
'joinMode:',
|
||||
'fromApiGenealogyAccess',
|
||||
'toApiGenealogyAccess'
|
||||
)) {
|
||||
Assert-DoesNotContain $accessContract 'utils/genealogy-contracts.js' $retiredAccessOwner
|
||||
}
|
||||
|
||||
# The release gate executes the dependency-injected state machine suite. The suite must
|
||||
# deep-compare the exact marker, use request/storage/cache/context/navigation spies, and
|
||||
# publish a machine-readable case ledger only after all assertions pass.
|
||||
$expectedCases = @(
|
||||
'ACCOUNT_EPOCH_ISOLATION',
|
||||
'CONTEXT_FAILURE_LOCAL_RETRY',
|
||||
'FAILED_CLEAR',
|
||||
'FATAL_EXPLICIT_ABANDON_CLEAR',
|
||||
'KEY_REUSED_QUARANTINE',
|
||||
'KNOWN_NO_COMMIT',
|
||||
'LOCAL_ZERO_DISPATCH',
|
||||
'MARKER_EXACT',
|
||||
'NAVIGATION_FAILURE_LOCAL_RETRY',
|
||||
'NO_MOCK_MUTATION',
|
||||
'NO_NEW_KEY',
|
||||
'NO_PII',
|
||||
'PENDING_RETRY_AFTER',
|
||||
'POST_408_UNKNOWN',
|
||||
'POST_CANCEL_UNKNOWN',
|
||||
'POST_UNEXPECTED_STATUS_UNKNOWN',
|
||||
'POST_UNKNOWN',
|
||||
'PRECLAIM_400',
|
||||
'PRECLAIM_401',
|
||||
'PRECLAIM_403',
|
||||
'PROCESS_RECOVERY_STATUS_ONLY',
|
||||
'REQUEST_BUILD_ZERO_DISPATCH',
|
||||
'RETRY_429',
|
||||
'STATUS_400_CLEAR',
|
||||
'STATUS_401_CLEAR_SESSION',
|
||||
'STATUS_404_KEEP',
|
||||
'STATUS_429_KEEP',
|
||||
'STATUS_500_KEEP',
|
||||
'STATUS_CANCEL_KEEP',
|
||||
'STATUS_MALFORMED_KEEP',
|
||||
'STATUS_NETWORK_KEEP',
|
||||
'STATUS_UNEXPECTED_STATUS_KEEP',
|
||||
'SUCCEEDED_ORDER'
|
||||
) | Sort-Object
|
||||
|
||||
if (-not (Test-Path -LiteralPath $runtimePath -PathType Leaf)) {
|
||||
Add-Issue 'missing executable state-machine suite: tests/g03-bootstrap-runtime-smoke.js'
|
||||
} else {
|
||||
$runtimeOutput = @(& node $runtimePath 2>&1)
|
||||
$runtimeExit = $LASTEXITCODE
|
||||
if ($runtimeExit -ne 0) {
|
||||
Add-Issue "G03 runtime state-machine suite failed: $($runtimeOutput -join ' | ')"
|
||||
} else {
|
||||
if ('G03-BOOTSTRAP-RUNTIME PASS' -notin $runtimeOutput) {
|
||||
Add-Issue 'G03 runtime state-machine suite did not emit its PASS marker'
|
||||
}
|
||||
$coverageLine = @($runtimeOutput | Where-Object { $_ -like 'G03-BOOTSTRAP-RUNTIME-COVERAGE *' })
|
||||
if ($coverageLine.Count -ne 1) {
|
||||
Add-Issue 'G03 runtime state-machine suite must emit exactly one coverage ledger'
|
||||
} else {
|
||||
$actualCases = @(($coverageLine[0] -replace '^G03-BOOTSTRAP-RUNTIME-COVERAGE\s+', '').Split(',') | Where-Object { $_ } | Sort-Object)
|
||||
if (($actualCases -join ',') -ne ($expectedCases -join ',')) {
|
||||
Add-Issue "G03 runtime coverage ledger drifted: $($actualCases -join ',')"
|
||||
}
|
||||
}
|
||||
}
|
||||
Assert-DoesNotContain $page 'G03 page' $forbidden
|
||||
}
|
||||
|
||||
if ($issues.Count -gt 0) {
|
||||
$lines = New-Object System.Collections.Generic.List[string]
|
||||
$lines.Add('G03-BOOTSTRAP-CLIENT-RELEASE BLOCKED')
|
||||
foreach ($issue in $issues) { $lines.Add("- $issue") }
|
||||
$lines.Add('- Keep the honest local preview until backend, workspace, client, and MuMu release gates are green.')
|
||||
$lines.Add('- Migrate the coordinator, strict transport, marker/status recovery, context, fixtures, focused tests, and docs as one owner change.')
|
||||
throw ($lines -join [Environment]::NewLine)
|
||||
Write-Output 'G03-BOOTSTRAP-CLIENT-RELEASE BLOCKED'
|
||||
foreach ($issue in $issues) { Write-Output "- $issue" }
|
||||
Write-Output '- Keep the two-step visual preview local until Apifox supplies a recoverable create/result contract with a stable lexical genealogyId.'
|
||||
exit 1
|
||||
}
|
||||
|
||||
Write-Output 'G03-BOOTSTRAP-CLIENT-RELEASE PASS'
|
||||
|
||||
Reference in New Issue
Block a user