Skip to content

8. Read and migrate a legacy 0.2 pack

This is a separate migration exercise, not the next revision of the VN pack. Download this lesson’s start (0.2 host profile, revision 20) and finished (0.3, revision 21). Both tell the same greenhouse situation. Return to the Lesson 7 branch for publication practice afterward.

The legacy pack names the reader as actor visitor, declares Rowan in actors, records the initial dry soil in canon, and offers a shared_care event card. Entries connect the cast, established facts and reader-known facts. experience describes the roleplay contract; instructions is an object, unlike 0.3’s string.

Use the site’s exact 0.2 host profile schema. A portable Playground 0.2 schema can differ. The new teaching checker supports the bundled host snapshot but does not replace a legacy host admission review. Origins remain proposed, so the example is intentionally not ready for admission.

0.2 concept 0.3 treatment in this exercise
actors and participant persona Rowan becomes an actor reader card; reader agency and Rowan’s behavior move into instructions
Public initial canon fact dry_soil becomes an always-selected public content block, phrased as a fact about arrival
event_cards.shared_care An observable completed-care answer, state update rule and guidance; no forced outcome
opening_text A list of paragraphs in entries[].opening, plus exact dialogue annotations
Entry cast/knowledge graph Explicit instructions, public content and stable entry/card IDs; not a copied graph

The finished example deliberately redesigns care as repeatable state increments capped at 2; the legacy event was once-only. That is an authored behavior change, not automatic backward compatibility. The historical dry-soil fact remains true after watering because it says the soil was dry on arrival. Current moisture belongs in state.

Compare both complete JSON files. Preserve pack_id, arrival and rowan where their identity still means the same thing. Remove obsolete legacy structures rather than leaving them alongside the new contract. Recompute paragraph digests after splitting text, and set the new revision to 21.

Run the checker on both start/pack.json and finished/pack.json. It selects the corresponding exact bundled schema. Changing only protocol_version on the start pack should fail; undo that experiment. Review privacy and knowledge assumptions manually: this exercise contains only public facts and does not show how to migrate secrets.

For a real migration, keep a backup, record intentional behavior changes, run host semantic checks and privately replay important choices. Existing journeys retain their original pack revision; a newly published revision is not a migration of their saved state.

Check your work locally

From the extracted bundle folder, create the environment and install the pinned dependencies once. Then check both files, and repeat the start check after your edits. The same commands work for every lesson.

macOS / Linux

python3 -m venv .venv
.venv/bin/python -m pip install -r requirements.txt
.venv/bin/python check.py start/pack.json
.venv/bin/python check.py finished/pack.json

Windows PowerShell

py -3 -m venv .venv
.venv\Scripts\python.exe -m pip install -r requirements.txt
.venv\Scripts\python.exe check.py start/pack.json
.venv\Scripts\python.exe check.py finished/pack.json

Expected for the finished pack: Structural check passed: Creator Pack 0.3 followed by the exact Schema SHA-256. This is a structural check, not host admission or a live playtest.

Working excerpt from the finished pack

This excerpt is generated from the tested download. It is not a complete pack; edit the named fields inside start/pack.json or compare finished/pack.json.

{
  "legacy_canon": [
    {
      "id": "dry_soil",
      "entry_ids": [
        "arrival"
      ],
      "statement": "The seedling's soil was dry when the visitor arrived.",
      "kind": "initial_state",
      "origin": {
        "basis": "creator_design",
        "source_refs": [],
        "review": "proposed"
      },
      "disclosure": "public",
      "reveal_condition": {
        "literal": true
      }
    }
  ],
  "migrated_content": [
    {
      "id": "dry_soil",
      "entry_ids": [
        "arrival"
      ],
      "text": "The seedling's soil was dry when the visitor arrived.",
      "selection": "always",
      "when": {
        "op": "literal",
        "value": true
      }
    }
  ],
  "migrated_actor": {
    "id": "rowan",
    "kind": "actor",
    "display_name": "Rowan",
    "introduction": "A patient caretaker with time for one more seedling and visitor.",
    "entry_ids": [
      "arrival"
    ],
    "reveal_when": {
      "op": "literal",
      "value": true
    }
  }
}

Look up the fields: content · reader_cards · runtime

Next lesson