{
  "schemaVersion": 1,
  "lessonId": "recovery-04",
  "contentHash": "24da684f527e7b04d4809cc6a23ec0be5882e57eed5b0bb5aa7f9b6ded984682",
  "rendererHash": "a1bd5b648f4731ae5d5f0a24811c2540d1a0a132149ce589d17c4113509cbedf",
  "kind": "executed",
  "generatedAt": "2026-10-20T10:45:45.668045+00:00",
  "provenance": "recorded_cpu_computation",
  "environment": {
    "backend": "cpu",
    "deviceCount": 1,
    "jax": "0.9.2",
    "numpy": "2.4.4",
    "matplotlib": "3.10.8"
  },
  "stdout": "Restored next four ID batches: [[4, 10, 11, 3], [2, 0, 11, 1], [5, 7, 6, 8], [4, 3, 10, 9]]\nRestored next four losses: [0.5496272444725037, 0.8390463590621948, 0.07169045507907867, 0.32427603006362915]\nFull state agrees at step six\n",
  "data": {
    "kind": "line",
    "x": [
      3,
      4,
      5,
      6
    ],
    "xlabel": "training step after checkpoint",
    "ylabel": "batch loss",
    "series": [
      {
        "label": "uninterrupted reference_losses",
        "y": [
          0.5496272444725037,
          0.8390463590621948,
          0.07169045507907867,
          0.32427603006362915
        ]
      },
      {
        "label": "checkpoint resumed_losses",
        "y": [
          0.5496272444725037,
          0.8390463590621948,
          0.07169045507907867,
          0.32427603006362915
        ]
      }
    ]
  },
  "diagram": {
    "title": "One checkpoint, one completed-step boundary",
    "prediction": "Why reject a resume even when its first loss nearly matches the reference?",
    "reading": "Read down the middle column: all state describes the same completed update. Across each row is its next use. An older cursor repeats data and a newer cursor skips it. The table shows logical state, not wall-clock timing.",
    "alt": "Read down the middle column: all state describes the same completed update. Across each row is its next use. An older cursor repeats data and a newer cursor skips it. The table shows logical state, not wall-clock timing.",
    "scope": "Architecture and dataflow mechanism diagram.",
    "height": 5,
    "panel": {
      "kind": "table",
      "headers": [
        "State",
        "Accepted boundary",
        "Next use"
      ],
      "rows": [
        [
          "Parameters",
          "after update t",
          "forward at t + 1"
        ],
        [
          "Optimizer",
          "after update t",
          "next update"
        ],
        [
          "Random key",
          "next unused key",
          "next stochastic input"
        ],
        [
          "Iterator",
          "next unconsumed batch",
          "batch for t + 1"
        ],
        [
          "Step counter",
          "t completed",
          "schedule convention"
        ]
      ]
    }
  }
}
