← Back to PRs

#10327: Fix: persist original prompt to transcript, not plugin-modified prompt (#287)

by GodsBoy open 2026-02-06 10:12 View on GitHub →
agents stale
## Summary Fixes the issue where `prependContext` from `before_agent_start` hooks (used by memory plugins like hindsight-openclaw) appeared as visible user messages in the chat UI. **Related:** https://github.com/vectorize-io/hindsight/issues/287 ## Root Cause In `attempt.ts`, the modified `effectivePrompt` (containing prepended memory context) was passed to `activeSession.prompt()`, which persists it verbatim to the session transcript. ## Fix Added `installTranscriptPromptGuard()` — a one-shot `appendMessage` interceptor that: - Replaces the content of the first user-role message with the **original** `params.prompt` (what the user actually typed) - Passes all other messages (assistant, toolResult, etc.) through untouched - Auto-disarms after the first interception - Only activates when hooks actually modified the prompt ## Changes - `src/agents/pi-embedded-runner/run/attempt.ts` — Added transcript guard - `src/agents/pi-embedded-runner/run/attempt.test.ts` — Added 5 tests ## Verification - All 8 tests pass (3 existing + 5 new) - Type-check clean - Formatter ran via pre-commit hook <!-- greptile_comment --> <h2>Greptile Overview</h2> <h3>Greptile Summary</h3> - Adds a one-shot `appendMessage` interceptor to prevent `before_agent_start` hook prepended context from being persisted as a user-visible transcript message. - Wraps the `activeSession.prompt()` call with a try/finally that installs the guard only when the hook-modified prompt differs from the original. - Adds unit tests validating that the first user message is replaced with the original prompt and that teardown restores behavior. - Main concern: the guard’s teardown restores a bound wrapper, which can undo/bypass the existing sessionManager tool-result guard wrapper and potentially break transcript/tool-result consistency after the prompt. <h3>Confidence Score: 3/5</h3> - This PR is close, but there’s a real risk of breaking the existing SessionManager tool-result guard due to how appendMessage is restored. - The functional intent is clear and the tests cover the guard in isolation, but the implementation stacks monkey patches on `sessionManager.appendMessage`. Because teardown restores a bound wrapper rather than the prior function reference, it can bypass `installSessionToolResultGuard()`’s patched appendMessage, potentially breaking tool-result persistence behavior in real runs. - src/agents/pi-embedded-runner/run/attempt.ts <!-- greptile_other_comments_section --> <!-- /greptile_comment -->

Most Similar PRs