Prune terminal self-state audit residue

This commit is contained in:
Meta Vens 2026-05-22 20:45:39 +01:00
commit ae9fedd3eb
6 changed files with 38 additions and 29 deletions

View file

@ -245,11 +245,14 @@ function normalizeTypedStateForWrite(
}
function pruneRetiredTypedState(state: VoidSelfStateTypedProjection): void {
state.moderationCursor.openCases = state.moderationCursor.openCases.filter((entry) =>
!isTerminalCaseStatus(entry.status)
);
state.thoughtMemory.shortTerm = state.thoughtMemory.shortTerm.filter(isNotRetiredEntry);
state.thoughtMemory.memories = state.thoughtMemory.memories.filter(isNotRetiredEntry);
state.thoughtMemory.incubation = state.thoughtMemory.incubation.filter(isNotRetiredEntry);
state.agencyPressure.pressures = state.agencyPressure.pressures.filter(isNotRetiredEntry);
state.candidateInterventions.interventions = state.candidateInterventions.interventions.filter(isNotRetiredEntry);
state.candidateInterventions.interventions = state.candidateInterventions.interventions.filter(isLiveCandidateIntervention);
state.faceAffect.needs = state.faceAffect.needs.filter(isNotRetiredEntry);
state.faceAffect.socialBonds = state.faceAffect.socialBonds.filter(isNotRetiredEntry);
state.faceAffect.statusReads = state.faceAffect.statusReads.filter(isNotRetiredEntry);
@ -259,6 +262,10 @@ function isNotRetiredEntry(entry: { status?: string; retiredAt?: string }): bool
return entry.status !== "retired" && !entry.retiredAt;
}
function isLiveCandidateIntervention(entry: { status?: string; retiredAt?: string }): boolean {
return (entry.status === "queued" || entry.status === "deferred") && !entry.retiredAt;
}
function clampFutureTimestampFields<T extends Record<string, unknown>>(
value: T,
observedAt: string,

View file

@ -395,7 +395,7 @@ function Test-CandidateMatchesPressure {
[Parameter(Mandatory = $true)]
[string] $PressureId,
[string] $PressureTargetKey,
[string[]] $AllowedStatuses = @("queued", "spoken")
[string[]] $AllowedStatuses = @("queued", "deferred")
)
$status = Get-ObjectPropertyString -Value $Candidate -Name "status"
@ -511,7 +511,7 @@ function Get-SpeechPressureObligations {
$pressureId = Get-ObjectPropertyString -Value $_ -Name "pressureId"
$pressureTargetKey = Get-ThoughtTargetKey -Target (Get-ObjectPropertyValue -Value $_ -Name "target")
-not ($candidateInterventions | Where-Object {
Test-CandidateMatchesPressure -Candidate $_ -PressureId $pressureId -PressureTargetKey $pressureTargetKey -AllowedStatuses @("queued")
Test-CandidateMatchesPressure -Candidate $_ -PressureId $pressureId -PressureTargetKey $pressureTargetKey -AllowedStatuses @("queued", "deferred")
} | Select-Object -First 1)
} |
ForEach-Object {
@ -845,17 +845,17 @@ function Assert-SpokenCandidateApplied {
$candidate = @(
@(Convert-ToValueArray -Value $state.candidateInterventions.interventions) |
Where-Object { (Get-ObjectPropertyString -Value $_ -Name "interventionId") -eq $InterventionId }
)[0]
) | Select-Object -First 1
$receipt = @(
@(Convert-ToValueArray -Value $state.speechReceipts.recentReceipts) |
Where-Object { (Get-ObjectPropertyString -Value $_ -Name "receiptKey") -eq $ReceiptKey }
)[0]
) | Select-Object -First 1
if ($null -eq $candidate -or (Get-ObjectPropertyString -Value $candidate -Name "status") -ne "spoken") {
throw "Delivery receipt '$ReceiptKey' was recorded without retiring candidate '$InterventionId' as spoken."
if ($null -ne $candidate) {
throw "Delivery receipt '$ReceiptKey' was recorded but terminal candidate '$InterventionId' stayed in current state."
}
if ($null -eq $receipt -or (Get-ObjectPropertyString -Value $receipt -Name "candidateInterventionId") -ne $InterventionId) {
throw "Candidate '$InterventionId' was marked spoken without a linked delivery receipt '$ReceiptKey'."
throw "Candidate '$InterventionId' was delivered without a linked delivery receipt '$ReceiptKey'."
}
}

View file

@ -139,8 +139,8 @@ try {
if ($activeMemories.Count -ne 1 -or $identityMemory.memoryId -ne "identity-memory-plasticity") {
throw "Memory lifecycle fixture expected one active crystallized identity memory."
}
if ($retiredMemories.Count -lt 2) {
throw "Memory lifecycle fixture expected superseded durable memories to be retired."
if ($retiredMemories.Count -ne 0) {
throw "Memory lifecycle fixture left superseded durable memories in current state."
}
if ($null -eq $value) {
throw "Memory lifecycle fixture did not crystallize a self-profile value."
@ -149,7 +149,7 @@ try {
@{
status = "ok"
activeMemoryCount = $activeMemories.Count
retiredMemoryCount = $retiredMemories.Count
retainedRetiredMemoryCount = $retiredMemories.Count
value = $value.label
} | ConvertTo-Json -Compress
} finally {

View file

@ -242,7 +242,8 @@ process.stdout.write(JSON.stringify({ ok: true, mode: "channel", channelId }) +
$status = Get-Content -LiteralPath $statusPath -Raw -Encoding UTF8 | ConvertFrom-Json
if ($status.status -ne "ok") {
throw "Speech fixture did not finish ok."
$failureMessage = if ($null -ne $status.PSObject.Properties["failureMessage"]) { [string]$status.failureMessage } else { "(no failure message)" }
throw "Speech fixture did not finish ok: $failureMessage"
}
if ([int]$status.proposedOperationCount -ne 3 -or [int]$status.appliedOperationCount -ne 5 -or [int]$status.deliveredCandidateCount -ne 1) {
throw "Speech fixture expected three proposals, five applied operations, and one delivered candidate."
@ -250,25 +251,25 @@ process.stdout.write(JSON.stringify({ ok: true, mode: "channel", channelId }) +
$stateJson = node -e "const core=require('./packages/core/dist/index.js'); core.loadVoidSelfStateTypedDocuments({canonicalPath: process.argv[1]}).then((state)=>console.log(JSON.stringify(state))).catch((error)=>{ console.error(error); process.exit(1); })" $stateFilePath
$state = $stateJson | ConvertFrom-Json
$candidate = @($state.candidateInterventions.interventions | Where-Object { $_.interventionId -eq "fixture-parent-owned-speech" })[0]
$duplicateCandidate = @($state.candidateInterventions.interventions | Where-Object { $_.interventionId -eq "fixture-duplicate-same-reply-target" })[0]
$alreadyAnsweredCandidate = @($state.candidateInterventions.interventions | Where-Object { $_.interventionId -eq "fixture-already-answered-reply-target" })[0]
$candidate = @($state.candidateInterventions.interventions | Where-Object { $_.interventionId -eq "fixture-parent-owned-speech" }) | Select-Object -First 1
$duplicateCandidate = @($state.candidateInterventions.interventions | Where-Object { $_.interventionId -eq "fixture-duplicate-same-reply-target" }) | Select-Object -First 1
$alreadyAnsweredCandidate = @($state.candidateInterventions.interventions | Where-Object { $_.interventionId -eq "fixture-already-answered-reply-target" }) | Select-Object -First 1
$receipt = @(
$state.speechReceipts.recentReceipts |
Where-Object {
$property = $_.PSObject.Properties["candidateInterventionId"]
$null -ne $property -and $property.Value -eq "fixture-parent-owned-speech"
}
)[0]
) | Select-Object -First 1
if ($candidate.status -ne "spoken") {
throw "Speech fixture did not mark the candidate spoken."
if ($null -ne $candidate) {
throw "Speech fixture left the delivered candidate in current state."
}
if ($duplicateCandidate.status -ne "retired") {
throw "Speech fixture did not retire the duplicate same-target candidate."
if ($null -ne $duplicateCandidate) {
throw "Speech fixture left the duplicate same-target candidate in current state."
}
if ($alreadyAnsweredCandidate.status -ne "retired") {
throw "Speech fixture did not retire the already-answered reply target candidate."
if ($null -ne $alreadyAnsweredCandidate) {
throw "Speech fixture left the already-answered reply target candidate in current state."
}
if ($receipt.channelId -ne "fixture-channel-id" -or $receipt.replyToMessageId -ne "fixture-message-id") {
throw "Speech fixture did not preserve the delivery receipt target."
@ -276,9 +277,9 @@ process.stdout.write(JSON.stringify({ ok: true, mode: "channel", channelId }) +
if ($receipt.candidateInterventionId -ne "fixture-parent-owned-speech") {
throw "Speech fixture did not link the delivery receipt back to the spoken candidate."
}
$answeredCase = @($state.moderationCursor.openCases | Where-Object { $_.sourceMessageId -eq "fixture-answered-message-id" })[0]
if ($answeredCase.status -ne "answered" -or $answeredCase.summary -match "not answered") {
throw "Speech fixture did not normalize the answered open-case summary."
$answeredCase = @($state.moderationCursor.openCases | Where-Object { $_.sourceMessageId -eq "fixture-answered-message-id" }) | Select-Object -First 1
if ($null -ne $answeredCase) {
throw "Speech fixture left an answered open case in current state."
}
$lastMessage = Get-Content -LiteralPath (Join-Path $fixtureStatusDir "moderation-rumination-last-message.txt") -Raw -Encoding UTF8
if ($lastMessage -notmatch "deliveredCandidates=1") {
@ -287,8 +288,8 @@ process.stdout.write(JSON.stringify({ ok: true, mode: "channel", channelId }) +
@{
status = "ok"
candidateStatus = $candidate.status
staleDuplicateStatus = $alreadyAnsweredCandidate.status
candidateRetained = $null -ne $candidate
staleDuplicateRetained = $null -ne $alreadyAnsweredCandidate
receiptCount = @($state.speechReceipts.recentReceipts).Count
deliveredCandidateCount = [int]$status.deliveredCandidateCount
} | ConvertTo-Json -Compress

View file

@ -269,8 +269,8 @@ try {
$stateJson = Invoke-NodeChecked -Arguments @("-e", "const core=require('./packages/core/dist/index.js'); core.loadVoidSelfStateTypedDocuments({canonicalPath: process.argv[1]}).then((state)=>console.log(JSON.stringify(state))).catch((error)=>{ console.error(error); process.exit(1); })", $candidate.stateFilePath)
$state = $stateJson | ConvertFrom-Json
$queued = @($state.candidateInterventions.interventions | Where-Object { $_.interventionId -eq "fixture-pressure-candidate" })[0]
if ($null -eq $queued -or $queued.status -ne "queued" -or -not @($queued.tags).Contains("source_pressure:fixture-pressure-wants-a-mouth")) {
throw "Candidate speech-pressure fixture did not preserve the queued pressure candidate."
if ($null -eq $queued -or $queued.status -ne "deferred" -or -not @($queued.tags).Contains("source_pressure:fixture-pressure-wants-a-mouth")) {
throw "Candidate speech-pressure fixture did not preserve the live deferred pressure candidate."
}
@{

View file

@ -282,3 +282,4 @@
{"ts":"2026-05-22T19:12:12Z","type":"fix","status":"ok","note":"Fixed Void self-state write semantics so retired typed entries are pruned from current documents instead of retained as tombstones. Repaired Mimir's .cc: file shrank from about 54KB to 27KB, retains 8 global typed documents, has zero retired entries in typed arrays, and raw bytes no longer contain LocalCastBridge/wet-voice/witness/canary residue."}
{"ts":"2026-05-22T19:23:18Z","type":"maintenance","status":"ok","note":"Ran swarm-wide .cc hygiene after Mimir exposed retained tombstones. Repo Face state files now repair through pruned writes: all registered repo Faces retain 8 global typed documents with zero retired entries; collapse loop terms LocalCastBridge/wet-voice/canary were removed from active repo Face .cc state except Nibu's legitimate Aetheria witness vocabulary. Void's own self-state was also repaired, shrinking from about 171KB to 135KB and removing 5 retired memories, 5 retired agency pressures, and 11 retired interventions."}
{"ts":"2026-05-22T19:24:10Z","type":"maintenance","status":"ok","note":"Completed swarm-wide state pocket-cleaning. Repaired all registered repo Face .cc files and Void self-state with pruned write semantics, removed old proof-loop receipts/state from Aqua/Epiphany/Libby/Bifrost and stale LocalCastBridge memories/cursor entries from Void, verified registered Face state files have 8 envelopes and zero retired entries; only Nibu retains witness wording as active Aetheria continuity/residue vocabulary."}
{"ts":"2026-05-22T19:45:13Z","type":"fix","status":"ok","note":"Pruned terminal audit residue from current self-state: write normalization now drops terminal open cases and keeps only queued/deferred candidate interventions. Repaired Void self-state from about 125KB to 95KB by removing 21 terminal candidates and 2 answered cases; speech receipts remain bounded audit evidence. Updated speech and memory lifecycle fixtures for the new contract."}