Cleaning things up
This commit is contained in:
parent
92a336d32d
commit
b91d5b9acd
10 changed files with 81 additions and 58 deletions
|
|
@ -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.
|
> **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
|
### 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 `<game>/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:
|
||||||
|
- `<game>/skills/game.md` - Translation Frame (theme / era / register / naming)
|
||||||
|
- `<game>/skills/quirks.md` - cross-cutting voice habits
|
||||||
|
- optional extra `<game>/skills/*.md` custom overlays
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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 |
|
| `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 |
|
| `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 |
|
| `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:
|
Hard rules:
|
||||||
1. Per-character voice → `glossary` only.
|
1. Per-character voice → `glossary` only.
|
||||||
2. Category-wide / cross-cutting voice → `translation_quirks` 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.
|
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.
|
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)
|
### 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
|
- `世界観 (Theme / setting)` - genre, world type, core atmosphere
|
||||||
- `時代感 (Era / technology level)` - medieval / modern / sci-fi / historical / etc.
|
- `時代感 (Era / technology level)` - medieval / modern / sci-fi / historical / etc.
|
||||||
- `文体方針 (Register policy)` - overall English style (plain RPG, mythic, courtly, modern casual, military, gothic, …)
|
- `文体方針 (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)
|
- `固有名詞方針 (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
|
- `神話・伝承 (Myth / folklore basis)` - **omit unless** evidence supports a specific tradition or source family
|
||||||
|
|
||||||
Also include:
|
Do **not** include:
|
||||||
- **Voice rules** - pointer only to ``skills/quirks.md`` (authoritative)
|
- Voice-rules pointers, tool-boundary essays, or IDE instructions
|
||||||
- **Tool boundaries** - codes/formatting owned by the tool; do not reprint quirks or glossary
|
- Repo file inventories / "files that matter"
|
||||||
- Do **not** list repo files / "files that matter"
|
- Per-character register (glossary) or battle-log / dialect bullets (quirks)
|
||||||
- Do **not** put per-character register here (glossary) or battle-log / dialect bullets here (quirks)
|
- Verbatim quirks or glossary entries
|
||||||
|
|
||||||
**Path names (required):**
|
**Paths:**
|
||||||
- Voice quirks file: ``skills/quirks.md`` (never ``translation_quirks.txt`` or any other legacy name)
|
- Game skill (API): ``skills/game.md``
|
||||||
- This IDE skill file: ``skills/translation.md``
|
- Quirks (API): ``skills/quirks.md`` (never ``translation_quirks.txt``)
|
||||||
- Optional user overlays (if mentioned): other ``skills/*.md`` files except ``quirks.md`` / ``translation.md``
|
- Optional custom API overlays: other ``skills/*.md`` except those two
|
||||||
|
|
||||||
<!-- /engine:rpgmaker -->
|
<!-- /engine:rpgmaker -->
|
||||||
|
|
||||||
|
|
@ -173,12 +174,10 @@ Label the fence language as `translation_quirks`. Inside: imperative bullet list
|
||||||
|
|
||||||
### Block `game_skill`
|
### Block `game_skill`
|
||||||
|
|
||||||
Label the fence language as `game_skill`. Inside: full markdown for `skills/translation.md`.
|
Label the fence language as `game_skill`. Inside: markdown for `skills/game.md` (Translation Frame only).
|
||||||
|
|
||||||
Required skeleton (fill in the blanks; keep the Voice rules path exactly):
|
|
||||||
|
|
||||||
```markdown
|
```markdown
|
||||||
# <Game title> - Translation skill
|
# <Game title> - Translation Frame
|
||||||
|
|
||||||
## Translation Frame
|
## Translation Frame
|
||||||
世界観 (Theme / setting) - <one compact line>
|
世界観 (Theme / setting) - <one compact line>
|
||||||
|
|
@ -186,15 +185,6 @@ Required skeleton (fill in the blanks; keep the Voice rules path exactly):
|
||||||
文体方針 (Register policy) - <one compact line>
|
文体方針 (Register policy) - <one compact line>
|
||||||
固有名詞方針 (Naming policy) - <one compact line>
|
固有名詞方針 (Naming policy) - <one compact line>
|
||||||
神話・伝承 (Myth / folklore basis) - <one compact line, or omit this line entirely if unsupported>
|
神話・伝承 (Myth / folklore basis) - <one compact line, or omit this line entirely if unsupported>
|
||||||
|
|
||||||
## 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 `<known_speakers>` block above this skill, prefer those names in the glossary, then cross-check Actors.json for other major named actors.
|
If known speakers were prepended in a `<known_speakers>` block above this skill, prefer those names in the glossary, then cross-check Actors.json for other major named actors.
|
||||||
|
|
|
||||||
|
|
@ -59,8 +59,8 @@ class SkillsTab(QWidget):
|
||||||
|
|
||||||
intro = QLabel(
|
intro = QLabel(
|
||||||
"Tool-level AI instructions live here. "
|
"Tool-level AI instructions live here. "
|
||||||
"Per-game quirks, the game IDE skill, and optional custom skills are edited "
|
"Per-game quirks, Translation Frame (game skill), and optional custom skills are edited "
|
||||||
"in Workflow Step 2 (they travel with the game folder)."
|
"in Workflow Step 2 (they travel with the game folder and merge into the API prompt)."
|
||||||
)
|
)
|
||||||
intro.setWordWrap(True)
|
intro.setWordWrap(True)
|
||||||
intro.setStyleSheet(_HINT_STYLE)
|
intro.setStyleSheet(_HINT_STYLE)
|
||||||
|
|
|
||||||
|
|
@ -3018,7 +3018,7 @@ class TranslationTab(QWidget):
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
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:
|
try:
|
||||||
game_root = ""
|
game_root = ""
|
||||||
if self.settings:
|
if self.settings:
|
||||||
|
|
|
||||||
|
|
@ -445,10 +445,10 @@ _STEP_HELP: dict[int, str] = {
|
||||||
"• <code>translation_quirks</code> → Quirks tab "
|
"• <code>translation_quirks</code> → Quirks tab "
|
||||||
"(<code>skills/quirks.md</code>)<br>"
|
"(<code>skills/quirks.md</code>)<br>"
|
||||||
"• <code>game_skill</code> → Game skills → translation tab "
|
"• <code>game_skill</code> → Game skills → translation tab "
|
||||||
"(<code>skills/translation.md</code>)<br><br>"
|
"(<code>skills/game.md</code> - Translation Frame, merged into the API prompt)<br><br>"
|
||||||
"Optional: <b>+</b> on Game skills adds custom <code>skills/*.md</code> "
|
"Optional: <b>+</b> on Game skills adds custom <code>skills/*.md</code> "
|
||||||
"overlays (merged into the API prompt - can hurt quality; use sparingly).<br><br>"
|
"overlays (also merged into the API prompt - can hurt quality; use sparingly).<br><br>"
|
||||||
"Use one game folder per translation run so quirks stay in the prompt cache."
|
"Use one game folder per translation run so frame/quirks stay in the prompt cache."
|
||||||
),
|
),
|
||||||
3: (
|
3: (
|
||||||
"<b>Step 3 - TL Phase 1</b><br><br>"
|
"<b>Step 3 - TL Phase 1</b><br><br>"
|
||||||
|
|
@ -1793,7 +1793,7 @@ class WorkflowTab(QWidget):
|
||||||
"Quirks",
|
"Quirks",
|
||||||
)
|
)
|
||||||
|
|
||||||
# Game skills: built-in translation.md + optional custom overlays
|
# Game skills: built-in game.md + optional custom overlays
|
||||||
game_skills_page = QWidget()
|
game_skills_page = QWidget()
|
||||||
gs_layout = QVBoxLayout(game_skills_page)
|
gs_layout = QVBoxLayout(game_skills_page)
|
||||||
gs_layout.setContentsMargins(0, 0, 0, 0)
|
gs_layout.setContentsMargins(0, 0, 0, 0)
|
||||||
|
|
@ -1845,11 +1845,11 @@ class WorkflowTab(QWidget):
|
||||||
gs_layout.addWidget(self._game_skills_stack, 1)
|
gs_layout.addWidget(self._game_skills_stack, 1)
|
||||||
|
|
||||||
self._add_game_skill_page(
|
self._add_game_skill_page(
|
||||||
"translation",
|
"game",
|
||||||
_editor_page(
|
_editor_page(
|
||||||
"<game>/skills/translation.md",
|
"<game>/skills/game.md",
|
||||||
"Paste the game_skill block (Translation Frame + voice/tool pointers). "
|
"Paste the game_skill Translation Frame. Merged into the translation "
|
||||||
"IDE companion skill for this game repo (not injected into the API prompt).",
|
"system prompt (before quirks) when this game folder is selected.",
|
||||||
self._save_game_skill,
|
self._save_game_skill,
|
||||||
self._reload_game_skill,
|
self._reload_game_skill,
|
||||||
"game_skill_editor",
|
"game_skill_editor",
|
||||||
|
|
@ -2437,7 +2437,7 @@ class WorkflowTab(QWidget):
|
||||||
# Pre-populate all Phase 2 checkboxes from current module state
|
# Pre-populate all Phase 2 checkboxes from current module state
|
||||||
self._populate_p2_checkboxes()
|
self._populate_p2_checkboxes()
|
||||||
|
|
||||||
# ── Step 5: Plugins/scripts + Export ───────────────────────────────────
|
# ── Step 5: Plugins.js + Export ────────────────────────────────────────
|
||||||
|
|
||||||
def _build_step5_finish(self, layout: QVBoxLayout):
|
def _build_step5_finish(self, layout: QVBoxLayout):
|
||||||
self._add_step_header(layout, "Step 5 — Plugins & Export", 5)
|
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:
|
if bar is None or stack is None:
|
||||||
return
|
return
|
||||||
|
|
||||||
# Remove existing custom tabs (index 0 is always translation).
|
# Remove existing custom tabs (index 0 is always game.md).
|
||||||
while bar.count() > 1:
|
while bar.count() > 1:
|
||||||
bar.removeTab(1)
|
bar.removeTab(1)
|
||||||
while stack.count() > 1:
|
while stack.count() > 1:
|
||||||
|
|
@ -3757,8 +3757,8 @@ class WorkflowTab(QWidget):
|
||||||
"<b>Custom skills are merged into the translation system prompt.</b><br><br>"
|
"<b>Custom skills are merged into the translation system prompt.</b><br><br>"
|
||||||
"Extra or poorly written skills can <b>distract the model and hurt "
|
"Extra or poorly written skills can <b>distract the model and hurt "
|
||||||
"translation quality</b> (conflicting rules, prompt bloat, diluted quirks).<br><br>"
|
"translation quality</b> (conflicting rules, prompt bloat, diluted quirks).<br><br>"
|
||||||
"Prefer <code>quirks.md</code> for voice rules and <code>translation.md</code> "
|
"Prefer <code>quirks.md</code> for voice rules and <code>game.md</code> "
|
||||||
"for IDE guidance. Add a custom skill only if you need a rare, tightly scoped "
|
"for the Translation Frame. Add a custom skill only if you need a rare, tightly scoped "
|
||||||
"overlay - <b>at your own risk</b>."
|
"overlay - <b>at your own risk</b>."
|
||||||
)
|
)
|
||||||
warn.setStandardButtons(QMessageBox.Cancel | QMessageBox.Ok)
|
warn.setStandardButtons(QMessageBox.Cancel | QMessageBox.Ok)
|
||||||
|
|
@ -3783,7 +3783,7 @@ class WorkflowTab(QWidget):
|
||||||
self,
|
self,
|
||||||
"Invalid name",
|
"Invalid name",
|
||||||
"Use a short name like battle-log or honorifics_extra.\n"
|
"Use a short name like battle-log or honorifics_extra.\n"
|
||||||
"Reserved: quirks, translation.",
|
"Reserved: quirks, game, translation.",
|
||||||
)
|
)
|
||||||
return
|
return
|
||||||
if stem in self._custom_skill_editors:
|
if stem in self._custom_skill_editors:
|
||||||
|
|
|
||||||
|
|
@ -251,7 +251,7 @@ def handleMVMZ(filename, estimate):
|
||||||
except Exception:
|
except Exception:
|
||||||
pass
|
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()
|
PROMPT = load_system_prompt()
|
||||||
TRANSLATION_CONFIG.prompt = PROMPT
|
TRANSLATION_CONFIG.prompt = PROMPT
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -154,7 +154,7 @@ def handleWolfDawn(filename, estimate):
|
||||||
# that an earlier Phase 0 (names) harvested into vocab.txt.
|
# that an earlier Phase 0 (names) harvested into vocab.txt.
|
||||||
VOCAB = VOCAB_PATH.read_text(encoding="utf-8")
|
VOCAB = VOCAB_PATH.read_text(encoding="utf-8")
|
||||||
TRANSLATION_CONFIG.vocab = VOCAB
|
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()
|
PROMPT = load_system_prompt()
|
||||||
TRANSLATION_CONFIG.prompt = PROMPT
|
TRANSLATION_CONFIG.prompt = PROMPT
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -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.
|
# Per-game quirks skill (API overlay). Legacy flat file still migrated on load.
|
||||||
GAME_QUIRKS_RELATIVE = Path("skills") / "quirks.md"
|
GAME_QUIRKS_RELATIVE = Path("skills") / "quirks.md"
|
||||||
LEGACY_QUIRKS_FILENAME = "translation_quirks.txt"
|
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 <game>/skills/ (not user-custom overlays).
|
# Built-in skill filenames under <game>/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 = (
|
_ROOT_DATA_FILES = (
|
||||||
"vocab.txt",
|
"vocab.txt",
|
||||||
|
|
|
||||||
|
|
@ -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
|
from __future__ import annotations
|
||||||
|
|
||||||
|
|
@ -10,12 +10,19 @@ from util.paths import (
|
||||||
GAME_QUIRKS_RELATIVE,
|
GAME_QUIRKS_RELATIVE,
|
||||||
GAME_SKILL_RELATIVE,
|
GAME_SKILL_RELATIVE,
|
||||||
GAME_SKILL_RESERVED_NAMES,
|
GAME_SKILL_RESERVED_NAMES,
|
||||||
|
LEGACY_GAME_SKILL_RELATIVE,
|
||||||
LEGACY_QUIRKS_FILENAME,
|
LEGACY_QUIRKS_FILENAME,
|
||||||
PROMPT_PATH,
|
PROMPT_PATH,
|
||||||
)
|
)
|
||||||
|
|
||||||
_SKILL_NAME_RE = re.compile(r"^[A-Za-z0-9][A-Za-z0-9._-]{0,63}$")
|
_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:
|
def quirks_path_for_game(game_root: str | Path | None) -> Path | None:
|
||||||
"""Return ``<game_root>/skills/quirks.md`` when *game_root* is set.
|
"""Return ``<game_root>/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:
|
def game_skill_path_for_game(game_root: str | Path | None) -> Path | None:
|
||||||
"""Return ``<game_root>/skills/translation.md`` when *game_root* is set."""
|
"""Return ``<game_root>/skills/game.md`` when *game_root* is set.
|
||||||
|
|
||||||
|
Migrates legacy ``skills/translation.md`` to ``skills/game.md`` when needed.
|
||||||
|
"""
|
||||||
if not game_root:
|
if not game_root:
|
||||||
return None
|
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:
|
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:
|
if not text:
|
||||||
return text
|
return text
|
||||||
# Common stale pointers from older Project Setup output.
|
# Common stale pointers from older Project Setup output.
|
||||||
updated = text.replace("translation_quirks.txt", "skills/quirks.md")
|
updated = text.replace("translation_quirks.txt", "skills/quirks.md")
|
||||||
updated = updated.replace("`translation_quirks.md`", "`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(
|
updated = re.sub(
|
||||||
r"(?<!skills/)(?<![\w./-])quirks\.md(?![\w.-])",
|
r"(?<!skills/)(?<![\w./-])quirks\.md(?![\w.-])",
|
||||||
"skills/quirks.md",
|
"skills/quirks.md",
|
||||||
updated,
|
updated,
|
||||||
)
|
)
|
||||||
# Avoid double skills/skills/
|
|
||||||
updated = updated.replace("skills/skills/quirks.md", "skills/quirks.md")
|
updated = updated.replace("skills/skills/quirks.md", "skills/quirks.md")
|
||||||
|
# Older templates included IDE-only Voice rules / Tool boundaries sections.
|
||||||
|
updated = _IDE_SECTION_RE.sub("\n", updated)
|
||||||
|
updated = re.sub(r"\n{3,}", "\n\n", updated).strip() + "\n"
|
||||||
return updated
|
return updated
|
||||||
|
|
||||||
|
|
||||||
|
|
@ -98,7 +118,7 @@ def custom_skill_path_for_game(
|
||||||
def list_custom_skill_paths(game_root: str | Path | None) -> list[Path]:
|
def list_custom_skill_paths(game_root: str | Path | None) -> list[Path]:
|
||||||
"""List user custom skill markdown files under ``<game>/skills/``.
|
"""List user custom skill markdown files under ``<game>/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)
|
skills = game_skills_dir(game_root)
|
||||||
if skills is None or not skills.is_dir():
|
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:
|
def load_system_prompt(game_root: str | Path | None = None) -> str:
|
||||||
"""Load ``data/skills/system.md`` plus optional per-game overlays.
|
"""Load ``data/skills/system.md`` plus optional per-game overlays.
|
||||||
|
|
||||||
Overlay order:
|
Overlay order (when ``DAZED_GAME_ROOT`` / *game_root* is set):
|
||||||
1. ``skills/quirks.md`` (voice quirks)
|
1. ``skills/game.md`` - Translation Frame / game skill (API)
|
||||||
2. Any other ``skills/*.md`` except ``translation.md`` (custom skills)
|
2. ``skills/quirks.md`` - cross-cutting voice quirks
|
||||||
|
3. other ``skills/*.md`` - optional custom overlays
|
||||||
|
|
||||||
Path resolution order for the game root:
|
Path resolution order for the game root:
|
||||||
1. Explicit *game_root* argument
|
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 []
|
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)
|
quirks_file = quirks_path_for_game(root)
|
||||||
if quirks_file and quirks_file.is_file():
|
if quirks_file and quirks_file.is_file():
|
||||||
quirks = quirks_file.read_text(encoding="utf-8").strip()
|
quirks = quirks_file.read_text(encoding="utf-8").strip()
|
||||||
|
|
|
||||||
|
|
@ -1945,7 +1945,7 @@ def createContext(config, subbedText, formatType, history=None):
|
||||||
cache invalidation caused by changing vocabulary matches.
|
cache invalidation caused by changing vocabulary matches.
|
||||||
|
|
||||||
Cached in static_system:
|
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:
|
Dynamic in vocab_text:
|
||||||
- only vocab terms found in the current batch text
|
- only vocab terms found in the current batch text
|
||||||
|
|
|
||||||
Loading…
Reference in a new issue