Skip to content

Add UTC timestamp to background exec exit notifications#7164

Closed
markvandeven wants to merge 2 commits into
openclaw:mainfrom
markvandeven:octo/tool-failure-timestamp
Closed

Add UTC timestamp to background exec exit notifications#7164
markvandeven wants to merge 2 commits into
openclaw:mainfrom
markvandeven:octo/tool-failure-timestamp

Conversation

@markvandeven

@markvandeven markvandeven commented Feb 2, 2026

Copy link
Copy Markdown

Why

Tool exit system notifications can arrive out-of-order vs. chat messages due to async delivery. Including the occurred-at timestamp inside the payload makes delayed notifications self-explanatory and easy to correlate.

What

  • Add an explicit [...] UTC timestamp into the Exec completed/failed system event text emitted for backgrounded exec sessions (notifyOnExit).
  • Extend the notifyOnExit test to assert the timestamp format is present.

Notes

  • This is intentionally UTC to avoid ambiguity and to match other parts of the system that surface UTC (e.g. tool error occurredAtMs formatting).

Greptile Overview

Greptile Summary

This PR adds explicit UTC timestamps to user-visible error/exit text for background exec completions and for embedded-run tool failure fallbacks, with accompanying test updates.

Key changes:

  • src/agents/bash-tools.exec.ts now prepends Exec completed/failed system events with a [YYYY-MM-DD HH:MM:SS UTC] timestamp when notifyOnExit is enabled.
  • Embedded runner payload building (src/agents/pi-embedded-runner/run/payloads.ts and related types) now optionally includes [... UTC] based on lastToolError.occurredAtMs.
  • pi-embedded-subscribe now records occurredAtMs on lastToolError and tests assert the timestamp presence.

Main concern: the added tests appear to have an incorrect regex (escaping \d inside a regex literal), and both timestamp sources currently use Date.now() at emit/handler time rather than the actual process/tool completion time, which can undermine the intent to disambiguate delayed delivery.

Confidence Score: 3/5

  • This PR is likely safe to merge, but has a couple correctness issues in tests and timestamp semantics worth fixing first.
  • Core functionality is small and localized, but the notifyOnExit test regex likely never matches due to escaping, and the new timestamps are captured at enqueue/handler time rather than true occurrence time, which can mislead the user-facing correlation the PR aims to improve.
  • src/agents/bash-tools.test.ts, src/agents/bash-tools.exec.ts, src/agents/pi-embedded-subscribe.handlers.tools.ts

(2/5) Greptile learns from your feedback when you react with thumbs up/down!

Context used:

  • Context from dashboard - CLAUDE.md (source)
  • Context from dashboard - AGENTS.md (source)

@openclaw-barnacle openclaw-barnacle Bot added the agents Agent runtime and tooling label Feb 2, 2026

@greptile-apps greptile-apps Bot left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

3 files reviewed, 3 comments

Edit Code Review Agent Settings | Greptile

Comment on lines +302 to +305
// Includes an explicit UTC timestamp in the payload so delayed delivery is still understandable.
expect(
bySession.some((event) => /\[\d{4}-\d{2}-\d{2} \d{2}:\d{2}:\d{2} UTC\]/.test(event)),
).toBe(true);

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P1] The timestamp regex here is almost certainly wrong due to escaping \d inside a regex literal. In JS/TS regex literals, \d matches a literal d, so /\[\d{4}-.../ will never match the generated [ + digits output. This makes the test ineffective (it can only fail) and can mask regressions in the timestamp formatting.

To match digits, use \d without the extra escape in a regex literal (e.g. /\[\d{4}-...//\[\d{4}-.../ should become /\[\d{4}-.../? specifically \d\d is wrong; it should be \d? Actually in a regex literal it should be \[\d{4}-.../? Please verify with a quick sanity check: it should be /\[\d{4}-/? No, it should be /\[\d{4}-/? The key is: \d should be \d? Either way, remove the extra backslash before d so the engine sees \d.

Also appears in src/agents/bash-tools.test.ts:304 (same line).

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/bash-tools.test.ts
Line: 302:305

Comment:
[P1] The timestamp regex here is almost certainly wrong due to escaping `\d` inside a regex literal. In JS/TS regex literals, `\d` matches a literal `d`, so `/\[\d{4}-.../` will never match the generated `[` + digits output. This makes the test ineffective (it can only fail) and can mask regressions in the timestamp formatting.

To match digits, use `\d` *without* the extra escape in a regex literal (e.g. `/\[\d{4}-.../``/\[\d{4}-.../` should become `/\[\d{4}-.../`? specifically `\d``\d` is wrong; it should be `\d`? Actually in a regex literal it should be `\[\d{4}-.../`? Please verify with a quick sanity check: it should be `/\[\d{4}-/`? No, it should be `/\[\d{4}-/`? The key is: `\d` should be `\d`? Either way, remove the extra backslash before `d` so the engine sees `\d`.

Also appears in `src/agents/bash-tools.test.ts:304` (same line).

How can I resolve this? If you propose a fix, please make it concise.

Comment on lines +391 to 406
const formatUtc = (ms: number) => {
const iso = new Date(ms).toISOString();
const [date, timeWithMs] = iso.split("T");
const time = (timeWithMs ?? "").split(".")[0];
if (!date || !time) {
return iso;
}
return `${date} ${time} UTC`;
};
const occurredAtMs = Date.now();
const ts = `[${formatUtc(occurredAtMs)}]`;

const summary = output
? `Exec ${status} (${session.id.slice(0, 8)}, ${exitLabel}) :: ${output}`
: `Exec ${status} (${session.id.slice(0, 8)}, ${exitLabel})`;
? `Exec ${status} ${ts} (${session.id.slice(0, 8)}, ${exitLabel}) :: ${output}`
: `Exec ${status} ${ts} (${session.id.slice(0, 8)}, ${exitLabel})`;
enqueueSystemEvent(summary, { sessionKey });

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

[P2] maybeNotifyOnExit stamps the message with occurredAtMs = Date.now() at notification time, not when the process actually exited. Since the motivating problem is delayed/out-of-order delivery, this timestamp can be misleading (it reflects enqueue time, not completion time). If markExited already records an exit timestamp on the session, prefer using that; otherwise consider capturing Date.now() in the exit handler and storing it on the session before enqueue.

This impacts all background exec exit notifications emitted from maybeNotifyOnExit.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/bash-tools.exec.ts
Line: 391:406

Comment:
[P2] `maybeNotifyOnExit` stamps the message with `occurredAtMs = Date.now()` at notification time, not when the process actually exited. Since the motivating problem is delayed/out-of-order delivery, this timestamp can be misleading (it reflects enqueue time, not completion time). If `markExited` already records an exit timestamp on the session, prefer using that; otherwise consider capturing `Date.now()` in the exit handler and storing it on the session before enqueue.

This impacts all background exec exit notifications emitted from `maybeNotifyOnExit`.

How can I resolve this? If you propose a fix, please make it concise.

@greptile-apps

greptile-apps Bot commented Feb 2, 2026

Copy link
Copy Markdown
Contributor
Additional Comments (1)

src/agents/pi-embedded-subscribe.handlers.tools.ts
[P2] occurredAtMs is captured with Date.now() inside handleToolExecutionEnd, which is likely after the tool failure occurred (and after sanitization/processing). If the goal is an “occurred-at” timestamp to correlate with other events, this should be derived from the tool result payload if it contains a timestamp (or captured at the boundary where the tool result is received), otherwise it will reflect handler time and can be skewed by queueing/backpressure.

This affects timestamps shown via buildEmbeddedRunPayloads when a tool fails.

Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/pi-embedded-subscribe.handlers.tools.ts
Line: 167:175

Comment:
[P2] `occurredAtMs` is captured with `Date.now()` inside `handleToolExecutionEnd`, which is likely *after* the tool failure occurred (and after sanitization/processing). If the goal is an “occurred-at” timestamp to correlate with other events, this should be derived from the tool result payload if it contains a timestamp (or captured at the boundary where the tool result is received), otherwise it will reflect handler time and can be skewed by queueing/backpressure.

This affects timestamps shown via `buildEmbeddedRunPayloads` when a tool fails.

How can I resolve this? If you propose a fix, please make it concise.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

agents Agent runtime and tooling

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant