-
Notifications
You must be signed in to change notification settings - Fork 33.6k
messages.timestamp is always DB write-time, lost during fork/compress/branch #28841
Copy link
Copy link
Open
Labels
P2Medium — degraded but workaround existsMedium — degraded but workaround existscomp/agentCore agent loop, run_agent.py, prompt builderCore agent loop, run_agent.py, prompt buildercomp/cliCLI entry point, hermes_cli/, setup wizardCLI entry point, hermes_cli/, setup wizardcomp/gatewayGateway runner, session dispatch, deliveryGateway runner, session dispatch, deliverycomp/tuiTerminal UI (ui-tui/ + tui_gateway/)Terminal UI (ui-tui/ + tui_gateway/)type/bugSomething isn't workingSomething isn't working
Metadata
Metadata
Assignees
Labels
P2Medium — degraded but workaround existsMedium — degraded but workaround existscomp/agentCore agent loop, run_agent.py, prompt builderCore agent loop, run_agent.py, prompt buildercomp/cliCLI entry point, hermes_cli/, setup wizardCLI entry point, hermes_cli/, setup wizardcomp/gatewayGateway runner, session dispatch, deliveryGateway runner, session dispatch, deliverycomp/tuiTerminal UI (ui-tui/ + tui_gateway/)Terminal UI (ui-tui/ + tui_gateway/)type/bugSomething isn't workingSomething isn't working
Type
Fields
Give feedbackNo fields configured for issues without a type.
messages.timestampin the SQLite database is always set totime.time()atINSERT time. There is no way for callers to supply an explicit timestamp, and
the message dict's existing
timestampfield is silently ignored during bulkrewrites.
As a result, when a session is forked (
/branch), compressed, or rewritten(
/retry//undo), every message gets a new DB write-time timestamp. Aconversation 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 exportscripts, session analytics,
/insights, and anything consuming the messagestable — gets misleading wall-clock times.
To reproduce
/compressor/branch.messages.timestampfrom SQLite for the child session.conversation time.
Root cause
append_message()always bindstime.time()to thetimestampcolumn.No caller can supply an explicit value.
replace_messages()assigns a singletime.time()base to every message.The
msg["timestamp"]field, which is already present in the dict whenloaded from
get_messages(), is never read._flush_messages_to_session_db()andappend_to_transcript()callappend_message()without forwarding the message's existingtimestampfield.
Fix (minimal)
hermes_state.py: Add optionaltimestamp: float = Noneparameter toappend_message(). Readmsg.get("timestamp")inreplace_messages()per-message.run_agent.py,cli.py,gateway/run.py,tui_gateway/server.py,gateway/session.py,gateway/mirror.py): Forwardmsg.get("timestamp")toappend_message(). Each change is +1 line.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?