switchroom 0.14.37 → 0.14.39

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -153,3 +153,53 @@ describe('backfillJsonlAgentId — parent_turn_key resolution', () => {
153
153
  expect(row?.parent_turn_key == null).toBe(true)
154
154
  })
155
155
  })
156
+
157
+ // ─── #2081: overlapping windows + hook-stamped value precedence ───────────────
158
+ // The backfill is now only a FALLBACK — the PreToolUse hook stamps
159
+ // parent_turn_key from the live turn-active marker at dispatch
160
+ // (subagent-tracker-pretool.mjs readActiveTurnKey). These tests pin the two
161
+ // guarantees that make the hook fix correct end-to-end.
162
+ describe('backfillJsonlAgentId — overlapping windows / hook precedence (#2081)', () => {
163
+ it('does NOT overwrite a hook-stamped parent_turn_key, even when overlapping windows would resolve differently', () => {
164
+ // Supergroup: two forum topics under one chat with OVERLAPPING windows.
165
+ // Topic A (thread 4) started first and is still open; topic B (thread 7)
166
+ // started later. A sub-agent dispatched at 1500 falls inside BOTH windows.
167
+ insertTurn({ turnKey: '-100:4:1000', chatId: '-100', threadId: '4', startedAt: 1000, endedAt: null })
168
+ insertTurn({ turnKey: '-100:7:1400', chatId: '-100', threadId: '7', startedAt: 1400, endedAt: null })
169
+
170
+ // The hook already stamped the CORRECT parent (topic A) from the marker.
171
+ insertSub({
172
+ id: 'toolu_overlap',
173
+ agentType: 'worker',
174
+ description: 'Topic-A worker',
175
+ startedAt: 1500,
176
+ parentTurnKey: '-100:4:1000',
177
+ })
178
+
179
+ const jsonlPath = writeMeta('worker', 'Topic-A worker')
180
+ backfillJsonlAgentId(db, jsonlPath, 'agentstem_overlap')
181
+
182
+ const row = readSub('toolu_overlap')
183
+ expect(row?.jsonl_agent_id).toBe('agentstem_overlap')
184
+ // The IS NULL guard means the hook's correct value survives — NOT the
185
+ // window query's ORDER BY started_at DESC pick (which would be topic B).
186
+ expect(row?.parent_turn_key).toBe('-100:4:1000')
187
+ })
188
+
189
+ it('fallback window-match (NULL parent) picks the latest-started overlapping turn — the documented fallback limitation', () => {
190
+ // When the hook left parent_turn_key NULL (no active marker at dispatch),
191
+ // the backfill falls back to the started_at window match. With overlapping
192
+ // windows it resolves to the latest-started containing turn. This is a
193
+ // best-effort fallback for the no-marker case — the hook path above is the
194
+ // correct primary. Pinned here so the fallback behaviour is explicit.
195
+ insertTurn({ turnKey: '-100:4:1000', chatId: '-100', threadId: '4', startedAt: 1000, endedAt: null })
196
+ insertTurn({ turnKey: '-100:7:1400', chatId: '-100', threadId: '7', startedAt: 1400, endedAt: null })
197
+ insertSub({ id: 'toolu_fallback', agentType: 'worker', description: 'No-marker worker', startedAt: 1500 })
198
+
199
+ const jsonlPath = writeMeta('worker', 'No-marker worker')
200
+ backfillJsonlAgentId(db, jsonlPath, 'agentstem_fallback')
201
+
202
+ const row = readSub('toolu_fallback')
203
+ expect(row?.parent_turn_key).toBe('-100:7:1400')
204
+ })
205
+ })