Skip to content

Commit 986f8e8

Browse files
committed
file: ultraworkers#158 — compact_messages_if_needed drops turns silently, no structured compaction event
1 parent ef1cfa1 commit 986f8e8

1 file changed

Lines changed: 32 additions & 0 deletions

File tree

ROADMAP.md

Lines changed: 32 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -6043,3 +6043,35 @@ New users see these commands in the help output but have no explanation of:
60436043
**Blocker.** None. Natural Phase 3 progression from #77 P1 (JSON kind) → #156 (text kind) → #157 (structured remediation).
60446044

60456045
**Source.** gaebal-gajae dogfood sweep 2026-04-22 05:30 KST — identified that `kind` is structured but `hint` remains prose-derived, leaving downstream claws with half an error contract.
6046+
6047+
## Pinpoint #158. `compact_messages_if_needed` drops turns silently — no structured compaction event emitted
6048+
6049+
**Gap.** `QueryEnginePort.compact_messages_if_needed()` (`src/query_engine.py:129`) silently truncates `mutable_messages` and `transcript_store` whenever turn count exceeds `compact_after_turns` (default 12). The truncation is invisible to any consumer — `TurnResult` carries no compaction indicator, the streaming path emits no `compaction_occurred` event, and `persist_session()` persists only the post-compaction slice. A claw polling session state after compaction sees the same `session_id` but a different (shorter) context window with no structured signal that turns were dropped.
6050+
6051+
**Repro.**
6052+
```python
6053+
import sys; sys.path.insert(0, 'src')
6054+
from query_engine import QueryEnginePort, QueryEngineConfig
6055+
6056+
engine = QueryEnginePort.from_workspace()
6057+
engine.config = QueryEngineConfig(compact_after_turns=3)
6058+
for i in range(5):
6059+
r = engine.submit_message(f'turn {i}')
6060+
# TurnResult has no compaction field
6061+
assert not hasattr(r, 'compaction_occurred') # passes every time
6062+
print(len(engine.mutable_messages)) # 3 — silently truncated from 5
6063+
```
6064+
6065+
**Root cause.** `compact_messages_if_needed` is called inside `submit_message` with no return value and no side-channel notification. `stream_submit_message` yields a `message_stop` event that includes `transcript_size` but not a `compaction_occurred` flag or `turns_dropped` count.
6066+
6067+
**Fix shape (~15 lines).**
6068+
1. Add `compaction_occurred: bool` and `turns_dropped: int` to `TurnResult`.
6069+
2. In `compact_messages_if_needed`, return `(bool, int)` — whether compaction ran and how many turns were dropped.
6070+
3. Propagate into `TurnResult` in `submit_message`.
6071+
4. In `stream_submit_message`, include `compaction_occurred` and `turns_dropped` in the `message_stop` event.
6072+
6073+
**Acceptance.** A claw watching the stream can detect that compaction occurred and how many turns were silently dropped, without polling `transcript_size` across two consecutive turns.
6074+
6075+
**Blocker.** None.
6076+
6077+
**Source.** Jobdori dogfood sweep 2026-04-22 06:36 KST — probed `query_engine.py` compact path, confirmed no structured compaction signal in `TurnResult` or stream output.

0 commit comments

Comments
 (0)