CON-216: stop campaign_assistant replaying stale prior instructions - #115
Conversation
The Haiku planner could re-issue a write tool (e.g. generatePosts) for a read-only question, reusing a date pulled from conversation history rather than the current message — the "stuck in previous user message" bug. Two targeted fixes: - Prompt discipline (campaign_assistant.tmpl): act only on the current message; treat history as background, not a queue to replay. Questions are read-only and never trigger a write/generation tool; resolve dates only from the current request against today, never reuse a date from history. - Late heavy-action reservation (toolGeneratePosts): reserve the turn's single heavy slot only after the user-correctable validations pass, mirroring draftPost (CON-207). A mis-routed/invalid generatePosts that fails soft (CON-215) no longer burns the slot for a legitimate heavy action in the same turn. ensureCampaignAssetUse also moved past the reservation so a skipped turn never flips UseAssets in the DB. Layer 2 (the past-date abort surfacing as a raw "model call failed") was already resolved by CON-215's soft-fail; this addresses the root-cause mis-routing. Adds a regression test that the heavy slot is burned only on a successful generation.
|
No actionable comments were generated in the recent review. 🎉 ℹ️ Recent review info⚙️ Run configurationConfiguration used: Path: .coderabbit.yaml Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (3)
WalkthroughThe campaign assistant now uses only current-message instructions for write actions and dates. ChangesCampaign assistant behavior
Estimated code review effort: 3 (Moderate) | ~20 minutes Merge Risk: ⚪ Minimal · up to The change limits stale-instruction replay and prevents invalid generation attempts from consuming the turn's heavy-action slot; no actionable merge-blocking risk remains after normal checks and review. Sequence Diagram(s)sequenceDiagram
participant UserMessage
participant CampaignAssistant
participant generatePosts
participant HeavyActionSlot
participant GenerationFlow
UserMessage->>CampaignAssistant: current request
CampaignAssistant->>generatePosts: explicit generation request
generatePosts->>generatePosts: validate request
generatePosts->>HeavyActionSlot: reserve after valid checks
generatePosts->>GenerationFlow: generate posts
GenerationFlow-->>CampaignAssistant: generated posts
Possibly related PRs
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✨ Finishing Touches 💡 1📝 Generate docstrings 💡
🧪 Generate unit tests (beta)
Thanks for using CodeRabbit! It's free for OSS, and your support helps us grow. If you like it, consider giving us a shout-out. Comment |
|
@CodeRabbit review |
✅ Action performedReview finished.
|
Fixes CON-216 — "post_assistant seems stuck in previous user message instructions in case of an internal error."
Problem
A user asked a read-only question ("tell me about assets attached to this campaign"), but the cheap Haiku planner:
generatePosts(a write action nobody asked for) alongside the correctaskCampaignAssets, and2026-07-28) that appears only in earlier conversation history, not the current message.resolveWindowrejected the past date with a Go error, which aborts the whole genkitGenerateturn → surfaced to the user as a raw redmodel call failed: … is in the pastand discarded the good asset answer.What was already fixed
generatePosts/draftPostnow fail soft on a past date / non-target platform / unknown phase (a zero-post warning, not a turn-aborting error), leaving the turn conversational. The red 502 in the screenshot can no longer recur.This PR addresses Layer 1 — the root-cause mis-routing named in the ticket title — plus a slot-leak the mis-route exposed.
Changes
prompts/campaign_assistant.tmpl): act only on the current message; treat history as background, not a queue to replay. Questions are read-only and must never trigger a write/generation tool; resolve dates only from the current request against today — never reuse a date from an earlier message.toolGeneratePosts): reserve the turn's single heavy slot only after the user-correctable validations pass, mirroring the CON-207draftPostrefactor. A mis-routed/invalidgeneratePoststhat fails soft no longer burns the slot for a legitimate heavy action in the same turn.ensureCampaignAssetUse(which persistsUseAssetsto the DB) also moved past the reservation, so a skipped/soft-failed turn never writes state for work that won't run.tools_test.go):TestGeneratePosts_HeavySlotOnlyBurnedOnSuccess— a soft-failedgeneratePostsleaves the slot claimable; a successful one claims it (second heavy reservation turned away).Why no server-side date guard
Dates are model-resolved and history is legitimately needed (
draftPostsources its material from it), and the crash path is already handled. Prompt discipline + the reservation reorder is the proportionate fix.Testing
go build,go vet, andgo test -race ./src/genkit/flows/campaign_assistant/all pass (existing CON-213/214/215 tests still green).system/contextblocks intact.Summary by CodeRabbit