Skip to content

feat(store,api): preview + number on conversation summaries (HT-27) - #26

Merged
zaridan merged 1 commit into
mainfrom
feat/ht-27-preview-number
Jul 12, 2026
Merged

feat(store,api): preview + number on conversation summaries (HT-27)#26
zaridan merged 1 commit into
mainfrom
feat/ht-27-preview-number

Conversation

@zaridan

@zaridan zaridan commented Jul 12, 2026

Copy link
Copy Markdown
Contributor

Why

Second v1.1 increment (HT-27) — the inbox-row fields the designed UI renders: a human-facing #number and a one-line preview excerpt. Spec: agent-inbox-v1.md §2 (v1.1, merged in #24).

What

Migration 005 — number

  • ADD COLUMN (nullable) → backfill existing rows in (created_at, id) order via row_number()CREATE SEQUENCE + setval(max+1, false) → only then DEFAULT nextval(...), NOT NULL, UNIQUE.
  • The nextval DEFAULT binds the sequence's OID at ALTER time, so the HT-20 schema option is honored.
  • Display-only by contract: every path parameter remains the uuid.

preview — derived, never stored

  • SQL selects the most recent thread with non-null body_text (any direction, notes-ready); derivePreview() does the whitespace collapse + 120-char cap in TS.
  • Exported once from the store; the detail handler applies the identical rule to threads it already holds — one definition, no drift between list and detail.
  • setConversationStatus's RETURNING carries both fields so PATCH responses stay complete summaries.

Evidence

  • 350/350 tests pass; 9 new: migration-005 upgrade path (rows inserted out of order get numbered by creation time; a fresh insert continues at max+1), fresh-install numbering + UNIQUE rejection, preview derivation edge cases (html-only latest thread falls back to older text; whitespace collapse; exact 120 cap; '' when textless), and wire-shape assertions on list + detail.
  • Typecheck + Biome clean. No mail-path changes.

🤖 Generated with Claude Code

Summary by CodeRabbit

  • New Features

    • Added sequential conversation numbers to conversation lists and details.
    • Added conversation previews based on the latest available message text.
    • Previews normalize whitespace and are limited to 120 characters.
    • HTML-only messages fall back to the most recent available text.
  • Bug Fixes

    • Conversation numbers and previews now remain consistent across status updates and API responses.
    • Existing conversations receive numbers automatically during database upgrades.

Migration 005 adds the human-facing sequential number: nullable ADD
COLUMN, backfill in (created_at, id) order via row_number(), a dedicated
sequence setval'd past the backfill, then DEFAULT/NOT NULL/UNIQUE —
the 002/004 backfill-before-constraint discipline. The uuid stays the
only accepted identifier; number is display-only.

preview is derived, not stored: SQL picks the most recent thread with
non-null body_text (any direction); derivePreview() collapses
whitespace and caps at 120 chars, '' when no thread has text. The API
detail handler applies the same exported rule to the threads it
already holds, so list and detail can never drift.

Per specs/api/agent-inbox-v1.md §2 (v1.1, HT-25). 350/350 tests,
including the migration-005 upgrade path over a seeded pre-005
database (out-of-order inserts numbered by creation time; sequence
continues at max+1) and preview edge cases (html-only fallback,
collapse, cap, empty).

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
@coderabbitai

coderabbitai Bot commented Jul 12, 2026

Copy link
Copy Markdown

Review Change Stack

📝 Walkthrough

Walkthrough

Adds sequential conversation numbers and normalized previews derived from thread text across the database migration, conversation store, and API list/detail responses, with coverage for backfills, uniqueness, fallback behavior, truncation, and status updates.

Changes

Conversation summary fields

Layer / File(s) Summary
Conversation number migration
src/db/migrate.ts, src/db/migrate.test.ts
Migration 005 adds and backfills unique sequential conversation numbers, configures the sequence, and validates upgrade, fresh-install, continuation, and uniqueness behavior.
Store summary derivation
src/store/conversations.ts, src/store/conversations.test.ts
Conversation read models and queries return numbers and latest eligible thread text; previews normalize whitespace, truncate to 120 characters, and fall back when text is unavailable.
API response mapping
src/api/conversations.ts, src/api/index.test.ts
List and detail responses expose conversation numbers and previews, including detail fallback behavior for HTML-only latest threads.

Estimated code review effort: 3 (Moderate) | ~25 minutes

Possibly related PRs

Sequence Diagram(s)

sequenceDiagram
  participant Client
  participant ConversationAPI
  participant ConversationStore
  participant PostgreSQL
  Client->>ConversationAPI: Request conversation summaries
  ConversationAPI->>ConversationStore: listConversations()
  ConversationStore->>PostgreSQL: Select number and latest body text
  PostgreSQL-->>ConversationStore: Return summary rows
  ConversationStore-->>ConversationAPI: Return normalized summaries
  ConversationAPI-->>Client: Return number and preview
Loading
🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 71.43% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (4 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title clearly summarizes the main change: adding preview and number fields to conversation summaries in the store and API.
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 feat/ht-27-preview-number

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.

🧹 Nitpick comments (2)
src/db/migrate.ts (1)

232-239: 🚀 Performance & Scalability | 🔵 Trivial

Consider lock duration on large production tables.

ADD COLUMN, backfill UPDATE, SET NOT NULL, and ADD CONSTRAINT UNIQUE each take an ACCESS EXCLUSIVE lock and/or full table scan on conversations, blocking reads/writes for the duration. Fine for the test-scale fixtures here, but worth confirming this migration's runtime is acceptable against the largest expected conversations table size before deploying to a live environment with real traffic.

🤖 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 `@src/db/migrate.ts` around lines 232 - 239, Review the migration block that
adds and backfills conversations.number for production-scale tables, and
redesign or sequence the ALTER TABLE, UPDATE, SET NOT NULL, and UNIQUE
constraint steps to minimize blocking and full-table lock duration. Preserve the
existing row-number backfill, sequence default, non-null requirement, and
uniqueness guarantees while ensuring the migration runtime is acceptable for the
largest expected conversations table.
src/store/conversations.ts (1)

781-781: 🚀 Performance & Scalability | 🔵 Trivial

Add a partial index for latest_body_text. threads_conversation_id_idx already covers thread_count, but the ORDER BY t.created_at DESC, t.id DESC LIMIT 1 lookup still has to sort per conversation. Add threads (conversation_id, created_at DESC, id DESC) WHERE body_text IS NOT NULL so the preview query stays cheap.

🤖 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 `@src/store/conversations.ts` at line 781, Add a partial index for the threads
lookup used by LATEST_BODY_TEXT_SUBQUERY, covering conversation_id, created_at
DESC, and id DESC, with a WHERE body_text IS NOT NULL predicate. Preserve the
existing thread_count index and ensure the new index supports the ORDER BY and
LIMIT 1 access pattern.
🤖 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.

Nitpick comments:
In `@src/db/migrate.ts`:
- Around line 232-239: Review the migration block that adds and backfills
conversations.number for production-scale tables, and redesign or sequence the
ALTER TABLE, UPDATE, SET NOT NULL, and UNIQUE constraint steps to minimize
blocking and full-table lock duration. Preserve the existing row-number
backfill, sequence default, non-null requirement, and uniqueness guarantees
while ensuring the migration runtime is acceptable for the largest expected
conversations table.

In `@src/store/conversations.ts`:
- Line 781: Add a partial index for the threads lookup used by
LATEST_BODY_TEXT_SUBQUERY, covering conversation_id, created_at DESC, and id
DESC, with a WHERE body_text IS NOT NULL predicate. Preserve the existing
thread_count index and ensure the new index supports the ORDER BY and LIMIT 1
access pattern.

ℹ️ Review info
⚙️ Run configuration

Configuration used: defaults

Review profile: CHILL

Plan: Pro Plus

Run ID: 0201322e-64f5-4dab-b6f3-cf9040723e10

📥 Commits

Reviewing files that changed from the base of the PR and between 127af9d and 981ea0a.

📒 Files selected for processing (6)
  • src/api/conversations.ts
  • src/api/index.test.ts
  • src/db/migrate.test.ts
  • src/db/migrate.ts
  • src/store/conversations.test.ts
  • src/store/conversations.ts

@zaridan
zaridan merged commit c1b14b3 into main Jul 12, 2026
5 checks passed
@zaridan
zaridan deleted the feat/ht-27-preview-number branch August 2, 2026 19:19
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