Skip to content

Cherry-pick issue #823: compaction-safeguards-prompt-hooks-config#1697

Merged
alexey-pelykh merged 187 commits intofork-sync-basefrom
cherry-pick/staging-823
Mar 20, 2026
Merged

Cherry-pick issue #823: compaction-safeguards-prompt-hooks-config#1697
alexey-pelykh merged 187 commits intofork-sync-basefrom
cherry-pick/staging-823

Conversation

@alexey-pelykh
Copy link
Copy Markdown

Cherry-picks from upstream (issue #823)

Commits picked (4 of 9)

Commit Subject Result
df0f2e349 Compaction/Safeguard: require structured summary headings (openclaw#25555) SKIPPED — all files in gutted pi-extensions
96021a2b1 fix: align AGENTS.md template section names with post-compaction extraction SKIPPED — all files gutted (pi-extensions, post-compaction-context, zh-CN)
60a6d1111 fix(embedded): classify model_context_window_exceeded as context overflow RESOLVED — partial pick: context_window_exceeded detection in errors.ts (rename-tracked)
6c0376145 fix(agents): skip compaction API call when session has no real messages SKIPPED — pi-embedded-runner/compact.ts gutted
036c32971 Compaction/Safeguard: add summary quality audit retries (openclaw#25556) RESOLVED — partial pick: wrapUntrustedPromptDataBlock in sanitize-for-prompt
7a22b3fa0 feat(agents): flush reply pipeline before compaction wait (openclaw#35489) SKIPPED — all files gutted (llm-task ext, pi-embedded)
09c68f8f0 add prependSystemContext/appendSystemContext to before_prompt_build SKIPPED — before_prompt_build hook gutted from fork
a0b731e2c fix(config): prevent RangeError in merged schema cache key generation PICKED
688b72e15 plugins: enforce prompt hook policy with runtime validation (openclaw#36567) RESOLVED — partial pick with conflict resolution across 8 files

Conflict resolutions

  • pi-extensions, pi-embedded-runner, memory: All gutted from fork — discarded
  • post-compaction-context: Removed in fork (Remove post-compaction AGENTS.md injection pipeline (#258) #272) — discarded
  • before_prompt_build hook: Gutted from fork hooks.ts — skipped commit 7 entirely
  • Compaction config (schema.help.ts, schema.labels.ts, types.agent-defaults.ts, zod-schema.agent-defaults.ts): Fork removed compaction config — kept fork version
  • Plugin types (types.ts): Restored upstream hook types needed by commit 9's policy enforcement; added fork-specific hook names to PLUGIN_HOOK_NAMES array; removed duplicate PluginHookAgentEndEvent
  • Registry (registry.ts): Merged fork's DEAD_HOOKS warning with upstream's hookPolicy parameter
  • Loader tests (loader.test.ts): Added new hook policy tests; skipped memory slot tests (gutted)
  • Config tests (config-misc.test.ts): Added allowPromptInjection schema test; fixed OpenClawSchema→RemoteClawSchema
  • Docs (plugin.md, configuration-reference.md): Rebranded openclaw→remoteclaw; included hook policy docs

mbelinky and others added 30 commits March 19, 2026 16:55
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: b99ad80
Co-authored-by: mbelinky <[email protected]>
Co-authored-by: mbelinky <[email protected]>
Reviewed-by: @mbelinky

(cherry picked from commit 6df57d9)
Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: 9917165
Co-authored-by: mbelinky <[email protected]>
Co-authored-by: mbelinky <[email protected]>
Reviewed-by: @mbelinky

(cherry picked from commit a3112d6)
…law#33032)

Merged via /review-pr -> /prepare-pr -> /merge-pr.

Prepared head SHA: f77e3d7
Co-authored-by: mbelinky <[email protected]>
Co-authored-by: mbelinky <[email protected]>
Reviewed-by: @mbelinky

(cherry picked from commit bf70610)
…aw#27613)

Merged via squash.

Prepared head SHA: 31ddd43
Co-authored-by: dorukardahan <[email protected]>
Co-authored-by: grp06 <[email protected]>
Reviewed-by: @grp06

(cherry picked from commit 2cd3be8)
…penclaw#30356)

Merged via squash.

Prepared head SHA: b14f9ad
Co-authored-by: 13otKmdr <[email protected]>
Co-authored-by: grp06 <[email protected]>
Reviewed-by: @grp06

(cherry picked from commit a8dd9ff)
Merged via squash.

Prepared head SHA: 6078cd9
Co-authored-by: clawdoo <[email protected]>
Co-authored-by: grp06 <[email protected]>
Reviewed-by: @grp06

(cherry picked from commit b1a7358)
…3262)

Merged via squash.

Prepared head SHA: 5fe8170
Co-authored-by: cu1ch3n <[email protected]>
Co-authored-by: grp06 <[email protected]>
Reviewed-by: @grp06

(cherry picked from commit e8cb048)
…ers (openclaw#30186)

Merged via squash.

Prepared head SHA: 0dac892
Co-authored-by: habakan <[email protected]>
Co-authored-by: grp06 <[email protected]>
Reviewed-by: @grp06

(cherry picked from commit 4b17d6d)
The upstream commit e8cb048 added acceptsArgs to model-auth-label.ts
(gutted in fork) and its test expectation in commands.test.ts. Since the
production code path that populates acceptsArgs was discarded, revert
the test assertion to match.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Merged via squash.

Prepared head SHA: b9675d1
Co-authored-by: liuxiaopai-ai <[email protected]>
Co-authored-by: gumadeiras <[email protected]>
Reviewed-by: @gumadeiras

(cherry picked from commit ae29842)
openclaw#32831)

Merged via squash.

Prepared head SHA: 2aa58f6
Co-authored-by: Sid-Qin <[email protected]>
Co-authored-by: shakkernerd <[email protected]>
Reviewed-by: @shakkernerd

(cherry picked from commit 3ad3a90)
… probes (openclaw#33831)

* fix(gateway): correct launchctl command sequence for gateway restart (closes openclaw#20030)

* fix(restart): expand HOME and escape label in launchctl plist path

* fix(restart): poll port free after SIGKILL to prevent EADDRINUSE restart loop

When cleanStaleGatewayProcessesSync() kills a stale gateway process,
the kernel may not immediately release the TCP port. Previously the
function returned after a fixed 500ms sleep (300ms SIGTERM + 200ms
SIGKILL), allowing triggerOpenClawRestart() to hand off to systemd
before the port was actually free. The new systemd process then raced
the dying socket for port 18789, hit EADDRINUSE, and exited with
status 1, causing systemd to retry indefinitely — the zombie restart
loop reported in openclaw#33103.

Fix: add waitForPortFreeSync() that polls lsof at 50ms intervals for
up to 2 seconds after SIGKILL. cleanStaleGatewayProcessesSync() now
blocks until the port is confirmed free (or the budget expires with a
warning) before returning. The increased SIGTERM/SIGKILL wait budgets
(600ms / 400ms) also give slow processes more time to exit cleanly.

Fixes openclaw#33103
Related: openclaw#28134

* fix: add EADDRINUSE retry and TIME_WAIT port-bind checks for gateway startup

* fix(ports): treat EADDRNOTAVAIL as non-retryable and fix flaky test

* fix(gateway): hot-reload agents.defaults.models allowlist changes

The reload plan had a rule for `agents.defaults.model` (singular) but
not `agents.defaults.models` (plural — the allowlist array).  Because
`agents.defaults.models` does not prefix-match `agents.defaults.model.`,
it fell through to the catch-all `agents` tail rule (kind=none), so
allowlist edits in openclaw.json were silently ignored at runtime.

Add a dedicated reload rule so changes to the models allowlist trigger
a heartbeat restart, which re-reads the config and serves the updated
list to clients.

Fixes openclaw#33600

Co-authored-by: HCL <[email protected]>
Signed-off-by: HCL <[email protected]>

* test(restart): 100% branch coverage — audit round 2

Audit findings fixed:
- remove dead guard: terminateStaleProcessesSync pids.length===0 check was
  unreachable (only caller cleanStaleGatewayProcessesSync already guards)
- expose __testing.callSleepSyncRaw so sleepSync's real Atomics.wait path
  can be unit-tested directly without going through the override
- fix broken sleepSync Atomics.wait test: previous test set override=null
  but cleanStaleGatewayProcessesSync returned before calling sleepSync —
  replaced with direct callSleepSyncRaw calls that actually exercise L36/L42-47
- fix pid collision: two tests used process.pid+304 (EPERM + dead-at-SIGTERM);
  EPERM test changed to process.pid+305
- fix misindented tests: 'deduplicates pids' and 'lsof status 1 container
  edge case' were outside their intended describe blocks; moved to correct
  scopes (findGatewayPidsOnPortSync and pollPortOnce respectively)
- add missing branch tests:
  - status 1 + non-empty stdout with zero openclaw pids → free:true (L145)
  - mid-loop non-openclaw cmd in &&-chain (L67)
  - consecutive p-lines without c-line between them (L67)
  - invalid PID in p-line (p0 / pNaN) — ternary false branch (L67)
  - unknown lsof output line (else-if false branch L69)

Coverage: 100% stmts / 100% branch / 100% funcs / 100% lines (36 tests)

* test(restart): fix stale-pid test typing for tsgo

* fix(gateway): address lifecycle review findings

* test(update): make restart-helper path assertions windows-safe

---------

Signed-off-by: HCL <[email protected]>
Co-authored-by: Glucksberg <[email protected]>
Co-authored-by: Efe Büken <[email protected]>
Co-authored-by: Riccardo Marino <[email protected]>
Co-authored-by: HCL <[email protected]>
(cherry picked from commit 1be39d4)
…enclaw#32363) (openclaw#32381)

Merged via squash.

Prepared head SHA: aee998a
Co-authored-by: chengzhichao-xydt <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

(cherry picked from commit 53727c7)
…openclaw#24867)

Complete the stop reason propagation chain so ACP clients can
distinguish end_turn from max_tokens:

- server-chat.ts: emitChatFinal accepts optional stopReason param,
  includes it in the final payload, reads it from lifecycle event data
- translator.ts: read stopReason from the final payload instead of
  hardcoding end_turn

Chain: LLM API → run.ts (meta.stopReason) → agent.ts (lifecycle event)
→ server-chat.ts (final payload) → ACP translator (PromptResponse)

(cherry picked from commit 0b3bbfe)
- Add threadId to MessagingToolSend type (needed by reply-payloads)
- Remove shouldHideHeartbeatChatOutput call (function not in fork)
- Rebrand OpenClawConfig to RemoteClawConfig in auto-merged test files
- Rebrand openclaw to remoteclaw in restart-stale-pids test fixtures
- Rebrand OPENCLAW_LAUNCHD_LABEL to REMOTECLAW_LAUNCHD_LABEL in test
Merged via squash.

Prepared head SHA: 563fee0
Co-authored-by: altaywtf <[email protected]>
Co-authored-by: altaywtf <[email protected]>
Reviewed-by: @altaywtf

(cherry picked from commit 627813a)
…law#30894) (openclaw#32706)

Merged via squash.

Prepared head SHA: 1714ffe
Co-authored-by: xiwan <[email protected]>
Co-authored-by: gumadeiras <[email protected]>
Reviewed-by: @gumadeiras

(cherry picked from commit caa748b)
- Remove bash-tools.exec-runtime.test.ts (imports from gutted module)
- Fix OpenClawConfig → RemoteClawConfig in heartbeat scheduler test

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
Merged via squash.

Prepared head SHA: 612ecc0
Co-authored-by: Mylszd <[email protected]>
Co-authored-by: gumadeiras <[email protected]>
Reviewed-by: @gumadeiras

(cherry picked from commit d89e1e4)
shakkernerd and others added 27 commits March 20, 2026 00:32
(cherry picked from commit f771ba8)

[partial: memory subsystem files discarded — FORK_DELETED; changelog entry kept]
…rding + topic-aware reply targeting (openclaw#33789)

* fix(feishu): comprehensive reply mechanism fix — outbound replyToId forwarding + topic-aware reply targeting

- Forward replyToId from ChannelOutboundContext through sendText/sendMedia
  to sendMessageFeishu/sendMarkdownCardFeishu/sendMediaFeishu, enabling
  reply-to-message via the message tool.

- Fix group reply targeting: use ctx.messageId (triggering message) in
  normal groups to prevent silent topic thread creation (openclaw#32980). Preserve
  ctx.rootId targeting for topic-mode groups (group_topic/group_topic_sender)
  and groups with explicit replyInThread config.

- Add regression tests for both fixes.

Fixes openclaw#32980
Fixes openclaw#32958
Related openclaw#19784

* fix: normalize Feishu delivery.to before comparing with messaging tool targets

- Add normalizeDeliveryTarget helper to strip user:/chat: prefixes for Feishu
- Apply normalization in matchesMessagingToolDeliveryTarget before comparison
- This ensures cron duplicate suppression works when session uses prefixed targets
  (user:ou_xxx) but messaging tool extract uses normalized bare IDs (ou_xxx)

Fixes review comment on PR openclaw#32755

(cherry picked from commit fc20106)

* fix(feishu): catch thrown SDK errors for withdrawn reply targets

The Feishu Lark SDK can throw exceptions (SDK errors with .code or
AxiosErrors with .response.data.code) for withdrawn/deleted reply
targets, in addition to returning error codes in the response object.

Wrap reply calls in sendMessageFeishu and sendCardFeishu with
try-catch to handle thrown withdrawn/not-found errors (230011,
231003) and fall back to client.im.message.create, matching the
existing response-level fallback behavior.

Also extract sendFallbackDirect helper to deduplicate the
direct-send fallback block across both functions.

Closes openclaw#33496

(cherry picked from commit ad0901a)

* feishu: forward outbound reply target context

(cherry picked from commit c129a69)

* feishu extension: tighten reply target fallback semantics

(cherry picked from commit f85ec61)

* fix(feishu): align synthesized fallback typing and changelog attribution

* test(feishu): cover group_topic_sender reply targeting

---------

Co-authored-by: Xu Zimo <[email protected]>
Co-authored-by: Munem Hashmi <[email protected]>
Co-authored-by: bmendonca3 <[email protected]>
Co-authored-by: Tak Hoffman <[email protected]>
(cherry picked from commit 63ce7c7)
…penclaw#33720)

* fix(feishu): use msg_type media for mp4 video (fixes openclaw#33674)

* Feishu: harden streaming merge semantics and final reply dedupe

Use explicit streaming update semantics in the Feishu reply dispatcher:
treat onPartialReply payloads as snapshot updates and block fallback payloads
as delta chunks, then merge final text with the shared overlap-aware
mergeStreamingText helper before closing the stream.

Prevent duplicate final text delivery within the same dispatch cycle, and add
regression tests covering overlap snapshot merge, duplicate final suppression,
and block-as-delta behavior to guard against repeated/truncated output.

* fix(feishu): prefer message.reply for streaming cards in topic threads

* fix: reduce Feishu streaming card print_step to avoid duplicate rendering

Fixes openclaw#33751

* Feishu: preserve media sends on duplicate finals and add media synthesis changelog

* Feishu: only dedupe exact duplicate final replies

* Feishu: use scoped plugin-sdk import in streaming-card tests

---------

Co-authored-by: 倪汉杰0668001185 <[email protected]>
Co-authored-by: zhengquanliu <[email protected]>
Co-authored-by: nick <[email protected]>
Co-authored-by: linhey <[email protected]>
Co-authored-by: Tak Hoffman <[email protected]>
(cherry picked from commit 68e68bf)
…claw#33245)

* Feishu: close duplicate final gap and cover routing precedence

* Feishu: resolve reviewer duplicate-final and routing feedback

* Feishu: tighten streaming send-mode option typing

* Feishu: fix reverse-overlap streaming merge ordering

* Feishu: align streaming final dedupe test expectation

* Feishu: allow distinct streaming finals while deduping repeats

---------

Co-authored-by: Tak Hoffman <[email protected]>
(cherry picked from commit 3bf6ed1)
…aming card (openclaw#35628)

Merged via squash.

Prepared head SHA: 62c3fec
Co-authored-by: Sid-Qin <[email protected]>
Co-authored-by: jalehman <[email protected]>
Reviewed-by: @jalehman

(cherry picked from commit 06ff25c)
…enclaw#36430)

When the Feishu API hangs or responds slowly, the sendChain never settles,
causing the per-chat queue to remain in a processing state forever and
blocking all subsequent messages in that thread. This adds a 30-second
default timeout to all Feishu HTTP requests by providing a timeout-aware
httpInstance to the Lark SDK client.

Closes openclaw#36412

Co-authored-by: Ayane <[email protected]>
(cherry picked from commit ba223c7)
…law#36358)

* fix(feishu): accept groupPolicy "allowall" as alias for "open"

When users configure groupPolicy: "allowall" in Feishu channel config,
the Zod schema rejects the value and the runtime policy check falls
through to the allowlist path.  With an empty allowFrom array, all group
messages are silently dropped despite the intended "allow all" semantics.

Accept "allowall" at the schema level (transform to "open") and add a
runtime guard in isFeishuGroupAllowed so the value is handled even if it
bypasses schema validation.

Closes openclaw#36312

Made-with: Cursor

* Feishu: tighten allowall alias handling and coverage

---------

Co-authored-by: Tak Hoffman <[email protected]>
(cherry picked from commit 2972d6f)
## Summary\n\nFeishu group slash command parsing is fixed for mentions and command probes across authorization paths.\n\nThis includes:\n- Normalizing bot mention text in group context for reliable slash detection in message parsing.\n- Adding command-probe normalization for group slash invocations.\n\nCo-authored-by: Sid Qin <[email protected]>\nCo-authored-by: Tak Hoffman <[email protected]>

(cherry picked from commit 995ae73)
- Feishu/group slash command detection: normalize group mention wrappers before command-authorization probing so mention-prefixed commands are recognized in group routing.\n- Source PR: openclaw#36011\n- Contributor: @liuxiaopai-ai\n\nCo-authored-by: Tak Hoffman <[email protected]>\nCo-authored-by: liuxiaopai-ai <[email protected]>

(cherry picked from commit 174eeea)
…aw#36500)

* fix(feishu): avoid media regressions from global http timeout

* fix(feishu): source HTTP timeout from config

* fix(feishu): apply media timeout override to image uploads

* fix(feishu): invalidate cached client when timeout changes

* fix(feishu): clamp timeout values and cover image download

(cherry picked from commit bc66a8f)
…guardrails (openclaw#35094)

(cherry picked from commit 72cf925)

[AUTO-PARTIAL] Discarded gutted src/secrets/ layer files and files
depending on gutted secrets module (resolve-configured-secret-input-string,
doctor-gateway-auth-token, gateway-install-token, secretref test).
Kept gateway config types, schema, auth-mode-policy, and doc changes.
The Feishu SDK type definitions don't include timeout in method option
types, but the runtime accepts it. Use spread with as-any cast to
preserve the timeout while satisfying the type checker.

Co-Authored-By: Claude Opus 4.6 (1M context) <[email protected]>
…flow, trigger compaction (openclaw#35934)

Merged via squash.

Prepared head SHA: 4301a03e48e6e6b2f5870e8a1305b3b9f45e32a3
Co-authored-by: Kai <[email protected]>
Co-authored-by: RealKai42 <[email protected]>
Reviewed-by: @gumadeiras

(cherry picked from commit 60a6d11116d7e8f0412157dff3e1e967e7e1e6e0)
Merged via squash.

Prepared head SHA: ae29f39cd6e103f34e47b4f5ee5b9f12f06b1076
Co-authored-by: Rodrigo Uroz <[email protected]>
Co-authored-by: dra11y <[email protected]>
Reviewed-by: @gumadeiras

(cherry picked from commit 036c329716f69e06e14bda12e0e39b27a7b7e285)
Fix merged schema cache key generation for high-cardinality plugin/channel metadata by hashing incrementally instead of serializing one large aggregate string.

Includes changelog entry for the user-visible regression fix.

Co-authored-by: Tak Hoffman <[email protected]>
Co-authored-by: Bill <[email protected]>
(cherry picked from commit a0b731e)
…#36567)

Merged via squash.

Prepared head SHA: 6b9d883
Co-authored-by: gumadeiras <[email protected]>
Co-authored-by: gumadeiras <[email protected]>
Reviewed-by: @gumadeiras

(cherry picked from commit 688b72e)
Commit 688b72e (prompt hook policy) requires before_model_resolve,
before_prompt_build, and before_agent_start hooks to be registrable
so the per-plugin allowPromptInjection policy can filter them.

- Add missing entries to PluginHookHandlerMap for restored hook types
- Add merge functions and runner stubs for model/prompt/agent hooks
- Remove model/prompt/agent hooks from DEAD_HOOKS (policy handles them)
- Add PluginHookName entries for all upstream hook names
- Add PLUGIN_HOOK_NAMES entries for fork-specific runtime hooks
before_model_resolve, before_prompt_build, before_agent_start were
removed from DEAD_HOOKS to enable prompt hook policy enforcement.
@alexey-pelykh alexey-pelykh merged commit 6a28bc3 into fork-sync-base Mar 20, 2026
7 checks passed
@alexey-pelykh alexey-pelykh deleted the cherry-pick/staging-823 branch March 20, 2026 00:46
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.