Skip to content

messages.timestamp is always DB write-time, lost during fork/compress/branch #28841

@yitang

Description

@yitang

messages.timestamp in the SQLite database is always set to time.time() at
INSERT time. There is no way for callers to supply an explicit timestamp, and
the message dict's existing timestamp field is silently ignored during bulk
rewrites.

As a result, when a session is forked (/branch), compressed, or rewritten
(/retry//undo), every message gets a new DB write-time timestamp. A
conversation that started at 05:00 can show every message timestamped at
08:00 — the time of the last compress or branch.

Downstream tooling that reads messages.timestamp — transcript export
scripts, session analytics, /insights, and anything consuming the messages
table — gets misleading wall-clock times.

To reproduce

  1. Start a conversation at time T0.
  2. Run /compress or /branch.
  3. Query messages.timestamp from SQLite for the child session.
  4. All timestamps now reflect the compress/branch time, not the original
    conversation time.

Root cause

  • append_message() always binds time.time() to the timestamp column.
    No caller can supply an explicit value.
  • replace_messages() assigns a single time.time() base to every message.
    The msg["timestamp"] field, which is already present in the dict when
    loaded from get_messages(), is never read.
  • _flush_messages_to_session_db() and append_to_transcript() call
    append_message() without forwarding the message's existing timestamp
    field.

Fix (minimal)

  1. hermes_state.py: Add optional timestamp: float = None parameter to
    append_message(). Read msg.get("timestamp") in replace_messages() per-message.
  2. 6 callers (run_agent.py, cli.py, gateway/run.py, tui_gateway/server.py,
    gateway/session.py, gateway/mirror.py): Forward msg.get("timestamp") to
    append_message(). Each change is +1 line.
  3. tests/test_hermes_state.py: 8 new tests verifying explicit timestamps,
    fallback behavior, mixed usage, and fork chain preservation.

Are you willing to submit a PR for this?

  • I'd like to fix this myself and submit a PR

Metadata

Metadata

Assignees

No one assigned

    Labels

    P2Medium — degraded but workaround existscomp/agentCore agent loop, run_agent.py, prompt buildercomp/cliCLI entry point, hermes_cli/, setup wizardcomp/gatewayGateway runner, session dispatch, deliverycomp/tuiTerminal UI (ui-tui/ + tui_gateway/)type/bugSomething isn't working

    Type

    No type
    No fields configured for issues without a type.

    Projects

    No projects

    Milestone

    No milestone

    Relationships

    None yet

    Development

    No branches or pull requests

    Issue actions