Skip to content

fix(agents): preserve cron heartbeat suppression during compaction#53468

Open
Protocol-zero-0 wants to merge 2 commits intoopenclaw:mainfrom
Protocol-zero-0:fix/heartbeat-compaction-trigger-followup
Open

fix(agents): preserve cron heartbeat suppression during compaction#53468
Protocol-zero-0 wants to merge 2 commits intoopenclaw:mainfrom
Protocol-zero-0:fix/heartbeat-compaction-trigger-followup

Conversation

@Protocol-zero-0
Copy link
Copy Markdown
Contributor

Summary

  • carry the original embedded-run trigger into overflow compaction rebuilds
  • suppress heartbeat prompt reinjection when a cron-origin session compacts
  • add regression coverage for the compaction heartbeat policy

Test plan

  • pnpm exec vitest run src/agents/pi-embedded-runner/compact.hooks.test.ts src/agents/pi-embedded-runner/run/attempt.test.ts
  • pnpm check

Made with Cursor

Carry the original embedded-run trigger into overflow compaction so cron-origin sessions do not regain the heartbeat prompt when the system prompt is rebuilt.

Made-with: Cursor
@greptile-apps
Copy link
Copy Markdown
Contributor

greptile-apps bot commented Mar 24, 2026

Greptile Summary

This PR correctly propagates the original run trigger (sourceTrigger) into overflow-compaction rebuilds so that cron-originated sessions properly suppress heartbeat prompt reinjection during compaction. The implementation is clean and well-scoped across three files.

Changes:

  • compact.ts: adds sourceTrigger?: EmbeddedRunTrigger to CompactEmbeddedPiSessionParams and introduces shouldInjectHeartbeatPromptDuringCompaction, which gates heartbeat prompt injection on both isDefaultAgent and the existing shouldInjectHeartbeatPromptForTrigger policy lookup
  • run.ts: threads params.trigger as sourceTrigger into the overflow compaction call — a single-line, targeted fix
  • compact.hooks.test.ts: adds regression coverage for the new policy function; one test description is slightly misleading (see inline comment)

Issues found:

  • P2 style: the second assertion in "preserves heartbeat prompt rebuilds for non-cron compaction" actually tests the isDefaultAgent: false guard path, not the non-cron scenario, and the false result contradicts the "preserves" framing in the test name

Confidence Score: 5/5

  • Safe to merge — the logic change is minimal and correct, and is covered by regression tests.
  • The production-code changes are small and precisely targeted: one new optional field on a params type, one small guard function, and one line in the overflow-compaction call site. The new function delegates to the already-tested shouldInjectHeartbeatPromptForTrigger policy and adds no branching risk. The only open item is a P2 test-description quality issue that does not affect runtime correctness.
  • No files require special attention.
Prompt To Fix All With AI
This is a comment left during a code review.
Path: src/agents/pi-embedded-runner/compact.hooks.test.ts
Line: 120-133

Comment:
**Misleading test description and assertion**

The second assertion in this test — `{ isDefaultAgent: false, sourceTrigger: "cron" }``false` — returns `false` because `isDefaultAgent` is `false`, not because the trigger is non-cron. It doesn't validate the "preserves heartbeat prompt rebuilds for non-cron compaction" claim stated in the test title, and actually contradicts the "preserves" framing (the heartbeat prompt is not injected here). Consider splitting this into its own test that describes what it actually covers:

```suggestion
  it("preserves heartbeat prompt rebuilds for non-cron compaction", () => {
    expect(
      compactTesting.shouldInjectHeartbeatPromptDuringCompaction({
        isDefaultAgent: true,
        sourceTrigger: "memory",
      }),
    ).toBe(true);
  });

  it("does not inject heartbeat prompt for non-default agents", () => {
    expect(
      compactTesting.shouldInjectHeartbeatPromptDuringCompaction({
        isDefaultAgent: false,
        sourceTrigger: "cron",
      }),
    ).toBe(false);
  });
```

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

Reviews (1): Last reviewed commit: "fix(agents): preserve cron heartbeat sup..." | Re-trigger Greptile

Comment on lines +120 to +133
it("preserves heartbeat prompt rebuilds for non-cron compaction", () => {
expect(
compactTesting.shouldInjectHeartbeatPromptDuringCompaction({
isDefaultAgent: true,
sourceTrigger: "memory",
}),
).toBe(true);
expect(
compactTesting.shouldInjectHeartbeatPromptDuringCompaction({
isDefaultAgent: false,
sourceTrigger: "cron",
}),
).toBe(false);
});
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 Misleading test description and assertion

The second assertion in this test — { isDefaultAgent: false, sourceTrigger: "cron" }false — returns false because isDefaultAgent is false, not because the trigger is non-cron. It doesn't validate the "preserves heartbeat prompt rebuilds for non-cron compaction" claim stated in the test title, and actually contradicts the "preserves" framing (the heartbeat prompt is not injected here). Consider splitting this into its own test that describes what it actually covers:

Suggested change
it("preserves heartbeat prompt rebuilds for non-cron compaction", () => {
expect(
compactTesting.shouldInjectHeartbeatPromptDuringCompaction({
isDefaultAgent: true,
sourceTrigger: "memory",
}),
).toBe(true);
expect(
compactTesting.shouldInjectHeartbeatPromptDuringCompaction({
isDefaultAgent: false,
sourceTrigger: "cron",
}),
).toBe(false);
});
it("preserves heartbeat prompt rebuilds for non-cron compaction", () => {
expect(
compactTesting.shouldInjectHeartbeatPromptDuringCompaction({
isDefaultAgent: true,
sourceTrigger: "memory",
}),
).toBe(true);
});
it("does not inject heartbeat prompt for non-default agents", () => {
expect(
compactTesting.shouldInjectHeartbeatPromptDuringCompaction({
isDefaultAgent: false,
sourceTrigger: "cron",
}),
).toBe(false);
});
Prompt To Fix With AI
This is a comment left during a code review.
Path: src/agents/pi-embedded-runner/compact.hooks.test.ts
Line: 120-133

Comment:
**Misleading test description and assertion**

The second assertion in this test — `{ isDefaultAgent: false, sourceTrigger: "cron" }``false` — returns `false` because `isDefaultAgent` is `false`, not because the trigger is non-cron. It doesn't validate the "preserves heartbeat prompt rebuilds for non-cron compaction" claim stated in the test title, and actually contradicts the "preserves" framing (the heartbeat prompt is not injected here). Consider splitting this into its own test that describes what it actually covers:

```suggestion
  it("preserves heartbeat prompt rebuilds for non-cron compaction", () => {
    expect(
      compactTesting.shouldInjectHeartbeatPromptDuringCompaction({
        isDefaultAgent: true,
        sourceTrigger: "memory",
      }),
    ).toBe(true);
  });

  it("does not inject heartbeat prompt for non-default agents", () => {
    expect(
      compactTesting.shouldInjectHeartbeatPromptDuringCompaction({
        isDefaultAgent: false,
        sourceTrigger: "cron",
      }),
    ).toBe(false);
  });
```

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

Copy link
Copy Markdown
Contributor

Copilot AI left a comment

Choose a reason for hiding this comment

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

Pull request overview

This PR fixes embedded agent compaction behavior so that cron-triggered runs keep cron-specific prompt policies even when an overflow compaction rebuild occurs (i.e., compaction no longer “forgets” the original run trigger).

Changes:

  • Propagate the original embedded-run trigger into overflow-compaction runtimeContext (sourceTrigger).
  • Update compaction prompt construction to suppress heartbeat prompt reinjection based on the original trigger (not just the compaction trigger).
  • Add regression tests for the compaction heartbeat prompt policy.

Reviewed changes

Copilot reviewed 3 out of 3 changed files in this pull request and generated 1 comment.

File Description
src/agents/pi-embedded-runner/run.ts Adds sourceTrigger to overflow compaction runtime context so downstream compaction logic can apply original-trigger policies.
src/agents/pi-embedded-runner/compact.ts Uses sourceTrigger + trigger policy to decide whether to inject the heartbeat prompt during compaction rebuilds.
src/agents/pi-embedded-runner/compact.hooks.test.ts Adds unit coverage for the new compaction heartbeat injection policy behavior.

Comment on lines 1157 to 1160
runId: params.runId,
trigger: "overflow",
sourceTrigger: params.trigger,
...(observedOverflowTokens !== undefined
Copy link

Copilot AI Mar 24, 2026

Choose a reason for hiding this comment

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

The new sourceTrigger propagation in the overflow-compaction runtimeContext isn’t covered by existing overflow-compaction regression tests. Please add/extend a test (e.g., in run.overflow-compaction.test.ts) to assert that when a run is triggered by cron and overflow recovery compaction happens, the compaction runtimeContext includes sourceTrigger: "cron" (so downstream prompt rebuild policy is actually exercised end-to-end).

Copilot uses AI. Check for mistakes.
@fabianwilliams fabianwilliams self-assigned this Mar 24, 2026
Copy link
Copy Markdown
Contributor

@fabianwilliams fabianwilliams left a comment

Choose a reason for hiding this comment

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

Clean fix, directly relevant to real-world cron workloads.

What I like:

  • Threading sourceTrigger through overflow compaction is the right approach — the trigger context should survive the full session lifecycle, not just the initial run.
  • The shouldInjectHeartbeatPromptDuringCompaction wrapper keeps the decision logic in one place instead of scattering conditionals.
  • Test coverage is solid — both the suppression case (cron trigger) and the preservation case (non-cron trigger) are covered, and the isDefaultAgent: false + sourceTrigger: "cron" combo correctly returns false.

One question:
The sourceTrigger param in CompactEmbeddedPiSessionParams is optional (sourceTrigger?: EmbeddedRunTrigger). If sourceTrigger is undefined (e.g., compaction triggered from a code path that doesn't set it), shouldInjectHeartbeatPromptForTrigger(undefined) falls through to the default policy (inject = true). That's safe, but worth a comment in the code noting that the undefined case intentionally falls through to "inject heartbeat" as the conservative default.

Otherwise LGTM — this fixes a real pain point for anyone running cron-heavy OpenClaw setups.

Document the conservative sourceTrigger fallback and tighten the regression coverage around overflow compaction so the cron trigger propagation remains obvious to reviewers and future maintainers.

Made-with: Cursor
@Protocol-zero-0
Copy link
Copy Markdown
Contributor Author

Follow-up pushed in f03453e368 to tighten the review nits:

  • split the non-default-agent assertion into its own test so the description matches the behavior
  • added an overflow-compaction regression that asserts sourceTrigger: "cron" is preserved end-to-end
  • documented the conservative fallback when sourceTrigger is absent

That should cover both the wording nit and the missing regression-path coverage.

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

Labels

agents Agent runtime and tooling size: S

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants