Files
claude-mem/URGENT-FIX-TIMESTAMPS.md
T
Alex Newman 266c746d50 feat: Fix observation timestamps, refactor session management, and enhance worker reliability (#437)
* Refactor worker version checks and increase timeout settings

- Updated the default hook timeout from 5000ms to 120000ms for improved stability.
- Modified the worker version check to log a warning instead of restarting the worker on version mismatch.
- Removed legacy PM2 cleanup and worker start logic, simplifying the ensureWorkerRunning function.
- Enhanced polling mechanism for worker readiness with increased retries and reduced interval.

* feat: implement worker queue polling to ensure processing completion before proceeding

* refactor: change worker command from start to restart in hooks configuration

* refactor: remove session management complexity

- Simplify createSDKSession to pure INSERT OR IGNORE
- Remove auto-create logic from storeObservation/storeSummary
- Delete 11 unused session management methods
- Derive prompt_number from user_prompts count
- Keep sdk_sessions table schema unchanged for compatibility

* refactor: simplify session management by removing unused methods and auto-creation logic

* Refactor session prompt number retrieval in SessionRoutes

- Updated the method of obtaining the prompt number from the session.
- Replaced `store.getPromptCounter(sessionDbId)` with `store.getPromptNumberFromUserPrompts(claudeSessionId)` for better clarity and accuracy.
- Adjusted the logic for incrementing the prompt number to derive it from the user prompts count instead of directly incrementing a counter.

* refactor: replace getPromptCounter with getPromptNumberFromUserPrompts in SessionManager

Phase 7 of session management simplification. Updates SessionManager to derive
prompt numbers from user_prompts table count instead of using the deprecated
prompt_counter column.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* refactor: simplify SessionCompletionHandler to use direct SQL query

Phase 8: Remove call to findActiveSDKSession() and replace with direct
database query in SessionCompletionHandler.completeByClaudeId().

This removes dependency on the deleted findActiveSDKSession() method
and simplifies the code by using a straightforward SELECT query.

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* refactor: remove markSessionCompleted call from SDKAgent

- Delete call to markSessionCompleted() in SDKAgent.ts
- Session status is no longer tracked or updated
- Part of phase 9: simplifying session management

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* refactor: remove markSessionComplete method (Phase 10)

- Deleted markSessionComplete() method from DatabaseManager
- Removed markSessionComplete call from SessionCompletionHandler
- Session completion status no longer tracked in database
- Part of session management simplification effort

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* refactor: replace deleted updateSDKSessionId calls in import script (Phase 11)

- Replace updateSDKSessionId() calls with direct SQL UPDATE statements
- Method was deleted in Phase 3 as part of session management simplification
- Import script now uses direct database access consistently

🤖 Generated with [Claude Code](https://claude.com/claude-code)

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* test: add validation for SQL updates in sdk_sessions table

* refactor: enhance worker-cli to support manual and automated runs

* Remove cleanup hook and associated session completion logic

- Deleted the cleanup-hook implementation from the hooks directory.
- Removed the session completion endpoint that was used by the cleanup hook.
- Updated the SessionCompletionHandler to eliminate the completeByClaudeId method and its dependencies.
- Adjusted the SessionRoutes to reflect the removal of the session completion route.

* fix: update worker-cli command to use bun for consistency

* feat: Implement timestamp fix for observations and enhance processing logic

- Added `earliestPendingTimestamp` to `ActiveSession` to track the original timestamp of the earliest pending message.
- Updated `SDKAgent` to capture and utilize the earliest pending timestamp during response processing.
- Modified `SessionManager` to track the earliest timestamp when yielding messages.
- Created scripts for fixing corrupted timestamps, validating fixes, and investigating timestamp issues.
- Verified that all corrupted observations have been repaired and logic for future processing is sound.
- Ensured orphan processing can be safely re-enabled after validation.

* feat: Enhance SessionStore to support custom database paths and add timestamp fields for observations and summaries

* Refactor pending queue processing and add management endpoints

- Disabled automatic recovery of orphaned queues on startup; users must now use the new /api/pending-queue/process endpoint.
- Updated processOrphanedQueues method to processPendingQueues with improved session handling and return detailed results.
- Added new API endpoints for managing pending queues: GET /api/pending-queue and POST /api/pending-queue/process.
- Introduced a new script (check-pending-queue.ts) for checking and processing pending observation queues interactively or automatically.
- Enhanced logging and error handling for better monitoring of session processing.

* updated agent sdk

* feat: Add manual recovery guide and queue management endpoints to documentation

---------

Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
2025-12-25 15:36:46 -05:00

4.4 KiB

FIXED: Corrupted Observation Timestamps

What Happened

On Dec 24, 2025, orphan queue processing was enabled without a working timestamp fix. This caused 25 observations from old sessions (Dec 16-22) to be saved with Dec 24 timestamps instead of their original timestamps.

The Fix - COMPLETED

Status: All corrupted timestamps have been repaired

Date Fixed: Dec 24, 2025 at 20:55 PM PST

Results:

  • Fixed 25 observations with corrupted timestamps
  • Observations restored to correct dates (Dec 16-22)
  • Remaining 31 observations in the window are legitimate (from Dec 24 sessions)

The Original Damage

Observations created between approximately 19:45-20:31 on Dec 24 had wrong timestamps. These observations came from processing old pending_messages that were stuck in "processing" status.

How to Identify Affected Observations

The affected observations were created from pending_messages that had created_at_epoch from Dec 17-20, but the observations got Dec 24 timestamps.

-- Find observations created during the bad window (Dec 24 ~19:45-20:31)
SELECT id, sdk_session_id,
       datetime(created_at_epoch/1000, 'unixepoch', 'localtime') as obs_time,
       title
FROM observations
WHERE created_at_epoch >= 1735098300000  -- Dec 24 19:45
  AND created_at_epoch <= 1735101060000  -- Dec 24 20:31
ORDER BY id;

How to Fix

Option 1: Match via processed pending_messages

The pending_messages table has completed_at_epoch which shows when they were processed, and created_at_epoch which has the CORRECT original timestamp.

-- Find pending_messages processed during the bad window
SELECT id, session_db_id, tool_name,
       datetime(created_at_epoch/1000, 'unixepoch', 'localtime') as original_time,
       datetime(completed_at_epoch/1000, 'unixepoch', 'localtime') as processed_time
FROM pending_messages
WHERE status = 'processed'
  AND completed_at_epoch >= 1735098300000
  AND completed_at_epoch <= 1735101060000
ORDER BY completed_at_epoch;

Option 2: Match by session and sequence

For each affected session, observations should be ordered by their original pending_message timestamps:

-- Get the correct timestamp for each observation by matching session
-- This requires correlating sdk_session_id with session_db_id

Fix Script Approach

  1. Get all pending_messages processed during the bad window
  2. For each, get its session_db_id and created_at_epoch (original timestamp)
  3. Find observations for that session created during the bad window
  4. Update observations with the correct created_at_epoch from their source pending_message
-- Example fix for a single observation (after identifying the correct timestamp):
UPDATE observations
SET created_at_epoch = [correct_epoch],
    created_at = datetime([correct_epoch]/1000, 'unixepoch')
WHERE id = [observation_id];

The Timestamp Fix (Already Deployed)

The code now correctly passes overrideTimestampEpoch through:

  • SessionStore.storeObservation() - accepts optional timestamp override
  • SessionStore.storeSummary() - accepts optional timestamp override
  • ActiveSession.earliestPendingTimestamp - tracks original message timestamp
  • SDKAgent.processSDKResponse() - passes timestamp to storage

Scripts Created

Three scripts were created to handle this issue:

  1. scripts/fix-corrupted-timestamps.ts - Identifies and repairs corrupted timestamps

    bun scripts/fix-corrupted-timestamps.ts --dry-run  # Preview fixes
    bun scripts/fix-corrupted-timestamps.ts --yes      # Apply fixes
    
  2. scripts/verify-timestamp-fix.ts - Verifies the fix was successful

    bun scripts/verify-timestamp-fix.ts
    
  3. scripts/investigate-timestamps.ts - Investigates timestamp data

    bun scripts/investigate-timestamps.ts
    

Orphan Processing Status

The timestamp fix has been verified and is working correctly. Orphan processing can now be safely re-enabled in src/services/worker-service.ts if needed.

Files Changed

  • src/services/sqlite/SessionStore.ts - added overrideTimestampEpoch param
  • src/services/worker-types.ts - added earliestPendingTimestamp to ActiveSession
  • src/services/worker/SessionManager.ts - tracks earliest timestamp when yielding
  • src/services/worker/SDKAgent.ts - passes timestamp through processSDKResponse
  • src/services/worker-service.ts - orphan processing disabled