Add proactive context prompt MVP#188
Conversation
|
Warning Review limit reached
More reviews will be available in 2 minutes and 31 seconds. Learn how PR review limits work. Your organization has used up its prepaid credits, and credit purchases are no longer available. Enable the review add-on in the billing tab to keep reviews running — you're only billed for reviews past your plan's rate limits ($0.25/file). ⌛ How to resolve this issue?After more reviews become available, a review can be triggered using the To avoid repeated limits, reduce automatic review volume by pausing incremental auto-reviews earlier, using label-based review opt-in, excluding WIP or generated PR titles, or requesting reviews manually when the PR is ready. If your team needs uninterrupted high-volume reviews, an organization admin can enable usage-based credits. 🚦 How do rate limits work?CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan refill rate. For paid Pro and Pro+ PR reviews, CodeRabbit uses adaptive limits for sustained high-volume activity. When a developer's recent PR review activity reaches the 95th percentile or higher among CodeRabbit users, the refill rate gradually slows as usage increases. The highest same-day bursts are limited more strictly. Please see our Fair Usage Limits Policy for further information. ℹ️ Review info⚙️ Run configurationConfiguration used: defaults Review profile: CHILL Plan: Pro Plus Run ID: 📒 Files selected for processing (4)
📝 WalkthroughWalkthroughThis PR implements two features: (1) a proactive context prompt MVP that detects low-sleep anomalies, reserves Telegram inline-keyboard prompts asking users to categorize the reason, stores answers, and renders annotations in morning reports; and (2) a subjective check-in calendar SLA that synthesizes missing/pending days after a configurable ChangesProactive Context Prompts MVP
Subjective Check-in Calendar SLA
Sequence Diagram(s)sequenceDiagram
participant Scheduler
participant DB as storage.DB
participant TrySend as trySendContextPromptAfterMorning
participant NotifyBot as notify.SendContextPrompt
participant TelegramAPI
Scheduler->>DB: MarkMorningSent (under sendMu lock)
Scheduler->>Scheduler: sendMu.Unlock (explicit)
Scheduler->>TrySend: signalDate, db, bot, lang
TrySend->>DB: IsContextPromptsEnabled?
DB-->>TrySend: true/false
alt prompts enabled
TrySend->>DB: ReserveLowSleepContextPrompt(signalDate, expiresAt+36h)
DB-->>TrySend: ContextPromptInteraction or nil (conflict)
TrySend->>NotifyBot: SendContextPrompt(bot, store, lang, prompt, now)
NotifyBot->>TelegramAPI: SendInlineKeyboard(text, rows)
TelegramAPI-->>NotifyBot: msgID
NotifyBot->>DB: MarkContextPromptSent(promptID, msgID, now)
end
sequenceDiagram
participant TelegramWebhook
participant WebhookHandler as NewWebhookHandler
participant Router as liveCheckinRouter
participant DB as storage.DB
TelegramWebhook->>WebhookHandler: POST callback_data="ctx:cp_abc:stress"
WebhookHandler->>WebhookHandler: parseContextPromptCallback → (promptID, category, ok)
WebhookHandler->>Router: SaveContextPromptAnswer(promptID, category, source, now)
Router->>DB: SaveContextPromptAnswer (FOR UPDATE tx, expiry/category check)
DB-->>Router: (status, err)
Router-->>WebhookHandler: status
WebhookHandler->>TelegramAPI: AnswerCallbackQuery(contextAckText(lang, status))
WebhookHandler-->>TelegramWebhook: HTTP 200
Estimated code review effort🎯 5 (Critical) | ⏱️ ~120 minutes Possibly related PRs
Poem
🚥 Pre-merge checks | ✅ 4 | ❌ 1❌ Failed checks (1 warning)
✅ Passed checks (4 passed)
✏️ Tip: You can configure your own custom pre-merge checks in the settings. ✨ Finishing Touches🧪 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 |
There was a problem hiding this comment.
💡 Codex Review
Here are some automated review suggestions for this pull request.
Reviewed commit: 3748547265
ℹ️ About Codex in GitHub
Your team has set up Codex to review pull requests in this repo. Reviews are triggered when you
- Open a pull request for review
- Mark a draft as ready
- Comment "@codex review".
If Codex has suggestions, it will comment; otherwise it will react with 👍.
Codex can also answer questions or update the PR. Try commenting "@codex address that feedback".
| COALESCE(category, ''), COALESCE(source, ''), COALESCE(prompt_message_id, 0), | ||
| COALESCE(prompted_at, '0001-01-01'::timestamptz), expires_at, | ||
| COALESCE(answered_at, '0001-01-01'::timestamptz), allowed_categories, metadata`, | ||
| promptID, signalDate, promptLocalDate, reason, detectorVersion, ContextPromptStatusReserved, expiresAt, allowedJSON, metadataJSON, now). |
There was a problem hiding this comment.
Wrap context prompt JSONB values before insert
When proactive_context_prompts is enabled and a low-sleep candidate reaches this insert, allowedJSON and metadataJSON are plain []byte values from json.Marshal. With this repo's pgx setup, plain byte slices are encoded as bytea, so the $8::jsonb/$9::jsonb parameters fail the JSONB write instead of reserving the prompt; use json.RawMessage (as the other JSONB writers do) or another JSON-typed value.
Useful? React with 👍 / 👎.
| health.ApplyIllnessSafetyCap(resp, health.GetStrings(lang)) | ||
|
|
||
| if IsContextCaveatsEnabled(s) { | ||
| if annotations, aerr := s.GetContextAnnotationsForDate(*lastDate); aerr == nil { |
There was a problem hiding this comment.
Look back for answered context caveats
Because prompts are sent only after the morning report for signalDate, the user normally answers after that report is already gone. The next morning GetHealthBriefing advances lastDate to the newer daily score, but this lookup only asks for annotations whose signal_date equals that new date, so the saved context for yesterday's low-sleep signal is never rendered in any future morning report even with context_caveats_enabled on.
Useful? React with 👍 / 👎.
There was a problem hiding this comment.
Actionable comments posted: 5
🧹 Nitpick comments (1)
internal/storage/context_prompt.go (1)
545-585: 💤 Low valueRemove or annotate unused timing functions.
contextSleepTimingForDateandhhmmToMinuteare flagged as unused by static analysis. SincecontextSleepTimingDeviationis disabled for MVP (returnsfalse, nil), these functions are dead code. Either remove them to reduce maintenance burden, or add a// nolint:unuseddirective with a comment explaining they're retained for post-MVP enablement.🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the rest with a brief reason, keep changes minimal, and validate. In `@internal/storage/context_prompt.go` around lines 545 - 585, The functions contextSleepTimingForDate and hhmmToMinute are flagged as unused by static analysis because they are only called by the disabled contextSleepTimingDeviation function. Either remove both functions entirely to eliminate dead code, or add a nolint:unused directive above each function definition with a comment explaining that they are intentionally retained for post-MVP enablement when contextSleepTimingDeviation is re-enabled.Source: Linters/SAST tools
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@docs/ai-plans/2026-06-18-checkin-calendar-sla.html`:
- Around line 204-209: The Approval Gate section containing the h2 "Approval
Gate" and paragraph about needing explicit user approval before implementation
is misleading because the document already shows an "Implemented Result" and
completed checks, indicating the work is finished. Either remove the entire
approval gate section entirely, or reword it to clearly indicate that this was a
historical approval requirement that has already been satisfied, making it clear
to future readers that the plan has been implemented and is not a current
blocker.
- Line 189: The gofmt command contains Windows-style path separators
(backslashes) in all file paths which will fail in Linux CI environments.
Replace all backslashes with forward slashes in the paths listed in the gofmt
command (internal\storage\subjective_checkin.go,
internal\storage\subjective_checkin_test.go, internal\ui\handler.go,
internal\ui\admin_checkin_coverage_test.go, internal\ui\i18n_en.go,
internal\ui\i18n_ru.go, and internal\ui\i18n_sr.go) to use POSIX-compatible
forward slashes instead.
In `@docs/ai-plans/2026-06-20-proactive-context-prompts-mvp.html`:
- Around line 135-153: Update the DDL documentation in the
context_prompt_interactions table definition to match the actual schema
implementation. First, add the NOT NULL constraint to the expires_at field
(currently shown as nullable). Second, add the DEFAULT '[]'::jsonb clause to the
allowed_categories field to match the actual implementation in
internal/storage/context_prompt.go. These two changes will align the documented
schema with what is actually implemented.
- Around line 154-157: Update the unique index definition for
context_prompt_interactions by making two corrections: first, change the index
name from `ux_context_prompt_one_sent_per_day` to
`idx_context_prompt_one_sent_per_day` to use the correct naming prefix, and
second, add `'send_failed'` to the status list in the WHERE clause alongside the
existing statuses ('reserved', 'prompted', 'answered', 'skipped', 'expired') to
match the design requirement stated elsewhere that send_failed is terminal and
part of the one-prompt-per-local-day deduplication constraint.
In `@internal/storage/context_prompt.go`:
- Around line 597-619: The JSONB parameters allowedJSON and metadataJSON are
being passed directly as []byte to the pgx query without proper wrapping. Modify
the code to wrap both allowedJSON and metadataJSON in json.RawMessage after
their respective json.Marshal calls, then pass these wrapped values to the
QueryRow call instead of the raw byte slices. This ensures proper handling of
JSONB parameters when writing via pgx v5.
---
Nitpick comments:
In `@internal/storage/context_prompt.go`:
- Around line 545-585: The functions contextSleepTimingForDate and hhmmToMinute
are flagged as unused by static analysis because they are only called by the
disabled contextSleepTimingDeviation function. Either remove both functions
entirely to eliminate dead code, or add a nolint:unused directive above each
function definition with a comment explaining that they are intentionally
retained for post-MVP enablement when contextSleepTimingDeviation is re-enabled.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: defaults
Review profile: CHILL
Plan: Pro Plus
Run ID: a5854ee0-47c7-4deb-93e6-619878a1f1d6
📒 Files selected for processing (26)
cmd/server/main.godocs/ai-plans/2026-06-18-checkin-calendar-sla.htmldocs/ai-plans/2026-06-20-proactive-context-prompts-mvp.htmlinternal/health/i18n_en.gointernal/health/i18n_ru.gointernal/health/i18n_sr.gointernal/health/types.gointernal/notify/checkin_callback.gointernal/notify/checkin_callback_test.gointernal/notify/context_prompt.gointernal/notify/context_prompt_test.gointernal/notify/report.gointernal/notify/report_rich.gointernal/storage/briefing.gointernal/storage/context_prompt.gointernal/storage/context_prompt_test.gointernal/storage/subjective_checkin.gointernal/storage/subjective_checkin_test.gointernal/tenants/manager.gointernal/ui/admin_checkin_coverage_test.gointernal/ui/handler.gointernal/ui/i18n_en.gointernal/ui/i18n_ru.gointernal/ui/i18n_sr.gointernal/ui/style.gointernal/ui/templates/pages/admin.html
…ontext-prompts # Conflicts: # docs/ai-plans/2026-06-18-checkin-calendar-sla.html
Summary
Validation
Closes #185
Summary by CodeRabbit
Release Notes
New Features
Documentation