scroll: tag the disembody + relinquish un-do events as Fable, not Frame — TDD
SIG_UNREADY ("disembodies POSS Significator") + SEA_RELINQUISHED ("relinquishes
POSS affinity with the X") are the character un-doing its Significator / Sea —
the un-do counterparts of the fable SIG_READY / SEA_DRAWN. They were stranded in
FABLE_VERBS' blind spot, so the scroll tagged them data-base="frame" with a bare
@handle instead of "@handle's character", and the Fable filter never caught them
(a disembody log showed under Frame, split from its embody pair).
Add both to FABLE_VERBS so they render data-base="fable" + the "@handle's
character" stub and ride the Fable filter with their pair. The billboard recent-
room EMBED still drops SIG_UNREADY noise (a verb-based exclude, untouched); the
redact-pair machinery is verb-keyed too, so is_fable has no functional effect
beyond display/filter.
TDD: drama ITs +2 — sig-unready + sea-relinquished render fable + character
stub; is_fable test moves both verbs to the fable group (only table/gate events
— deposits, chair assignment — stay frame). 59 drama + 241 billboard + 407 epic
ITs green.
Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -63,10 +63,16 @@ class GameEvent(models.Model):
|
|||||||
]
|
]
|
||||||
|
|
||||||
# "Fable" events — the character-creation provenance (Significator / SkyDrive
|
# "Fable" events — the character-creation provenance (Significator / SkyDrive
|
||||||
# / Sea of Cards) the scroll tags data-label="fable" instead of "frame", and
|
# / Sea of Cards), INCL. their un-do counterparts (SIG_UNREADY "disembodies"
|
||||||
# prefixes with "@handle's character" (a stub for the character's name). The
|
# + SEA_RELINQUISHED "relinquishes"): the scroll tags data-base="fable" (not
|
||||||
# SEA_RELINQUISHED redact-pair counterpart inherits its struck=redact label.
|
# "frame") + prefixes "@handle's character" (a stub for the character's name).
|
||||||
FABLE_VERBS = frozenset({SIG_READY, SKY_SAVED, SEA_DRAWN})
|
# The un-do verbs are fable too so they ride the Fable filter with their
|
||||||
|
# ready/drawn pair — a disembody/relinquish is the character acting, not a
|
||||||
|
# table/gate frame event. A struck fable row still collapses to
|
||||||
|
# data-label="redact"; the per-base filter needs BOTH Fable AND Redact to show it.
|
||||||
|
FABLE_VERBS = frozenset({
|
||||||
|
SIG_READY, SIG_UNREADY, SKY_SAVED, SEA_DRAWN, SEA_RELINQUISHED,
|
||||||
|
})
|
||||||
|
|
||||||
room = models.ForeignKey(
|
room = models.ForeignKey(
|
||||||
"epic.Room", on_delete=models.CASCADE, related_name="events",
|
"epic.Room", on_delete=models.CASCADE, related_name="events",
|
||||||
|
|||||||
@@ -271,12 +271,15 @@ class GameEventModelTest(TestCase):
|
|||||||
self.assertTrue(event.struck)
|
self.assertTrue(event.struck)
|
||||||
|
|
||||||
def test_is_fable_for_character_creation_verbs(self):
|
def test_is_fable_for_character_creation_verbs(self):
|
||||||
# SIG_READY / SKY_SAVED / SEA_DRAWN are fable; everything else is not.
|
# The Significator / SkyDrive / Sea of Cards events — INCL. their un-do
|
||||||
for verb in (GameEvent.SIG_READY, GameEvent.SKY_SAVED, GameEvent.SEA_DRAWN):
|
# counterparts (disembody / relinquish) — are fable; table/gate events
|
||||||
|
# (deposits, chair assignment) are not.
|
||||||
|
for verb in (GameEvent.SIG_READY, GameEvent.SIG_UNREADY,
|
||||||
|
GameEvent.SKY_SAVED, GameEvent.SEA_DRAWN,
|
||||||
|
GameEvent.SEA_RELINQUISHED):
|
||||||
self.assertTrue(
|
self.assertTrue(
|
||||||
record(self.room, verb, actor=self.user).is_fable, verb)
|
record(self.room, verb, actor=self.user).is_fable, verb)
|
||||||
for verb in (GameEvent.SLOT_FILLED, GameEvent.ROLE_SELECTED,
|
for verb in (GameEvent.SLOT_FILLED, GameEvent.ROLE_SELECTED):
|
||||||
GameEvent.SEA_RELINQUISHED, GameEvent.SIG_UNREADY):
|
|
||||||
self.assertFalse(
|
self.assertFalse(
|
||||||
record(self.room, verb, actor=self.user).is_fable, verb)
|
record(self.room, verb, actor=self.user).is_fable, verb)
|
||||||
|
|
||||||
@@ -331,6 +334,29 @@ class GameEventModelTest(TestCase):
|
|||||||
self.assertIn('data-label="redact"', html)
|
self.assertIn('data-label="redact"', html)
|
||||||
self.assertIn('data-base="frame"', html)
|
self.assertIn('data-base="frame"', html)
|
||||||
|
|
||||||
|
def test_scroll_tags_sig_unready_as_fable_with_character_actor(self):
|
||||||
|
# "disembodies POSS Significator" is the character un-readying its sig —
|
||||||
|
# a FABLE event (rides the Fable filter with SIG_READY), so it gets the
|
||||||
|
# "@handle's character" stub + data-base="fable", not a bare @handle frame.
|
||||||
|
self.user.username = "disco"
|
||||||
|
self.user.save(update_fields=["username"])
|
||||||
|
ev = record(self.room, GameEvent.SIG_UNREADY, actor=self.user)
|
||||||
|
html = self._render_scroll(ev)
|
||||||
|
self.assertIn('data-base="fable"', html)
|
||||||
|
self.assertIn('<span class="ev-char-stub">\'s character</span>', html)
|
||||||
|
self.assertIn("disembodies", html)
|
||||||
|
|
||||||
|
def test_scroll_tags_sea_relinquished_as_fable_with_character_actor(self):
|
||||||
|
# The let-go counterpart of SEA_DRAWN is fable too, so the relinquishment
|
||||||
|
# rides the Fable filter with its pair (not stranded under Frame).
|
||||||
|
self.user.username = "disco"
|
||||||
|
self.user.save(update_fields=["username"])
|
||||||
|
ev = record(self.room, GameEvent.SEA_RELINQUISHED, actor=self.user,
|
||||||
|
card_name="The Magician")
|
||||||
|
html = self._render_scroll(ev)
|
||||||
|
self.assertIn('data-base="fable"', html)
|
||||||
|
self.assertIn('<span class="ev-char-stub">\'s character</span>', html)
|
||||||
|
|
||||||
def test_sig_ready_prose_degrades_without_corner_rank(self):
|
def test_sig_ready_prose_degrades_without_corner_rank(self):
|
||||||
# Old events recorded before this change have no corner_rank key
|
# Old events recorded before this change have no corner_rank key
|
||||||
event = record(self.room, GameEvent.SIG_READY, actor=self.user,
|
event = record(self.room, GameEvent.SIG_READY, actor=self.user,
|
||||||
|
|||||||
Reference in New Issue
Block a user