Skip to content

fix(transcript): project only a fork's own turns into its transcript - #3679

Open
liukx0205 wants to merge 3 commits into
mainfrom
fix/fork-transcript-inherited-turns
Open

fix(transcript): project only a fork's own turns into its transcript#3679
liukx0205 wants to merge 3 commits into
mainfrom
fix/fork-transcript-inherited-turns

Conversation

@liukx0205

@liukx0205 liukx0205 commented Sep 9, 2026

Copy link
Copy Markdown
Collaborator

Related Issue

Fixes #3672

Problem

Every /btw fork's transcript came out misaligned: the fork's own turn sat at ordinal 0, followed by the inherited main-conversation turns, followed by the fork's own turn again as a duplicate (empty frames). By agent-12 the turn's prompt was paired with the main conversation's answer, and the real answer was missing from the transcript. Any consumer that rebuilds from the transcript (e.g. the desktop side-chat panel resync) received the wrong content.

Root cause: AgentLifecycleService.fork seeds the child agent's context memory with the source agent's messages, and those inherited messages are persisted in the child's wire log as ordinary context.append_message records, indistinguishable from the child's own messages. The cold transcript projection (TranscriptService.readColdSnapshotreduceContextTranscriptgroupMessagesIntoSnapshot) rebuilt them as the fork's own turns: inherited turns took ordinals 0..N-1 and the fork's own turn ordinal N, while the live projection numbers the fork's own turns from 0 — so backfill merged by turnId paired the fork's prompt with the main conversation's answer and appended the fork's real turn as a duplicate.

What changed

  • agent-core-v2: ContextMessage gains an inherited flag; AgentLifecycleService.fork marks the messages it seeds into the child as inherited: true (LLM context is unchanged — the child still sees the inherited conversation). reduceContextTranscript preserves the flag.
  • kap-server: readColdSnapshot excludes inherited messages from the transcript snapshot projection, so a fork's transcript contains only its own turns, ordinals stay contiguous from 0 and match the live projection, and prompt/response pairing heals correctly on backfill.
  • Tests: fork seeding marks messages inherited (agent-core-v2); cold snapshot excludes inherited turns and keeps prompt/answer pairing (kap-server); live + backfill merge yields exactly one turn with the fork's own prompt and answer, no inherited turns, no duplicate empty frames (kap-server).

Note: wire logs written before this fix carry no inherited marker, so transcripts of forks created by older versions are not repaired retroactively.

Checklist

  • I have read the CONTRIBUTING document.
  • I have linked a related issue (external PRs: the issue must have a maintainer's /approve).
  • I have added tests that prove my feature works.
  • Ran gen-changesets skill, or this PR needs no changeset.
  • Ran gen-docs skill, or this PR needs no doc update.

Forked agents (e.g. /btw children) persist the inherited source context
in their wire log. The cold transcript projection rebuilt those inherited
messages as the fork's own turns, so fork transcripts contained the main
conversation, ordinals collided with the live projection, and prompts
paired with the wrong answers.

Mark fork-seeded context messages as inherited and exclude them from the
transcript snapshot projection.

Fixes #3672
@changeset-bot

changeset-bot Bot commented Sep 9, 2026

Copy link
Copy Markdown

🦋 Changeset detected

Latest commit: 0ff83d0

The changes in this PR will be included in the next version bump.

This PR includes changesets to release 1 package
Name Type
@moonshot-ai/kimi-code Patch

Not sure what this means? Click here to learn what changesets are.

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

@pkg-pr-new

pkg-pr-new Bot commented Sep 9, 2026

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

commit: 0ff83d0

@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: ceb122c21f

ℹ️ 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 thread packages/kap-server/src/services/transcript/transcriptService.ts Outdated
Comment thread packages/agent-core-v2/src/agent/contextMemory/contextTranscript.ts Outdated
Pass the optional inherited field directly instead of using a
conditional spread, per the repo's optional-property rule.

Side chats forked before the inherited marker existed keep their seeded
main-conversation messages unmarked, so the marker filter alone still
rebuilt them as the fork's own turns when reopening an old /btw chat.
Detect that legacy shape in the cold projection: when the agent meta
records a forkedFrom parent and the wire log carries no inherited
marker, drop context.append_message records preceding the fork's first
turn.prompt before reducing the transcript.

@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: e2f960ee3a

ℹ️ 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 thread packages/kap-server/src/services/transcript/transcriptService.ts
A fork that compacts summarizes its inherited parent history into the
compaction summary, but reduceContextTranscript synthesizes that summary
as an unmarked compaction_summary message, so the own-content projection
kept it and groupMessagesIntoSnapshot exposed its full text as a
compaction marker. When the agent meta records a forkedFrom parent,
drop compaction_summary messages from the cold projection alongside the
inherited ones; the main agent still projects its own summaries.
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.

btw fork transcript projection is misaligned (inherited parent turns + duplicated empty turn)

1 participant