fix: natural-language skip runs scene close detection (T82.2)
The natural-language skip dispatch in chat.web.turns.post_turn (intent="skip_elision") previously bypassed scene close detection entirely. User prose like "fade out, skip an hour" carries both a close signal and a skip directive — the close summary must capture the closing scene's final beat (and promote per-POV memories) before the time advances. Insert detect_scene_close + apply_scene_close_summary BEFORE the skip controller invocation in the skip_elision branch. Order: scene close -> skip narration -> time advance. When there's no active scene or the prose carries no close signal, detect_scene_close returns the safe should_close=False default and the flow drops straight to the skip controller — same behavior as today.
This commit is contained in:
@@ -317,6 +317,49 @@ async def post_turn(
|
||||
)
|
||||
|
||||
if intent == "skip_elision":
|
||||
# T82.2: run scene-close detection on the user's prose BEFORE
|
||||
# the skip controller fires. Prose like "fade out, skip an hour"
|
||||
# carries both a close signal and a skip directive; we want the
|
||||
# close summary to capture the closing scene's final beat (and
|
||||
# promote per-POV memories) before the time advances. Order
|
||||
# matters: scene close -> skip narration -> time advance.
|
||||
#
|
||||
# When there's no active scene (or the prose carries no close
|
||||
# signal) ``detect_scene_close`` returns the safe
|
||||
# ``should_close=False`` default and we drop straight to the
|
||||
# skip controller — same behavior as today, no extra cost.
|
||||
skip_scene = active_scene(conn, chat_id)
|
||||
if skip_scene is not None:
|
||||
container = None
|
||||
if skip_scene.get("container_id") is not None:
|
||||
container = get_container(conn, skip_scene["container_id"])
|
||||
container_name = container["name"] if container else "unknown"
|
||||
close_decision = await detect_scene_close(
|
||||
client,
|
||||
model=settings.classifier_model,
|
||||
prose=prose,
|
||||
current_container_name=container_name,
|
||||
)
|
||||
if close_decision.should_close:
|
||||
append_and_apply(
|
||||
conn,
|
||||
kind="scene_closed",
|
||||
payload={
|
||||
"scene_id": skip_scene["id"],
|
||||
"ended_at": chat.get("time"),
|
||||
"significance": 0,
|
||||
},
|
||||
)
|
||||
await apply_scene_close_summary(
|
||||
conn,
|
||||
client,
|
||||
classifier_model=settings.classifier_model,
|
||||
chat_id=chat_id,
|
||||
scene_id=skip_scene["id"],
|
||||
host_bot_id=host_bot["id"],
|
||||
timeout_s=settings.classifier_timeout_s,
|
||||
)
|
||||
|
||||
# Derive ``new_time`` from the chat clock. Phase 3 stub: bump by
|
||||
# 1 hour. The drawer's elision form is the structured path when
|
||||
# the author wants a specific landing time; here the goal is
|
||||
|
||||
Reference in New Issue
Block a user