# Bằng chứng TDD: `spawn_fork` Tài liệu này ghi lại feature `spawn_fork` được phát hành trong tarball `v0.6.0`. Tool dùng cùng selection/persona/follow-up contract của `spawn`, nhưng định tuyến qua DSH provider `fork` để kế thừa context parent. ## Contract được kiểm tra | Journey | Kết quả cần đảm bảo | | --- | --- | | Registration | DSH registry có cả `spawn` và `spawn_fork`; mô tả fork nêu completed turns. | | Explicit route | `provider`, `model` và `effort` (khi model công bố effort ids) được validate trước khi fork child. | | Persona | `ecc:architect` được normalize, không truyền upstream `tools`/`model`. | | Context seed | Child fork nhận các parent turn đã kết thúc; in-flight turn không được seed. | | Continuation | `operation: followup` dùng cùng fork binding và route/persona snapshot. | | Isolation | Binding của `spawn` và `spawn_fork` không được dùng chéo. | | Capability error | Host thiếu provider `fork` trả `TRANSPORT_UNAVAILABLE`, không fallback. | ## RED Test được viết trước implementation: ```text vitest run tests/tool-name.test.ts tests/spawn-service.test.ts 1 failed, 10 passed createSpawnForkTool is not a function ``` Failure này xác nhận registry factory và fork transport contract chưa tồn tại. ## GREEN Sau khi thêm `createSpawnForkTool`, fork service/binding riêng và kiểm tra transport khi follow-up: ```text vitest run tests/tool-name.test.ts tests/spawn-service.test.ts 12 passed tsc -p tsconfig.json --noEmit passed ``` Coverage sau vòng GREEN: ```text All files: 83.50% statements, 81.84% branches, 83.17% functions ``` Unit tests xác nhận `transportProvider: "fork"` được gửi vào runtime, persona không cần tool filter, và binding provider khác không bị reuse. Bổ sung branch tests trong `tests/runtime-dsh.test.ts` bao phủ provider không tồn tại, parent không có session id, optional service qua `ctx.get`, selection fallback từ request header và setup không có route. Full suite sau bổ sung: ```text pnpm test:coverage 13 files passed, 61 tests passed All files: 83.50% statements, 81.84% branches, 83.17% functions ``` ## Smoke test DSH thật Profile `web-test` được cập nhật bằng tarball local chưa publish: ```text C:\\Users\\Admin\\AppData\\Local\\Temp\\dsh-ecc-rc1-0.5.0-spawn-fork\\staavanothanh-dsh-ecc-0.5.0.tgz provider: ninerouter model: cmc/xiaomi/mimo-v2.5 effort: low ``` Trên DSH Web port `3098`, các bước thực tế đều thành công: 1. `spawn_fork` start tạo child `28157627-d11a-4968-aa21-30f269bcb799`. 2. Descriptor xác nhận `mode: continuable`, `provider: fork`, route `ninerouter/cmc/xiaomi/mimo-v2.5`, `reasoningEffort: low` và persona `ecc:architect` đã normalize. 3. Parent completed turn chứa sentinel `FORK_CONTEXT_SENTINEL_9A7Q`; child trả `FORK_CONTEXT_OK`, chứng minh fork seed được kế thừa. 4. `spawn_fork` follow-up trả `FORK_FOLLOWUP_OK`. 5. Sau khi stop/start lại DSH, cold-resume follow-up qua cùng child trả `FORK_COLD_RESUME_OK`. Server smoke đã được stop sau kiểm tra; port `3098` không còn listener. Feature được đóng gói trong release `v0.6.0`; tarball local `v0.5.0` ở trên được giữ lại như bằng chứng smoke test ban đầu. ## DSH upstream caveat DSH `subagent-fork-in-process` hỗ trợ `prepareContinuable`, nhưng upstream có cảnh báo về composition của fork seed với continuable setup/report prefix. Vì vậy smoke test phải kiểm tra cả nội dung context thực tế và descriptor; không chỉ kiểm tra child id hoặc status success.