Skip to content

fix(jcode): keep journal corrections turn-neutral so new turns still count#819

Merged
junhoyeo merged 3 commits into
junhoyeo:mainfrom
Nanako0129:fix-jcode-journal-pending-turn-start
Jul 5, 2026
Merged

fix(jcode): keep journal corrections turn-neutral so new turns still count#819
junhoyeo merged 3 commits into
junhoyeo:mainfrom
Nanako0129:fix-jcode-journal-pending-turn-start

Conversation

@Nanako0129

@Nanako0129 Nanako0129 commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

When a session snapshot ends on a user message, a turn-start is pending as the append-only journal is merged. parse_jcode_messages runs the journal through the same mutable turn-state context as the snapshot, so a journal entry that merely corrects an already-snapshotted assistant id (a replace, whose is_turn_start is overwritten by the snapshot's flag during the merge) consumes that pending turn-start. A subsequent brand-new journal assistant is then never marked is_turn_start, under-counting the session's turn_count by one.

This makes a journal message that only replaces an already-emitted dedup_key turn-neutral: it no longer advances the turn-state machine (its turn flag is discarded anyway), so the pending turn-start survives for the next new message. The snapshot pass passes None and is unchanged.

journal_correction_of_snapshot_message_keeps_pending_turn_start builds a snapshot ending on a user message, a journal that first corrects the snapshot assistant and then opens a new turn, and asserts both turns are counted; it fails before the change (the new turn's is_turn_start is false) and passes after.

Bumps CACHE_SCHEMA_VERSION 24 -> 25 so caches holding the under-counted turn flags reparse. (If a sibling schema-touching fix lands first, this needs a trivial rebase to the next number.)

Fixes #818


Summary by cubic

Fixes under-counted turn tracking in Jcode sessions by making journal corrections turn-neutral, so a new assistant message after a user still starts a turn. Also bumps cache schema and includes a minor rustfmt cleanup.

  • Bug Fixes

    • Use known snapshot dedup_keys to detect journal replacements and keep them turn-neutral.
    • Only non-replacement assistant messages consume a pending turn-start; snapshot parsing is unchanged.
    • Adds regression test journal_correction_of_snapshot_message_keeps_pending_turn_start.
  • Migration

    • Bump CACHE_SCHEMA_VERSION to 26 to invalidate caches carrying under-counted is_turn_start.

Written for commit b46b13b. Summary will update on new commits.

Review in cubic

…count

When a session snapshot ends on a user message, a turn-start is pending as the
append-only journal is merged. parse_jcode_messages runs the journal through
the same mutable turn-state context as the snapshot, so a journal entry that
merely corrects an already-snapshotted assistant id (a replace, whose
is_turn_start is overwritten by the snapshot's flag during the merge) consumes
that pending turn-start. A subsequent brand-new journal assistant is then never
marked is_turn_start, under-counting the session's turn_count by one.

Make a journal message that only replaces an already-emitted dedup_key
turn-neutral: it no longer advances the turn-state machine (its turn flag is
discarded anyway), so the pending turn-start survives for the next new message.
The snapshot pass passes `None` and is unchanged.

Bumps CACHE_SCHEMA_VERSION 24 -> 25 so caches holding the under-counted turn
flags reparse.
@vercel

vercel Bot commented Jul 4, 2026

Copy link
Copy Markdown
Contributor

The latest updates on your projects. Learn more about Vercel for GitHub.

1 Skipped Deployment
Project Deployment Actions Updated (UTC)
tokscale Ignored Ignored Preview Jul 5, 2026 6:50pm

Request Review

@cubic-dev-ai cubic-dev-ai Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

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

No issues found across 2 files

Re-trigger cubic

junhoyeo added 2 commits July 6, 2026 03:37
Review follow-up: CI's Lint job rejected the manual two-line wrap of
the is_replacement binding; the call fits under the 100-col limit, so
rustfmt collapses it onto one line.

Confidence: high
Scope-risk: narrow
# Conflicts:
#	crates/tokscale-core/src/message_cache.rs
@junhoyeo

junhoyeo commented Jul 5, 2026

Copy link
Copy Markdown
Owner

Thanks @Nanako0129 — this is a really well-built fix. The issue write-up in #818, the turn-neutral replacement approach, the regression test that genuinely fails pre-fix (I verified: without the fix it panics at assertion failed: messages[1].is_turn_start, exactly the under-count you described), and the correctly-annotated cache schema bump all made this easy to verify. The only thing standing between this and green CI was rustfmt wanting the is_replacement binding on one line, so I pushed that one-line formatting commit to your branch rather than bounce it back to you. Merging once CI confirms. Nice catch on a subtle interaction between the snapshot/journal merge and the turn-state machine!

@junhoyeo junhoyeo merged commit dcb053e into junhoyeo:main Jul 5, 2026
14 of 15 checks passed
@junhoyeo

junhoyeo commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Shipped in v4.0.11, included in the latest v4.1.0 🎉 @Nanako0129

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.

jcode: journal correction consumes a pending turn-start and under-counts turn_count

2 participants