Skip to content

fix(agent-core-v2): deliver cron-fired prompts as single opening turn message - #3723

Open
sailist wants to merge 2 commits into
MoonshotAI:devfrom
sailist:bug-198-09-11-cron-double-fire-empty
Open

fix(agent-core-v2): deliver cron-fired prompts as single opening turn message#3723
sailist wants to merge 2 commits into
MoonshotAI:devfrom
sailist:bug-198-09-11-cron-double-fire-empty

Conversation

@sailist

@sailist sailist commented Sep 11, 2026

Copy link
Copy Markdown
Collaborator

Related Issue

N/A — internal bug fix, no tracking issue.

Problem

When a cron job fires, the session transcript shows two user messages instead of one: first an empty user message carrying the cron origin, then a second one with the actual <cron-fire> envelope (observed as an empty t1.u0 immediately followed by t1.u1 with the envelope, same cron_id).

Root cause: the turn's opening message was expressed by two overlapping events. turn.started withheld its prompt for cron origins (the isDisplayablePromptOrigin gate, a leftover from the removed v1 transcript layer), so the v3 projector created the opening user entity with empty text. prompt.inject then dispatched a duplicate turn.steer for the same message, and the projector's opening-steer dedup — keyed on the withheld, empty prompt — could never match, so the same message materialized twice. cron_missed injections share the same path and defect.

What changed

  • isDisplayablePromptOrigin now admits cron_job / cron_missed, so turn.started carries the cron-fire prompt and the opening user message materializes once, whole, with its origin.
  • prompt.inject only dispatches turn.steer when the message actually steers into a running turn; a fresh-turn submission is fully expressed by turn.prompt / turn.started.
  • Removed the now-dead opening-steer dedup from the live projector and the cold-history fold (and the steerKeyOf helper), plus the two test scenarios that pinned it.
  • Also dropped a stale compaction-controller test that resurfaced in the dev branch rewrite: it imports requester modules that no longer exist and failed the suite at import time (base-branch breakage, removed here to unblock CI).

The cold-history fold already sourced opening messages solely from turn.prompt and never double-projected; this aligns the live path with that single-source model.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue — none; internal bug fix without a tracking issue.
  • I have added tests that prove my feature works — covered by the existing projection/history/loop/prompt suites (full suite green: 869 files / 15623 tests); the two removed scenarios pinned the deleted dedup behavior.
  • Ran gen-changesets skill, or this PR needs no changeset — evaluated; no changeset per review decision.
  • Ran gen-docs skill, or this PR needs no doc update — internal wire mechanics, no doc impact.

… message

isDisplayablePromptOrigin now admits cron_job/cron_missed, so the
observable turn.started carries the cron-fire prompt text instead of
leaving the opening wire user empty.

prompt.inject only dispatches turn.steer when the message actually
steers into a running turn; a fresh-turn submission is fully expressed
by turn.prompt/turn.started, so the duplicate materialization and both
opening-steer dedup hacks (live projector and coldFold) go away.
@pkg-pr-new

pkg-pr-new Bot commented Sep 11, 2026

Copy link
Copy Markdown
pnpm dlx https://pkg.pr.new/@moonshot-ai/kimi-code@4a56871
npx https://pkg.pr.new/@moonshot-ai/kimi-code@4a56871

commit: 4a56871

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 6ad9786705

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".

Comment on lines 533 to 536
if (rawId === undefined || hiddenTurnIds.has(rawId)) return;
const input = Array.isArray(record['input']) ? (record['input'] as ContentPart[]) : [];
const skipBlocks = kind === 'user' ? (origin?.skillActivations?.length ?? 0) : 0;
const entry = scratch(rawId);
if (
entry.currentStep === undefined &&
!entry.openingSteerDeduped &&
entry.openingInputKey !== undefined &&
entry.openingInputKey === JSON.stringify(input)
) {
entry.openingSteerDeduped = true;
return;
}
if (kind === 'user') {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P2 Badge Preserve opening-steer dedup for stored histories

When reading sessions written by the previous version, foldWireHistory still receives the turn.prompt followed by the identical opening turn.steer that the old prompt.inject emitted. Without this check, onTurnPrompt creates tN.u0 and this path unconditionally creates tN.u1, so reopening any pre-upgrade session containing an idle cron/user/skill injection reintroduces the duplicate message this change is intended to fix. Keep the cold-fold compatibility dedup even if new writes no longer need it.

Useful? React with 👍 / 👎.

…d modules

The file imports #/llm/requester/machine, #/llm/message and other
modules that no longer exist after the requester-pipeline refactor; it
resurfaced in the dev rewrite and fails the suite at import time.
@changeset-bot

changeset-bot Bot commented Sep 11, 2026

Copy link
Copy Markdown

⚠️ No Changeset found

Latest commit: 4a56871

Merging this PR will not cause a version bump for any packages. If these changes should not result in a new version, you're good to go. If these changes should result in a version bump, you need to add a changeset.

This PR includes no changesets

When changesets are added to this PR, you'll see the packages that this PR includes changesets for and the associated semver types

Click here to learn what changesets are, and how to add one.

Click here if you're a maintainer who wants to add a changeset to this PR

@chatgpt-codex-connector chatgpt-codex-connector Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 4a568713fd

ℹ️ About Codex in GitHub

Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you

  • Open a pull request for review
  • Mark a draft as ready
  • Comment "@codex review".

If Codex has suggestions, it will comment; otherwise it will react with 👍.

When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".


export function isDisplayablePromptOrigin(origin: PromptOrigin): boolean {
if (origin.kind === 'user') return true;
if (origin.kind === 'cron_job' || origin.kind === 'cron_missed') return true;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

P1 Badge Add a CLI changeset for the transcript fix

This change fixes a user-visible duplicate message in the CLI session transcript, but the commit adds no changeset. Without an @moonshot-ai/kimi-code patch changeset, the fix will ship without the required user-facing changelog entry; add the short changeset mandated for perceptible behavior changes.

AGENTS.md reference: AGENTS.md:L85-L86

Useful? React with 👍 / 👎.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant