assert(!/\bcombo\b/i.test(activeGameplaySource)&&!/\bundo\b/i.test(activeGameplaySource)&&!/\b(combo|undo)\b/i.test(html),'Combo or visible undo remains in active gameplay/UI source');
assert(/\bcombo\b/.test(retiredFieldCleanup)&&/\bundo\b/.test(retiredFieldCleanup),'Legacy combo/undo fields are not explicitly removed during synchronization');
assert(!functionSource('globalForStorage').includes('combo')&&!functionSource('globalForStorage').includes('undo'),'Retired fields are still written');
assert(lensReward(0)===1&&lensReward(1)===1.25&&lensReward(2)===1.4&&lensReward(99)===1.5,'Score-lens diminishing cap is invalid');
assert(functionSource('rewardDetailsForBoard').includes('timeAttackRewardModifier()')&&functionSource('recordTimeAttackScore').includes('baseCollected')&&functionSource('finishTimeAttack').includes('if(result.bonus>0)'),'Time-attack reward modifier is deferred or double-applied');
// 3. Difficulty-field feature removal and lightweight detailed-board rendering.
assert(!app.includes('level-min-10')&&!app.includes('level-max-10')&&!app.includes('fieldOverlayCanvas')&&!html.includes('fieldPreviewCanvas'),'Difficulty adjustment items or overlays remain active');
assert(functionSource('makeBoard').includes('boardCellsPath')&&!functionSource('makeBoard').includes('cellHits')&&functionSource('desiredInteractiveBoardIds').includes('for(const id of ids)'),'Visible detailed boards are missing or still allocate per-cell hit nodes');
// 4-6. Center snapping without sticky hysteresis/speculative turns, and silent invalid motion.
for(constmarkerof['rawPointerPosition','currentConfirmedCell','candidateDirection','currentCandidateCell','renderedHandlePosition'])assert(functionSource('drawingForPath').includes(marker),`Pointer state is missing ${marker}`);
assert(app.includes('POINTER_SNAP_THRESHOLD=CELL*.45')&&!app.includes('POINTER_SNAP_RELEASE')&&!app.includes('hysteresisDragPoint'),'Single-threshold pointer snapping or hysteresis removal is incomplete');
assert(functionSource('pointerEventSamples').includes("pointerType!=='mouse'")&&functionSource('processBoardDragFrame').includes('scheduler.latest()'),'Ordered pointer samples are not preserved through a drag frame');
assert(!functionSource('extendOne').includes('toast(')&&functionSource('extendOne').includes("if(lock&&!pathHasLockKey(path,lock))return false"),'Invalid direction still produces error feedback');
assert(functionSource('openTipMergePlan').includes('tipDistance!==0')&&!app.includes('function pickupJoinStepsAtPoint'),'Adjacent path pickups can still auto-connect');
assert(functionSource('openTipMergePlan').includes('seen.has(key)')&&functionSource('joinTips').includes('cancelBoardDragFrame(b)')&&functionSource('joinTips').includes('safeRelease(b.svg,pointerId)'),'Pickup merging can duplicate an overlapping route or retain pointer work after joining');
// 7. Level schedule and introduction memory.
for(letlevel=1;level<=4;level++)assert(AppLogic.specialSchedule(level,100,level).types.length===0,`Level ${level} scheduled a special`);
for(constlevelof[5,6]){constschedule=AppLogic.specialSchedule(level,100,level,['warp','lock','crossing'],[]);assert(schedule.types.length===1&&schedule.setCount===1,`Level ${level} did not schedule exactly one minimum type`)}
assert(introduction.types.length===1&&introduction.setCount===1&&introduction.introduction,'First encounter is not isolated at minimum density');
assert(functionSource('addSpecialCellPattern').includes('AppLogic.specialSchedule')&&!app.includes('SPECIAL_CELL_PRODUCTION_CHANCE'),'Legacy independent special chance remains active');
assert(functionSource('generatedPuzzleIssue').includes("crossingCoverage.has(key)?2:1"),'Generated crossing boards are rejected by single-owner coverage validation');
assert(first.status===second.status&&first.signature===second.signature,'Uniqueness result is not stable');
}
assert(BendPuzzle.verifyPuzzleUniqueness(multiple,{maxMs:1000,nodeCap:10000}).status==='multiple','Known multi-solution fixture was accepted');
assert(BendPuzzle.verifyPuzzleUniqueness({...plain,n:[[0,0,1]]},{maxMs:1000,nodeCap:10000}).status==='unsolved','Known unsolved fixture was not reported');
assert(BendPuzzle.verifyPuzzleUniqueness(multiple,{maxMs:1000,nodeCap:1}).status==='timeout','Node-cap timeout was not reported');
assert(worker.includes("action === 'verify'")&&functionSource('verifyPuzzleUniquenessAsync').includes("action:'verify'")&&!functionSource('verifyPuzzleUniquenessAsync').includes('verifyPuzzleUniqueness('),'Uniqueness is not worker-isolated');
// 9. Session suggestion.
assert(functionSource('scheduleTimeAttackSuggestionAfterCompletion').includes('sessionCompletionCount!==10')&&functionSource('tryShowTimeAttackSuggestion').includes('7000')&&html.includes('id="timeAttackSuggestion" role="status" aria-live="polite"'),'Completion-10 suggestion timing/live region is missing');
// 10. Minimap teleport and controls.
assert(!html.includes('id="teleportBtn"')&&html.includes('id="minimapOriginBtn"')&&html.includes('id="minimapRandomBtn"')&&!html.includes('id="minimapUnsolvedBtn"')&&!html.includes('id="minimapCurrentBtn"'),'Minimap teleport controls do not match origin/random');
assert(functionSource('centerRandomBoard').includes('getRandomValues')&&!app.includes('centerRandomUnsolved'),'Random minimap teleport still cycles through unsolved boards');
assert(functionSource('beginMinimapPointer').includes('centerWorldUnit')&&functionSource('moveMinimapPointer').includes('centerWorldUnit')&&html.includes('id="minimapCanvas" width="210" height="132" role="application" tabindex="0"'),'Direct/keyboard minimap interaction is missing');
assert(functionSource('centerWorldUnit').includes('worldNavigationBounds'),'Minimap teleport is not clamped to world navigation bounds');
assert(!functionSource('drawWorldOverview').includes('drawWorldOverviewPaths')&&functionSource('rebuildWorldOverviewCache').includes('drawMapLongLines'),'Far zoom does not use the minimap long-line renderer');
assert(functionSource('desiredInteractiveBoardIds').includes('for(const id of ids)')&&functionSource('renderBoardNow').includes('renderedConnectedLineWidth'),'Visible detailed boards do not preserve connected-line thickness');
assert(functionSource('rebuildWorldOverviewCache').includes('drawMapBoardCells')&&functionSource('rebuildWorldOverviewCache').includes('drawMapLongLines')&&!functionSource('rebuildWorldOverviewCache').includes('storeCellForMeta'),'Zoomed-out view no longer matches the minimap renderer');
assert(functionSource('leftFieldPanAllowed').includes("classList?.contains('solved')")&&functionSource('beginPan').includes('leftFieldPanAllowed(e)'),'Solved/undiscovered left-drag field panning is missing');
assert(priceContext.storeItemPrice({},null,{cost:2500})===3000&&priceContext.storeItemPrice({},null,{cost:10000})===8000,'Store prices do not enforce a 3,000 minimum while retaining higher price variation');
assert(JSON.stringify(seedA)===JSON.stringify(seedARepeat)&&JSON.stringify(seedA)!==JSON.stringify(seedB),'Store inventory is not deterministic per field seed');
assert(seedA.length===12&&newSet(seedA).size===12&&selected.filter(item=>item.cursorStyle).length===6&&selected.filter(item=>!item.cursorStyle).length===6,'Seeded store inventory is not exactly six cursors and six cosmetic/tool items');
assert(JSON.stringify(shopContext.shop.storeInventoryItems({seed:9},{itemIds:seedA}).map(item=>item.id))===JSON.stringify(seedA),'Persisted store inventory IDs are not honored');
// 11-12. Noise/reduced motion and bounded caches/worker.
assert(html.includes('id="noiseCanvas" width="80" height="64"')&&functionSource('scheduleNoiseBackground').includes('noisePainted')&&!functionSource('scheduleNoiseBackground').includes('setTimeout')&&functionSource('paintNoiseBackground').includes("perfCount('noiseFrames')"),'Static low-cost noise background is missing');
assert(css.includes('#noiseCanvas{')&&css.includes('opacity:.06'),'Noise effective opacity exceeds the low-contrast budget');
assert(functionSource('evictHydratedBoardDetails').includes('hydratedBoardLru.size>32')&&functionSource('evictHydratedBoardDetails').includes('hydratedBoardBytes>8*1024*1024')&&worker.includes('uniquenessCache.size > 256'),'Hydration or uniqueness cache is unbounded/missing');
// 13-14. Contextual HUD and active-board isolation.
assert(css.includes('#topbar.drawing-active')&&css.includes(':focus-within')&&css.includes('transition:opacity'),'Contextual HUD fading constraints are missing');
assert(!css.includes('.board-card:not(.input-active) .static-layer')&&!css.includes('filter:saturate')&&!css.includes('backdrop-filter')&&!css.includes('.board-card{filter:drop-shadow'),'Non-selected boards are dimmed or global presentation still creates costly filter surfaces');
assert(solveSource.indexOf('persistence=save(true)')<solveSource.indexOf('completionEffect(immediateBoard,award)')&&solveSource.indexOf('pushCloudPending(b.id)')<solveSource.indexOf('completionEffect(immediateBoard,award)'),'Completion is displayed before local persistence and shared-world confirmation');
assert(solveSource.includes('preparation=prepareExpansionCandidate(b.meta)')&&solveSource.includes('expandMeta(durableMeta,prepared)'),'Expansion generation does not start with the clear display or does not install against durable metadata');
assert(solveSource.includes('playGemCollectionAnimation(immediateBoard,award)')&&functionSource('playGemCollectionAnimation').includes('gemCollectionSources')&&functionSource('playGemCollectionAnimation').includes('scoreCountEl'),'Clear rewards do not travel from the board to the gem wallet');
assert(functionSource('skipCompletionVisuals').includes('finishCompletionVisual')&&functionSource('finishCompletionVisual').includes('visual.resolve'),'Completion visual is not independently skippable');
assert(app.includes('MAX_FRONTIER_GENERATION_CYCLES=3')&&functionSource('placeChildAtFrontier').includes('cycle<MAX_FRONTIER_GENERATION_CYCLES'),'Expansion generation can enter an unbounded retry loop');
assert(functionSource('expandMetaNow').includes('expansionRetryRound')&&functionSource('repairMetaFrontierNow').includes('round%frontiers.length')&&functionSource('repairExpansions').includes('repairMetaFrontier(meta)'),'Expansion repair repeats one deterministic seed/order and can leave permanent gaps');
assert(!functionSource('repairExpansions').includes('&&meta.puzzle')&&!functionSource('pendingExpansionCount').includes('&&meta.puzzle'),'Off-screen compact solved boards are excluded from expansion repair');
// 16. Bounded hydration and memory use without hiding visible puzzle details.
assert(functionSource('desiredInteractiveBoardIds').includes('for(const id of ids)')&&!app.includes('function promoteStaticBoard('),'Visible puzzles can still be replaced by on-demand summaries');
assert(app.includes('HYDRATE_CONCURRENCY=4')&&functionSource('evictHydratedBoardDetails').includes('hydratedBoardLru.size>32')&&functionSource('evictHydratedBoardDetails').includes('hydratedBoardBytes>8*1024*1024')&&app.includes('BOARD_RENDERS_PER_FRAME=6'),'Hydration, cache, or render work is not bounded');
assert(functionSource('drawPresenceLayer').includes('dpr=1')&&functionSource('drawReactionLayer').includes('dpr=1'),'Fullscreen online canvases still allocate high-DPR backing stores');
assert(html.includes('id="fpsCounter"')&&functionSource('refreshFpsCounter').includes('FPS ${fpsLastValue}')&&app.includes('MAX_RENDER_FPS=30')&&app.includes('AUXILIARY_FPS=30')&&app.includes('DRAG_TARGET_FPS=30'),'FPS diagnostics or split interaction budgets are missing');
assert(functionSource('scheduleNoiseBackground').includes('noisePainted')&&!functionSource('scheduleNoiseBackground').includes('setTimeout'),'Noise background still repaints continuously');
// 17. Bounded interaction burden in candidate selection.
assert(AppLogic.interactionBurden(plain).score<=40&&functionSource('placeChildAtFrontierAttempt').includes('AppLogic.interactionBurden')&&functionSource('placeChildAtFrontierAttempt').includes('boundedBurdenPenalty'),'Interaction burden is unbounded or not integrated');
assert(BendPuzzle.UNIQUENESS_RULE_VERSION===2&&BendPuzzle.verifyPuzzleUniqueness(lock,{maxMs:1000,nodeCap:10000}).quality?.contributingSpecials>=1,'Solution quality does not measure special contribution');
// 18. Encounter migration and synchronization.
assert(functionSource('normalizeSnapshot').includes('mechanicTypesForPuzzle')&&functionSource('mergeGlobalRecords').includes('specialMechanicsSeen')&&functionSource('addSpecialCellPattern').includes('data.specialMechanicsSeen'),'Special encounter memory is not migrated, synchronized, and consumed');
console.log('Gameplay simplification regression groups 1-18 passed');