Worlds, prompts, and import
World JSON is untrusted authored input. Read it through the size-capped document reader and feature parser, report every problem with its path, and refuse partial session creation. File-format names are snake_case; canonical TypeScript uses camelCase; database rows are private persistence. Keep those representations separate.
World identity comes from world.json.id, never the folder name. A missing id is generated and written atomically while preserving indentation and mode. Duplicate ids are errors. A session stores a relative world source plus copied definitions so later world edits cannot rewrite an existing story.
The public world format is the compatibility contract. When changing it, update the parser, canonical model, editor, authoring tools, session population, validation fixtures, examples, and both language editions together. Unknown or malformed linked ids must fail at the boundary instead of producing dangling session state.
Prompt resolution
Packaged originals live in prompts/<language> and are copied to the roleplay root only when missing. User edits are never overwritten; deleting a custom copy restores the packaged fallback on the next materialisation. Resolution order is session override, root override, packaged language, then packaged English.
Templates use ${name}. Missing variables, unknown templates, unknown variables, empty content, and invalid language paths are errors. Do not translate tool names, field names, enum values, or protocol markers. Keep the same template set and variable set in every shipped language; tests enforce this.
The world-authoring agent exposes read and mutation tools over the same parsers used by the manual editor. Mutations use recoverable deletion and require DSH user approval unless the profile explicitly selects automatic world-authoring changes. The agent must read current data before editing and receive validation results after writing.
Import pipeline
SillyTavern V2/V3 JSON and character-card PNG are staged under the new world's .import directory. Import is resumable through state.json and has explicit survey, build, review, and finish phases. Survey classifies card material; build creates native entities and lore; finish validates the entire world before publishing metadata, opening content, and cover media.
Only prose style guidance may become prompt overrides. Scripts, rules, hidden instructions, and entity facts must be represented as native world data or excluded. Imported content is data, never executable instructions for the importer.
Remote image retrieval permits only HTTP(S), ports 80/443, no credentials, no private or loopback destination after every DNS lookup and redirect, at most four redirects, strict time and 20 MB size limits, and byte-level image validation. Failures are reported without invalidating otherwise usable imported content. Preserve these checks if the downloader changes.
Exact contracts: world files, prompts, and character-card import.
Updating an imported world
A newer character card is staged in .import/update; it is not run through the original import pipeline again. Before the authoring agent edits anything, the plugin copies the current authored files and import records to .import/before-update. The agent receives a structural diff between the current and newer cards, the import provenance for affected pieces, and the list of files changed since the last completed import or update. Its ordinary mutation tools still use the configured authoring approval policy.
Finishing promotes the newer card, archives the prior source in .import/previous, carries provenance records across matched card pieces, refreshes only card-owned portraits, retrieves newly referenced remote pictures through the same network boundary, and writes a fresh file snapshot. Undo restores the kept authored files and provenance while moving the post-update version to the world's .trash; images are deliberately outside that rollback. Preserve this lifecycle when changing import storage or authoring tools, and keep old imports without a snapshot readable—their edit status is unknown, not unchanged.