{"record":{"id":"7def3d224bf1a539","repo":"Hmbown/CodeWhale","slug":"pet-checkpoint-does-not-match-its-recording","errorCode":null,"errorMessage":"Pet checkpoint does not match its recording.","messagePattern":"Pet checkpoint does not match its recording\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/tui/pet_watch/pet-native.js","lineNumber":382,"sourceCode":"            || c.voices.some(v => !v || typeof v.id !== 'string' || v.id.length > 256))\n            throw new Error('Invalid pet world checkpoint.');\n        (0, pet_sim_js_1.validatePetState)(c.frame.state);\n        (0, pet_audio_js_1.renderPetPCM)(c.voices, 0, 0);\n        const world = new PetWorld(points, tape, interactions, c.sim?.expressionVersion ?? 1, c.petCheckpointVersion === 2);\n        if (c.petCheckpointVersion === 2) {\n            world.hasTelemetry = c.hasTelemetry;\n            world.origin = structuredClone(c);\n        }\n        if (c.history !== world.historyDigest()\n            || c.bucketIndex >= 0 && world.tape[c.bucketIndex].simTimeMs > c.frame.timeMs + 1e-7\n            // acceptTelemetry may fill past gaps after the most recent fixed tick.\n            // Preserve that pending cursor exactly; it may lag only over empty gaps.\n            || world.tape.some((b, i) => i > c.bucketIndex && b.simTimeMs <= c.frame.timeMs + 1e-7\n                && (b.observed !== 0 || b.channel !== 'other' || b.errors || b.waiting || b.agentIds.length\n                    || b.onsets.some(Boolean) || b.activeMs.some(Boolean)))\n            || world.interactionLog.slice(0, c.interactionIndex).some(e => e.timeMs > c.frame.timeMs + 1e-7)\n            || world.interactionLog[c.interactionIndex]?.timeMs <= c.frame.timeMs + 1e-7)\n            throw new Error('Pet checkpoint does not match its recording.');\n        const candidate = world.tape[c.bucketIndex];\n        const telemetry = candidate && c.frame.timeMs < candidate.simTimeMs + candidate.durationMs ? candidate : undefined;\n        if (JSON.stringify(c.frame.telemetry) !== JSON.stringify(telemetry))\n            throw new Error('Pet checkpoint telemetry does not match its clock.');\n        world.sim.restore(c.sim);\n        world.score.restore(c.score);\n        world.random.restore(c.random);\n        world.accumulator = c.accumulator;\n        world.tick = c.tick;\n        world.bucketIndex = c.bucketIndex;\n        world.interactionIndex = c.interactionIndex;\n        world.branchTick = c.branchTick;\n        world.behaviour = c.behaviour;\n        world.until = c.until;\n        world.targetX = c.targetX;\n        world.targetY = c.targetY;\n        world.x = c.x;\n        world.y = c.y;","sourceCodeStart":364,"sourceCodeEnd":400,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/tui/pet_watch/pet-native.js#L364-L400","documentation":"After rebuilding the world from a checkpoint, PetWorld cross-checks the snapshot against its recording: every tape bucket after bucketIndex must be empty of observed activity, all interaction-log entries before interactionIndex must be at or before frame.timeMs, and the next interaction entry must be after it. A mismatch means the checkpoint and its backing recording are inconsistent, so resume would replay or drop events incorrectly. The library throws rather than silently diverging from the recorded timeline.","triggerScenarios":"Restoring a checkpoint where a non-empty tape bucket exists after c.bucketIndex with simTimeMs <= frame.timeMs, where logged interactions before interactionIndex are later than frame.timeMs, or where the interaction at interactionIndex has timeMs <= frame.timeMs + 1e-7 — i.e. the checkpoint's playhead and interaction cursor disagree with the tape/interaction log.","commonSituations":"Mixing a checkpoint from one recording with the tape of another; trimming or rotating the tape log after the checkpoint was taken; checkpoint/telemetry writes that are not atomic so the tape advanced past the saved playhead; hand-splicing interaction logs.","solutions":["Restore the checkpoint together with the exact tapeLog and interactionLog it was saved from — do not mix snapshots across recordings.","Re-take the checkpoint at the current playhead instead of restoring the stale one.","If the tape was trimmed, advance bucketIndex/interactionIndex in the checkpoint to a consistent point or drop the checkpoint.","Enable atomic persistence so tape and checkpoint are written together."],"exampleFix":"// before: pairing checkpoint c with a longer/newer tapeLog\nconst world = new PetWorld(points, c.tapeLog, c.interactionLog, ...); // throws\n// after: use the tapeLog snapshotted inside the same checkpoint\nconst world = new PetWorld(points, c.tape, c.interactionLog, ...);","handlingStrategy":"validation","validationCode":"function checkpointMatchesRecording(c, tape, interactionLog) {\n  const eps = 1e-7;\n  const stray = tape.some((b, i) => i > c.bucketIndex && b.simTimeMs <= c.frame.timeMs + eps &&\n    (b.observed !== 0 || b.channel !== 'other' || b.errors || b.waiting || b.agentIds.length || b.onsets.some(Boolean) || b.activeMs.some(Boolean)));\n  if (stray) return false;\n  if (interactionLog.slice(0, c.interactionIndex).some(e => e.timeMs > c.frame.timeMs + eps)) return false;\n  return !(interactionLog[c.interactionIndex]?.timeMs <= c.frame.timeMs + eps);\n}","typeGuard":"const isConsistentCheckpoint = (c) => Number.isInteger(c?.bucketIndex) && Number.isInteger(c?.interactionIndex) && typeof c?.frame?.timeMs === 'number';","tryCatchPattern":"try {\n  world = new PetWorld(points, tape, interactions, ver, v2);\n  // matching checks run during restore\n} catch (e) {\n  if (e.message === 'Pet checkpoint does not match its recording.') {\n    world = replayFromStart(tape); // fall back to full replay\n  } else throw e;\n}","preventionTips":["Always persist checkpoint, tapeLog, and interactionLog atomically in one write","Never pair a checkpoint with a different recording's tape","Re-take checkpoints after any tape trimming or rotation","Test restore against the exact recording it was saved from"],"tags":["checkpoint","consistency","replay"],"backgroundTag":"internal-invariant-violation","analyzedSha":"73e0f67d83c59909b571efdfc88c4bc28c309cb1","analyzedAt":"2026-09-22T01:30:00.501Z","contentChangedAt":"2026-09-22T01:30:00.501Z","schemaVersion":2},"datasetVersion":"2026-09-22T16:17:23.217Z"}