Skip to content

fix(assistant): complete PR3 conversation history#57

Merged
kl3inIT merged 4 commits into
mainfrom
kl3inIT/asset-registry-pr3-assistant-web
Jul 25, 2026
Merged

fix(assistant): complete PR3 conversation history#57
kl3inIT merged 4 commits into
mainfrom
kl3inIT/asset-registry-pr3-assistant-web

Conversation

@kl3inIT

@kl3inIT kl3inIT commented Jul 25, 2026

Copy link
Copy Markdown
Owner

What changed

  • adds tenant/user-owned assistant conversations with list, replay, inline rename, and confirmed delete
  • keeps a bounded Spring AI message window for normal multi-turn context while retrieving fresh authorized evidence on every turn
  • moves current evidence and safe display-name/role personalization into the current system message
  • simplifies direct feedback submission so explicit user clicks do not require a redundant second confirmation
  • records the Onyx-derived history patterns and the pragmatic retention/authorization boundary in the active increment and domain specs
  • adds forward-only Flyway migration V6; merged V5 remains unchanged

Why

PR #56 shipped the assistant Asset workspace, but its original memory conclusion was too strict and the history experience was incomplete. This follow-up finishes PR3 without adding a rare-case purge/re-authorization pipeline or expanding into PR4 MCP work.

Validation

  • ./gradlew.bat --no-daemon clean test — passed, 97 tasks
  • corepack pnpm -C web build — passed (Oxlint, TypeScript, Vite production build)
  • migration/package/zero-byte checks and git diff --check — passed
  • Spring AI 2.0.0 JDBC memory schema verified against the dependency source

Impact

The Assistant now supports practical, URL-addressable conversation history and normal bounded multi-turn context. Existing tenant, actor, retrieval, citation, and permission checks remain authoritative.

Summary by CodeRabbit

  • New Features

    • Added persistent assistant conversations with automatic titles and message history.
    • Browse recent conversations, start new ones, replay history, rename titles, and delete transcripts from the sidebar.
    • Active conversations are preserved when navigating or refreshing, with loading and error states for history.
    • Assistant responses can use conversation context and personalized user information.
  • Bug Fixes

    • Feedback can now be submitted directly without an extra confirmation step.
    • Improved handling of unavailable conversations with consistent error responses.

@coderabbitai

coderabbitai Bot commented Jul 25, 2026

Copy link
Copy Markdown

Review Change Stack

Warning

Review limit reached

@kl3inIT, you've reached your PR review limit, so we couldn't start this review.

Next review available in: 28 minutes

Enable usage-based reviews in Billing to review now. Otherwise, wait until the next included review is available.
You're only billed for reviews past your plan's rate limits ($0.25/file).

How can I continue?

After more reviews become available, a review can be triggered using the @coderabbitai review command as a PR comment. Alternatively, push new commits to this PR.

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 reviews.

How do review limits work?

CodeRabbit enforces per-developer PR review limits for each organization. Most developers receive the normal plan review availability.

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, additional reviews become available more gradually as earlier reviews age out of the rolling window.

Please refer docs for additional details.

Review details
⚙️ Run configuration

Configuration used: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: 59c4a06c-3ad6-4fb6-9b68-4795acc80ee2

📥 Commits

Reviewing files that changed from the base of the PR and between d1dc235 and bc9786b.

