Skip to content

Conversation

@coodos
Copy link
Contributor

@coodos coodos commented Jan 20, 2026

Description of change

Wishlist Summarization Flow

Current System Architecture

flowchart TD
    A[User Creates/Updates Wishlist] --> B[Raw Content Stored]
    B --> C[WishlistSummaryService.summarizeWishlistContent]
    C --> D[AI Request: Generate Arrays]
    D --> E{AI Response}
    E -->|Success| F[Parse JSON Arrays]
    E -->|Failure| G[Fallback: Extract from Markdown]
    F --> H["summaryWants: string array"]
    F --> I["summaryOffers: string array"]
    G --> H
    G --> I
    H --> J[Save to DB as jsonb]
    I --> J
    
    K[Platform Startup] --> L[summarizeAllWishlists]
    L --> M[Load All Active Wishlists]
    M --> N[For Each Wishlist]
    N --> C
    N --> O[Log Raw Content + Summary Arrays]
    O --> P[Save to Database]
    
    Q[Matching Process] --> R[Load Wishlists with Summaries]
    R --> S{Has Valid Arrays?}
    S -->|No| T[Skip Wishlist]
    S -->|Yes| U[Join Arrays with Semicolons]
    U --> V[Create CSV Format]
    V --> W["userId|userEname|userName|wants|offers"]
    W --> X[Send to AI Matching]
    X --> Y[Generate Matches]
Loading

Issue Number

closes #642
closes #644

Type of change

  • Update (a change which updates existing functionality)

How the change has been tested

Change checklist

  • I have ensured that the CI Checks pass locally
  • I have removed any unnecessary logic
  • My code is well documented
  • I have signed my commits
  • My code follows the pattern of the application
  • I have self reviewed my code

Summary by CodeRabbit

  • New Features

    • Wishlist summaries now store multiple items per category and a new operation to summarize all wishlists.
  • Bug Fixes

    • Improved matching accuracy with stricter validation and filtering to exclude incomplete or templated wishlists.
    • More robust summarization handling and safer error paths during processing.
  • Chores

    • Data migration to convert summary storage to structured arrays and a new migration script to assist migration.
    • Minor repository ignore and formatting cleanup.

✏️ Tip: You can customize this high-level summary in your review settings.

@coderabbitai
Copy link
Contributor

coderabbitai bot commented Jan 20, 2026

Warning

Rate limit exceeded

@coodos has exceeded the limit for the number of commits that can be reviewed per hour. Please wait 15 minutes and 6 seconds before requesting another review.

⌛ How to resolve this issue?

After the wait time has elapsed, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

We recommend that you space out your commits to avoid hitting the rate limit.

🚦 How do rate limits work?

CodeRabbit enforces hourly rate limits for each developer per organization.

Our paid plans have higher rate limits than the trial, open-source and free plans. In all cases, we re-allow further reviews after a brief timeout.

Please see our FAQ for further information.

📥 Commits

Reviewing files that changed from the base of the PR and between a01e4d6 and 41a6292.

📒 Files selected for processing (2)
  • platforms/dreamsync-api/src/services/MatchingService.ts
  • platforms/dreamsync-api/src/services/WishlistSummaryService.ts
📝 Walkthrough

Walkthrough

The PR migrates wishlist summaries from single strings to JSON arrays, updates summarization and matching services to operate on arrays with stricter validation (confidence > 0.85), adds a TypeORM migration and a standalone migration script to populate new fields, and includes minor docs and gitignore cleanups.

Changes

Cohort / File(s) Summary
Entity & Schema
platforms/dreamsync-api/src/database/entities/Wishlist.ts, platforms/dreamsync-api/src/database/migrations/1768904445609-migration.ts
Changed summaryWants/summaryOffers types from text/string to jsonb/string[]; added migration to convert columns (up/down implemented).
Summarization Service & Script
platforms/dreamsync-api/src/services/WishlistSummaryService.ts, platforms/dreamsync-api/scripts/migrate-summaries.ts
Summary output changed to arrays (string[]); added summarizeAllWishlists() and array-oriented parsing/validation; new CLI migration script to generate/persist array summaries across wishlists with logging and error tracking.
Matching Logic
platforms/dreamsync-api/src/services/MatchingService.ts, platforms/dreamsync-api/src/services/SharedMatchingService.ts, platforms/dreamsync-api/src/services/AIMatchingService.ts
Updated to consume array-based summaries; filter out wishlists without non-empty arrays; increased AI confidence threshold from 0.7 → 0.85; updated prompts, parsing, and diagnostic logs.
Platform Init & Scripts
platforms/dreamsync-api/src/index.ts, platforms/dreamsync-api/package.json
Replaced backfillMissingSummaries() call with summarizeAllWishlists() on startup; added migrate-summaries npm script; minor logging text changes.
Misc / Cleanup
docs/src/pages/index.tsx, mappings/.gitignore, .gitignore
Removed stray useHistory expression and extra blank lines; mappings/.gitignore cleared of rules; added .docusaurus to top-level .gitignore.

Sequence Diagram(s)

mermaid
sequenceDiagram
actor CLI
participant Script as "migrate-summaries.ts"
participant DB as "Database (TypeORM)"
participant Service as "WishlistSummaryService"
participant OpenAI as "AI provider"
CLI->>Script: run migrate-summaries
Script->>DB: connect / fetch active wishlists (+users)
Script->>Service: ensure summaries for each wishlist
Service->>OpenAI: request summary (wants/offers arrays)
OpenAI-->>Service: return JSON arrays
Service->>DB: persist summaryWants/summaryOffers (jsonb)
Script->>DB: close connection
Script-->>CLI: exit (0 / 1)

Estimated code review effort

🎯 4 (Complex) | ⏱️ ~45 minutes

Possibly related PRs

  • Docs/bootstrap docusaurus #688 — touches same docs page (docs/src/pages/index.tsx) and may overlap the small cleanup there.
  • Feat/dreamsync #367 — similar API-level changes to wishlist summaries, migrations, and matching logic; likely closely related.

Suggested reviewers

  • sosweetham

Poem

🐰 From single strings to arrays I leap,
I tidy summaries while you sleep.
I raise the bar so matches are true,
Skip the blanks, keep the helpful few.
Hop—migrations run, and data blooms anew.

🚥 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 Title 'Fix/dreamsync recommendations' is vague and generic; it lacks specificity about the actual changes made to the codebase. Provide a more descriptive title that clearly conveys the main change, such as 'Convert wishlist summaries from strings to arrays and enforce validation'.
✅ Passed checks (3 passed)
Check name Status Explanation
Description check ✅ Passed The description is mostly complete with a clear mermaid diagram explaining the flow, linked issues, and type of change identified. However, 'How the change has been tested' section is empty.
Linked Issues check ✅ Passed The PR implements changes that directly address both linked issues: higher confidence threshold (>0.85 instead of >0.7) for matches [#642], filtering out wishlists without valid arrays [#644], and database schema changes from text to jsonb arrays.
Out of Scope Changes check ✅ Passed Minor cleanup changes to docs/src/pages/index.tsx and .gitignore are incidental; all substantial changes directly relate to wishlist summarization, array-based storage, and matching validation.

✏️ Tip: You can configure your own custom pre-merge checks in the settings.


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 and usage tips.

@coodos coodos force-pushed the fix/dreamsync-recommendations branch from 2fec9ff to 6d7c819 Compare January 20, 2026 10:30
Copy link
Contributor

@coderabbitai coderabbitai bot left a comment

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)
platforms/dreamsync-api/src/services/WishlistSummaryService.ts (1)

96-101: Logic issue: Wishlists with legitimately empty offers/wants get re-processed.

The condition requires both summaryWants.length > 0 AND summaryOffers.length > 0. If a user genuinely has no offers (e.g., only wants things), this wishlist will be re-summarized on every call to ensureSummaries, even though the summary was already computed correctly.

Consider checking for the presence of the arrays (not their length) or accepting that empty arrays are valid summaries:

🐛 Proposed fix
     async ensureSummaries(wishlist: Wishlist): Promise<Wishlist> {
-        if (wishlist.summaryWants && wishlist.summaryWants.length > 0 && 
-            wishlist.summaryOffers && wishlist.summaryOffers.length > 0) {
+        // Arrays exist (even if empty) means summary was already generated
+        if (Array.isArray(wishlist.summaryWants) && Array.isArray(wishlist.summaryOffers)) {
             return wishlist;
         }
         return this.summarizeAndPersist(wishlist);
     }
🤖 Fix all issues with AI agents
In `@platforms/dreamsync-api/src/database/migrations/1768904445609-migration.ts`:
- Around line 6-11: The migration currently drops and re-adds summaryWants and
summaryOffers which destroys existing data; update the up(queryRunner:
QueryRunner) implementation to convert in-place instead of DROP/ADD by using
ALTER TABLE "wishlists" ALTER COLUMN "<column>" TYPE jsonb USING
to_json("<column>")::jsonb for both summaryWants and summaryOffers (remove the
DROP and ADD statements), so existing text summaries are preserved and cast to
jsonb; if deletion was intentional, add a clear comment and ensure the
migrate-summaries.ts runs immediately after deployment instead of changing the
migration.
🧹 Nitpick comments (4)
platforms/dreamsync-api/src/services/WishlistSummaryService.ts (1)

135-174: Performance concern: Re-summarizing all wishlists on every platform start is expensive.

This method makes an OpenAI API call for every active wishlist on each platform restart. With N wishlists, this incurs N API calls (cost, latency, rate limits) even if summaries already exist.

Consider either:

  1. Checking if summaries already exist before calling OpenAI (like the migration script does)
  2. Making this opt-in via environment variable or CLI flag
  3. Using backfillMissingSummaries() for startup instead
♻️ Proposed optimization
         for (const wishlist of allWishlists) {
             try {
+                // Skip if already has valid array summaries
+                if (Array.isArray(wishlist.summaryWants) && Array.isArray(wishlist.summaryOffers)) {
+                    console.log(`[${wishlist.id}] Already has summaries, skipping`);
+                    continue;
+                }
+
                 const summary = await this.summarizeWishlistContent(wishlist.content);
platforms/dreamsync-api/scripts/migrate-summaries.ts (2)

35-68: Consider adding rate limiting for large datasets.

The migration script processes wishlists sequentially without delays. For large datasets, this could trigger OpenAI rate limits. Consider adding a small delay between API calls:

♻️ Optional: Add rate limiting
+const delay = (ms: number) => new Promise(resolve => setTimeout(resolve, ms));
+
         for (const wishlist of wishlists) {
             try {
                 // ... existing code ...

                 console.log(`  Saved successfully\n`);
                 processedCount++;
+                
+                // Small delay to avoid rate limits
+                await delay(200);

             } catch (error) {

23-27: Minor: Unused user relation.

The query loads relations: ["user"] but the user data is never used in the migration logic. Consider removing it to reduce query overhead.

♻️ Proposed cleanup
         const wishlists = await wishlistRepository.find({
             where: { isActive: true },
-            relations: ["user"],
             order: { updatedAt: "DESC" },
         });
platforms/dreamsync-api/src/services/AIMatchingService.ts (1)

396-429: Inconsistency: Uses raw content instead of summary arrays.

This prompt uses wishlist.content (raw text) while SharedMatchingService.buildAnalysisPrompt uses the structured summaryWants/summaryOffers arrays. This inconsistency could lead to different matching behavior depending on which code path is used.

Consider aligning this method to use the array-based summaries for consistency:

♻️ Suggested alignment with SharedMatchingService
 private buildAnalysisPrompt(wishlistA: Wishlist, wishlistB: Wishlist): string {
+    const wantsA = (wishlistA.summaryWants || []).join(', ');
+    const offersA = (wishlistA.summaryOffers || []).join(', ');
+    const wantsB = (wishlistB.summaryWants || []).join(', ');
+    const offersB = (wishlistB.summaryOffers || []).join(', ');
+    
     return `
 Analyze these two wishlists to determine if there's a meaningful connection:
 
 **User A (${wishlistA.user.ename}):**
-Title: ${wishlistA.title}
-Content: ${wishlistA.content}
+Wants: ${wantsA || 'None specified'}
+Offers: ${offersA || 'None specified'}
 
 **User B (${wishlistB.user.ename}):**
-Title: ${wishlistB.title}
-Content: ${wishlistB.content}
+Wants: ${wantsB || 'None specified'}
+Offers: ${offersB || 'None specified'}

Comment on lines +6 to +11
public async up(queryRunner: QueryRunner): Promise<void> {
await queryRunner.query(`ALTER TABLE "wishlists" DROP COLUMN "summaryWants"`);
await queryRunner.query(`ALTER TABLE "wishlists" ADD "summaryWants" jsonb`);
await queryRunner.query(`ALTER TABLE "wishlists" DROP COLUMN "summaryOffers"`);
await queryRunner.query(`ALTER TABLE "wishlists" ADD "summaryOffers" jsonb`);
}
Copy link
Contributor

@coderabbitai coderabbitai bot Jan 20, 2026

Choose a reason for hiding this comment

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

⚠️ Potential issue | 🔴 Critical

Data loss risk: Dropping columns destroys existing summaries.

The migration drops summaryWants and summaryOffers columns before re-adding them as jsonb. Any existing text summaries in production will be permanently lost. The migrate-summaries.ts script cannot help because it runs after the migration has already deleted the data.

Consider using ALTER COLUMN ... TYPE jsonb USING to preserve and convert existing data:

🐛 Proposed fix to preserve existing data
     public async up(queryRunner: QueryRunner): Promise<void> {
-        await queryRunner.query(`ALTER TABLE "wishlists" DROP COLUMN "summaryWants"`);
-        await queryRunner.query(`ALTER TABLE "wishlists" ADD "summaryWants" jsonb`);
-        await queryRunner.query(`ALTER TABLE "wishlists" DROP COLUMN "summaryOffers"`);
-        await queryRunner.query(`ALTER TABLE "wishlists" ADD "summaryOffers" jsonb`);
+        // Convert existing text to jsonb arrays, wrapping single strings in arrays
+        await queryRunner.query(`
+            ALTER TABLE "wishlists" 
+            ALTER COLUMN "summaryWants" TYPE jsonb 
+            USING CASE 
+                WHEN "summaryWants" IS NULL THEN NULL
+                ELSE to_jsonb(ARRAY["summaryWants"])
+            END
+        `);
+        await queryRunner.query(`
+            ALTER TABLE "wishlists" 
+            ALTER COLUMN "summaryOffers" TYPE jsonb 
+            USING CASE 
+                WHEN "summaryOffers" IS NULL THEN NULL
+                ELSE to_jsonb(ARRAY["summaryOffers"])
+            END
+        `);
     }

Alternatively, if re-generating all summaries is intentional, document this clearly and ensure the migration script runs immediately after on deployment.

🤖 Prompt for AI Agents
In `@platforms/dreamsync-api/src/database/migrations/1768904445609-migration.ts`
around lines 6 - 11, The migration currently drops and re-adds summaryWants and
summaryOffers which destroys existing data; update the up(queryRunner:
QueryRunner) implementation to convert in-place instead of DROP/ADD by using
ALTER TABLE "wishlists" ALTER COLUMN "<column>" TYPE jsonb USING
to_json("<column>")::jsonb for both summaryWants and summaryOffers (remove the
DROP and ADD statements), so existing text summaries are preserved and cast to
jsonb; if deletion was intentional, add a clear comment and ensure the
migrate-summaries.ts runs immediately after deployment instead of changing the
migration.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

nack this data is essentially platform level logic which can be discarded and is not important, the only truly important thing is keeping the actual wishlist safe

Copy link
Contributor

Choose a reason for hiding this comment

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

@coodos, understood! Since summaryWants and summaryOffers are derived from the wishlist content and can be regenerated via the migrate-summaries.ts script, dropping them is safe. The source data remains intact. Thanks for the clarification.


✏️ Learnings added
Learnt from: coodos
Repo: MetaState-Prototype-Project/prototype PR: 691
File: platforms/dreamsync-api/src/database/migrations/1768904445609-migration.ts:6-11
Timestamp: 2026-01-20T10:41:46.622Z
Learning: In the DreamSync platform (platforms/dreamsync-api), the `summaryWants` and `summaryOffers` fields in the Wishlist entity are derived/computed data that can be safely discarded and regenerated from the wishlist content. Only the actual wishlist content is considered critical data that must be preserved.

Note: Learnings are effective only in the context of similar code segments. To apply general coding guidelines, please configure review instructions. You can manage existing learnings in the app.

@coodos coodos force-pushed the fix/dreamsync-recommendations branch from 6d7c819 to 2fec9ff Compare January 20, 2026 10:35
@coodos coodos force-pushed the fix/dreamsync-recommendations branch from 2fec9ff to 4e92c08 Compare January 20, 2026 10:40
@coodos coodos force-pushed the fix/dreamsync-recommendations branch from 998f088 to 344b9da Compare January 20, 2026 10:42
@coodos coodos force-pushed the fix/dreamsync-recommendations branch from aabae04 to 41a6292 Compare January 20, 2026 11:12
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.

[Bug] DreamSync generates recommendations for empty wishlist [Bug] DreamSync sends irrelevant recommendations

2 participants