{"record":{"id":"f68a01789984b0ab","repo":"Hmbown/CodeWhale","slug":"pet-checkpoint-does-not-match-its-recording-world","errorCode":null,"errorMessage":"Pet checkpoint does not match its recording.","messagePattern":"Pet checkpoint does not match its recording\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"pet/src/core/pet-world.ts","lineNumber":251,"sourceCode":"      || c.frame.food !== null && (!c.frame.food || !range(c.frame.food.x, -1, 1) || !range(c.frame.food.y, -1, 1.21) || !range(c.frame.food.life, 0, 1))\n      || JSON.stringify(c.frame.pod) !== JSON.stringify(c.members)\n      || !Array.isArray(c.voices) || c.voices.length > 1024\n      || c.voices.some(v => !v || typeof v.id !== 'string' || v.id.length > 256))\n      throw new Error('Invalid pet world checkpoint.');\n    validatePetState(c.frame.state);\n    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) { world.hasTelemetry = c.hasTelemetry!; world.origin = structuredClone(c); }\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)) throw new Error('Pet checkpoint telemetry does not match its clock.');\n    world.sim.restore(c.sim); world.score.restore(c.score); world.random.restore(c.random);\n    world.accumulator = c.accumulator; world.tick = c.tick; world.bucketIndex = c.bucketIndex;\n    world.interactionIndex = c.interactionIndex; world.branchTick = c.branchTick;\n    world.behaviour = c.behaviour; world.until = c.until; world.targetX = c.targetX; world.targetY = c.targetY;\n    world.x = c.x; world.y = c.y; world.flip = c.flip; world.lit = c.lit;\n    world.lastActivity = c.lastActivity; world.addressedAt = c.addressedAt ?? -Infinity; world.waitSince = c.waitSince;\n    world.food = structuredClone(c.food); world.members = new Map(c.members.map(m => [m.id, { ...m }]));\n    world.lastStill = c.lastStill;\n    // JSON omits undefined properties; keep the same frame shape as makeFrame.\n    world.frame = { ...structuredClone(c.frame), telemetry: telemetry ? structuredClone(telemetry) : undefined };\n    world.voices = structuredClone(c.voices);\n    return world;\n  }\n\n  /** Resume observation beyond all already accepted live packets, without","sourceCodeStart":233,"sourceCodeEnd":269,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/pet/src/core/pet-world.ts#L233-L269","documentation":"After structural validation, restore replays the tape/interactions and checks the checkpoint is consistent with the recording it claims to summarize: no unconsumed tape bucket before/at the checkpoint time may carry observed events, prior interactions must not exceed frame time, and the next interaction must not already be due. A mismatch means the checkpoint was not taken at that exact point of that recording.","triggerScenarios":"Calling PetWorld.restore(points, tape, interactions, c) with a checkpoint that belongs to a different tape/interaction log, a tape truncated or extended after the checkpoint was taken, or interactions reordered/inserted before interactionIndex.","commonSituations":"Pairing a checkpoint from session A with the tape from session B; editing the tape to drop buckets without re-taking the checkpoint; reordering interaction events during storage migration.","solutions":["Restore using the tape and interaction log that were captured together with the checkpoint (as in the original recording blob).","Re-take the checkpoint (world.checkpoint(2)) against the current tape if the recording was legitimately modified.","Verify storage did not reorder or drop tape buckets/interactions between capture and restore."],"exampleFix":"// before\nPetWorld.restore(points, tapeFromOtherSession, interactions, c); // throws\n// after\nconst rec = JSON.parse(world.recording());\nPetWorld.restore(points, rec.tape, rec.interactions, c);","handlingStrategy":"validation","validationCode":"// Ensure checkpoint and tape came from the same recording blob:\nif (!recordingContainsCheckpoint(rec, c)) throw new Error('checkpoint does not belong to this recording');","typeGuard":"function isCheckpointOf(rec: PetRecording, c: PetCheckpoint): boolean {\n  return rec.checkpoint === c || rec.start === c || (rec.checkpoint && JSON.stringify(rec.checkpoint) === JSON.stringify(c));\n}","tryCatchPattern":"try {\n  const world = PetWorld.restore(points, rec.tape, rec.interactions, c);\n} catch (e) {\n  if (e.message === 'Pet checkpoint does not match its recording.') {\n    // re-pair checkpoint with its original tape/interactions\n  } else throw e;\n}","preventionTips":["Always restore with the tape/interactions stored alongside the checkpoint.","Never mutate a recording's tape after checkpointing.","Keep recording blobs immutable once written."],"tags":["checkpoint","replay","consistency"],"backgroundTag":"internal-invariant-violation","analyzedSha":"433685b2024e7bc4c99e1e2e326bcad39b4d9d65","analyzedAt":"2026-09-15T12:24:24.634Z","contentChangedAt":"2026-09-15T12:24:24.634Z","schemaVersion":2},"datasetVersion":"2026-09-22T16:17:23.217Z"}