MoonshotAI / MoonshotAI/kimi-code

0.40.1: plan-mode prompt cadence amplifies alternating Bash no-op loops; #1314 recovery absent

Open
#3,489 0 comments 0 reactions 0 assignees View on GitHub

Nobody has claimed this yet.

Dominant language
TypeScript
Stars
7.5k
Forks
1.2k
Avg merge
11h 53m
Merged PRs (30d)
350

Description

Summary

After upgrading Kimi Code from 0.39.1 to 0.40.1, an interactive long-running planning session with kimi-code/k3 became trapped in a no-op tool-call loop. The model repeatedly emitted real Bash calls with true, echo ., and echo ok rather than writing the file it had just said it would write.

This is not an MCP server, hook, or transport/replay rewrite:

  • The raw session wire records the model's actual Bash calls with those arguments.
  • The repair log reports no dropped or synthesized tool calls; it only reorders calls.
  • The behavior continued after plugin-session guidance was neutralized.

I found two interacting core behaviors in the released source:

  1. PlanModeInjector appends a user-role plan reminder at the first step and then after every two assistant messages during the same user turn. In the affected turn this yielded 57 plan-mode injections and 103 total system-reminder tags.
  2. ToolCallDeduplicator keys a call by the complete canonicalized tool arguments. It therefore treats Bash(true), Bash(echo .), and Bash(echo ok) as different calls and resets the cross-step streak whenever the model alternates them. The forced stop is only reachable after 12 identical calls.

The plan-mode write restriction itself is enforced separately by plan-mode-guard-deny.ts; repeatedly re-injecting the prose reminder is therefore not required to preserve the safety boundary.

Reproduction characteristics

  • Kimi Code: 0.40.1
  • Source checkout: 052e98ec1 (current main on 2026-09-02)
  • Model: kimi-code/k3, high/always thinking
  • Context limit: 1,048,576
  • Session had 139 exposed tools, including 112 MCP-discovered schemas
  • Observed tool totals: 187 Bash, 16 Read, zero Write or Edit
  • Placeholder calls: 84 total: 72 true, 11 echo ., 1 echo ok
  • First placeholder call preceded the first anti-loop reminder. The guard warning is therefore downstream, not the origin.

The large tool surface and long context seem to amplify the model failure, but they do not create the prompt injection or rewrite tools.

Relation to #1314

This is the exact failure class described by #1314. That issue was closed as completed without a linked closing commit, but 0.40.1 still has argument-exact-only deduplication and no progress-based text-only recovery in the legacy agent-core path. The report above adds a plan-mode interaction and a released-version reproduction.

Suggested fix

I tested the following minimal regressions locally in packages/agent-core; 47 focused tests passed and tsc -p tsconfig.json --noEmit passed.

  1. Do not cadence-reinject plan-mode reminders during a continuous tool-use turn. Inject on entering plan mode, after an actual new user message, and on explicit re-entry only. Continue using the existing deny policy as the authoritative plan-mode enforcement.
  2. Normalize known inert Bash placeholders (true, :, echo, echo ., echo ok) to one deduplication key so alternating variants cannot evade the existing 12-step forced stop.

A more complete resolution remains the progress-based detector proposed in #1314: detect a run of calls with no filesystem change, background-task state change, or meaningful new output, then issue a final tool-free model step. That protects against unanticipated placeholder variants and non-Bash idle loops.

Version note

The symptom first appeared immediately after the 0.40.1 upgrade. I compared the relevant legacy injector/deduper path with 0.39.1 and did not find a direct code change there, so I cannot prove that 0.40.1 introduced the root cause; it is a reproducible currently released behavior rather than a confirmed regression commit.

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start in packages/agent-core by tracing PlanModeInjector and ToolCallDeduplicator, then compare their behavior with the separate plan-mode-guard-deny.ts enforcement path. Reproduce the alternating Bash placeholder loop and inspect the existing focused regressions. Done means plan reminders no longer cadence-reinject during a continuous turn, inert placeholders cannot evade the stop, and the focused tests plus tsc -p tsconfig.json --noEmit pass.

Written by the indexing model from the issue text.

Assessment

Tech stack
typescript
Domain
cli, tooling
Issue type
Bug
Difficulty
5/5
Estimated time
Over a week
Activity status
Active
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.