Skip to content

fix(coding-agent): repair incomplete session JSONL tails - #959

Closed
fettpl wants to merge 3 commits into
PrimeIntellect-ai:mainfrom
fettpl:agent/928-jsonl-tail-repair
Closed

fix(coding-agent): repair incomplete session JSONL tails#959
fettpl wants to merge 3 commits into
PrimeIntellect-ai:mainfrom
fettpl:agent/928-jsonl-tail-repair

Conversation

@fettpl

@fettpl fettpl commented Aug 8, 2026

Copy link
Copy Markdown
Contributor

What changed

  • Detect unterminated JSONL tails when a persisted session is opened, without mutating read-only opens.
  • At the first persistence boundary, atomically append a missing newline to a complete record or truncate an incomplete terminal record before writing the next entry.
  • Preserve earlier raw bytes, including malformed middle rows, and retain per-open recovery metadata through getFileRecovery().
  • Add faux-provider regression coverage for mid-UTF-8 and mid-JSON tears, valid JSON without a newline, malformed middle rows, empty files, read-only opens, and restart safety after repair.

Why

The session loaders either accepted a complete final JSON record without a newline or skipped an incomplete final fragment. SessionManager then treated the file as flushed, so the next fast-path append started at the existing EOF and concatenated the new entry with those terminal bytes.

Impact

Resuming and writing to an interrupted session now preserves all earlier valid records and allows the next entry to round-trip. Catalog, export, and other read-only opens do not modify session files. Repair uses same-directory atomic replacement and preserves the existing file metadata and symlink target behavior.

Checks

  • npx tsx ../../node_modules/vitest/dist/cli.js --run test/suite/regressions/928-jsonl-tail-repair.test.ts
  • npm run check

Fixes #928

Note

Fix incomplete JSONL tail repair in SessionManager to prevent bad concatenation on resume

  • Detects unterminated JSONL tails when resuming a session file and marks them for repair before any subsequent writes.
  • Adds repairUnterminatedSessionTail which either appends a newline (if the final record is valid JSON) or truncates the file to discard an incomplete record.
  • File rewrites now use replaceFileAtomically, writing to a temp file in the same directory then renaming, preserving prior file ownership and mode.
  • Failed mid-write appends set a needsTailRepair flag so the next persist triggers a rewrite rather than concatenating onto a broken tail.
  • Adds a getFileRecovery() accessor on SessionManager exposing details of the last repair performed (action, original size, repaired size, discarded bytes).

Macroscope summarized a7d7490.

@fettpl
fettpl marked this pull request as ready for review August 8, 2026 17:54
@fettpl

fettpl commented Aug 8, 2026

Copy link
Copy Markdown
Contributor Author

@snimu This is ready for review. It repairs incomplete JSONL tails atomically before a resumed append while preserving valid unterminated records, read-only open behavior, retry safety, metadata, and branched sessions.

Independent review is clean. All required CI checks pass at a7d7490fcaf68d297a8ca85d696efa312989dfb0.

@sethkarten

Copy link
Copy Markdown
Contributor

Thank you for the report and proposed work. This root cause is now covered by maintainer-owned stacked PR #1160, authored independently from upstream/main.

We did not inspect or reuse this PR's diff, branch, commits, implementation code, or tests; its public description/comments were used only as a bug report. To keep one review surface, this PR is superseded by #1160 and is being closed.

The complete review stack is #1158#1165. It is being left unmerged for human review after CI and review-bot findings are cleared.

@sethkarten sethkarten closed this Aug 10, 2026
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.

Repair an incomplete JSONL tail before resuming session appends

2 participants