From b91d5b9acd8de811150b74d29eff01f7d6c79d6e Mon Sep 17 00:00:00 2001 From: DazedAnon Date: Sat, 11 Jul 2026 12:24:34 -0500 Subject: [PATCH] Cleaning things up --- README.md | 7 +++++- data/skills/project_setup.md | 42 ++++++++++++-------------------- gui/skills_tab.py | 4 +-- gui/translation_tab.py | 2 +- gui/workflow_tab.py | 26 ++++++++++---------- modules/rpgmakermvmz.py | 2 +- modules/wolfdawn.py | 2 +- util/paths.py | 5 ++-- util/skills/system.py | 47 ++++++++++++++++++++++++++++-------- util/translation.py | 2 +- 10 files changed, 81 insertions(+), 58 deletions(-) diff --git a/README.md b/README.md index 78c628d..682bbab 100644 --- a/README.md +++ b/README.md @@ -177,7 +177,12 @@ Format: Japanese name, English name in parentheses, then gender. > **Note:** A very large vocab file can increase API costs and potentially reduce quality. Focus on the most important characters and terms. ### data/skills/system.md -This is the system prompt skill sent to the AI on every translation call. A default `data/skills/system.md` is included and works well for most games. You generally don't need to edit it unless you want to customize the translation style. Per-game voice rules go in `/skills/quirks.md` instead. +This is the system prompt skill sent to the AI on every translation call. A default `data/skills/system.md` is included and works well for most games. You generally don't need to edit it unless you want to customize the translation style. + +Per-game overlays (when a game folder is selected in Workflow) live next to the game: +- `/skills/game.md` - Translation Frame (theme / era / register / naming) +- `/skills/quirks.md` - cross-cutting voice habits +- optional extra `/skills/*.md` custom overlays --- diff --git a/data/skills/project_setup.md b/data/skills/project_setup.md index 7f470f1..b5c9e73 100644 --- a/data/skills/project_setup.md +++ b/data/skills/project_setup.md @@ -22,13 +22,13 @@ Regenerate mode: if the user asks for only one block (`glossary`, `speakers`, `t | `glossary` | Named characters (gender, role, **per-character** speech register) + worldbuilding terms | Global dialect / person rules; honorific policy; speaker-format flags; formatting | | `speakers` | Tool flag ENABLE/SKIP + short evidence | Character bios; quirks; full glossary | | `translation_quirks` | Cross-cutting voice rules (battle-log person, global dialect, item-description style, **unusual** honorific habits) | Per-character register; "always keep -san" (tool base prompt already does); codes/wrap/line counts; speaker flags | -| `game_skill` | **Translation Frame** (theme / era / register / naming / optional myth), pointer to `skills/quirks.md`, tool boundaries | File inventories; verbatim quirks; verbatim glossary; per-character register; restating base honorific/formatting policy | +| `game_skill` | **Translation Frame** for the API (theme / era / register / naming / optional myth) saved at `skills/game.md` | File inventories; quirks bullets; glossary; per-character register; IDE scaffolding; restating base honorific/formatting policy | Hard rules: 1. Per-character voice → `glossary` only. 2. Category-wide / cross-cutting voice → `translation_quirks` only. 3. Default honorifics policy is owned by the tool base prompt - only note **unusual** honorific habits in quirks. -4. `game_skill` **references** `skills/quirks.md` only; do not reprint those rules or cite legacy names like `translation_quirks.txt`. +4. `game_skill` is the title's Translation Frame for the translation API - keep it compact; do not reprint quirks or glossary. 5. `speakers` is config, not lore. --- @@ -98,25 +98,26 @@ Output as short imperative bullets suitable to paste into `skills/quirks.md`. ### Game skill rules (for `game_skill` block) -Produce a durable IDE skill for this title saved at `skills/translation.md`. +Produce the per-game translation skill saved at `skills/game.md`. +DazedMTLTool **merges this file into the translation system prompt** (before quirks). -**Translation Frame** (required section - one compact line per field; evidence-based only): +**Translation Frame only** (one compact line per field; evidence-based): - `世界観 (Theme / setting)` - genre, world type, core atmosphere - `時代感 (Era / technology level)` - medieval / modern / sci-fi / historical / etc. - `文体方針 (Register policy)` - overall English style (plain RPG, mythic, courtly, modern casual, military, gothic, …) - `固有名詞方針 (Naming policy)` - invented names, titles, ranks, honorifics, myth-derived terms (high-level only; default honorific keep-policy stays in the tool base prompt) - `神話・伝承 (Myth / folklore basis)` - **omit unless** evidence supports a specific tradition or source family -Also include: -- **Voice rules** - pointer only to ``skills/quirks.md`` (authoritative) -- **Tool boundaries** - codes/formatting owned by the tool; do not reprint quirks or glossary -- Do **not** list repo files / "files that matter" -- Do **not** put per-character register here (glossary) or battle-log / dialect bullets here (quirks) +Do **not** include: +- Voice-rules pointers, tool-boundary essays, or IDE instructions +- Repo file inventories / "files that matter" +- Per-character register (glossary) or battle-log / dialect bullets (quirks) +- Verbatim quirks or glossary entries -**Path names (required):** -- Voice quirks file: ``skills/quirks.md`` (never ``translation_quirks.txt`` or any other legacy name) -- This IDE skill file: ``skills/translation.md`` -- Optional user overlays (if mentioned): other ``skills/*.md`` files except ``quirks.md`` / ``translation.md`` +**Paths:** +- Game skill (API): ``skills/game.md`` +- Quirks (API): ``skills/quirks.md`` (never ``translation_quirks.txt``) +- Optional custom API overlays: other ``skills/*.md`` except those two @@ -173,12 +174,10 @@ Label the fence language as `translation_quirks`. Inside: imperative bullet list ### Block `game_skill` -Label the fence language as `game_skill`. Inside: full markdown for `skills/translation.md`. - -Required skeleton (fill in the blanks; keep the Voice rules path exactly): +Label the fence language as `game_skill`. Inside: markdown for `skills/game.md` (Translation Frame only). ```markdown -# - Translation skill +# - Translation Frame ## Translation Frame 世界観 (Theme / setting) - @@ -186,15 +185,6 @@ Required skeleton (fill in the blanks; keep the Voice rules path exactly): 文体方針 (Register policy) - 固有名詞方針 (Naming policy) - 神話・伝承 (Myth / folklore basis) - - -## Voice rules -Follow `skills/quirks.md` as the authoritative cross-cutting voice guide for this title. -Do not invent alternate quirk filenames. - -## Tool boundaries -- DazedMTLTool owns formatting codes, wrap, line counts, and honorifics defaults via its base system skill. -- Per-character register lives in the glossary (`vocab.txt`), not here. -- Do not reprint quirks or glossary entries in this file. ``` If known speakers were prepended in a `` block above this skill, prefer those names in the glossary, then cross-check Actors.json for other major named actors. diff --git a/gui/skills_tab.py b/gui/skills_tab.py index 2f60bc3..5c96b59 100644 --- a/gui/skills_tab.py +++ b/gui/skills_tab.py @@ -59,8 +59,8 @@ class SkillsTab(QWidget): intro = QLabel( "Tool-level AI instructions live here. " - "Per-game quirks, the game IDE skill, and optional custom skills are edited " - "in Workflow Step 2 (they travel with the game folder)." + "Per-game quirks, Translation Frame (game skill), and optional custom skills are edited " + "in Workflow Step 2 (they travel with the game folder and merge into the API prompt)." ) intro.setWordWrap(True) intro.setStyleSheet(_HINT_STYLE) diff --git a/gui/translation_tab.py b/gui/translation_tab.py index 0b16a89..b10ac04 100644 --- a/gui/translation_tab.py +++ b/gui/translation_tab.py @@ -3018,7 +3018,7 @@ class TranslationTab(QWidget): except Exception: pass - # Per-game quirks overlay: Workflow Step 0 folder → DAZED_GAME_ROOT + # Per-game overlays (game.md / quirks / custom): Workflow folder → DAZED_GAME_ROOT try: game_root = "" if self.settings: diff --git a/gui/workflow_tab.py b/gui/workflow_tab.py index cf44825..3f05176 100644 --- a/gui/workflow_tab.py +++ b/gui/workflow_tab.py @@ -445,10 +445,10 @@ _STEP_HELP: dict[int, str] = { "• translation_quirks → Quirks tab " "(skills/quirks.md)
" "• game_skill → Game skills → translation tab " - "(skills/translation.md)

