{"record":{"id":"eec091ebbc0a318d","repo":"Hmbown/CodeWhale","slug":"pet-segment-checkpoints-do-not-agree","errorCode":null,"errorMessage":"Pet segment checkpoints do not agree.","messagePattern":"Pet segment checkpoints do not agree\\.","errorType":"exception","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"crates/tui/src/tui/pet_watch/pet-native.js","lineNumber":265,"sourceCode":"        if (!r || ![1, 2].includes(r.petReplayVersion) || !Array.isArray(r.tape) || !Array.isArray(r.interactions))\n            throw new Error('Invalid pet recording.');\n        const version = r.expressionVersion === undefined ? 1 : r.expressionVersion;\n        if (![1, 2].includes(version))\n            throw new Error('Unsupported pet expression version.');\n        if (r.checkpoint !== undefined && !r.checkpoint || r.start !== undefined && !r.start)\n            throw new Error('Invalid pet checkpoint.');\n        for (const c of [r.start, r.checkpoint])\n            if (c && (c.sim?.expressionVersion ?? 1) !== version)\n                throw new Error('Pet expression version does not match its checkpoint.');\n        if (r.petReplayVersion === 1 && (r.start || r.checkpoint && r.checkpoint.petCheckpointVersion !== 1))\n            throw new Error('Invalid legacy pet recording.');\n        if (r.petReplayVersion === 2 && (!r.start || r.start.petCheckpointVersion !== 2 || r.start.historyStart !== r.start.tick))\n            throw new Error('The recording segment is missing its starting checkpoint.');\n        const first = r.start && PetWorld.restore(points, r.tape, r.interactions, r.start);\n        const world = r.checkpoint ? PetWorld.restore(points, r.tape, r.interactions, r.checkpoint) : first ?? new PetWorld(points, r.tape, r.interactions, version);\n        if (first) {\n            if (!world.segmented || world.tick < first.tick || r.checkpoint && r.checkpoint.historyStart !== first.tick)\n                throw new Error('Pet segment checkpoints do not agree.');\n            world.origin = first.checkpoint();\n        }\n        return world;\n    }\n    /** Retire only consumed input. The exact origin makes each archived segment\n     * independently replayable; no particle, random stream or score is reset. */\n    prepareSegment() {\n        const dropTape = Math.max(0, this.bucketIndex), dropInputs = this.interactionIndex, previous = this.origin;\n        const tape = this.tapeLog.slice(dropTape), interactions = this.interactionLog.slice(dropInputs);\n        const points = this.sim.p.map(p => [p.hx, p.hy]);\n        const c = this.checkpoint();\n        c.petCheckpointVersion = 2;\n        c.historyStart = this.tick;\n        c.hasTelemetry = this.hasTelemetry;\n        c.bucketIndex -= dropTape;\n        c.interactionIndex = 0;\n        c.history = new PetWorld(points, tape, interactions, this.sim.expressionVersion, true).historyDigest();\n        const next = PetWorld.restore(points, tape, interactions, c);","sourceCodeStart":247,"sourceCodeEnd":283,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/73e0f67d83c59909b571efdfc88c4bc28c309cb1/crates/tui/src/tui/pet_watch/pet-native.js#L247-L283","documentation":"After restoring both the start checkpoint (`first`) and the checkpoint (or falling back), fromRecording cross-checks them: the restored world must be segmented, the checkpoint's tick must be at or after the start's tick, and if a mid-recording checkpoint exists its historyStart must equal the start's tick. Any disagreement means the start and checkpoint were not produced by the same segment and the combined replay would be incoherent.","triggerScenarios":"Calling `PetWorld.fromRecording(points, r)` with both r.start and r.checkpoint where: the restored world is not segmented, world.tick < first.tick (checkpoint earlier than start), or r.checkpoint.historyStart !== first.tick.","commonSituations":"Mixing start/checkpoint pairs from different segments or recordings; appending ticks to one segment but not the other; copying a checkpoint from an older archive into a newer segment file; a commit() race in prepareSegment after the world advanced.","solutions":["Use start and checkpoint from the same recording/segment export — never mix them across files.","Verify checkpoint.tick >= start.tick and checkpoint.historyStart === start.tick before restoring.","Re-prepare the segment with prepareSegment() so both checkpoints are regenerated together.","Re-record the segment if the originals came from divergent histories."],"exampleFix":"// before\nconst r = { start: segA.start, checkpoint: segB.checkpoint, ... }; // mixed segments\nconst world = PetWorld.fromRecording(points, r); // throws\n// after\nconst r = { ...segA, start: segA.start, checkpoint: segA.checkpoint };\nconst world = PetWorld.fromRecording(points, r);","handlingStrategy":"validation","validationCode":"if (r.start && r.checkpoint) {\n  if (r.checkpoint.tick < r.start.tick || r.checkpoint.historyStart !== r.start.tick)\n    throw new Error('start/checkpoint belong to different segments');\n}","typeGuard":null,"tryCatchPattern":"try {\n  world = PetWorld.fromRecording(points, r);\n} catch (err) {\n  if (err.message === 'Pet segment checkpoints do not agree.')\n    console.error('Mixed segment data; re-prepare the segment.');\n  else throw err;\n}","preventionTips":["Always take start and checkpoint from the same export object.","Commit prepared segments immediately so the live world cannot drift.","Do not interleave restore/rollback with segment preparation.","Checksum segment files to detect mixing or partial copies."],"tags":["replay","checkpoint","consistency"],"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"}