Normalize legacy moderation status output

This commit is contained in:
Meta Vens 2026-06-04 21:43:41 +01:00
commit d829c69ee2
3 changed files with 96 additions and 3 deletions

View file

@ -384,6 +384,57 @@ function Convert-ToOperationArray {
return @($Value)
}
function Convert-ModerationUserStatusesPatchToOperations {
param($Operation)
$userStatuses = Get-ObjectPropertyValue -Value $Operation -Name "userStatuses"
if ($null -eq $userStatuses) {
$userStatuses = Get-ObjectPropertyValue -Value $Operation -Name "moderationUserStatuses"
}
if ($null -eq $userStatuses) {
return @()
}
return @(
@(Convert-ToValueArray -Value $userStatuses) |
Where-Object { $null -ne $_ } |
ForEach-Object {
@{
operation = "upsert_moderation_user_status"
status = $_
}
}
)
}
function Normalize-ProposedRuminationOperations {
param($Operations)
$normalized = @()
foreach ($operation in @(Convert-ToOperationArray -Value $Operations)) {
if ($null -eq $operation) {
continue
}
$operationName = Get-ObjectPropertyString -Value $operation -Name "operation"
if ($null -ne $operationName) {
$normalized += $operation
continue
}
$statusOperations = @(Convert-ModerationUserStatusesPatchToOperations -Operation $operation)
if ($statusOperations.Count -gt 0) {
Append-RunLog ("normalized legacy moderation user status patch into {0} operation(s)." -f $statusOperations.Count)
$normalized += $statusOperations
continue
}
$normalized += $operation
}
return @($normalized)
}
function Test-OpenCaseRequiresRumination {
param($Case)
@ -1346,7 +1397,7 @@ if (-not (Test-Path $operationOutputPath)) {
}
Append-RunLog "reading proposed operation output."
$proposedOperations = @(Convert-ToOperationArray -Value (Read-JsonFile -Path $operationOutputPath))
$proposedOperations = @(Normalize-ProposedRuminationOperations -Operations (Read-JsonFile -Path $operationOutputPath))
$appliedOperations = @()
Assert-SpeechPressureObligationsResolved -Obligations $speechPressureObligations -Operations $proposedOperations

View file

@ -157,6 +157,41 @@ process.stdin.on("end", () => {
tags: ["fixture"],
},
},
{
userStatuses: [
{
userId: "fixture-status-user",
userName: "Fixture Status User",
status: "active",
summary: "Fixture legacy patch should normalize into an upsert operation.",
strikes: [
{
strikeId: "fixture-status-strike",
reason: "testing legacy userStatuses normalization",
ruleRef: "fixture-rule",
sourceMessageId: "fixture-status-message",
channelId: "fixture-channel",
issuedAt: "2026-06-04T00:00:00.000Z",
expiresAt: "2026-06-11T00:00:00.000Z",
issuedBy: "Void",
tags: ["fixture"],
},
],
pendingNotices: [
{
noticeId: "fixture-status-notice",
kind: "strike_added",
summary: "Fixture status notice",
body: "Fixture moderation status notice.",
createdAt: "2026-06-04T00:00:00.000Z",
tags: ["fixture"],
},
],
updatedAt: "2026-06-04T00:00:00.000Z",
tags: ["fixture"],
},
],
},
];
mkdirSync(dirname(operationOutputPath), { recursive: true });
@ -212,8 +247,8 @@ process.stdin.on("end", () => {
if ($status.status -ne "ok") {
throw "Rumination fixture did not finish ok."
}
if ([int]$status.proposedOperationCount -ne 4 -or [int]$status.appliedOperationCount -ne 4) {
throw "Rumination fixture expected four proposed/applied operations."
if ([int]$status.proposedOperationCount -ne 5 -or [int]$status.appliedOperationCount -ne 5) {
throw "Rumination fixture expected five proposed/applied operations."
}
$contextRaw = Get-Content -LiteralPath $contextPath -Raw -Encoding UTF8
@ -241,6 +276,7 @@ process.stdin.on("end", () => {
$incubation = @($state.thoughtMemory.incubation)
$agency = @($state.agencyPressure.pressures)
$candidates = @($state.candidateInterventions.interventions)
$moderationStatuses = @($state.moderationCursor.userStatuses)
if ($shortTerm.Count -ne 1 -or $shortTerm[0].memoryId -ne "fixture-rumination-short-term") {
throw "Rumination fixture did not persist the short-term memory proposal."
@ -257,6 +293,10 @@ process.stdin.on("end", () => {
if ($candidates.Count -ne 1 -or $candidates[0].interventionId -ne "fixture-rumination-candidate") {
throw "Rumination fixture did not persist the candidate intervention proposal."
}
$userStatus = @($moderationStatuses | Where-Object { $_.userId -eq "fixture-status-user" }) | Select-Object -First 1
if ($null -eq $userStatus -or $userStatus.strikes[0].strikeId -ne "fixture-status-strike") {
throw "Rumination fixture did not normalize the legacy userStatuses patch."
}
@{
status = "ok"
@ -264,6 +304,7 @@ process.stdin.on("end", () => {
incubationCount = $incubation.Count
agencyPressureCount = $agency.Count
candidateCount = $candidates.Count
moderationStatusCount = $moderationStatuses.Count
} | ConvertTo-Json -Compress
} finally {
Remove-Item -LiteralPath $tempRoot -Recurse -Force -ErrorAction SilentlyContinue

View file

@ -342,3 +342,4 @@
{"ts":"2026-06-04T18:54:39Z","type":"implementation","status":"ok","note":"Created a canonical GameCult structured text CultCache store at .voidbot/private/gamecult-text-documents.cc. The first document is gamecult.odin_verse_poem with title, GameCult author, and half-line arrays; repo Face prompts now render the Odin poem from that typed document while Nightwing-style consumers can lower the same arrays with their own caesura/marquee formatting."}
{"ts":"2026-06-04T19:02:38Z","type":"implementation","status":"ok","note":"Added gamecult.love_colossus_poem as the second canonical GameCult structured text document, based on the 2026-06-01 Love Is How The Colossus Wakes article and refreshed against Bellows' Poetic Edda register. The document uses title/author/half-line arrays and previews through texts:seed --document-id gamecult.love_colossus_poem."}
{"ts":"2026-06-04T19:28:18Z","type":"implementation","status":"ok","note":"Moderation consequences now live in typed void.moderation_cursor userStatuses with one-week strike expiry and pending user-status notices; unattended Discord egress defaults through Bifrost bridge posts/DMs with direct VoidBot send helper retained only behind VOID_DISCORD_TRANSPORT=direct fallback."}
{"ts":"2026-06-04T20:43:18Z","type":"verification","status":"ok","note":"Rumination parent normalizes legacy top-level userStatuses model output into upsert_moderation_user_status operations; fixtures cover the stale shape and moderation status DM delivery."}