" + "(skills/game.md - Translation Frame, merged into the API prompt)

" "Optional: + on Game skills adds custom skills/*.md " - "overlays (merged into the API prompt - can hurt quality; use sparingly).

" - "Use one game folder per translation run so quirks stay in the prompt cache." + "overlays (also merged into the API prompt - can hurt quality; use sparingly).

" + "Use one game folder per translation run so frame/quirks stay in the prompt cache." ), 3: ( "Step 3 - TL Phase 1

" @@ -1793,7 +1793,7 @@ class WorkflowTab(QWidget): "Quirks", ) - # Game skills: built-in translation.md + optional custom overlays + # Game skills: built-in game.md + optional custom overlays game_skills_page = QWidget() gs_layout = QVBoxLayout(game_skills_page) gs_layout.setContentsMargins(0, 0, 0, 0) @@ -1845,11 +1845,11 @@ class WorkflowTab(QWidget): gs_layout.addWidget(self._game_skills_stack, 1) self._add_game_skill_page( - "translation", + "game", _editor_page( - "/skills/translation.md", - "Paste the game_skill block (Translation Frame + voice/tool pointers). " - "IDE companion skill for this game repo (not injected into the API prompt).", + "/skills/game.md", + "Paste the game_skill Translation Frame. Merged into the translation " + "system prompt (before quirks) when this game folder is selected.", self._save_game_skill, self._reload_game_skill, "game_skill_editor", @@ -2437,7 +2437,7 @@ class WorkflowTab(QWidget): # Pre-populate all Phase 2 checkboxes from current module state self._populate_p2_checkboxes() - # ── Step 5: Plugins/scripts + Export ─────────────────────────────────── + # ── Step 5: Plugins.js + Export ──────────────────────────────────────── def _build_step5_finish(self, layout: QVBoxLayout): self._add_step_header(layout, "Step 5 — Plugins & Export", 5) @@ -3692,7 +3692,7 @@ class WorkflowTab(QWidget): if bar is None or stack is None: return - # Remove existing custom tabs (index 0 is always translation). + # Remove existing custom tabs (index 0 is always game.md). while bar.count() > 1: bar.removeTab(1) while stack.count() > 1: @@ -3757,8 +3757,8 @@ class WorkflowTab(QWidget): "Custom skills are merged into the translation system prompt.

" "Extra or poorly written skills can distract the model and hurt " "translation quality (conflicting rules, prompt bloat, diluted quirks).

" - "Prefer quirks.md for voice rules and translation.md " - "for IDE guidance. Add a custom skill only if you need a rare, tightly scoped " + "Prefer quirks.md for voice rules and game.md " + "for the Translation Frame. Add a custom skill only if you need a rare, tightly scoped " "overlay - at your own risk." ) warn.setStandardButtons(QMessageBox.Cancel | QMessageBox.Ok) @@ -3783,7 +3783,7 @@ class WorkflowTab(QWidget): self, "Invalid name", "Use a short name like battle-log or honorifics_extra.\n" - "Reserved: quirks, translation.", + "Reserved: quirks, game, translation.", ) return if stem in self._custom_skill_editors: diff --git a/modules/rpgmakermvmz.py b/modules/rpgmakermvmz.py index a65dd10..2ca4106 100644 --- a/modules/rpgmakermvmz.py +++ b/modules/rpgmakermvmz.py @@ -251,7 +251,7 @@ def handleMVMZ(filename, estimate): except Exception: pass - # Reload base prompt + optional per-game quirks (DAZED_GAME_ROOT). + # Reload system.md + per-game overlays (game.md / quirks / custom) via DAZED_GAME_ROOT. PROMPT = load_system_prompt() TRANSLATION_CONFIG.prompt = PROMPT diff --git a/modules/wolfdawn.py b/modules/wolfdawn.py index 224d030..3e60a04 100644 --- a/modules/wolfdawn.py +++ b/modules/wolfdawn.py @@ -154,7 +154,7 @@ def handleWolfDawn(filename, estimate): # that an earlier Phase 0 (names) harvested into vocab.txt. VOCAB = VOCAB_PATH.read_text(encoding="utf-8") TRANSLATION_CONFIG.vocab = VOCAB - # Reload base prompt + optional per-game quirks (DAZED_GAME_ROOT). + # Reload system.md + per-game overlays (game.md / quirks / custom) via DAZED_GAME_ROOT. PROMPT = load_system_prompt() TRANSLATION_CONFIG.prompt = PROMPT diff --git a/util/paths.py b/util/paths.py index 7a9551b..74fc9e2 100644 --- a/util/paths.py +++ b/util/paths.py @@ -20,9 +20,10 @@ TRANSLATION_CONTEXTS_PATH = DATA_DIR / "translation_contexts.json" # Per-game quirks skill (API overlay). Legacy flat file still migrated on load. GAME_QUIRKS_RELATIVE = Path("skills") / "quirks.md" LEGACY_QUIRKS_FILENAME = "translation_quirks.txt" -GAME_SKILL_RELATIVE = Path("skills") / "translation.md" +GAME_SKILL_RELATIVE = Path("skills") / "game.md" +LEGACY_GAME_SKILL_RELATIVE = Path("skills") / "translation.md" # Built-in skill filenames under /skills/ (not user-custom overlays). -GAME_SKILL_RESERVED_NAMES = frozenset({"quirks.md", "translation.md"}) +GAME_SKILL_RESERVED_NAMES = frozenset({"quirks.md", "game.md", "translation.md"}) _ROOT_DATA_FILES = ( "vocab.txt", diff --git a/util/skills/system.py b/util/skills/system.py index 4e65692..633ffab 100644 --- a/util/skills/system.py +++ b/util/skills/system.py @@ -1,4 +1,4 @@ -"""Load the static system prompt and optional per-game quirks overlay.""" +"""Load the static system prompt and optional per-game skill overlays.""" from __future__ import annotations @@ -10,12 +10,19 @@ from util.paths import ( GAME_QUIRKS_RELATIVE, GAME_SKILL_RELATIVE, GAME_SKILL_RESERVED_NAMES, + LEGACY_GAME_SKILL_RELATIVE, LEGACY_QUIRKS_FILENAME, PROMPT_PATH, ) _SKILL_NAME_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$") +# Drop legacy IDE-only sections from older game skill files. +_IDE_SECTION_RE = re.compile( + r"\n## (?:Voice rules|Tool boundaries)\b.*?(?=\n## |\Z)", + re.DOTALL | re.IGNORECASE, +) + def quirks_path_for_game(game_root: str | Path | None) -> Path | None: """Return ``/skills/quirks.md`` when *game_root* is set. @@ -38,27 +45,40 @@ def quirks_path_for_game(game_root: str | Path | None) -> Path | None: def game_skill_path_for_game(game_root: str | Path | None) -> Path | None: - """Return ``/skills/translation.md`` when *game_root* is set.""" + """Return ``/skills/game.md`` when *game_root* is set. + + Migrates legacy ``skills/translation.md`` to ``skills/game.md`` when needed. + """ if not game_root: return None - return Path(game_root) / GAME_SKILL_RELATIVE + root = Path(game_root) + preferred = root / GAME_SKILL_RELATIVE + legacy = root / LEGACY_GAME_SKILL_RELATIVE + if not preferred.is_file() and legacy.is_file(): + preferred.parent.mkdir(parents=True, exist_ok=True) + try: + legacy.rename(preferred) + except OSError: + return legacy + return preferred def migrate_game_skill_text(text: str) -> str: - """Rewrite legacy quirk path names inside a game skill markdown body.""" + """Normalize a game skill body for API use (path fixes + drop IDE scaffolding).""" if not text: return text # Common stale pointers from older Project Setup output. updated = text.replace("translation_quirks.txt", "skills/quirks.md") updated = updated.replace("`translation_quirks.md`", "`skills/quirks.md`") - # Bare relative quirks.md without skills/ prefix (keep skills/quirks.md intact). updated = re.sub( r"(? list[Path]: """List user custom skill markdown files under ``/skills/``. - Excludes built-in ``quirks.md`` and ``translation.md``. + Excludes built-in ``quirks.md`` and ``game.md`` (and legacy ``translation.md``). """ skills = game_skills_dir(game_root) if skills is None or not skills.is_dir(): @@ -116,9 +136,10 @@ def list_custom_skill_paths(game_root: str | Path | None) -> list[Path]: def load_system_prompt(game_root: str | Path | None = None) -> str: """Load ``data/skills/system.md`` plus optional per-game overlays. - Overlay order: - 1. ``skills/quirks.md`` (voice quirks) - 2. Any other ``skills/*.md`` except ``translation.md`` (custom skills) + Overlay order (when ``DAZED_GAME_ROOT`` / *game_root* is set): + 1. ``skills/game.md`` - Translation Frame / game skill (API) + 2. ``skills/quirks.md`` - cross-cutting voice quirks + 3. other ``skills/*.md`` - optional custom overlays Path resolution order for the game root: 1. Explicit *game_root* argument @@ -135,6 +156,12 @@ def load_system_prompt(game_root: str | Path | None = None) -> str: parts = [base.rstrip()] if base.strip() else [] + skill_file = game_skill_path_for_game(root) + if skill_file and skill_file.is_file(): + skill = migrate_game_skill_text(skill_file.read_text(encoding="utf-8")).strip() + if skill: + parts.append("## Game Translation Frame\n\n" + skill) + quirks_file = quirks_path_for_game(root) if quirks_file and quirks_file.is_file(): quirks = quirks_file.read_text(encoding="utf-8").strip() diff --git a/util/translation.py b/util/translation.py index 201fed6..2109737 100644 --- a/util/translation.py +++ b/util/translation.py @@ -1945,7 +1945,7 @@ def createContext(config, subbedText, formatType, history=None): cache invalidation caused by changing vocabulary matches. Cached in static_system: - - data/skills/system.md content (plus optional game quirks overlay) + - data/skills/system.md content (plus optional game Translation Frame / quirks / custom overlays) Dynamic in vocab_text: - only vocab terms found in the current batch text