import assert from 'node:assert/strict'; import { readFile } from 'node:fs/promises'; const [battleSource, campaignSource] = await Promise.all([ readFile( new URL( '../src/game/scenes/BattleScene.ts', import.meta.url ), 'utf8' ), readFile( new URL( '../src/game/state/campaignState.ts', import.meta.url ), 'utf8' ) ]); const publishStart = battleSource.indexOf( 'private publishFirstBattleReport(' ); const publishEnd = battleSource.indexOf( '\n private resultSubtitle(', publishStart ); assert( publishStart >= 0 && publishEnd > publishStart, 'BattleScene must retain a bounded result-persistence method.' ); const publishSource = battleSource.slice( publishStart, publishEnd ); assert( publishSource.includes( 'persistedReport = setFirstBattleReport(' ), 'BattleScene must persist its complete battle report through the atomic campaign writer.' ); assert( publishSource.includes( "this.resultReportPersistenceStatus =\n 'failed';" ) && publishSource.includes('return false;'), 'A failed campaign write must leave the result screen in an explicit retry state.' ); assert( publishSource.includes( "this.resultReportPersistenceStatus =\n 'complete';" ) && publishSource.includes('return true;'), 'A successful campaign write must mark the result report complete.' ); const continueStart = battleSource.indexOf( 'private handleResultContinue()' ); const continueEnd = battleSource.indexOf( '\n private hideBattleResult(', continueStart ); assert( continueStart >= 0 && continueEnd > continueStart, 'BattleScene must retain a bounded result continuation handler.' ); const continueSource = battleSource.slice( continueStart, continueEnd ); assert( continueSource.includes( "this.resultReportPersistenceStatus ===\n 'failed'" ) && continueSource.includes( '!this.publishFirstBattleReport(outcome)' ) && continueSource.includes( 'this.showBattleResult(outcome);' ), 'The result CTA must retry persistence in place and redraw the result only after recovery.' ); assert( battleSource.includes("return '저장 다시 시도';"), 'The failed result CTA must clearly say “저장 다시 시도”.' ); assert( battleSource.includes( "outcome === 'victory' ||\n this.resultReportPersistenceStatus === 'failed'" ), 'Defeat results with an unsaved report must also expose the persistence retry CTA.' ); assert( battleSource.includes( 'const retryButton = this.addResultButton(' ) && battleSource.includes( 'const titleButton = this.addResultButton(' ) && battleSource.includes( 'this.setResultButtonEnabled(\n retryButton,\n false' ) && battleSource.includes( 'this.setResultButtonEnabled(\n titleButton,\n false' ), 'Normal retry and title navigation must be visibly disabled while result persistence has failed.' ); assert( battleSource.includes( 'this.resultNavigationPending ||\n this.blockResultNavigationWhilePersistenceFailed()' ), 'All result navigation must retain a persistence-failure guard even if a disabled button is invoked indirectly.' ); assert( battleSource.includes( "const improvementEnabled =\n this.resultReportPersistenceStatus !==\n 'failed';" ) && battleSource.includes( "improvementEnabled,\n false,\n () => this.openResultSortieImprovement(outcome)" ), 'Result-screen formation improvement must remain disabled until the battle report is durable.' ); assert( battleSource.includes( 'reportPersistence:\n this.resultReportPersistenceStatus' ), 'The result persistence state must remain observable to the browser regression.' ); const persistenceStart = campaignSource.indexOf( 'function persistCampaignState(' ); const persistenceEnd = campaignSource.indexOf( '\nfunction tryStorage()', persistenceStart ); assert( persistenceStart >= 0 && persistenceEnd > persistenceStart, 'Campaign persistence must retain a bounded writer.' ); const persistenceSource = campaignSource.slice( persistenceStart, persistenceEnd ); const canonicalWrite = persistenceSource.indexOf( 'campaignSaveSlotKey(state.activeSaveSlot)' ); const compatibilityWrite = persistenceSource.indexOf( 'storage.setItem(campaignStorageKey, serialized)' ); assert( canonicalWrite >= 0 && compatibilityWrite > canonicalWrite, 'The canonical campaign slot must be written before the compatibility mirror.' ); console.log( 'Verified battle-result persistence failure/retry UI, debug observability, and canonical-slot-first atomic write contract.' );