Files
Kay 4f922899af T6: multi-world namespace — world_id on every node, list_worlds(), arda_greyscale seed
Every read tool (entity_context, state_at, was_true_at, ancestors_of,
descendants_of, lineage_of, recall_images, search_images_by_caption,
register_image) now accepts an optional world_id parameter, defaulting
to 'default' so v1 callers see no change.

* Neo4j: every Person/Faction/Location/Item/Event/Lineage/Image node
  carries a world_id string property. seed.py backfills existing nodes
  to 'default' and writes a second minimal world 'arda_greyscale'
  (2 people, 1 faction, 1 location, 4 relations, 1 event, 1 era).
* Cypher: every MATCH in the world/lineage/images plugins filters by
  world_id on the right node type.
* New admin tool list_worlds() — runs
  MATCH (n) WHERE n.world_id IS NOT NULL RETURN DISTINCT n.world_id
  to expose the namespace.
* Postgres image_manifest gains a world_id column (init.sql).
* 4 placeholder images generated for the greyscale world (portraits of
  Mael and Sira, Ashen Hall, the Ashen Oath).
* test.sh now calls every tool with world_id='default' to verify v1
  behaviour, plus a new section 12 that calls list_worlds().
* tests/test_multi_world.py: 14 pytest cases covering list_worlds,
  entity_context/world isolation, was_true_at, state_at, lineage
  filter, image recall isolation, and the image_manifest schema.

Verification:
  pytest tests/test_multi_world.py         14/14 pass
  bash test.sh                             12/12 sections green,
                                           MinIO image bytes flow 200 OK
  list_worlds() returns [{arda_greyscale}, {default}]
2026-06-16 23:09:40 +00:00
..