⛔ Files ignored due to path filters (3)
  • contracts/openapi.json is excluded by !contracts/openapi.json
  • docs/increments/active/2026-07-25-unified-asset-registry-definition/design.md is excluded by !docs/**
  • docs/increments/active/2026-07-25-unified-asset-registry-definition/plan.md is excluded by !docs/**
📒 Files selected for processing (11)
  • apps/api/src/main/java/com/orgmemory/api/ApiExceptionHandler.java
  • apps/api/src/main/java/com/orgmemory/api/assistant/AssistantController.java
  • apps/api/src/test/java/com/orgmemory/api/ApiExceptionHandlerTests.java
  • apps/api/src/test/java/com/orgmemory/api/assistant/AssistantControllerStreamingTests.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversationMessageRepository.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversationService.java
  • core/src/main/resources/db/migration/V6__assistant_conversation_history.sql
  • core/src/test/java/com/orgmemory/core/assistant/AssistantConversationServiceTests.java
  • web/src/features/assistant/components/assistant-conversation-list.tsx
  • web/src/features/assistant/components/assistant-page.tsx
  • web/test/e2e/assistant-pipeline.spec.ts
📝 Walkthrough

Walkthrough

Adds persisted assistant conversation history with JDBC-backed chat memory, conversation lifecycle APIs, actor-scoped web history and navigation, prompt user context and XML escaping, and direct asset feedback submission.

Changes

Assistant conversations

Layer / File(s) Summary
Conversation persistence and lifecycle
core/src/main/java/com/orgmemory/core/assistant/*, core/src/main/resources/db/migration/V6__assistant_conversation_history.sql, core/src/test/java/com/orgmemory/core/assistant/AssistantConversationServiceTests.java
Adds conversation/message entities, repositories, ownership enforcement, lifecycle operations, database tables, and service tests.
Memory-backed assistant streaming
apps/api/build.gradle.kts, apps/api/src/main/java/com/orgmemory/api/assistant/AssistantConfiguration.java, core/src/main/java/com/orgmemory/core/assistant/AssistantPromptFactory.java, core/src/main/java/com/orgmemory/core/assistant/AssistantService.java, integrations/ai-openai-compatible/..., core/src/test/java/com/orgmemory/core/assistant/AssistantServiceTests.java
Threads conversation IDs through streaming, configures JDBC chat memory, adds actor-aware XML prompts, and updates streaming and prompt assertions.
Conversation API integration
apps/api/src/main/java/com/orgmemory/api/assistant/AssistantChatRequest.java, apps/api/src/main/java/com/orgmemory/api/assistant/AssistantController.java, apps/api/src/main/java/com/orgmemory/api/ApiExceptionHandler.java, apps/api/src/test/java/com/orgmemory/api/assistant/AssistantControllerStreamingTests.java
Adds conversation-aware requests, streaming completion persistence, list/history/rename/delete endpoints, and not-found handling.
Web conversation navigation and history
web/src/features/assistant/*, web/src/routes/_authenticated/index.tsx, web/src/components/app-shell/app-sidebar.tsx, web/src/features/session/actor-cache-key.ts, web/src/features/assets/actor-key.ts
Adds actor-scoped queries, conversation history loading, sidebar rename/delete controls, route-based conversation IDs, and response-header synchronization.

Asset feedback submission

Layer / File(s) Summary
Immediate feedback submission
web/src/features/assets/components/asset-detail-page.tsx
Replaces confirmation-based feedback submission with an immediate button mutation and pending-state label.

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

Sequence Diagram(s)

sequenceDiagram
  participant User
  participant AssistantPage
  participant AssistantController
  participant AssistantConversationService
  participant SpringAiChatModelAdapter
  User->>AssistantPage: Send message
  AssistantPage->>AssistantController: POST message with conversationId
  AssistantController->>AssistantConversationService: Begin user turn
  AssistantController->>SpringAiChatModelAdapter: Stream assistant response
  SpringAiChatModelAdapter-->>AssistantPage: Response chunks and conversation ID
  AssistantController->>AssistantConversationService: Complete assistant turn
Loading

Possibly related PRs

🚥 Pre-merge checks | ✅ 4 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 1.30% 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 matches the main change: completing assistant conversation history support.
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 unit tests (beta)
  • Create PR with unit tests
  • Commit unit tests in branch kl3inIT/asset-registry-pr3-assistant-web

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: 7

🤖 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 `@apps/api/src/main/java/com/orgmemory/api/assistant/AssistantController.java`:
- Around line 139-151: Update AssistantController.delete so conversations.delete
executes before memory.clear, ensuring chat memory is cleared only after the
transcript deletion succeeds. Replace the redundant conversations.requireAccess
pre-check with the existing ownership enforcement in conversations.delete, while
preserving actor and conversationId handling.

In
`@core/src/main/java/com/orgmemory/core/assistant/AssistantConversationService.java`:
- Around line 69-81: Update AssistantConversationService.list to eliminate the
per-conversation messages.countByConversationId call by loading message counts
for all returned conversation IDs in one repository query, then map those counts
when constructing AssistantConversationSummary and default missing IDs to zero.

In `@core/src/main/resources/db/migration/V6__assistant_conversation_history.sql`:
- Around line 41-65: Update the assistant_conversation_messages definition and
its parent conversation key constraints to add a composite foreign key tying
conversation_id and organization_id to the corresponding assistant_conversations
columns, while preserving the existing conversation_id cascade behavior. Ensure
the referenced parent columns have a matching primary or unique constraint and
retain the actor-user tenant foreign key.

In `@web/src/features/assistant/components/assistant-conversation-list.tsx`:
- Around line 123-135: Update the empty-state condition in the conversation list
rendering near conversations.isError so the “Your recent conversations will
appear here” message is suppressed when an error exists. Preserve the
empty-state message for non-pending, non-error conversations with no visible
items.

In `@web/src/features/assistant/components/assistant-page.tsx`:
- Around line 350-372: Update the loading and error state containers in the
conversation history flow of the assistant page: add an appropriate live-region
status announcement to the loading block and an alert announcement to the error
block, matching the existing accessible turn-error banner pattern while
preserving their current content and behavior.
- Around line 350-372: Prevent stale messages from rendering during a
conversation switch by deriving a synchronous switching state from the current
conversationId and the conversation identity associated with messages, rather
than relying solely on the reset useEffect. Update the assistant-page render
guards around the existing history loading/error checks to show the loading
state while switching, while preserving normal rendering once messages belong to
the active conversation.
- Around line 221-244: The useChat onFinish callback should also invalidate the
actor-scoped conversation history query identified by
scopeActorQueryKey(historyOptions.queryKey, actorKey), not only
conversationListQueryKey. Update the completion flow in the component so the
current conversation history is invalidated or refetched after each completed
turn, preserving the existing list-cache invalidation.
🪄 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: Path: .coderabbit.yaml

Review profile: ASSERTIVE

Plan: Pro Plus

Run ID: e4046aec-8f25-4e64-ab16-35381d5a85fd

📥 Commits

Reviewing files that changed from the base of the PR and between d8f26a9 and d1dc235.

⛔ Files ignored due to path filters (6)
  • contracts/openapi.json is excluded by !contracts/openapi.json
  • docs/increments/active/2026-07-25-unified-asset-registry-definition/design.md is excluded by !docs/**
  • docs/increments/active/2026-07-25-unified-asset-registry-definition/plan.md is excluded by !docs/**
  • docs/increments/active/2026-07-25-unified-asset-registry-definition/ui-reference-audit.md is excluded by !docs/**
  • docs/specs/domains/assistant-and-mcp.md is excluded by !docs/**
  • docs/tests/domains/assistant-and-mcp.md is excluded by !docs/**
📒 Files selected for processing (33)
  • apps/api/build.gradle.kts
  • apps/api/src/main/java/com/orgmemory/api/ApiExceptionHandler.java
  • apps/api/src/main/java/com/orgmemory/api/assistant/AssistantChatRequest.java
  • apps/api/src/main/java/com/orgmemory/api/assistant/AssistantConfiguration.java
  • apps/api/src/main/java/com/orgmemory/api/assistant/AssistantController.java
  • apps/api/src/main/java/com/orgmemory/api/security/OidcCurrentActorProvider.java
  • apps/api/src/main/resources/application.yml
  • apps/api/src/test/java/com/orgmemory/api/assistant/AssistantControllerStreamingTests.java
  • core/src/main/java/com/orgmemory/core/ai/ChatModelPort.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversation.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversationMessage.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversationMessageRepository.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversationMessageView.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversationNotFoundException.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversationRepository.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversationRole.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversationService.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversationSummary.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantPromptFactory.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantService.java
  • core/src/main/java/com/orgmemory/core/organization/CurrentActor.java
  • core/src/main/resources/db/migration/V6__assistant_conversation_history.sql
  • core/src/test/java/com/orgmemory/core/assistant/AssistantConversationServiceTests.java
  • core/src/test/java/com/orgmemory/core/assistant/AssistantServiceTests.java
  • integrations/ai-openai-compatible/src/main/java/com/orgmemory/integrations/ai/openai/SpringAiChatModelAdapter.java
  • web/src/components/app-shell/app-sidebar.tsx
  • web/src/features/assets/actor-key.ts
  • web/src/features/assets/components/asset-detail-page.tsx
  • web/src/features/assistant/api/chat-transport.ts
  • web/src/features/assistant/components/assistant-conversation-list.tsx
  • web/src/features/assistant/components/assistant-page.tsx
  • web/src/features/session/actor-cache-key.ts
  • web/src/routes/_authenticated/index.tsx
📜 Review details
⏰ Context from checks skipped due to timeout. (3)
  • GitHub Check: Backend · Java 25
  • GitHub Check: PostgreSQL GraphRAG
  • GitHub Check: Web · Node 24
🧰 Additional context used
📓 Path-based instructions (7)
**/*

