fix(reply): suppress unscheduled-reminder note when session has active cron#32255
Conversation
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: f1aba7d838
ℹ️ About Codex in GitHub
Codex has been enabled to automatically review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
When you sign up for Codex through ChatGPT, Codex can also answer questions or update the PR, like "@codex address that feedback".
| // If we have a session key, only consider cron jobs from the same session. | ||
| // This avoids suppressing the note due to unrelated cron jobs. | ||
| if (params.sessionKey) { | ||
| return store.jobs.some((job) => job.enabled && job.sessionKey === params.sessionKey); |
There was a problem hiding this comment.
Keep reminder guard unless a matching cron is verified
This suppression check treats any enabled cron in the same session as proof that the new reminder commitment is covered. If a session already has an unrelated job (for example, a daily digest cron), a reply like “I’ll remind you tomorrow” with successfulCronAdds === 0 will no longer get the safety note, so users can be told a reminder will happen when no new reminder was actually scheduled.
Useful? React with 👍 / 👎.
Greptile SummaryThis PR adds a session-scoped cron store check before appending the "I did not schedule a reminder" guard note, suppressing it when an existing enabled cron job from the same session already covers the commitment. The approach is sound and the three new tests cover the key scenarios well. One logic issue exists: the fallback branch in
Confidence Score: 3/5
Last reviewed commit: f1aba7d |
src/auto-reply/reply/agent-runner.ts
Outdated
| if (params.sessionKey) { | ||
| return store.jobs.some((job) => job.enabled && job.sessionKey === params.sessionKey); | ||
| } | ||
| // Fallback: any enabled cron job counts. | ||
| return store.jobs.some((job) => job.enabled); |
There was a problem hiding this comment.
Fallback suppresses note across unrelated sessions
When params.sessionKey is undefined, the fallback at line 96 returns true for any enabled cron job in the store — including jobs belonging to completely different sessions. This directly contradicts the PR's stated goal of session-scoped suppression and could produce exactly the cross-session false positive the PR is trying to prevent.
Since sessionKey is declared as sessionKey?: string on the runReplyAgent params (line 134 in the function signature), it genuinely can be undefined at runtime. A caller that omits sessionKey while another session holds an active cron job would have its reminder guard note silently suppressed.
The safest fix is to return false (don't suppress) when no session key is available rather than broadening to all enabled jobs:
| if (params.sessionKey) { | |
| return store.jobs.some((job) => job.enabled && job.sessionKey === params.sessionKey); | |
| } | |
| // Fallback: any enabled cron job counts. | |
| return store.jobs.some((job) => job.enabled); | |
| if (params.sessionKey) { | |
| return store.jobs.some((job) => job.enabled && job.sessionKey === params.sessionKey); | |
| } | |
| // No session key available — cannot scope the check, so do not suppress the note. | |
| return false; |
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/auto-reply/reply/agent-runner.ts
Line: 92-96
Comment:
**Fallback suppresses note across unrelated sessions**
When `params.sessionKey` is `undefined`, the fallback at line 96 returns `true` for any enabled cron job in the store — including jobs belonging to completely different sessions. This directly contradicts the PR's stated goal of session-scoped suppression and could produce exactly the cross-session false positive the PR is trying to prevent.
Since `sessionKey` is declared as `sessionKey?: string` on the `runReplyAgent` params (line 134 in the function signature), it genuinely can be `undefined` at runtime. A caller that omits `sessionKey` while another session holds an active cron job would have its reminder guard note silently suppressed.
The safest fix is to return `false` (don't suppress) when no session key is available rather than broadening to all enabled jobs:
```suggestion
if (params.sessionKey) {
return store.jobs.some((job) => job.enabled && job.sessionKey === params.sessionKey);
}
// No session key available — cannot scope the check, so do not suppress the note.
return false;
```
How can I resolve this? If you propose a fix, please make it concise.…as active cron Before appending the "I did not schedule a reminder" guard note, check the cron store for enabled jobs matching the current session key. This prevents false positives when the agent references an existing cron created in a prior turn (e.g. "I'll ping you when it's done" while a monitoring cron is already running). The check only fires on the rare path where the text matches commitment patterns AND no cron was added in the current turn, so the added I/O is negligible. Closes openclaw#32228 Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Address Greptile review: when sessionKey is undefined the fallback matched any enabled cron job, which could silently suppress the guard note due to jobs from unrelated sessions. Return false instead so the note always appears when session scoping is not possible. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
9a7c813 to
ebb9fbf
Compare
|
Landed via temp rebase onto main.
Thanks @scoootscooob! |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: ebb9fbf019
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| hasReminderCommitment && successfulCronAdds === 0 | ||
| ? await hasSessionRelatedCronJobs({ | ||
| cronStorePath: cfg.cron?.store, | ||
| sessionKey, |
There was a problem hiding this comment.
Preserve reminder guard when cron is globally disabled
This suppression path only checks for an enabled job in the store, so it will hide the unscheduled-reminder warning even when cron.enabled is off. In that configuration, CronService.start() exits early (src/cron/service/ops.ts:90-93), so stored jobs will not execute, but coveredByExistingCron can still become true here if a same-session job remains marked enabled in jobs.json. The result is a user-facing promise like “I’ll remind you…” without either scheduling a new reminder or showing the safety note.
Useful? React with 👍 / 👎.
Summary
Test plan
agent-runner.misc.runreplyagent.test.ts)Closes #32228
🤖 Generated with Claude Code