From 68e07adeb38a3eda8dc493677b45be5b9dd6c082 Mon Sep 17 00:00:00 2001 From: DazedAnon Date: Mon, 27 Jul 2026 19:35:11 -0500 Subject: [PATCH] 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 --- data/skills/image_translation.md | 28 +++++++++++++ modules/rpgmakermvmz.py | 9 +++-- tests/test_mvmz_script_patterns.py | 65 ++++++++++++++++++++++++++++++ tests/test_workflow_prompts.py | 11 +++++ 4 files changed, 109 insertions(+), 4 deletions(-) diff --git a/data/skills/image_translation.md b/data/skills/image_translation.md index 72f7a99..340730b 100644 --- a/data/skills/image_translation.md +++ b/data/skills/image_translation.md @@ -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. diff --git a/modules/rpgmakermvmz.py b/modules/rpgmakermvmz.py index 4e75943..db97af7 100644 --- a/modules/rpgmakermvmz.py +++ b/modules/rpgmakermvmz.py @@ -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): diff --git a/tests/test_mvmz_script_patterns.py b/tests/test_mvmz_script_patterns.py index 71afd45..f6d1aee 100644 --- a/tests/test_mvmz_script_patterns.py +++ b/tests/test_mvmz_script_patterns.py @@ -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())"] diff --git a/tests/test_workflow_prompts.py b/tests/test_workflow_prompts.py index 2aa5236..0463796 100644 --- a/tests/test_workflow_prompts.py +++ b/tests/test_workflow_prompts.py @@ -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")