mirror of
https://github.com/openclaw/openclaw.git
synced 2026-05-07 06:31:37 +00:00
test: expand reminder guard fail-closed coverage (#32255) (thanks @scoootscooob)
This commit is contained in:
@@ -58,6 +58,7 @@ Docs: https://docs.openclaw.ai
|
|||||||
- Gateway/Security canonicalization hardening: decode plugin route path variants to canonical fixpoint (with bounded depth), fail closed on canonicalization anomalies, and enforce gateway auth for deeply encoded `/api/channels/*` variants to prevent alternate-path auth bypass through plugin handlers. Thanks @tdjackey for reporting.
|
- Gateway/Security canonicalization hardening: decode plugin route path variants to canonical fixpoint (with bounded depth), fail closed on canonicalization anomalies, and enforce gateway auth for deeply encoded `/api/channels/*` variants to prevent alternate-path auth bypass through plugin handlers. Thanks @tdjackey for reporting.
|
||||||
- Security/Prompt spoofing hardening: stop injecting queued runtime events into user-role prompt text, route them through trusted system-prompt context, and neutralize inbound spoof markers like `[System Message]` and line-leading `System:` in untrusted message content. (#30448)
|
- Security/Prompt spoofing hardening: stop injecting queued runtime events into user-role prompt text, route them through trusted system-prompt context, and neutralize inbound spoof markers like `[System Message]` and line-leading `System:` in untrusted message content. (#30448)
|
||||||
- Auto-reply/followup queue: avoid stale callback reuse across idle-window restarts by caching the followup runner only when a drain actually starts, preserving enqueue ordering after empty-finalize paths. (#31902) Thanks @Lanfei.
|
- Auto-reply/followup queue: avoid stale callback reuse across idle-window restarts by caching the followup runner only when a drain actually starts, preserving enqueue ordering after empty-finalize paths. (#31902) Thanks @Lanfei.
|
||||||
|
- Auto-reply/reminder guard note suppression: when a turn makes reminder-like commitments but schedules no new cron jobs, suppress the unscheduled-reminder warning note only if an enabled cron already exists for the same session; keep warnings for unrelated sessions, disabled jobs, or unreadable cron store paths. (#32255) Thanks @scoootscooob.
|
||||||
- Cron/HEARTBEAT_OK summary leak: suppress fallback main-session enqueue for heartbeat/internal ack summaries in isolated announce mode so `HEARTBEAT_OK` noise never appears in user chat while real summaries still forward. (#32093) Thanks @scoootscooob.
|
- Cron/HEARTBEAT_OK summary leak: suppress fallback main-session enqueue for heartbeat/internal ack summaries in isolated announce mode so `HEARTBEAT_OK` noise never appears in user chat while real summaries still forward. (#32093) Thanks @scoootscooob.
|
||||||
- Cron/isolated announce heartbeat suppression: treat multi-payload runs as skippable when any payload is a heartbeat ack token and no payload has media, preventing internal narration + trailing `HEARTBEAT_OK` from being delivered to users. (#32131) Thanks @adhishthite.
|
- Cron/isolated announce heartbeat suppression: treat multi-payload runs as skippable when any payload is a heartbeat ack token and no payload has media, preventing internal narration + trailing `HEARTBEAT_OK` from being delivered to users. (#32131) Thanks @adhishthite.
|
||||||
- Sessions/lock recovery: reclaim orphan legacy same-PID lock files missing `starttime` when no in-process lock ownership exists, avoiding false lock timeouts after PID reuse while preserving active lock safety checks. (#32081) Thanks @bmendonca3.
|
- Sessions/lock recovery: reclaim orphan legacy same-PID lock files missing `starttime` when no in-process lock ownership exists, avoiding false lock timeouts after PID reuse while preserving active lock safety checks. (#32081) Thanks @bmendonca3.
|
||||||
|
|||||||
@@ -1108,7 +1108,7 @@ describe("runReplyAgent messaging tool suppression", () => {
|
|||||||
});
|
});
|
||||||
|
|
||||||
describe("runReplyAgent reminder commitment guard", () => {
|
describe("runReplyAgent reminder commitment guard", () => {
|
||||||
function createRun() {
|
function createRun(params?: { sessionKey?: string; omitSessionKey?: boolean }) {
|
||||||
const typing = createMockTypingController();
|
const typing = createMockTypingController();
|
||||||
const sessionCtx = {
|
const sessionCtx = {
|
||||||
Provider: "telegram",
|
Provider: "telegram",
|
||||||
@@ -1156,7 +1156,7 @@ describe("runReplyAgent reminder commitment guard", () => {
|
|||||||
isStreaming: false,
|
isStreaming: false,
|
||||||
typing,
|
typing,
|
||||||
sessionCtx,
|
sessionCtx,
|
||||||
sessionKey: "main",
|
...(params?.omitSessionKey ? {} : { sessionKey: params?.sessionKey ?? "main" }),
|
||||||
defaultModel: "anthropic/claude-opus-4-5",
|
defaultModel: "anthropic/claude-opus-4-5",
|
||||||
resolvedVerboseLevel: "off",
|
resolvedVerboseLevel: "off",
|
||||||
isNewSession: false,
|
isNewSession: false,
|
||||||
@@ -1273,6 +1273,48 @@ describe("runReplyAgent reminder commitment guard", () => {
|
|||||||
text: "I'll check back in an hour.\n\nNote: I did not schedule a reminder in this turn, so this will not trigger automatically.",
|
text: "I'll check back in an hour.\n\nNote: I did not schedule a reminder in this turn, so this will not trigger automatically.",
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it("still appends guard note when sessionKey is missing", async () => {
|
||||||
|
loadCronStoreMock.mockResolvedValueOnce({
|
||||||
|
version: 1,
|
||||||
|
jobs: [
|
||||||
|
{
|
||||||
|
id: "existing-job",
|
||||||
|
name: "monitor-task",
|
||||||
|
enabled: true,
|
||||||
|
sessionKey: "main",
|
||||||
|
createdAtMs: Date.now() - 60_000,
|
||||||
|
updatedAtMs: Date.now() - 60_000,
|
||||||
|
},
|
||||||
|
],
|
||||||
|
});
|
||||||
|
|
||||||
|
runEmbeddedPiAgentMock.mockResolvedValueOnce({
|
||||||
|
payloads: [{ text: "I'll ping you later." }],
|
||||||
|
meta: {},
|
||||||
|
successfulCronAdds: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await createRun({ omitSessionKey: true });
|
||||||
|
expect(result).toMatchObject({
|
||||||
|
text: "I'll ping you later.\n\nNote: I did not schedule a reminder in this turn, so this will not trigger automatically.",
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
|
it("still appends guard note when cron store read fails", async () => {
|
||||||
|
loadCronStoreMock.mockRejectedValueOnce(new Error("store read failed"));
|
||||||
|
|
||||||
|
runEmbeddedPiAgentMock.mockResolvedValueOnce({
|
||||||
|
payloads: [{ text: "I'll remind you after lunch." }],
|
||||||
|
meta: {},
|
||||||
|
successfulCronAdds: 0,
|
||||||
|
});
|
||||||
|
|
||||||
|
const result = await createRun({ sessionKey: "main" });
|
||||||
|
expect(result).toMatchObject({
|
||||||
|
text: "I'll remind you after lunch.\n\nNote: I did not schedule a reminder in this turn, so this will not trigger automatically.",
|
||||||
|
});
|
||||||
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
describe("runReplyAgent fallback reasoning tags", () => {
|
describe("runReplyAgent fallback reasoning tags", () => {
|
||||||
|
|||||||
Reference in New Issue
Block a user