MoonshotAI / MoonshotAI/kimi-code
Background tasks marked "lost" without liveness check; resume spawns duplicate concurrent workers
Nobody has claimed this yet.
- Dominant language
- TypeScript
- Stars
- 7.5k
- Forks
- 1.2k
- Avg merge
- 11h 53m
- Merged PRs (30d)
- 350
Description
Summary
When a kimi-code process with live background tasks is still running and a second process resumes the same session, markLoadedTasksLost marks the first process's non-terminal tasks as lost — without any liveness probe, even though the task's PID is persisted on disk. The resume_hint returned to the model then explicitly instructs Agent(resume=agent_id) on task.lost, spawning a second concurrent worker on the same task while the first is still alive.
We hit this in production: two subagent instances ran concurrently for ~65 minutes, each editing the same file, each reporting "another session is modifying this file" — they were seeing each other. Both eventually completed; the task record had marked one of them lost while it was demonstrably alive.
Evidence (all paths verified against current master)
packages/agent-core-v2/src/agent/task/taskService.ts:854-869—markLoadedTasksLostiterates ghost tasks and marks every non-terminal one aslostand writes it back to disk. There is noprocess.kill(pid, 0)-style probe anywhere in this path.packages/agent-core-v2/src/agent/task/persist.ts:236,276— the persisted task record already containspid(LegacyPersistedTask.pid, mapped intoProcessTaskInfo), so the material for a liveness check is on disk, unused.packages/agent-core-v2/src/session/subagent/tools/agent.ts:481—resume_hintliststask.lostas a recovery case and tells the model to callAgent(resume=agent_id), which makes duplicate workers a scripted outcome rather than an accident.- There is no per-session cross-process lock, so two processes resuming the same session (e.g. a supervisor that spawns one CLI process per message with
--resume) race: the live one's tasks get markedlost, and the task JSON itself is last-writer-wins between the two processes.
This is the same "killed but not reaped" family as #1882 (torn wire.jsonl after SIGKILL), one layer up in the stack.
Suggested fixes (in order of effort)
- Probe before marking lost (small): in
markLoadedTasksLost, forkind === 'process'ghosts, runprocess.kill(pid, 0). If the process is alive, keep the taskrunningand skip the lost notification. A ready-made probe pattern exists inapps/kap-server/src/lock.ts(PID + liveness check for instance locks). - Fix the guidance (trivial): change
resume_hintto state thatlostdoes not mean the worker is dead, and that the caller should verify the old instance is gone before resuming. - Per-session cross-process lock (design-level): owner PID + heartbeat, reusing the
kap-server/src/lock.tspattern.reconcile()skips lost-marking while the lock owner is alive. This also covers agent-kind tasks, which have no PID to probe (same-process loops).
We'd be happy to contribute (1) as a PR if the direction sounds right.
Environment
- kimi-code 0.27.0, agent-core-v2
- Linux, supervisor spawning one CLI process per message with
--resume(cc-connect)
Contributor guide
First steps
- Read the whole issue, then the project's contributing guide.
- Comment on the issue to say you are picking it up — it saves two people doing the same work.
- Fork the repository and make your change on a branch.
- Open a pull request that references the issue number.
Research direction
Start with markLoadedTasksLost in packages/agent-core-v2/src/agent/task/taskService.ts and compare the PID liveness pattern in apps/kap-server/src/lock.ts. Check the persisted PID mapping in packages/agent-core-v2/src/agent/task/persist.ts and the recovery wording in packages/agent-core-v2/src/session/subagent/tools/agent.ts. Done means live process tasks are not marked lost and the resume guidance no longer treats lost as proof that a worker is dead.
Written by the indexing model from the issue text.
Assessment
- Tech stack
- typescript
- Domain
- cli
- Issue type
- Bug
- Difficulty
- 3/5
- Estimated time
- 1-2 days
- Activity status
- Quiet
- Clarity
- Clearly specified
- Newbie friendliness
- 76/100