📄 CodeRabbit inference engine (CLAUDE.md)

**/*: Record current behavior in architecture/specification documentation only after it exists in code; keep intended behavior in vision, roadmap, or an active increment, and do not duplicate state.
Before using unfamiliar Spring Boot 4, Spring Modulith 2, Spring AI 2, Gradle, React, Vite, Tailwind, or TypeScript APIs, consult current official documentation via Context7 and the project orgmemory-* verification skills.
Before retrieval, AI, MCP, permission, upload, graph, or export work, read docs/guidelines/agent-safety.md.
Never commit .env files, provider keys, tokens, or customer data.
Run the relevant verification gates from docs/guidelines/testing-harness.md; use a terminating clean test as the context gate, and do not treat bootRun as verification.

Files:

  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversationRole.java
  • apps/api/build.gradle.kts
  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversationNotFoundException.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversationSummary.java
  • apps/api/src/main/resources/application.yml
  • web/src/features/session/actor-cache-key.ts
  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversationMessageView.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversationMessageRepository.java
  • web/src/features/assistant/api/chat-transport.ts
  • core/src/main/java/com/orgmemory/core/ai/ChatModelPort.java
  • apps/api/src/test/java/com/orgmemory/api/assistant/AssistantControllerStreamingTests.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversationRepository.java
  • web/src/features/assets/components/asset-detail-page.tsx
  • apps/api/src/main/java/com/orgmemory/api/assistant/AssistantConfiguration.java
  • web/src/routes/_authenticated/index.tsx
  • core/src/test/java/com/orgmemory/core/assistant/AssistantConversationServiceTests.java
  • web/src/components/app-shell/app-sidebar.tsx
  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversation.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversationMessage.java
  • core/src/main/resources/db/migration/V6__assistant_conversation_history.sql
  • apps/api/src/main/java/com/orgmemory/api/assistant/AssistantChatRequest.java
  • core/src/main/java/com/orgmemory/core/organization/CurrentActor.java
  • apps/api/src/main/java/com/orgmemory/api/security/OidcCurrentActorProvider.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantService.java
  • web/src/features/assets/actor-key.ts
  • integrations/ai-openai-compatible/src/main/java/com/orgmemory/integrations/ai/openai/SpringAiChatModelAdapter.java
  • apps/api/src/main/java/com/orgmemory/api/ApiExceptionHandler.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversationService.java
  • web/src/features/assistant/components/assistant-page.tsx
  • core/src/test/java/com/orgmemory/core/assistant/AssistantServiceTests.java
  • apps/api/src/main/java/com/orgmemory/api/assistant/AssistantController.java
  • web/src/features/assistant/components/assistant-conversation-list.tsx
  • core/src/main/java/com/orgmemory/core/assistant/AssistantPromptFactory.java
**/*.{java,kt}

📄 CodeRabbit inference engine (CLAUDE.md)

JetBrains IDE inspection is a verification gate for the Java backend.

Files:

  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversationRole.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversationNotFoundException.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversationSummary.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversationMessageView.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversationMessageRepository.java
  • core/src/main/java/com/orgmemory/core/ai/ChatModelPort.java
  • apps/api/src/test/java/com/orgmemory/api/assistant/AssistantControllerStreamingTests.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversationRepository.java
  • apps/api/src/main/java/com/orgmemory/api/assistant/AssistantConfiguration.java
  • core/src/test/java/com/orgmemory/core/assistant/AssistantConversationServiceTests.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversation.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversationMessage.java
  • apps/api/src/main/java/com/orgmemory/api/assistant/AssistantChatRequest.java
  • core/src/main/java/com/orgmemory/core/organization/CurrentActor.java
  • apps/api/src/main/java/com/orgmemory/api/security/OidcCurrentActorProvider.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantService.java
  • integrations/ai-openai-compatible/src/main/java/com/orgmemory/integrations/ai/openai/SpringAiChatModelAdapter.java
  • apps/api/src/main/java/com/orgmemory/api/ApiExceptionHandler.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantConversationService.java
  • core/src/test/java/com/orgmemory/core/assistant/AssistantServiceTests.java
  • apps/api/src/main/java/com/orgmemory/api/assistant/AssistantController.java
  • core/src/main/java/com/orgmemory/core/assistant/AssistantPromptFactory.java
**/application*.{yml,yaml,properties}

📄 CodeRabbit inference engine (CLAUDE.md)

Keep JPA ddl-auto=validate; pair JPA schema or entity changes with a Flyway migration.

Files:

  • apps/api/src/main/resources/application.yml
**/*.{ts,tsx,js,jsx,css,scss,html}

📄 CodeRabbit inference engine (CLAUDE.md)

For frontend files, run Oxlint, TypeScript typecheck, the production build, and browser tests when the UI flow matters; do not run JetBrains IDE inspection on TypeScript, TSX, or web configuration.

Files:

  • web/src/features/session/actor-cache-key.ts
  • web/src/features/assistant/api/chat-transport.ts
  • web/src/features/assets/components/asset-detail-page.tsx
  • web/src/routes/_authenticated/index.tsx
  • web/src/components/app-shell/app-sidebar.tsx
  • web/src/features/assets/actor-key.ts
  • web/src/features/assistant/components/assistant-page.tsx
  • web/src/features/assistant/components/assistant-conversation-list.tsx
web/src/**/*.{ts,tsx}

⚙️ CodeRabbit configuration file

web/src/**/*.{ts,tsx}: OAuth access and refresh tokens must never enter browser JavaScript or
browser storage. Use the HttpOnly BFF session, CSRF-protected mutations,
generated Hey API data clients, accessible states, and both light and
dark themes. Handwritten transport is reserved for documented protocol
flows such as navigation redirects and streaming.

Files:

  • web/src/features/session/actor-cache-key.ts
  • web/src/features/assistant/api/chat-transport.ts
  • web/src/features/assets/components/asset-detail-page.tsx
  • web/src/routes/_authenticated/index.tsx
  • web/src/components/app-shell/app-sidebar.tsx
  • web/src/features/assets/actor-key.ts
  • web/src/features/assistant/components/assistant-page.tsx
  • web/src/features/assistant/components/assistant-conversation-list.tsx
apps/api/src/main/java/**/*.java

⚙️ CodeRabbit configuration file

apps/api/src/main/java/**/*.java: Enforce the browser-BFF and resource-server boundaries. Authentication
must resolve an active internal actor through the explicit issuer and
subject binding. Reject identity, tenant, roles, or permissions supplied
by request payloads, JWT email, or untrusted JWT role claims.

Files:

  • apps/api/src/main/java/com/orgmemory/api/assistant/AssistantConfiguration.java
  • apps/api/src/main/java/com/orgmemory/api/assistant/AssistantChatRequest.java
  • apps/api/src/main/java/com/orgmemory/api/security/OidcCurrentActorProvider.java
  • apps/api/src/main/java/com/orgmemory/api/ApiExceptionHandler.java
  • apps/api/src/main/java/com/orgmemory/api/assistant/AssistantController.java
core/src/main/resources/db/migration/*.sql

⚙️ CodeRabbit configuration file

core/src/main/resources/db/migration/*.sql: The repository is pre-release: V1 is the intentionally resettable clean
baseline and development data carries no migration cost. Once a release
baseline is frozen, later Flyway migrations are immutable. Check tenant
isolation, foreign keys, uniqueness, indexes, append-only evidence
semantics, safe defaults, and PostgreSQL 18 plus pgvector compatibility.

Files:

  • core/src/main/resources/db/migration/V6__assistant_conversation_history.sql
🧠 Learnings (1)
📚 Learning: 2026-07-23T23:30:44.585Z
Learnt from: kl3inIT
Repo: kl3inIT/OrgMemory PR: 30
File: core/src/main/resources/db/migration/V32__evidence_scoped_graph_semantics.sql:0-0
Timestamp: 2026-07-23T23:30:44.585Z
Learning: For OrgMemory PostgreSQL Flyway migrations under core/src/main/resources/db/migration, do not recommend using `CREATE INDEX CONCURRENTLY` or `DROP INDEX CONCURRENTLY` inside application-owned Flyway migration SQL. Flyway’s schema-history connection may hold a transaction that can cause concurrent index operations to wait indefinitely (e.g., on a `virtualxid`), and docs/conventions.md forbids this pattern. If you need large production-table index replacement, pre-stage online index operations via the deployment pipeline (outside Flyway) rather than inside the migration; “ordinary” index replacement is acceptable for unreleased projections before production traffic.

Applied to files:

  • core/src/main/resources/db/migration/V6__assistant_conversation_history.sql
🪛 ast-grep (0.44.1)
core/src/main/java/com/orgmemory/core/assistant/AssistantService.java

[warning] 34-34: Avoid LDAP injections
Context: retrieval.search(actor, question, requestedLimit, requestId)
Note: [CWE-90] Improper Neutralization of Special Elements used in an LDAP Query ('LDAP Injection'). Security best practice.

(ldap-injection-java)

🪛 SQLFluff (4.2.2)
core/src/main/resources/db/migration/V6__assistant_conversation_history.sql

[error] 13-14: CREATE INDEX should use CONCURRENTLY to avoid locking the table during the build.

(PG01)


[error] 16-17: CREATE INDEX should use CONCURRENTLY to avoid locking the table during the build.

(PG01)


[error] 36-39: CREATE INDEX should use CONCURRENTLY to avoid locking the table during the build.

(PG01)


[error] 70-73: CREATE INDEX should use CONCURRENTLY to avoid locking the table during the build.

(PG01)

🪛 Squawk (2.59.0)
core/src/main/resources/db/migration/V6__assistant_conversation_history.sql

[warning] 4-4: Changing the size of a varchar field requires an ACCESS EXCLUSIVE lock, that will prevent all reads and writes to the table. Use a TEXT field with a CHECK constraint.

(prefer-text-field)


[warning] 6-6: Changing the size of a varchar field requires an ACCESS EXCLUSIVE lock, that will prevent all reads and writes to the table. Use a TEXT field with a CHECK constraint.

(prefer-text-field)


[warning] 7-7: When Postgres stores a datetime in a timestamp field, Postgres drops the UTC offset. This means 2019-10-11 21:11:24+02 and 2019-10-11 21:11:24-06 will both be stored as 2019-10-11 21:11:24 in the database, even though they are eight hours apart in time. Use timestamptz instead of timestamp for your column type.

(prefer-timestamp-tz)


[warning] 23-23: Changing the size of a varchar field requires an ACCESS EXCLUSIVE lock, that will prevent all reads and writes to the table. Use a TEXT field with a CHECK constraint.

(prefer-text-field)


[warning] 46-46: Changing the size of a varchar field requires an ACCESS EXCLUSIVE lock, that will prevent all reads and writes to the table. Use a TEXT field with a CHECK constraint.

(prefer-text-field)

🔇 Additional comments (34)
core/src/main/java/com/orgmemory/core/assistant/AssistantConversationSummary.java (1)

1-11: LGTM!

web/src/features/assets/components/asset-detail-page.tsx (1)

702-715: 🎯 Functional Correctness

Run the required frontend verification gates.

This changes a user-facing mutation flow. Confirm Oxlint, TypeScript typecheck, production build, and browser coverage for submit, pending, and disabled states. As per coding guidelines, “For frontend files, run Oxlint, TypeScript typecheck, the production build, and browser tests when the UI flow matters.”

Source: Coding guidelines

web/src/features/session/actor-cache-key.ts (1)

1-20: LGTM!

web/src/features/assets/actor-key.ts (1)

1-13: LGTM!

web/src/features/assistant/api/chat-transport.ts (1)

5-20: LGTM!

Also applies to: 32-32

web/src/features/assistant/components/assistant-page.tsx (2)

2-5: LGTM!

Also applies to: 39-47, 156-212, 255-268, 303-304


144-154: 🎯 Functional Correctness

No change needed for persisted message role mapping.

AssistantConversationRole only defines USER and ASSISTANT, so the "ASSISTANT" -> "assistant" default maps the persisted history roles cleanly.

web/src/features/assistant/components/assistant-conversation-list.tsx (1)

1-122: LGTM!

Also applies to: 136-236

web/src/routes/_authenticated/index.tsx (1)

4-19: LGTM!

Also applies to: 21-37

web/src/components/app-shell/app-sidebar.tsx (1)

5-6: LGTM!

Also applies to: 33-38, 79-84

core/src/main/java/com/orgmemory/core/assistant/AssistantConversation.java (1)

1-74: LGTM!

core/src/main/java/com/orgmemory/core/assistant/AssistantConversationMessage.java (1)

1-74: LGTM!

core/src/main/java/com/orgmemory/core/assistant/AssistantConversationMessageView.java (1)

6-12: LGTM!

core/src/main/java/com/orgmemory/core/assistant/AssistantConversationRole.java (1)

3-6: LGTM!

core/src/main/java/com/orgmemory/core/assistant/AssistantConversationNotFoundException.java (1)

5-10: LGTM!

core/src/main/java/com/orgmemory/core/assistant/AssistantConversationMessageRepository.java (1)

1-15: LGTM!

core/src/main/java/com/orgmemory/core/assistant/AssistantConversationService.java (1)

27-67: LGTM!

Also applies to: 83-113

core/src/main/resources/db/migration/V6__assistant_conversation_history.sql (1)

1-40: LGTM!

Also applies to: 66-74

core/src/main/java/com/orgmemory/core/assistant/AssistantPromptFactory.java (1)

5-118: LGTM!

core/src/main/java/com/orgmemory/core/assistant/AssistantService.java (1)

29-77: LGTM!

apps/api/src/main/java/com/orgmemory/api/assistant/AssistantChatRequest.java (1)

5-10: LGTM!

apps/api/src/main/java/com/orgmemory/api/assistant/AssistantController.java (1)

44-101: LGTM!

Also applies to: 103-137

core/src/main/java/com/orgmemory/core/assistant/AssistantConversationRepository.java (1)

1-15: LGTM!

core/src/test/java/com/orgmemory/core/assistant/AssistantConversationServiceTests.java (1)

1-143: LGTM!

apps/api/build.gradle.kts (1)

27-27: LGTM!

apps/api/src/main/java/com/orgmemory/api/assistant/AssistantConfiguration.java (1)

31-42: LGTM!

apps/api/src/main/resources/application.yml (1)

6-10: LGTM!

apps/api/src/main/java/com/orgmemory/api/security/OidcCurrentActorProvider.java (1)

49-56: LGTM! Role is sourced from the internally-resolved AppUser, not from JWT claims, consistent with the resource-server boundary requirement.

core/src/main/java/com/orgmemory/core/ai/ChatModelPort.java (1)

9-15: LGTM!

core/src/test/java/com/orgmemory/core/assistant/AssistantServiceTests.java (1)

34-297: LGTM!

apps/api/src/main/java/com/orgmemory/api/ApiExceptionHandler.java (1)

59-69: 🎯 Functional Correctness | ⚡ Quick win

Misleading error message for conversation-not-found.

AssistantConversationNotFoundException is grouped into knowledgeResourceNotFound, which always returns "The requested knowledge resource is not available" — inaccurate for a missing/inaccessible conversation (history/rename/delete endpoints).

🐛 Proposed fix: dedicated handler with accurate message
     `@ExceptionHandler`({
-        AssistantConversationNotFoundException.class,
         AssetNotFoundException.class,
         KnowledgeAssetNotFoundException.class,
         KnowledgeResourceNotFoundException.class
     })
     ProblemDetail knowledgeResourceNotFound(RuntimeException e) {
         return ProblemDetail.forStatusAndDetail(
                 HttpStatus.NOT_FOUND,
                 "The requested knowledge resource is not available");
     }
+
+    `@ExceptionHandler`(AssistantConversationNotFoundException.class)
+    ProblemDetail assistantConversationNotFound(AssistantConversationNotFoundException e) {
+        return ProblemDetail.forStatusAndDetail(HttpStatus.NOT_FOUND, e.getMessage());
+    }
apps/api/src/test/java/com/orgmemory/api/assistant/AssistantControllerStreamingTests.java (1)

68-76: LGTM!

core/src/main/java/com/orgmemory/core/organization/CurrentActor.java (1)

14-21: 🎯 Functional Correctness

No change needed for null-role prompt rendering.

AssistantPromptFactory already maps a null CurrentActor role to UNSPECIFIED before emitting the <role> tag.

integrations/ai-openai-compatible/src/main/java/com/orgmemory/integrations/ai/openai/SpringAiChatModelAdapter.java (1)

66-109: 🩺 Stability & Availability

Validate multi-turn assistant memory before relying on fresh evidence per turn.

MessageChatMemoryAdvisor rewrites the prompt when history is present, and AssistantControllerStreamingTests does not exercise this path with an existing chatMemory. Add a second-turn integration test, including spring-ai-openai, to cover an existing conversation plus a new per-turn system message before using this in production.

Comment thread web/src/features/assistant/components/assistant-page.tsx
Comment thread web/src/features/assistant/components/assistant-page.tsx Outdated
@kl3inIT
kl3inIT merged commit 078898c into main Jul 25, 2026
11 checks 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