From b126537a7d244e9abdf586f29bf5d548f0e0c086 Mon Sep 17 00:00:00 2001 From: Eva Date: Wed, 3 Jun 2026 09:18:11 +0700 Subject: [PATCH] Hide wrapper progress filler from Chronicle --- viewer/openworlds/screen-table.jsx | 14 +++++++++++++- viewer/tests/test_sanitize_narration.py | 24 ++++++++++++++++++++++++ 2 files changed, 37 insertions(+), 1 deletion(-) diff --git a/viewer/openworlds/screen-table.jsx b/viewer/openworlds/screen-table.jsx index 2d83bb06..ed82bad6 100644 --- a/viewer/openworlds/screen-table.jsx +++ b/viewer/openworlds/screen-table.jsx @@ -165,6 +165,16 @@ function _stripInlineMarkdown(line) { .replace(/\*([^*\n]+)\*/g, "$1") .replace(/(^|[^A-Za-z0-9])_([^_\n]+)_([^A-Za-z0-9]|$)/g, "$1$2$3"); } +const _WRAPPER_PROGRESS_LINES = new Set([ + "The first scene gathers around you; voices, risks, and choices come into focus.", + "Your choice takes hold; nearby voices, risks, and consequences begin to answer.", + "The world turns with your action; the scene shifts toward its answer.", + "Your move lands; attention gathers around what changes next.", + "Momentum carries through the scene; consequences are beginning to surface.", +]); +function _isWrapperProgressLine(line) { + return _WRAPPER_PROGRESS_LINES.has((line || "").trim()); +} function sanitizeNarration(text) { if (typeof text !== "string" || !text) return ""; const kept = text @@ -178,7 +188,9 @@ function sanitizeNarration(text) { // …then drop any line that is wholly a #335 advisory/tool-name internal line (or was // emptied by the scaffolding strip above — _isInternalLine returns false on "", so an // emptied line survives as "" and is harmlessly collapsed by the blank-run join below). - .filter((line) => !_isInternalLine(line)); + // Also drop the wrapper-authored generic progress placeholders. They are useful only while + // a provider turn is in flight; once the real DM beat arrives they read like canned story prose. + .filter((line) => !_isInternalLine(line) && !_isWrapperProgressLine(line)); // Collapse the blank-line runs an excised directive may leave behind. return kept.join("\n").replace(/\n{3,}/g, "\n\n").trim(); } diff --git a/viewer/tests/test_sanitize_narration.py b/viewer/tests/test_sanitize_narration.py index 20a048be..31bcaeba 100644 --- a/viewer/tests/test_sanitize_narration.py +++ b/viewer/tests/test_sanitize_narration.py @@ -230,6 +230,30 @@ def test_markdown_wrapped_scaffolding_tallies_are_still_stripped(self): with self.subTest(value=value): self.assertEqual(value, "The lock holds.") + def test_wrapper_progress_placeholders_do_not_become_story(self): + cases = { + "opening": "The first scene gathers around you; voices, risks, and choices come into focus.", + "move_1": "Your choice takes hold; nearby voices, risks, and consequences begin to answer.", + "move_2": "The world turns with your action; the scene shifts toward its answer.", + "move_3": "Your move lands; attention gathers around what changes next.", + "move_4": "Momentum carries through the scene; consequences are beginning to surface.", + "mixed": ( + "The guard leans closer.\n" + "The world turns with your action; the scene shifts toward its answer.\n" + "The rooftop hand tightens on the dart." + ), + "near_miss": ( + "The world turns with your action; the scene shifts toward its answer " + "as the gate opens." + ), + } + out = self._sanitize_many(cases) + for key in ("opening", "move_1", "move_2", "move_3", "move_4"): + with self.subTest(case=key): + self.assertEqual(out[key], "") + self.assertEqual(out["mixed"], "The guard leans closer.\nThe rooftop hand tightens on the dart.") + self.assertEqual(out["near_miss"], cases["near_miss"]) + if __name__ == "__main__": unittest.main()