Commit Graph

6 Commits

Author SHA1 Message Date
mikkeli 1f9bf9bb93 new characters 2026-08-14 08:47:47 +09:00
Mikkeli d00af71a91 Prune card exports whose PNG is gone
Deleting a character in the UI left _text/cards/<Name>.json behind, describing a
card that no longer exists. A stale derived file is worse than a missing one
because it reads as current -- which is the exact reason the pre-commit hook
regenerates _text/ at all, so the script was failing its own premise.

Found by testing a deletion rather than reading the code. The write path was
obviously correct; the delete path had simply never been written.
2026-08-13 18:03:31 +09:00
Mikkeli 0b784be586 Aino Vihtanen, and the Ohkotska (SES Pilot) world 2026-08-13 17:01:45 +09:00
mikkeli 2e23cb64ca Capture world GATING, not just the worlds
A lorebook is inert until something selects it, and SillyTavern gates three ways
-- globally, per character card, and per persona. All of that selection lives in
settings.json, which is untracked, so versioning worlds/*.json alone captured
the content and lost the wiring. A restore would have handed back every lorebook
with no record of which were active or what the token budget was.

_text/world-settings.json now carries the selection and the tuning that decides
how entries fire: budget, scan depth, recursion, whole-word matching, and the
character-vs-global strategy. Non-secret, small, and regenerated by the same
pre-commit hook.
2026-08-12 22:30:54 +09:00
mikkeli 4d3bf61d56 Regenerate _text/ on commit, so the readable copy cannot drift
_text/ is derived from the PNG tEXt chunks and settings.json, and derived data
regenerated by hand goes stale silently -- which is worse than absent, because a
stale card reads as current. A pre-commit hook now regenerates and stages it.

Blocking, unlike the halogen repo's advisory doc-check: that one reports a
judgement call, this one rebuilds a file. Install with
`./st-export.py --install-hook`, since hooks are not versioned.

Verified by renaming a persona in the untracked settings.json and committing
WITHOUT running the export -- _text/personas.json updated itself and was
included. Test edit reverted.
2026-08-12 22:23:10 +09:00
Mikkeli 00f5e2fa72 SillyTavern world artifacts, versioned in place
Tracked inside SillyTavern's live data directory rather than symlinked out of
it. data/ is a bind mount into the container, so a symlink to a host path
outside that mount resolves inside the container where the target does not
exist -- broken to SillyTavern while looking correct on the host.

The .gitignore is an allowlist, denying everything and re-including named paths,
because this is live application data rather than a curated export. secrets.json
is the reason: empty today because API keys go through LiteLLM with a
placeholder, and it arms itself the moment a key is typed into the UI. This repo
is public. A denylist protects only the paths someone remembered.

Two of the four artifact types are not diffable as stored. Character cards are
PNGs with the card JSON in a tEXt chunk, and personas live inside a 48 KB
settings.json that SillyTavern rewrites on any change. st-export.py extracts
both into _text/ so the reviewable artifact is text, one-way on purpose --
re-embedding JSON into a PNG is where a mistake corrupts authored content.

Stock content is excluded: Seraphina's expression pack is 3.6 MiB of PNG the app
regenerates on startup. The stock lorebook Eldoria.json stays -- 8 KB of
readable JSON is a useful worked example of the format.
2026-08-12 20:59:32 +09:00