feat(translation): expand RPG Maker and image handling

- support CBR status text and update script/plugin defaults
- require skipped image reports to include recovery options
This commit is contained in:
DazedAnon 2026-07-27 19:35:11 -05:00
parent ca7cb81929
commit 68e07adeb3
4 changed files with 109 additions and 4 deletions

View file

@ -381,6 +381,32 @@ Report:
- Validation performed.
- Work-log location.
If any image or text region has a `skipped` or `review` disposition, append a
`### Skipped / review items` section as the literal final section of the user-facing response.
Do not put a closing sentence, follow-up offer, or any other content after it.
In that final section:
1. Group entries by image and list every skipped or review region, the reason it was not changed,
and what was preserved. Keep the list concise, but do not hide or summarize away individual
skipped images.
2. End with `Possible next steps:` and list only relevant options the user can explicitly choose:
- **Try it anyway** — attempt a best-effort deterministic edit despite the stated risk. Explain
what artwork, alpha, layout, or runtime behavior might be affected, and obtain permission
before proceeding.
- **Use generative AI** — try an isolated generated wordmark or label first, or a broader
generative edit only when the user explicitly authorizes it. State that model safety rules
may reject some inputs and that generated output still requires deterministic compositing
and validation.
- **Provide clean source art or layers** — request a title-free background, layered source,
alternate asset, or other clean reconstruction input.
- **Manual artist review** — recommend a human paint-over or source-file edit when neither
deterministic nor permitted generative methods can preserve the artwork safely.
3. Never imply that an option is guaranteed to succeed, and never perform a newly suggested
higher-risk or generative method without the required authorization.
If nothing was skipped or marked for review, omit this section entirely.
Do not paste full image files, large encoded data, or unrelated source code.
## Hard safety rules
@ -442,3 +468,5 @@ Consider the task complete only when:
- Originals remain recoverable.
- `image_translation_log.md` accounts for every reviewed image and text region without duplicate
current-run entries.
- When any disposition is `skipped` or `review`, the user-facing response ends with the complete
skipped/review list and relevant recovery options; when none exist, that section is omitted.

View file

@ -157,13 +157,13 @@ CODE122_VAR_MAX = 2000
# Plugins / Scripts
CODE355655 = False
CODE357 = False
CODE357 = True
CODE657 = False
CODE356 = False
CODE320 = False
CODE324 = False
CODE325 = False
CODE111 = True
CODE111 = False
CODE108 = False
# ─── Plugin Manager ──────────────────────────────────────────────────────────
@ -195,11 +195,12 @@ HEADER_MAPPINGS_357 = {
"SceneGlossary": (["category"], None),
}
# Subset of HEADER_MAPPINGS_357 keys that should be processed (empty = none).
ENABLED_PLUGINS_357: set = {"BattleLogOutput"}
ENABLED_PLUGINS_357: set = {"DTextPicture", "TorigoyaMZ_NotifyMessage"}
# All known code-355/655 script patterns. Enable entries via ENABLED_PATTERNS_355655.
PATTERNS_355655 = {
"テキスト-": (r"テキスト-(.+)", False),
"CBR-エロステータス": (r"テキスト-(.+)", True),
"=": (r'=\s?(.*)",', False),
"var text": (r'var\stext\d+\s=\s\"(.+)\"', False),
"logtxt = ": (r"logtxt\s=\s'(.+)'", False),
@ -234,7 +235,7 @@ PATTERNS_355655 = {
"AddAddress": (r'AddAddress\(\d+,\s*\\?"(.+?)\\?"', False),
}
# Subset of PATTERNS_355655 keys that should be processed (empty = none).
ENABLED_PATTERNS_355655: set = {"if (BattleManager.canEscape())"}
ENABLED_PATTERNS_355655: set = set()
def _pat355655_captured_text(match):

View file

@ -18,6 +18,71 @@ import modules.rpgmakermvmz as mvmz # noqa: E402
class TestMVMZScriptPatterns(unittest.TestCase):
def test_cbr_erotic_status_pattern_definition(self):
regex, multiline = mvmz.PATTERNS_355655["CBR-エロステータス"]
self.assertEqual(regex, r"テキスト-(.+)")
self.assertTrue(multiline)
def test_cbr_erotic_status_multiline_integration(self):
source_statuses = ["", ""]
translated_statuses = ["times", "people"]
page = {
"list": [
{
"code": 355,
"indent": 0,
"parameters": ["CBR-エロステータス"],
},
{
"code": 655,
"indent": 0,
"parameters": ["コマンド-表示"],
},
*[
{
"code": 655,
"indent": 0,
"parameters": [f"テキスト-{status}"],
}
for status in source_statuses
],
{
"code": 655,
"indent": 0,
"parameters": ["テキスト-"],
},
]
}
captured = []
def translate(text, history, batch=False):
captured.append(copy.deepcopy(text))
return [copy.deepcopy(translated_statuses), [0, 0]]
original_translate = mvmz.translateAI
original_code355655 = mvmz.CODE355655
original_enabled = mvmz.ENABLED_PATTERNS_355655
mvmz.translateAI = translate
mvmz.CODE355655 = True
mvmz.ENABLED_PATTERNS_355655 = {"CBR-エロステータス"}
try:
translated_page = copy.deepcopy(page)
mvmz.searchCodes(translated_page, None, [], "TestMap.json")
finally:
mvmz.translateAI = original_translate
mvmz.CODE355655 = original_code355655
mvmz.ENABLED_PATTERNS_355655 = original_enabled
self.assertEqual(captured, [source_statuses])
self.assertEqual(translated_page["list"][0], page["list"][0])
self.assertEqual(translated_page["list"][1], page["list"][1])
self.assertEqual(
[entry["parameters"][0] for entry in translated_page["list"][2:4]],
[f"テキスト-{status}" for status in translated_statuses],
)
self.assertEqual(translated_page["list"][4], page["list"][4])
def test_battle_manager_can_escape_pattern_definition(self):
regex, multiline = mvmz.PATTERNS_355655["if (BattleManager.canEscape())"]

View file

@ -59,6 +59,17 @@ class WorkflowTranslationPromptTests(unittest.TestCase):
self.assertNotIn(constant, workflow_source)
self.assertNotIn("_WOLF_SPEAKER_PROMPT", wolf_source)
def test_image_translation_prompt_ends_skips_with_recovery_options(self):
prompt = load_clipboard_skill("image_translation.md")
self.assertIn("### Skipped / review items", prompt)
self.assertIn("literal final section of the user-facing response", prompt)
self.assertIn("Try it anyway", prompt)
self.assertIn("Use generative AI", prompt)
self.assertIn("Provide clean source art or layers", prompt)
self.assertIn("Manual artist review", prompt)
self.assertIn("If nothing was skipped or marked for review, omit", prompt)
def test_clipboard_skill_loader_rejects_paths(self):
with self.assertRaises(ValueError):
load_clipboard_skill("../system.md")