{"record":{"id":"5d5a994cce9730d9","repo":"Hmbown/CodeWhale","slug":"pet-segment-checkpoints-do-not-agree-world","errorCode":null,"errorMessage":"Pet segment checkpoints do not agree.","messagePattern":"Pet segment checkpoints do not agree\\.","errorType":"validation","errorClass":"Error","httpStatus":null,"severity":"error","filePath":"pet/src/core/pet-world.ts","lineNumber":148,"sourceCode":"    return { petReplayVersion: this.segmented ? 2 : 1, expressionVersion: this.sim.expressionVersion,\n      tape: this.tapeLog.slice(0, tapeEnd), interactions: this.interactionLog.slice(0, inputEnd).map(e => ({ ...e })),\n      ...(this.origin ? { start: { ...structuredClone(this.origin), hasTelemetry: this.hasTelemetry, history } } : {}),\n      ...(withCheckpoint ? { checkpoint: { ...this.checkpoint(), history } } : {}) };\n  }\n\n  static fromRecording(points: [number, number][], value: unknown): PetWorld {\n    const r = value as PetRecording;\n    if (!r || ![1, 2].includes(r.petReplayVersion) || !Array.isArray(r.tape) || !Array.isArray(r.interactions)) throw new Error('Invalid pet recording.');\n    const version = r.expressionVersion === undefined ? 1 : r.expressionVersion;\n    if (![1, 2].includes(version)) throw new Error('Unsupported pet expression version.');\n    if (r.checkpoint !== undefined && !r.checkpoint || r.start !== undefined && !r.start) throw new Error('Invalid pet checkpoint.');\n    for (const c of [r.start, r.checkpoint]) if (c && (c.sim?.expressionVersion ?? 1) !== version) throw new Error('Pet expression version does not match its checkpoint.');\n    if (r.petReplayVersion === 1 && (r.start || r.checkpoint && r.checkpoint.petCheckpointVersion !== 1)) throw new Error('Invalid legacy pet recording.');\n    if (r.petReplayVersion === 2 && (!r.start || r.start.petCheckpointVersion !== 2 || r.start.historyStart !== r.start.tick)) 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) throw new Error('Pet segment checkpoints do not agree.');\n      world.origin = first.checkpoint();\n    }\n    return world;\n  }\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(): PetSegment {\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] as [number, number]);\n    const c = this.checkpoint();\n    c.petCheckpointVersion = 2; c.historyStart = this.tick; c.hasTelemetry = this.hasTelemetry;\n    c.bucketIndex -= dropTape; 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); next.origin = next.checkpoint();\n    let committed = false;\n    return { recording: next.recording(), archive: this.recording(true, true), commit: () => {","sourceCodeStart":130,"sourceCodeEnd":166,"githubUrl":"https://github.com/Hmbown/CodeWhale/blob/433685b2024e7bc4c99e1e2e326bcad39b4d9d65/pet/src/core/pet-world.ts#L130-L166","documentation":"When a recording carries both a start checkpoint and a later checkpoint, fromRecording restores from the later checkpoint and cross-checks it against the start: the restored world must be segmented, must not be at an earlier tick than the start, and the checkpoint's historyStart must equal the start's tick. Any disagreement means the two checkpoints were not taken from the same continuous recording lineage.","triggerScenarios":"Calling PetWorld.fromRecording(points, value) where r.start and r.checkpoint come from different recordings, the checkpoint's historyStart does not match start.tick, or the checkpoint's tape index lands before the start tick.","commonSituations":"Splicing checkpoints from different sessions; re-archiving a segment so its historyStart moved while an old start checkpoint was retained; manually assembling a recording from partial exports.","solutions":["Re-export start and checkpoint together from the same PetWorld via recording()/prepareSegment so their metadata is consistent.","Ensure checkpoint.historyStart equals start.tick before assembling the recording.","Drop one of the two checkpoints if they are not from the same lineage and replay from the remaining anchor."],"exampleFix":"// before\nrec.start = oldSegmentStart; rec.checkpoint = checkpointFromOtherSession; // throws\n// after\nconst { recording } = world.prepareSegment(points, tape, interactions, dropTape, dropInputs);\nconst rec = JSON.parse(recording); // consistent start + checkpoint","handlingStrategy":"validation","validationCode":"if (rec.start && rec.checkpoint && rec.checkpoint.historyStart !== rec.start.tick)\n  throw new Error('start/checkpoint lineage mismatch before fromRecording');","typeGuard":"function checkpointsAgree(r: PetRecording): boolean {\n  return !r.start || !r.checkpoint || r.checkpoint.historyStart === r.start.tick;\n}","tryCatchPattern":"try {\n  return PetWorld.fromRecording(points, rec);\n} catch (e) {\n  if (e.message === 'Pet segment checkpoints do not agree.') {\n    // re-export both checkpoints together from the same world\n  } else throw e;\n}","preventionTips":["Treat start+checkpoint as an inseparable pair produced by one export.","Never splice checkpoints across sessions.","Archive segments atomically at prepareSegment time."],"tags":["replay","segmentation","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-22T21:17:16.096Z"}