{"record":{"id":"b35b60a67c7cbb2d","repo":"Hmbown/CodeWhale","slug":"pet-checkpoint-telemetry-does-not-match-its-clock-world","errorCode":null,"errorMessage":"Pet checkpoint telemetry does not match its clock.","messagePattern":"Pet checkpoint telemetry does not match its clock\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"pet/src/core/pet-world.ts","lineNumber":254,"sourceCode":"      || 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\n   * replaying their sound or exposing a stale request as current work. */\n  resumeObservation(): void {\n    const last = this.tapeLog.at(-1), end = last ? (last.sequence + 1) * 12 : 0;","sourceCodeStart":236,"sourceCodeEnd":272,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/pet/src/core/pet-world.ts#L236-L272","documentation":"A checkpoint's frame.telemetry snapshot must exactly equal the tape bucket the checkpoint's frame.timeMs falls inside (or be undefined when the time lies outside any bucket). restore recomputes the expected telemetry from the tape and compares; a mismatch means the checkpoint's telemetry was not derived from that tape at that clock time.","triggerScenarios":"Calling PetWorld.restore(points, tape, interactions, c) where c.frame.telemetry was hand-set, computed from a different tape bucket, or the frame.timeMs was edited so it now lands in a different bucket than the recorded telemetry.","commonSituations":"Adjusting frame.timeMs during a migration without recomputing telemetry; copying telemetry from another tick; serialization that altered telemetry fields subtly (float formatting aside, via JSON compare).","solutions":["Use checkpoints emitted by the library itself; do not edit frame.timeMs or frame.telemetry manually.","Re-take the checkpoint from a live world so telemetry and time are regenerated together.","Ensure the paired tape is the exact tape the checkpoint was captured against."],"exampleFix":"// before\nc.frame.timeMs = 12345; // edited by hand\nPetWorld.restore(points, tape, interactions, c); // throws\n// after\nconst world = PetWorld.restore(points, tape, interactions, originalC); // restore unmodified checkpoint","handlingStrategy":"try-catch","validationCode":null,"typeGuard":null,"tryCatchPattern":"try {\n  const world = PetWorld.restore(points, tape, interactions, c);\n} catch (e) {\n  if (e.message === 'Pet checkpoint telemetry does not match its clock.') {\n    // checkpoint was hand-edited or paired with the wrong tape; re-take it\n  } else throw e;\n}","preventionTips":["Never edit frame.timeMs or frame.telemetry in a checkpoint.","Use world.checkpoint(2) to generate checkpoints, never manual construction.","Migrate checkpoints with library tooling, not ad-hoc field edits."],"tags":["checkpoint","telemetry","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"}