Skip to content

Dev#46

Merged
aryansoni-dev merged 3 commits into
mainfrom
dev
Jul 1, 2026
Merged

Dev#46
aryansoni-dev merged 3 commits into
mainfrom
dev

Conversation

@aryansoni-dev

@aryansoni-dev aryansoni-dev commented Jul 1, 2026

Copy link
Copy Markdown
Owner

Summary by CodeRabbit

  • New Features

    • AI chat, reflections, and insights now use a unified renderer for richer formatting (including lists, headings, tables, and links).
    • Chat now shows a “Jump to latest” option and preserves scroll position when viewing older messages.
    • Insight reports now incorporate mood check-ins alongside journal entries.
  • Bug Fixes

    • Improved handling of partial/truncated AI responses with clearer “stopped early” indicators.
    • Enhanced long-text line breaking for better readability and accessibility, including selectable text where appropriate.
  • Documentation

    • Added documentation and a test matrix for dynamic AI text rendering behavior and parsing.

[+] Implemented code-rabbit's suggested patches.
[+] Implemented code-rabbit's suggested patches.
@coderabbitai

coderabbitai Bot commented Jul 1, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds a shared AI text renderer and markdown parser, then threads them through chat, insights, report, and reflection surfaces. Also adds partial-response handling, mood-log-aware insight/report logic, shared report narrative parsing with retries, and a few small UI/documentation updates.

Changes

AI Response Rendering and Text Integrity

Layer / File(s) Summary
Text parsing utilities
lib/text/add-safe-break-opportunities.ts, lib/text/parse-ai-markdown.ts
Adds long-token break insertion and markdown block parsing helpers for AI text.
AI response renderer
components/ai/ai-response-renderer.tsx
Adds the memoized AI text renderer with inline markdown, safe links, and fallback rendering.
Rendering tests, fixtures, and audit docs
tests/fixtures/ai-responses.ts, tests/ai-text-rendering.test.ts, docs/dynamic-ai-text-*
Adds AI text fixtures, rendering tests, and audit/test-matrix docs for the new text behavior.

Text Integrity and Partial AI Responses

Layer / File(s) Summary
Integrity logging
lib/ai/log-ai-text-integrity.ts, lib/ai/get-ai-text-length.ts, lib/ai/entryReflectionService.ts, lib/ai/remoteJournalAssistant.ts, lib/insights/aiInsightReportService.ts, store/useAIInsightReportStore.ts, store/useEntryReflectionStore.ts, store/useChatStore.ts
Adds AI text-length helpers and dev logging during validation and persistence of AI text.
Partial response types and validation
types/chat.ts, lib/ai/remoteJournalAssistant.ts, lib/validation/persistedDataValidators.ts
Adds the optional partial-response flag through chat and remote assistant types and persisted-message validation.
Journal chat truncation handling
supabase/functions/journal-ai-chat/index.ts
Detects provider truncation and returns partial content instead of a generic failure.

AI Text Rendering in UI

Layer / File(s) Summary
Chat screen rendering
components/ai-chat/ai-chat-screen.tsx
Updates assistant rendering, scroll behavior, and bubble text handling for partial responses and safer layout.
Insights and report UI
components/insights/*, app/insights/report/[periodType].tsx, components/journal-editor/entry-ai-reflection-card.tsx, components/auth/auth-screen.tsx
Uses the shared renderer and safe-break/selectable text across insight cards, report blocks, reflection cards, and related screens.

Mood Check-in Integration into Insights

Layer / File(s) Summary
Preferred mood utility and tests
lib/insights/getPreferredMoodForRange.ts, tests/preferred-mood.test.ts
Computes preferred mood from entries and mood logs and verifies override/fallback behavior.
Insights screen mood-log wiring
components/insights/insights-screen.tsx
Adds mood-log hydration gating and preferred-mood bucket computation on the insights screen.
AI insight report hook mood sync
hooks/useAIInsightReport.ts
Hydrates mood logs alongside journal entries and uses them for refresh, generation, and staleness checks.
Report analytics mood timeline
supabase/functions/_shared/buildReportAnalytics.ts, lib/insights/aiInsightReportMapper.ts, tests/report-analytics.test.ts
Merges mood logs into analytics, adjusts theme normalization, and updates the supported report format version.

Report Narrative Parsing Refactor

Layer / File(s) Summary
Shared narrative parser
supabase/functions/_shared/parseReportNarrative.ts
Adds shared report narrative types and text parsing/validation with structured failure reasons.
Insight report generation
supabase/functions/generate-insight-report/index.ts
Adds JWT-based auth, mood-log fetches, and narrative retry parsing using the shared parser.
Reflection text simplification
supabase/functions/reflect-on-entry/index.ts
Removes fixed-length truncation constraints and simplifies reflection text enforcement.
Narrative parser tests
tests/report-narrative-parser.test.ts
Tests successful parsing, fence extraction, capped mode, and invalid/incomplete content rejection.

Minor Cosmetic Fixes

Layer / File(s) Summary
Small wording and styling updates
AGENTS.md, app/(onboarding)/onboarding-screen-2.tsx, components/auth/auth-screen.tsx
Updates the SVG reminder wording, onboarding preview asset/label, and social button sizing/spacing.

Estimated code review effort: 5 (Critical) | ~120 minutes

🚥 Pre-merge checks | ✅ 3 | ❌ 2

❌ Failed checks (1 warning, 1 inconclusive)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 0.00% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
Title check ❓ Inconclusive The title is too generic and does not describe the actual changes in the pull request. Replace it with a concise title that names the main change, such as adding shared AI text rendering and mood-log/report updates.
✅ Passed checks (3 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Linked Issues check ✅ Passed Check skipped because no linked issues were found for this pull request.
Out of Scope Changes check ✅ Passed Check skipped because no linked issues were found for this pull request.
✨ Finishing Touches
📝 Generate docstrings
  • Create stacked PR
  • Commit on current branch
🧪 Generate unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch dev

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.

❤️ Share

Comment @coderabbitai help to get the list of available commands.

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 14

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
components/auth/auth-screen.tsx (1)

610-618: 📐 Maintainability & Code Quality | 🟡 Minor | ⚡ Quick win

leading-6/leading-5 inconsistency between the two social buttons.

The "Continue with Google" text now uses leading-6 (Line 618) while "Continue with Apple" (Line 637) still uses leading-5, so the two visually-paired buttons no longer have matching line heights.

✏️ Proposed fix
-        <Text className="text-[15px] font-semibold leading-5 text-zinc-950">
+        <Text className="text-[15px] font-semibold leading-6 text-zinc-950">
           Continue with Apple

As per coding guidelines, "Keep 'leading-6' in all components, and fix if you find any un-matching ones."

🤖 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 `@components/auth/auth-screen.tsx` around lines 610 - 618, The social button
labels in auth-screen.tsx are inconsistent because the Google and Apple variants
use different text line heights. Update the text styling in the shared social
button area (the Text elements used by the Google and Apple buttons) so both use
leading-6, keeping the paired buttons visually aligned and consistent.
🤖 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 `@AGENTS.md`:
- Line 284: The instruction text in AGENTS.md should capitalize the proper noun
“Google” in the sentence about creating the icon; update that guidance so the
reference to the Google icon uses the correctly capitalized name, and keep the
rest of the instruction unchanged.

In `@components/ai-chat/ai-chat-screen.tsx`:
- Around line 758-763: The first assistant bubble is being mutated before it
reaches AIResponseRenderer, so the integrity-logged render source no longer
matches the stored/validated assistant message. Update the AI-chat message
rendering path in ai-chat-screen.tsx so AIResponseRenderer receives the raw
assistant text for its content prop, and keep any greeting/prefix text separate
from the renderer’s logged source. Use the existing AIResponseRenderer call site
and the first-reply formatting logic that prepends the display name to ensure
the displayed UI can still show the greeting without altering the
integrity-checked content.
- Around line 239-251: The chat scroll handler in handleChatScroll only clears
the jump button state when near the bottom, so it never shows the control during
a manual upward scroll. Update handleChatScroll in ai-chat-screen.tsx so it also
calls setShowJumpToLatest(true) whenever isNearBottom is false, while keeping
isNearBottomRef.current in sync and preserving the existing hide behavior when
the user returns near the bottom.

In `@components/ai/ai-response-renderer.tsx`:
- Around line 72-73: The selectable render path in ai-response-renderer.tsx is
injecting U+200B into the same Text content that users can copy, which corrupts
copied URLs, IDs, and other unbroken tokens. Update the rendering logic around
AiResponseRenderer so selectable output keeps the original raw string, and move
any zero-width-space wrapping into a separate visual-only layer or disable that
injection when selectable is true. Check the token-wrapping logic in the
affected branches around the long-text/URL handling sections and the related
Text rendering helper so the displayed wrapping does not alter the copy source.

In `@components/insights/insights-screen.tsx`:
- Around line 125-134: Mood-log hydration failures are being treated as
successful readiness in the insights screen. Update insights-screen.tsx to
include the mood log store’s hydrationError alongside useJournalHydrationStore’s
hydrationError before deciding localDataHasHydrated and showHydrationState, so
the screen surfaces the failure instead of rendering as ready. Use the existing
useMoodLogStore selector and the localDataHasHydrated readiness gate as the main
place to apply the fix, and make sure any matching fallback logic around the
related render path also checks this error state.

In `@components/insights/report/ReportNarrativeBlocks.tsx`:
- Around line 106-110: Route the remaining `emotionalFlow` and `nextFocus`
narrative fields through `AIResponseRenderer` instead of rendering them as plain
`Text`, matching the existing shared AI rendering path used elsewhere in
`ReportNarrativeBlocks`. Update the relevant render branches for these sections
so they inherit markdown handling and `render_source` integrity logging, using
the same renderer component and props pattern already introduced for the other
report narrative blocks.

In `@hooks/useAIInsightReport.ts`:
- Around line 55-57: The new hydration guard in useAIInsightReport is incomplete
because useMoodLogStore can report hasHydrated=true even when rehydration
failed, so refresh() and requestGeneration() may proceed with missing mood logs
and overwrite a valid cached report. Update the checks around the mood log store
in useAIInsightReport to also block on state.hydrationError, mirroring how
cacheHydrationError is handled, and apply the same safeguard anywhere mood logs
are assumed ready in the refresh/requestGeneration flow. Use the existing
symbols useMoodLogStore, hasHydrated, hydrationError, refresh, and
requestGeneration to keep the condition consistent across the affected branches.
- Around line 90-96: The stale-source fingerprint in getLocalSource and
isReportStale still ignores mood-log-only changes, so update the local/report
contract to include mood-log identity data or the same snapshot hash used for
report freshness. Fold mood log IDs/counts (not just latestUpdatedAt) into the
source fingerprint returned from useAIInsightReport, and make isReportStale
compare against that expanded signature so syncs that add or change mood logs
invalidate the report correctly.

In `@lib/text/parse-ai-markdown.ts`:
- Around line 71-80: The table parsing in parse-ai-markdown.ts is too permissive
because the loop after isTableStart() treats any line containing "|" as part of
the table, causing non-table text to be swallowed. Update the row-collection
logic in the table block handling to validate each candidate line against the
table’s expected shape from the header/separator rows in addition to checking
for "|", and stop extending the table when the column count or structure no
longer matches.

In `@store/useChatStore.ts`:
- Around line 55-60: Keep the assistant surface label consistent across the
integrity pipeline by changing the `addMessage` path in `useChatStore` so
assistant messages use the same `surface` value as `remoteJournalAssistant` and
`ai-response-renderer` (that is, `ai_chat_message`) instead of deriving it from
`message.role`. Update the `logAITextIntegrity` call in `addMessage` so stored,
validate, and render stages can be correlated for assistant replies.

In `@supabase/functions/journal-ai-chat/index.ts`:
- Around line 1537-1540: The provider-response log in journal-ai-chat is missing
requestId, which makes it harder to correlate truncation metadata with a
specific request. Update the console.info call in the provider_response_received
path to include requestId, and verify the identifier is in scope at this call
site so the log stays consistent with the rest of the flow.

In `@supabase/functions/reflect-on-entry/index.ts`:
- Around line 942-945: The reflection text normalization in
ensureReflectionTerminal/isIncompleteReflectionText is allowing incomplete
endings like a trailing comma to become finalized after punctuation is appended.
Update the flow around the sanitization path in reflect-on-entry so incomplete
text is rejected before terminal normalization, or make ensureReflectionTerminal
preserve/refuse dangling punctuation; use the isIncompleteReflectionText check
and the terminal handling in the same validation path to catch cases before a
trailing period is added.
- Around line 690-691: Bound the provider-generated reflection lists in the
reflection parsing path, since getTrimmedStringArray currently accepts every
item for emotions and themes. Update the parsing logic around
parsedValue.emotions and parsedValue.themes to cap the number of returned
entries to a small fixed limit while still trimming and preserving valid items,
so the reflection card payload can’t grow unbounded from verbose or malformed
provider output.

In `@tests/report-analytics.test.ts`:
- Around line 108-136: Add a same-day mood-log precedence test in
report-analytics.test.ts to cover duplicate logs on the same date resolved by
latest updated_at. Extend the existing buildReportAnalytics setup by adding two
mood logs for the same day with different updated_at values, then assert that
moodTimeline picks the most recently updated mood as dominant. Use the existing
buildReportAnalytics, createMoodLog, and moodTimeline assertions to keep the
case near the current mood override tests.

---

Outside diff comments:
In `@components/auth/auth-screen.tsx`:
- Around line 610-618: The social button labels in auth-screen.tsx are
inconsistent because the Google and Apple variants use different text line
heights. Update the text styling in the shared social button area (the Text
elements used by the Google and Apple buttons) so both use leading-6, keeping
the paired buttons visually aligned and consistent.
🪄 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: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 367d1c83-cd48-4eb8-bd49-452d16cb8338

📥 Commits

Reviewing files that changed from the base of the PR and between 0a42685 and 58d8bd2.

📒 Files selected for processing (40)
  • AGENTS.md
  • app/(onboarding)/onboarding-screen-2.tsx
  • app/insights/report/[periodType].tsx
  • components/ai-chat/ai-chat-screen.tsx
  • components/ai/ai-response-renderer.tsx
  • components/auth/auth-screen.tsx
  • components/insights/RecurringThemesCard.tsx
  • components/insights/insights-screen.tsx
  • components/insights/report/MoodJourneyChart.tsx
  • components/insights/report/RecurringThemesChart.tsx
  • components/insights/report/ReportNarrativeBlocks.tsx
  • components/insights/report/ReportScreenStates.tsx
  • components/journal-editor/entry-ai-reflection-card.tsx
  • docs/dynamic-ai-text-rendering-audit.md
  • docs/dynamic-ai-text-test-matrix.md
  • hooks/useAIInsightReport.ts
  • lib/ai/entryReflectionService.ts
  • lib/ai/get-ai-text-length.ts
  • lib/ai/log-ai-text-integrity.ts
  • lib/ai/remoteJournalAssistant.ts
  • lib/insights/aiInsightReportMapper.ts
  • lib/insights/aiInsightReportService.ts
  • lib/insights/getPreferredMoodForRange.ts
  • lib/text/add-safe-break-opportunities.ts
  • lib/text/parse-ai-markdown.ts
  • lib/validation/persistedDataValidators.ts
  • store/useAIInsightReportStore.ts
  • store/useChatStore.ts
  • store/useEntryReflectionStore.ts
  • supabase/functions/_shared/buildReportAnalytics.ts
  • supabase/functions/_shared/parseReportNarrative.ts
  • supabase/functions/generate-insight-report/index.ts
  • supabase/functions/journal-ai-chat/index.ts
  • supabase/functions/reflect-on-entry/index.ts
  • tests/ai-text-rendering.test.ts
  • tests/fixtures/ai-responses.ts
  • tests/preferred-mood.test.ts
  • tests/report-analytics.test.ts
  • tests/report-narrative-parser.test.ts
  • types/chat.ts

Comment thread AGENTS.md Outdated
Comment thread components/ai-chat/ai-chat-screen.tsx Outdated
Comment thread components/ai-chat/ai-chat-screen.tsx
Comment thread components/ai/ai-response-renderer.tsx
Comment thread components/insights/insights-screen.tsx Outdated
Comment thread store/useChatStore.ts
Comment thread supabase/functions/journal-ai-chat/index.ts
Comment thread supabase/functions/reflect-on-entry/index.ts
Comment thread supabase/functions/reflect-on-entry/index.ts
Comment thread tests/report-analytics.test.ts

@coderabbitai coderabbitai Bot left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Actionable comments posted: 1

Caution

Some comments are outside the diff and can’t be posted inline due to platform limitations.

⚠️ Outside diff range comments (1)
components/ai-chat/ai-chat-screen.tsx (1)

506-518: 🎯 Functional Correctness | 🟡 Minor | ⚡ Quick win

Keep the jump button on the same keyboard offset as the composer.

footerKeyboardOffset lifts the footer on Android, but this new container ignores it. When the keyboard is open, the button stays in the old slot and can end up visually detached from or underneath the moved composer.

🤖 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 `@components/ai-chat/ai-chat-screen.tsx` around lines 506 - 518, The
jump-to-latest container in ai-chat-screen.tsx is not using the same keyboard
offset as the composer, so it can մն stay fixed while the footer moves. Update
the conditional View that renders when showJumpToLatest is true to apply the
same footerKeyboardOffset handling used by the composer/footer layout, so the
Pressable stays aligned with the lifted composer when the keyboard is open.
♻️ Duplicate comments (1)
hooks/useAIInsightReport.ts (1)

539-545: 🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win

Fail closed when snapshot hashes are unavailable.

moodLogCount/moodLogIds are computed but only affect staleness through snapshotHash. For legacy reports with no sourceSnapshotHash, or while local hashing is unavailable, mood-log-only changes with older updatedAt can still fall through as fresh.

Proposed fix
-  if (
-    report.sourceSnapshotHash.trim() &&
-    localSource.snapshotHash &&
-    report.sourceSnapshotHash !== localSource.snapshotHash
-  ) {
-    return true;
-  }
+  const reportSnapshotHash = report.sourceSnapshotHash.trim();
+
+  if (reportSnapshotHash) {
+    if (!localSource.snapshotHash) {
+      return true;
+    }
+
+    if (reportSnapshotHash !== localSource.snapshotHash) {
+      return true;
+    }
+  } else if (localSource.moodLogCount > 0) {
+    return true;
+  }
🤖 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 `@hooks/useAIInsightReport.ts` around lines 539 - 545, The staleness check in
useAIInsightReport should fail closed when snapshot hashes are missing, because
the current compare only uses report.sourceSnapshotHash and
localSource.snapshotHash. Update the freshness logic around the source snapshot
comparison to treat legacy reports with no sourceSnapshotHash, or cases where
local hashing is unavailable, as stale when moodLogCount or moodLogIds could
have changed. Use the existing report, localSource, moodLogCount, and moodLogIds
values in this guard so the report is not considered fresh unless hash-based
validation is actually possible.
🤖 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 `@AGENTS.md`:
- Line 284: Fix the pronoun mismatch in the SVG guidance by updating the
instruction in AGENTS.md to use a plural reference for missing SVGs; the
sentence currently says “we don't have it” after referring to multiple SVGs.
Change that wording to “we don't have them” so the guidance stays consistent and
clear.

---

Outside diff comments:
In `@components/ai-chat/ai-chat-screen.tsx`:
- Around line 506-518: The jump-to-latest container in ai-chat-screen.tsx is not
using the same keyboard offset as the composer, so it can մն stay fixed while
the footer moves. Update the conditional View that renders when showJumpToLatest
is true to apply the same footerKeyboardOffset handling used by the
composer/footer layout, so the Pressable stays aligned with the lifted composer
when the keyboard is open.

---

Duplicate comments:
In `@hooks/useAIInsightReport.ts`:
- Around line 539-545: The staleness check in useAIInsightReport should fail
closed when snapshot hashes are missing, because the current compare only uses
report.sourceSnapshotHash and localSource.snapshotHash. Update the freshness
logic around the source snapshot comparison to treat legacy reports with no
sourceSnapshotHash, or cases where local hashing is unavailable, as stale when
moodLogCount or moodLogIds could have changed. Use the existing report,
localSource, moodLogCount, and moodLogIds values in this guard so the report is
not considered fresh unless hash-based validation is actually possible.
🪄 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: Repository UI

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: c49eca05-5acf-4a5c-9a1f-c0ba808e6439

📥 Commits

Reviewing files that changed from the base of the PR and between 58d8bd2 and 48c3c5b.

📒 Files selected for processing (13)
  • AGENTS.md
  • components/ai-chat/ai-chat-screen.tsx
  • components/ai/ai-response-renderer.tsx
  • components/auth/auth-screen.tsx
  • components/insights/insights-screen.tsx
  • components/insights/report/ReportNarrativeBlocks.tsx
  • hooks/useAIInsightReport.ts
  • lib/text/parse-ai-markdown.ts
  • store/useChatStore.ts
  • supabase/functions/journal-ai-chat/index.ts
  • supabase/functions/reflect-on-entry/index.ts
  • tests/ai-text-rendering.test.ts
  • tests/report-analytics.test.ts

Comment thread AGENTS.md
@aryansoni-dev aryansoni-dev merged commit 103fd87 into main Jul 1, 2026
1 check passed
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.

1 participant