Skip to content

Bug: agy transcript watcher pins stale conversation after brain rotation/compaction #245

Description

@GSL-R

Summary

With cli-jaw 2.1.5 using agy 1.0.10, the Antigravity transcript watcher can pin the previous conversation's existing transcript.jsonl even when the current turn is written to a newly created brain/conversation directory.

This hides all current-turn activity from cli-jaw. If agy then stalls after a compaction checkpoint, cli-jaw keeps watching the stale file until the absolute watchdog timeout and returns no response.

Reproduction observed

  1. A previous main-session turn completed in conversation A.
  2. cli-jaw retained A as its saved agy session.
  3. A new Telegram request started at 09:04:51 UTC.
  4. agy created conversation B and wrote:
    • USER_INPUT at 09:04:55
    • a PLANNER_RESPONSE with a read-only grep tool call
    • CHECKPOINT at 09:05:18
  5. No more rows were written after the checkpoint.
  6. cli-jaw logged that it was tailing conversation A, whose transcript mtime was 09:02:42 and which never contained the current turn.
  7. At 610 seconds, the watchdog killed the run with:
    [jaw:watchdog] killing main - absolute timeout 610s

Root cause in cli-jaw

In agy-transcript-watcher.js, the watcher prefers resolveAgyTranscriptPath(...currentSessionId) whenever that old file exists. The recent-transcript fallback is therefore never evaluated. The later session-change check cannot recover because getSessionId() continues returning saved conversation A while agy is running in B.

A second issue appears after switching: the current session mismatch block discards B again on every poll because the persisted ID still points to A.

Expected behavior

  • A transcript resolved from the saved session should only be accepted for the current turn if it is fresh enough and belongs to the current invocation.
  • The watcher should periodically detect a newer prompt-matching transcript created after startedAt and switch to it.
  • A fresh prompt-matching transcript must take precedence while the saved session ID catches up.
  • Switching should reset offset and final-planner state safely.
  • A CHECKPOINT followed by no transcript/stdout activity should produce a distinct compaction-stall reason rather than waiting for the generic absolute timeout.

Suggested fix

  1. Treat a saved-session transcript with mtime < startedAt - lookback as stale for initial attachment.
  2. While the child is running, periodically call resolveRecentAgyTranscriptPath(startedAt - lookback, prompt).
  3. If a different, newer matching path appears, atomically switch paths and reset the read offset.
  4. Namespace transcript tool dedupe keys by conversation ID.
  5. Optionally detect CHECKPOINT inactivity separately. Do not automatically retry mutating runs; a retry is only safe when no side-effecting tool has completed.

This is separate from agy's apparent failure to resume after its own checkpoint. cli-jaw cannot necessarily repair that provider-side stall, but it can follow the correct transcript and report the failure accurately.

Local verification

A local 2.1.5 mitigation was tested with two fixtures:

  1. stale conversation A exists, the current prompt is written to B, and B ends at CHECKPOINT: the watcher attaches B and reports B stalled
  2. the current prompt is written to C and CHECKPOINT is followed by planner activity: no false stall

Both fixtures pass, and the production server restarts cleanly with the patch.

Environment

  • cli-jaw: 2.1.5
  • agy: 1.0.10
  • backend: Antigravity CLI print mode
  • channel: Telegram main session

Related context: #244 covers watchdog activity/timeout behavior, but this report concerns stale transcript selection and brain rotation.

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions