Skip to content

feat: fire session reset hooks for daily and idle resets#61675

Open
salvormallow wants to merge 2 commits into
openclaw:mainfrom
salvormallow:feat/session-reset-hooks-lazy
Open

feat: fire session reset hooks for daily and idle resets#61675
salvormallow wants to merge 2 commits into
openclaw:mainfrom
salvormallow:feat/session-reset-hooks-lazy

Conversation

@salvormallow

Copy link
Copy Markdown

Summary

Change Type (select all)

  • Bug fix
  • Feature

Scope (select all touched areas)

  • Memory / storage

Linked Issue/PR

Root Cause (if applicable)

  • Root cause: initSessionState() fires session_end/session_start plugin hooks for lazy resets but never fires triggerInternalHook or hookRunner.runBeforeReset. These only fire via emitResetCommandHooks() in commands-core.ts, which is only called for manual /new and /reset commands.
  • Missing detection / guardrail: No test asserted that internal hooks fire for lazy resets
  • Contributing context (if known): The lazy evaluation design means sessions aren't proactively killed — staleness is checked on next message arrival, a code path separate from manual commands

Regression Test Plan (if applicable)

  • Coverage level that should have caught this:
    • Unit test
  • Target test or file: src/auto-reply/reply/session.stale-hooks.test.ts (new), src/hooks/bundled/session-memory/handler.test.ts (extended)
  • Scenario the test should lock in: Internal hook fires with action: "daily" / "idle" when session is stale; before_reset plugin hook fires for lazy resets; no double-fire on manual reset
  • Why this is the smallest reliable guardrail: Mocks triggerInternalHook and hookRunner to assert dispatch without side-effects
  • Existing test that already covers this (if any): session-hooks-context.test.ts covers session_end/session_start but not internal hooks or before_reset

User-visible / Behavior Changes

session-memory now saves session summaries on daily (4AM) and idle-timeout resets, not just manual /new and /reset. Plugin before_reset hook now fires for lazy resets, giving plugins pre-archive transcript access.

Diagram (if applicable)

Before:
[lazy reset] -> session_end + session_start hooks only

After:
[lazy reset] -> internal hook (command:daily/idle) + before_reset + session_end + session_start

Security Impact (required)

  • New permissions/capabilities? No
  • Secrets/tokens handling changed? No
  • New/changed network calls? No
  • Command/tool execution surface changed? No
  • Data access scope changed? No

Repro + Verification

Environment

  • OS: Any
  • Runtime/container: Node.js 24
  • Integration/channel (if any): Any channel with daily or idle reset configured

Steps

  1. Configure a session with daily reset (default 4AM)
  2. Have an active session with messages before 4AM
  3. Send a message after 4AM (triggering lazy staleness detection)

Expected

  • session-memory saves a summary of the previous session
  • before_reset plugin hook fires with reason: "daily" and transcript messages

Actual (before this PR)

  • session-memory does not fire — no summary saved
  • before_reset plugin hook does not fire

Evidence

  • Failing test/log before + passing after

Human Verification (required)

  • Verified scenarios: Daily reset with stale session triggers session-memory save; idle reset triggers save; manual /new does not double-fire
  • Edge cases checked: First-ever session (no previous entry), system events (heartbeat), fresh session
  • What you did not verify: End-to-end with real LLM slug generation (mocked in tests)

Review Conversations

  • I replied to or resolved every bot review conversation I addressed in this PR.
  • I left unresolved only the conversations that still need reviewer or maintainer judgment.

Compatibility / Migration

  • Backward compatible? Yes
  • Config/env changes? No
  • Migration needed? No

Risks and Mitigations

  • Risk: before_reset receives the post-archive sessionFile path (after renameSync), not the original path. loadBeforeResetTranscript handles ENOENT by scanning for the latest .reset.* archived sibling.
    • Mitigation: This matches the manual reset path behavior. The stable post-archive path is intentional — it avoids racing transcript reads against the archive rename.

AI Disclosure

  • Mark as AI-assisted in the PR title or description
  • Note the degree of testing: fully tested — 10 unit tests (7 new + 3 extended) + manual daily/idle reset verification
  • Confirm: I understand what this code does and have verified the hook dispatch logic, guard conditions, and fire-and-forget patterns

🤖 AI-assisted with Claude Code

cc @vincentkoc (hooks/plugins CODEOWNER)

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: d004142bd1

ℹ️ 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".

Comment thread src/auto-reply/reply/session.ts
@greptile-apps

greptile-apps Bot commented Apr 6, 2026

Copy link
Copy Markdown
Contributor

Greptile Summary

Wires triggerInternalHook and hookRunner.runBeforeReset into the lazy staleness path in initSessionState() so daily (4AM) and idle-timeout resets fire the same hook sequence as manual /new and /reset. Both new blocks are correctly gated on previousSessionEndReason and !resetTriggered to prevent misfires and double-fires. The three helper functions in commands-core.ts are exported (no behavior change), session-memory's filter and HOOK.md events list are widened to command:daily and command:idle, and 7 new unit tests lock in the dispatch logic across all key scenarios.

Confidence Score: 5/5

Safe to merge — both new hook blocks are correctly guarded, fire-and-forget semantics match existing patterns, and tests cover all key scenarios including no-double-fire on manual resets.

All previously flagged issues are resolved. The missing previousSessionEndReason guard on before_reset (called out in prior review threads) is already present at line 788 in the current code, symmetric with the internal-hook block at line 762. No P0/P1 findings remain.

No files require special attention.

Greploops — Automatically fix all review issues by running /greploops in Claude Code. It iterates: fix, push, re-review, repeat until 5/5 confidence.
Use the Greptile plugin for Claude Code to query reviews, search comments, and manage custom context directly from your terminal.

Reviews (2): Last reviewed commit: "feat: fire session reset hooks for daily..." | Re-trigger Greptile

Comment thread src/auto-reply/reply/session.ts Outdated
Comment thread src/hooks/bundled/session-memory/handler.ts Outdated
@salvormallow
salvormallow force-pushed the feat/session-reset-hooks-lazy branch from d004142 to 86ec2f8 Compare April 6, 2026 09:50
@salvormallow

Copy link
Copy Markdown
Author

Addressed all three review comments in 86ec2f8:

@chatgpt-codex-connector P2 — Internal hooks gated behind hookRunner:
Moved the internal hook block above the if (hookRunner && isNewSession) guard so it fires independently of the plugin hook runner — matching how emitResetCommandHooks() fires triggerInternalHook without checking hookRunner.

@greptile-apps P1 — Missing previousSessionEndReason guard:
Added && previousSessionEndReason to the before_reset guard. Also removed the ?? "daily" fallback since with the guard, previousSessionEndReason is always defined inside the block. Both blocks are now symmetric.

@greptile-apps P2 — Long line:
Split isResetCommand predicate across multiple lines.

All 34 tests pass.

@salvormallow
salvormallow force-pushed the feat/session-reset-hooks-lazy branch from 86ec2f8 to 6682f77 Compare April 6, 2026 12:09
@salvormallow
salvormallow force-pushed the feat/session-reset-hooks-lazy branch from 6682f77 to 7e627e9 Compare April 6, 2026 12:15
@salvormallow

Copy link
Copy Markdown
Author

(Updated after rebase onto latest main — the review fixes from the previous comment are now in 7e627e9. Also resolved merge conflict in commands-core.ts where upstream extracted reset hooks into commands-reset-hooks.ts; our export additions now target that file instead.)

@chatgpt-codex-connector chatgpt-codex-connector 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.

💡 Codex Review

Here are some automated review suggestions for this pull request.

Reviewed commit: 7e627e9e55

ℹ️ 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".

Comment thread src/auto-reply/reply/session.ts Outdated
@salvormallow
salvormallow force-pushed the feat/session-reset-hooks-lazy branch from 7e627e9 to fbbf7bb Compare April 6, 2026 12:41
@salvormallow

Copy link
Copy Markdown
Author

@chatgpt-codex-connector Fixed in fbbf7bb — now uses the already-resolved agentId from resolveSessionAgentId() (config-aware) instead of re-parsing via resolveAgentIdFromSessionKey(). Note: the manual path in emitResetCommandHooks() has the same pattern — out of scope for this PR but worth a follow-up.

@chatgpt-codex-connector

Copy link
Copy Markdown
Contributor

To use Codex here, create a Codex account and connect to github.

@salvormallow

salvormallow commented Apr 8, 2026

Copy link
Copy Markdown
Author

CI note: All failures on this PR are pre-existing upstream breakage on main, not from this PR's changes:

  1. extensions/discord/src/proxy-request-client.ts(36,7)RequestClientOptions now requires scheduler and runtimeProfile, but the Discord extension wasn't updated. Breaks check, build-artifacts, build-smoke, checks-fast-contracts-protocol.
  2. src/plugins/provider-runtime.test.ts(611,51)"demo-cli" is no longer a valid ExternalOAuthManager value. Breaks check, check-additional.

These cascade into the extension shard cancellations. This PR only touches src/auto-reply/reply/, src/hooks/bundled/session-memory/, and src/commands/commands-reset-hooks.ts — none of the failing files.

Happy to rebase once main is green again. ready for review whenever you get a chance 🙏

@FeSens

FeSens commented Apr 8, 2026

Copy link
Copy Markdown

Amazing work! We need this fix!

Wire internal hooks and before_reset plugin hook into the lazy
staleness path so they fire on daily (4AM) and idle-timeout resets,
not just manual /new and /reset commands.

Both hooks fire as fire-and-forget to avoid blocking the user's
message response (session-memory's LLM slug generation can take
up to 15s). commands-core is dynamically imported inside the
fire-and-forget block to avoid pulling its heavy dependency tree
into session.ts's static imports.

Export loadBeforeResetTranscript from commands-core for use by
session.ts. Update bundled session-memory hook registration and
filter to accept "daily" and "idle" actions.

Fixes openclaw#10142, openclaw#31266, openclaw#50891, openclaw#43524

Co-Authored-By: Claude Opus 4.6 <[email protected]>
@openclaw-barnacle openclaw-barnacle Bot removed the stale Marked as stale due to inactivity label Jun 6, 2026
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. and removed rating: 🌊 off-meta tidepool PR readiness rating does not apply to this item. labels Jun 14, 2026
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. and removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. rating: 🦪 silver shellfish Thin PR readiness signal; proof, validation, or implementation needs work. labels Jun 16, 2026
@clawsweeper clawsweeper Bot removed rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 23, 2026
@openclaw-barnacle openclaw-barnacle Bot added the triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. label Jun 23, 2026
@clawsweeper clawsweeper Bot added rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. labels Jun 23, 2026
@clawsweeper

clawsweeper Bot commented Jul 18, 2026

Copy link
Copy Markdown
Contributor

@salvormallow thanks for the PR. ClawSweeper is still waiting on real behavior proof before this can move forward.

Useful proof can be a screenshot, short video, terminal output, copied live output, linked artifact, or redacted logs that show the changed behavior after the fix. Please redact private tokens, phone numbers, private endpoints, customer data, and anything else sensitive.

Once proof is added to the PR body or a comment, ClawSweeper or a maintainer can re-check it.

@clawsweeper

clawsweeper Bot commented Jul 19, 2026

Copy link
Copy Markdown
Contributor

ClawSweeper status: review started.

I am starting a fresh review of this pull request: feat: fire session reset hooks for daily and idle resets This is item 1/1 in the current shard. Shard 11/22.

This placeholder means the worker is alive and reading the current context. I will edit this same comment with the actual review when the claws are done clicking.

Crustacean status: shell secured, claws on keyboard, evidence pebbles being sorted.

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

Labels

clawsweeper Tracked by ClawSweeper automation docs Improvements or additions to documentation merge-risk: 🚨 compatibility 🚨 May break existing users, config, migrations, defaults, or upgrade paths. merge-risk: 🚨 session-state 🚨 May lose, corrupt, stale, or mis-associate session, agent, or context state. P2 Normal backlog priority with limited blast radius. rating: 🧂 unranked krab Not merge-ready due to missing proof or serious correctness/safety concerns. size: L status: 📣 needs proof The PR needs real behavior proof before ClawSweeper can clear the contributor ask. triage: needs-pr-context Candidate: external PR body lacks required problem context or evidence. triage: needs-real-behavior-proof Candidate: external PR needs after-fix proof from a real setup.

Projects

None yet

3 participants