deepseek-harness/packages/core/agent-loop/tests
Tianyi Cui b3d40d427e Persist the seed boundary so fork-child replay routes correctly
A fork subagent seeds its child session with a prefix of the parent's log, and
that seed becomes the child's persisted log — so a fork child's .jsonl begins
with the PARENT's events, including the parent's assistant/chunk events. The
snapshot replay harness derived a child's script from its whole log, which would
replay the parent's recorded responses as the child's model calls. Spawn-only
scenarios never hit it, but a fork snapshot would mis-route silently.

Record the seed boundary and skip the inherited prefix at replay:

- SessionHeader gains an optional `seedLength` (how many leading events were
  inherited via a seed), threaded through CreateSessionOptions/CreateAgentOptions
  meta and stamped by the fork backend (= seeded-prefix length; absent for spawn).
  It is EXPLICIT, never inferred from seed.length: a resume seeds the whole stored
  log, so the resume path passes the persisted boundary back.
- Both persistence backends round-trip it: JSONL header line, SQLite seed_length
  column. The SQLite table change bumps SCHEMA_VERSION 2->3; per the pre-release
  stance the backend rejects an older user_version on open with NO migration.
- llm-replay's parseSessionHeader reads seedLength and loadSessionScripts derives
  a child script from events AFTER the boundary. seedLength is 0 for spawn, so
  spawn replay is byte-for-byte unchanged.

Closes the routing-correctness gap the per-session snapshot replay RFC under-
stated; a recorded fork scenario remains a future addition but now derives
correctly. RFC: docs/rfc/implemented/testing/2026-06-22-fork-child-replay-seed-boundary.md.

Regression coverage: a fork child fixture whose seeded prefix carries a parent
chunk (derived script must exclude it, proven red without the slice); a seedLength
persistence round-trip through the shared coordinator contract (both backends);
the fork backend stamping it; resume preserving it from the persisted header.
2026-06-22 20:55:32 +08:00
..
agent.spec.ts simplify(agent): drop the unused public Agent.abort(), keep whenIdle() 2026-06-21 09:05:21 +08:00
cancel.spec.ts fix review findings: stale abort() docs + move RFC to implemented 2026-06-21 09:10:56 +08:00
config-session-id.spec.ts feat(types): brand bash ids + stop brand erosion; extract Branded to dsh-brand 2026-06-21 07:19:59 +08:00
coverage-edges.spec.ts simplify(session): fold trace-only usage/error events into load-bearing events 2026-06-21 10:00:06 +08:00
inbox.spec.ts Reorganize packages into a modular hierarchy 2026-06-20 22:55:20 +08:00
loop.spec.ts fix review findings: bump session format version + restore late turn-end warn 2026-06-21 11:08:10 +08:00
mock-adapter.ts Reorganize packages into a modular hierarchy 2026-06-20 22:55:20 +08:00
properties.spec.ts feat(types): brand bash ids + stop brand erosion; extract Branded to dsh-brand 2026-06-21 07:19:59 +08:00
resume.spec.ts Persist the seed boundary so fork-child replay routes correctly 2026-06-22 20:55:32 +08:00
review-fixes.spec.ts fix review findings: bump session format version + restore late turn-end warn 2026-06-21 11:08:10 +08:00