Skip to content

feat: tech debt sprint — sessions view + sidebar + DB cleanup#42

Merged
thebtf merged 4 commits into
mainfrom
worktree-tech-debt-sprint
Mar 23, 2026
Merged

feat: tech debt sprint — sessions view + sidebar + DB cleanup#42
thebtf merged 4 commits into
mainfrom
worktree-tech-debt-sprint

Conversation

@thebtf
Copy link
Copy Markdown
Owner

@thebtf thebtf commented Mar 23, 2026

Summary

  • Sessions view fixed: GET /api/sessions/list queries sdk_sessions table with pagination + project filter. Frontend switched from fetchIndexedSessions to fetchSDKSessions. Transcript search preserved.
  • Info sidebar relocated: System Health, Memory Contents, Retrieval Stats moved into AppSidebar (nav panel). Old Sidebar.vue removed from HomeView — timeline gets full width.
  • Migration 047: DROP TABLE IF EXISTS memory_blocks (unused since creation by migration 024)
  • Orphaned credential cleanup: DELETE /api/vault/orphaned-credentials endpoint purges credentials encrypted with a lost key (fingerprint mismatch)

Test plan

  • go build ./... passes
  • cd ui && npm run build passes
  • Sessions page shows real SDK sessions (not "No sessions found")
  • Info sidebar visible in nav panel on Home page
  • Transcript search still works in Sessions view
  • Migration 047 applies on server restart
  • DELETE /api/vault/orphaned-credentials returns count

Summary by CodeRabbit

  • Новые функции

    • Панель статистики в сайдбаре: статус компонентов, счётчики наблюдений, сессий и метрик retrieval.
    • Просмотр списка SDK‑сессий с пагинацией и фильтром по проекту.
    • API для удаления осиротевших зашифрованных учётных данных с возвращаемым счётом удалённых записей.
  • Улучшения

    • Клиентская загрузка сессий переключена на источник SDK; формат данных адаптирован.
    • Упрощён главный экран и поток активности для более компактного интерфейса.

thebtf added 2 commits March 23, 2026 03:14
Backend:
- Add ListSDKSessions with pagination + project filter
- Add GET /api/sessions/list endpoint
- Register route before /api/sessions (specificity)

Frontend:
- Sessions page now queries SDK sessions, not indexed transcripts
- Info sidebar (health, memory, retrieval) moved into AppSidebar
- Remove old Sidebar from HomeView — timeline gets full width
- Migration 047: DROP TABLE IF EXISTS memory_blocks (unused since creation)
- Add DeleteOrphanedCredentials method (by fingerprint mismatch)
- Add DELETE /api/vault/orphaned-credentials endpoint
@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 23, 2026

Caution

Review failed

The pull request is closed.

ℹ️ Recent review info
⚙️ Run configuration

Configuration used: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: d1da227a-bcf8-4fce-9da2-d4c53e099d0d

📥 Commits

Reviewing files that changed from the base of the PR and between 46f86ff and da64ae8.

📒 Files selected for processing (2)
  • internal/db/gorm/observation_store.go
  • internal/db/gorm/session_store.go

Walkthrough

PR добавляет миграцию для удаления таблицы memory_blocks, вводит удаление «осиротевших» зашифрованных credential‑записей и листинг SDK‑сессий, добавляет соответствующие HTTP‑хендлеры и маршруты, а также обновляет фронтенд: типы, API‑клиент, панель статистики и загрузку сессий.

Changes

Cohort / File(s) Summary
Database migrations
internal/db/gorm/migrations.go
Добавлена миграция 047_drop_memory_blocks, которая выполняет DROP TABLE IF EXISTS memory_blocks (Rollback — no-op).
Observation store
internal/db/gorm/observation_store.go
В UpdateObservation удалено автоматическое обновление updated_at_epoch; добавлен метод DeleteOrphanedCredentials(ctx, currentFingerprint string) (int64, error) для одноразового DELETE записей credential с ненулевым encrypted_secret и отличным encryption_key_fingerprint.
Session store
internal/db/gorm/session_store.go
Добавлен метод ListSDKSessions(ctx, project string, limit, offset int) — подсчёт общего количества и постраничный SELECT с сортировкой по started_at_epoch DESC, id DESC.
Worker HTTP handlers & routing
internal/worker/handlers_sessions.go, internal/worker/handlers_vault.go, internal/worker/service.go
Добавлены хендлеры: handleListSessions (GET /api/sessions/list) и handleDeleteOrphanedCredentials (DELETE /api/vault/orphaned-credentials); маршруты зарегистрированы, обработка ошибок возвращает 503/500 по контексту.
Frontend API & types
ui/src/types/api.ts, ui/src/utils/api.ts
Добавлены интерфейсы SDKSessionItem, SDKSessionListResponse и функция fetchSDKSessions(project?, limit, offset) для запроса списка SDK‑сессий.
Frontend UI & composables
ui/src/components/layout/AppSidebar.vue, ui/src/composables/useSessions.ts, ui/src/views/HomeView.vue
В сайдбар добавлена панель статистики (health, memory, retrieval); useSessions переключён на fetchSDKSessions с преобразованием полей в формат IndexedSession; HomeView упрощён — убран Sidebar и связанные привязки.

Sequence Diagram(s)

sequenceDiagram
  participant Client as Client
  participant Service as Service (worker)
  participant Vault as Vault
  participant ObservationStore as ObservationStore
  participant DB as Database

  Client->>Service: DELETE /api/vault/orphaned-credentials
  Service->>Vault: getVault()
  alt fingerprint available
    Service->>ObservationStore: DeleteOrphanedCredentials(ctx, fingerprint)
    ObservationStore->>DB: DELETE FROM observations WHERE type='credential' AND encrypted_secret IS NOT NULL AND encryption_key_fingerprint IS NOT NULL AND encryption_key_fingerprint != fingerprint
    DB-->>ObservationStore: RowsAffected
    ObservationStore-->>Service: (rows, nil)
    Service-->>Client: 200 {"status":"ok","deleted":rows}
  else missing fingerprint / service not ready
    Service-->>Client: 503 {"error": "..."}
  end
Loading
sequenceDiagram
  participant Client as Client
  participant Service as Service (worker)
  participant SessionStore as SessionStore
  participant DB as Database

  Client->>Service: GET /api/sessions/list?project=&limit=&offset=
  Service->>SessionStore: ListSDKSessions(ctx, project, limit, offset)
  SessionStore->>DB: COUNT ... WHERE project = ? (optional)
  DB-->>SessionStore: total
  SessionStore->>DB: SELECT ... ORDER BY started_at_epoch DESC, id DESC LIMIT ? OFFSET ?
  DB-->>SessionStore: rows
  SessionStore-->>Service: (sessions, total, nil)
  Service-->>Client: 200 {"sessions":[...],"total":total,"limit":...,"offset":...}
Loading

Estimated code review effort

🎯 3 (Moderate) | ⏱️ ~20 minutes

Possibly related PRs

Poem

🐰 Я кролик, копаю код ночами,
Таблицы чистлю, ключи считаю тайнами,
Сессии листаю, счёт держу в панеле,
Осиротевшим секретам — долгий путь в крошке поля.
Прыг‑скок — и всё в порядке, hoppity‑hop! ✨

🚥 Pre-merge checks | ✅ 2 | ❌ 1

❌ Failed checks (1 warning)

Check name Status Explanation Resolution
Docstring Coverage ⚠️ Warning Docstring coverage is 28.57% which is insufficient. The required threshold is 80.00%. Write docstrings for the functions missing them to satisfy the coverage threshold.
✅ Passed checks (2 passed)
Check name Status Explanation
Description Check ✅ Passed Check skipped - CodeRabbit’s high-level summary is enabled.
Title check ✅ Passed The title accurately summarizes the main changes: sessions view improvements, sidebar updates, and database cleanup including the migration and orphaned credentials feature.

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

✨ 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 worktree-tech-debt-sprint

Warning

There were issues while running some tools. Please review the errors and either fix the tool's configuration or disable the tool if it's a critical failure.

🔧 golangci-lint (2.11.3)

Error: can't load config: unsupported version of the configuration: "" See https://golangci-lint.run/docs/product/migration-guide for migration instructions
The command is terminated due to an error: can't load config: unsupported version of the configuration: "" See https://golangci-lint.run/docs/product/migration-guide for migration instructions


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

@gemini-code-assist
Copy link
Copy Markdown

Summary of Changes

Hello, I'm Gemini Code Assist1! I'm currently reviewing this pull request and will post my feedback shortly. In the meantime, here's a summary to help you and other reviewers quickly get up to speed!

This pull request addresses several technical debt items, significantly improving the application's session management, user interface layout, and backend data hygiene. The changes streamline how session data is retrieved and displayed, optimize the main view by integrating system information into the navigation sidebar, and enhance database integrity by removing unused tables and providing a mechanism to clean up unrecoverable encrypted credentials.

Highlights

  • Sessions View Enhancement: The sessions view has been updated to query the sdk_sessions table with pagination and project filtering via a new GET /api/sessions/list endpoint. The frontend now uses fetchSDKSessions instead of fetchIndexedSessions, while preserving transcript search functionality.
  • UI Sidebar Relocation: System Health, Memory Contents, and Retrieval Stats have been moved from the HomeView's Sidebar.vue component into the AppSidebar (navigation panel), allowing the timeline to occupy the full width of the main content area.
  • Database Cleanup: A new database migration (047) has been added to drop the memory_blocks table, which was created by an earlier migration (024) but never populated or used.
  • Orphaned Credential Management: A new DELETE /api/vault/orphaned-credentials endpoint has been implemented to purge credentials that were encrypted with a key whose fingerprint no longer matches the current vault key, making them irrecoverable.
Using Gemini Code Assist

The full guide for Gemini Code Assist can be found on our documentation page, here are some quick tips.

Invoking Gemini

You can request assistance from Gemini at any point by creating a comment using either /gemini <command> or @gemini-code-assist <command>. Below is a summary of the supported commands on the current page.

Feature Command Description
Code Review /gemini review Performs a code review for the current pull request in its current state.
Pull Request Summary /gemini summary Provides a summary of the current pull request in its current state.
Comment @gemini-code-assist Responds in comments when explicitly tagged, both in pull request comments and review comments.
Help /gemini help Displays a list of available commands.

Customization

To customize Gemini Code Assist for GitHub experience, repository maintainers can create a configuration file and/or provide a custom code review style guide (such as PEP-8 for Python) by creating and adding files to a .gemini/ folder in the base of the repository. Detailed instructions can be found here.

Limitations & Feedback

Gemini Code Assist may make mistakes. Please leave feedback on any instances where its feedback is incorrect or counter productive. You can react with 👍 and 👎 on @gemini-code-assist comments. If you're interested in giving your feedback about your experience with Gemini Code Assist for GitHub and other Google products, sign up here.

Footnotes

  1. Review the Privacy Notices, Generative AI Prohibited Use Policy, Terms of Service, and learn how to configure Gemini Code Assist in GitHub here. Gemini can make mistakes, so double check it and use code with caution.

@thebtf
Copy link
Copy Markdown
Owner Author

thebtf commented Mar 23, 2026

@coderabbitai review

@thebtf
Copy link
Copy Markdown
Owner Author

thebtf commented Mar 23, 2026

@gemini-code-assist review

@coderabbitai
Copy link
Copy Markdown

coderabbitai Bot commented Mar 23, 2026

✅ Actions performed

Review triggered.

Note: CodeRabbit is an incremental review system and does not re-review already reviewed commits. This command is applicable only when automatic reviews are paused.

@thebtf
Copy link
Copy Markdown
Owner Author

thebtf commented Mar 23, 2026

@codex review

Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces several valuable features and cleanups, including a new sessions view with a corresponding API, an endpoint for cleaning up orphaned credentials, and a database migration to remove an unused table. The frontend refactoring to relocate the info sidebar is also a good improvement. The code is generally well-structured and follows good practices. I have one suggestion to improve type safety in the useSessions composable by avoiding an as any type cast.

Comment thread ui/src/composables/useSessions.ts
Copy link
Copy Markdown

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

🧹 Nitpick comments (5)
internal/worker/handlers_sessions.go (1)

421-429: Лучше возвращать 400 для невалидных limit/offset, а не молча подставлять дефолт.

Сейчас ошибки параметров скрываются, из-за чего клиенту сложно понять причину «странной» пагинации.

💡 Предлагаемое исправление
 	if v := r.URL.Query().Get("limit"); v != "" {
-		if parsed, err := strconv.Atoi(v); err == nil && parsed > 0 && parsed <= 200 {
-			limit = parsed
-		}
+		parsed, err := strconv.Atoi(v)
+		if err != nil || parsed <= 0 || parsed > 200 {
+			http.Error(w, "invalid limit: must be 1..200", http.StatusBadRequest)
+			return
+		}
+		limit = parsed
 	}
 	if v := r.URL.Query().Get("offset"); v != "" {
-		if parsed, err := strconv.Atoi(v); err == nil && parsed >= 0 {
-			offset = parsed
-		}
+		parsed, err := strconv.Atoi(v)
+		if err != nil || parsed < 0 {
+			http.Error(w, "invalid offset: must be >= 0", http.StatusBadRequest)
+			return
+		}
+		offset = parsed
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/worker/handlers_sessions.go` around lines 421 - 429, The handler
currently swallows invalid limit/offset query values and falls back to defaults;
update the parsing in the sessions listing handler so that when
r.URL.Query().Get("limit") or "offset" is present but fails validation
(non-integer, limit <=0 or >200, or offset <0) the handler returns a 400
response instead of using defaults. Locate the parsing block around limit/offset
in internal/worker/handlers_sessions.go (the code using strconv.Atoi and
variables limit/offset) and change it to validate presence+value, and on invalid
input call the existing HTTP error response path (e.g., http.Error or the
handler's standard JSON error responder) with a clear message about the bad
parameter and stop further processing.
ui/src/composables/useSessions.ts (3)

20-21: Неиспользуемые реактивные переменные filterFrom и filterTo.

После перехода на fetchSDKSessions эти фильтры больше не передаются в API (строки 31-38), но продолжают возвращаться из composable (строка 109). Это мёртвый код, который может ввести в заблуждение.

Если фильтрация по дате планируется в будущем, стоит добавить TODO-комментарий. Иначе рекомендуется удалить эти переменные.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/src/composables/useSessions.ts` around lines 20 - 21, Remove the dead
reactive variables filterFrom and filterTo from useSessions.ts (delete their
declarations and remove them from the returned object) because fetchSDKSessions
no longer uses them; if date filtering is intended later, replace removal with a
single TODO comment near fetchSDKSessions and keep only the TODOed placeholders,
but do not return unused refs from the composable.

34-35: Жёстко заданная пагинация без возможности загрузки следующих страниц.

limit: 50 и offset: 0 зафиксированы. Если у пользователя более 50 сессий, остальные будут недоступны. Стоит предусмотреть механизм подгрузки (infinite scroll или кнопка "Load more").

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/src/composables/useSessions.ts` around lines 34 - 35, В текущем
useSessions композиционном файле жёстко зафиксированы параметры пагинации
(limit: 50, offset: 0) — это блокирует доступ к сессиям за пределами первых 50.
Измените реализацию в useSessions так, чтобы limit был конфигурируемым (по
умолчанию 50) и offset — реактивным состоянием, и добавьте метод (например
loadMore или fetchMoreSessions) который увеличивает offset и вызывает
существующую функцию загрузки (например fetchSessions или getSessions) для
подгрузки следующей страницы; альтернативно предоставьте общий
fetchSessions(limit, offset) API и событие/флаг isLastPage для infinite-scroll
или кнопки "Load more".

39-50: Приведение as any скрывает несоответствие типов.

Объект содержит дополнительные поля (status, user_prompt, completed_at), которых нет в типе IndexedSession. Использование as any обходит проверку типов, что может привести к ошибкам при рефакторинге.

Рекомендуется расширить тип IndexedSession или создать отдельный тип SDKSession для UI, чтобы сохранить типобезопасность.

🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@ui/src/composables/useSessions.ts` around lines 39 - 50, The mapped session
object in useSessions.ts is being cast with "as any", hiding type mismatches
between the returned SDK shape and our IndexedSession type; instead, define a
proper UI-facing type (e.g., SDKSession or extend IndexedSession) that includes
status, user_prompt, completed_at and use that type for the mapped object in
sessions.value (or adapt fields to match IndexedSession) so you can remove "as
any" and restore type safety for the mapping in the sessions.value =
(result.sessions || []).map(...) block.
internal/worker/handlers_vault.go (1)

313-317: Отсутствует логирование ошибки и детали в HTTP-ответе.

В отличие от других обработчиков в этом файле (например, handleListCredentials, handleDeleteCredential), при ошибке удаления не логируется сама ошибка и не включаются её детали в ответ. Это затрудняет диагностику проблем.

♻️ Предлагаемое исправление
 	deleted, err := s.observationStore.DeleteOrphanedCredentials(r.Context(), fingerprint)
 	if err != nil {
-		http.Error(w, "failed to delete orphaned credentials", http.StatusInternalServerError)
+		log.Error().Err(err).Msg("delete orphaned credentials failed")
+		http.Error(w, "delete orphaned credentials: "+err.Error(), http.StatusInternalServerError)
 		return
 	}
🤖 Prompt for AI Agents
Verify each finding against the current code and only fix it if needed.

In `@internal/worker/handlers_vault.go` around lines 313 - 317, В обработчике где
вызывается s.observationStore.DeleteOrphanedCredentials(r.Context(),
fingerprint) добавьте логирование ошибки через существующий logger (или
s.logger/processLogger, использовать тот же логгер, что и в других обработчиках)
и верните более информативный HTTP-ответ: при err вызовите logger.Errorf/Log
with context including fingerprint и err, затем используйте http.Error(w,
fmt.Sprintf("failed to delete orphaned credentials: %v", err),
http.StatusInternalServerError) чтобы включить детали ошибки в ответ;
ориентируйтесь на реализацию handleListCredentials и handleDeleteCredential для
стиля логирования и формата ответа.
🤖 Prompt for all review comments with AI agents
Verify each finding against the current code and only fix it if needed.

Inline comments:
In `@internal/db/gorm/migrations.go`:
- Around line 1580-1583: Функция Rollback в записи миграции (Rollback func(tx
*gorm.DB) error) сейчас всегда возвращает nil, давая ложное подтверждение
успешного отката при фактически необратимом удалении таблицы; замените
реализацию Rollback в этом месте файла migrations.go: либо реализуйте реальное
восстановление таблицы через tx (например вызвать tx.Exec/tx.CreateTable с
нужной схемой) если возможна корректная реверсия, либо явно возвращайте ошибку
(fmt.Errorf или errors.New) с понятным сообщением вроде "irreversible migration:
table X cannot be restored" чтобы сигнализировать о невозможности отката.
Укажите имя миграции/таблицы из той же записи при формировании сообщения для
однозначной идентификации.

In `@internal/db/gorm/observation_store.go`:
- Around line 1530-1538: The DeleteOrphanedCredentials method is deleting from
the observations table without limiting to credential-type records; update
DeleteOrphanedCredentials (in ObservationStore) to add a WHERE filter
restricting deletions to only credential records (e.g. add a condition like type
= 'credential' or equivalent column/enum check) so only Observation rows
representing credentials with non-null encrypted_secret and a non-matching
encryption_key_fingerprint are removed; ensure the new Where clause is combined
with the existing conditions before calling Delete(&Observation{}).

In `@internal/db/gorm/session_store.go`:
- Around line 218-221: В запросе q.Order("started_at_epoch DESC") (в коде, где
вызывается Find(&sessions)) сортировка по одному полю может давать нестабильный
порядок при равных timestamp; измените выражение Order, чтобы добавить вторичную
детерминированную сортировку по уникальному ключу записи (например, первичному
ключу "id" или полю с UUID) — например: q.Order("started_at_epoch DESC, id
DESC") — сохранив направление сортировки одинаковым, чтобы обеспечить стабильную
пагинацию при использовании Limit/Offset и Find(&sessions).

---

Nitpick comments:
In `@internal/worker/handlers_sessions.go`:
- Around line 421-429: The handler currently swallows invalid limit/offset query
values and falls back to defaults; update the parsing in the sessions listing
handler so that when r.URL.Query().Get("limit") or "offset" is present but fails
validation (non-integer, limit <=0 or >200, or offset <0) the handler returns a
400 response instead of using defaults. Locate the parsing block around
limit/offset in internal/worker/handlers_sessions.go (the code using
strconv.Atoi and variables limit/offset) and change it to validate
presence+value, and on invalid input call the existing HTTP error response path
(e.g., http.Error or the handler's standard JSON error responder) with a clear
message about the bad parameter and stop further processing.

In `@internal/worker/handlers_vault.go`:
- Around line 313-317: В обработчике где вызывается
s.observationStore.DeleteOrphanedCredentials(r.Context(), fingerprint) добавьте
логирование ошибки через существующий logger (или s.logger/processLogger,
использовать тот же логгер, что и в других обработчиках) и верните более
информативный HTTP-ответ: при err вызовите logger.Errorf/Log with context
including fingerprint и err, затем используйте http.Error(w, fmt.Sprintf("failed
to delete orphaned credentials: %v", err), http.StatusInternalServerError) чтобы
включить детали ошибки в ответ; ориентируйтесь на реализацию
handleListCredentials и handleDeleteCredential для стиля логирования и формата
ответа.

In `@ui/src/composables/useSessions.ts`:
- Around line 20-21: Remove the dead reactive variables filterFrom and filterTo
from useSessions.ts (delete their declarations and remove them from the returned
object) because fetchSDKSessions no longer uses them; if date filtering is
intended later, replace removal with a single TODO comment near fetchSDKSessions
and keep only the TODOed placeholders, but do not return unused refs from the
composable.
- Around line 34-35: В текущем useSessions композиционном файле жёстко
зафиксированы параметры пагинации (limit: 50, offset: 0) — это блокирует доступ
к сессиям за пределами первых 50. Измените реализацию в useSessions так, чтобы
limit был конфигурируемым (по умолчанию 50) и offset — реактивным состоянием, и
добавьте метод (например loadMore или fetchMoreSessions) который увеличивает
offset и вызывает существующую функцию загрузки (например fetchSessions или
getSessions) для подгрузки следующей страницы; альтернативно предоставьте общий
fetchSessions(limit, offset) API и событие/флаг isLastPage для infinite-scroll
или кнопки "Load more".
- Around line 39-50: The mapped session object in useSessions.ts is being cast
with "as any", hiding type mismatches between the returned SDK shape and our
IndexedSession type; instead, define a proper UI-facing type (e.g., SDKSession
or extend IndexedSession) that includes status, user_prompt, completed_at and
use that type for the mapped object in sessions.value (or adapt fields to match
IndexedSession) so you can remove "as any" and restore type safety for the
mapping in the sessions.value = (result.sessions || []).map(...) block.
🪄 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: Organization UI

Review profile: CHILL

Plan: Pro

Run ID: f15d36d0-b1b9-4946-b757-842a47f5f55f

📥 Commits

Reviewing files that changed from the base of the PR and between 4189f97 and d408d0b.

📒 Files selected for processing (11)
  • internal/db/gorm/migrations.go
  • internal/db/gorm/observation_store.go
  • internal/db/gorm/session_store.go
  • internal/worker/handlers_sessions.go
  • internal/worker/handlers_vault.go
  • internal/worker/service.go
  • ui/src/components/layout/AppSidebar.vue
  • ui/src/composables/useSessions.ts
  • ui/src/types/api.ts
  • ui/src/utils/api.ts
  • ui/src/views/HomeView.vue

Comment thread internal/db/gorm/migrations.go
Comment thread internal/db/gorm/observation_store.go
Comment thread internal/db/gorm/session_store.go Outdated
Copy link
Copy Markdown

@gemini-code-assist gemini-code-assist Bot left a comment

Choose a reason for hiding this comment

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

Code Review

This pull request introduces several significant features and cleanups. It adds a new paginated sessions list view, though the frontend pagination controls are not yet implemented. It also relocates the info sidebar into the main navigation panel, improving the layout of the home view. On the backend, a new endpoint is added to clean up orphaned credentials, and a database migration is included to drop an unused table. The code changes are generally well-structured. I've added a couple of suggestions on the frontend to improve type safety and to point out the missing pagination implementation.

Comment thread ui/src/composables/useSessions.ts
Comment thread ui/src/composables/useSessions.ts
thebtf added 2 commits March 23, 2026 03:24
Column updated_at_epoch doesn't exist on observations table.
The update was crashing all edit_observation calls with SQLSTATE 42703.
- DeleteOrphanedCredentials now filters by type='credential' (CRIT fix)
- Session listing sort includes id DESC for deterministic pagination
- edit_observation fixed (removed non-existent updated_at_epoch column)
@thebtf
Copy link
Copy Markdown
Owner Author

thebtf commented Mar 23, 2026

🤖 PR Review MCP State (auto-managed, do not edit)
{
  "version": 2,
  "parentChildren": {},
  "resolvedNitpicks": {
    "coderabbit-nitpick-9a80535a-421": {
      "resolvedAt": "2026-03-23T00:27:22.115Z",
      "resolvedBy": "agent"
    },
    "coderabbit-nitpick-e9af09c3-20": {
      "resolvedAt": "2026-03-23T00:27:24.788Z",
      "resolvedBy": "agent"
    },
    "coderabbit-nitpick-fb25fb6c-34": {
      "resolvedAt": "2026-03-23T00:27:27.580Z",
      "resolvedBy": "agent"
    },
    "coderabbit-nitpick-ee3ab6ce-39": {
      "resolvedAt": "2026-03-23T00:27:30.064Z",
      "resolvedBy": "agent"
    },
    "coderabbit-nitpick-84d484f0-313": {
      "resolvedAt": "2026-03-23T00:27:32.700Z",
      "resolvedBy": "agent"
    }
  },
  "updatedAt": "2026-03-23T00:27:33.165Z"
}

@thebtf thebtf merged commit a5a369a into main Mar 23, 2026
1 of 2 checks passed
thebtf added a commit that referenced this pull request Apr 12, 2026
The 'english' dictionary drops Cyrillic tokens and mishandles product
names like "SocratiCode". Combining it with 'simple' (no stemming, no
stopword removal) ensures all tokens are indexed verbatim, so mixed-
language queries like "socraticode сломался" correctly find memories.

- Migration 075: drops and recreates search_vector generated column
  as to_tsvector('english',...) || to_tsvector('simple',...); recreates
  GIN index as idx_observations_search_vector.
- SearchObservationsFTS, SearchObservationsFTSFiltered,
  SearchObservationsFTSScored: all @@ predicates and ts_rank calls
  now use (websearch_to_tsquery('english', ?) || websearch_to_tsquery('simple', ?));
  query param passed twice to match the two placeholders.
thebtf added a commit that referenced this pull request Apr 12, 2026
The 'english' dictionary drops Cyrillic tokens and mishandles product
names like "SocratiCode". Combining it with 'simple' (no stemming, no
stopword removal) ensures all tokens are indexed verbatim, so mixed-
language queries like "socraticode сломался" correctly find memories.

- Migration 075: drops and recreates search_vector generated column
  as to_tsvector('english',...) || to_tsvector('simple',...); recreates
  GIN index as idx_observations_search_vector.
- SearchObservationsFTS, SearchObservationsFTSFiltered,
  SearchObservationsFTSScored: all @@ predicates and ts_rank calls
  now use (websearch_to_tsquery('english', ?) || websearch_to_tsquery('simple', ?));
  query param passed twice to match the two placeholders.
thebtf added a commit that referenced this pull request Apr 12, 2026
The 'english' dictionary drops Cyrillic tokens and mishandles product
names like "SocratiCode". Combining it with 'simple' (no stemming, no
stopword removal) ensures all tokens are indexed verbatim, so mixed-
language queries like "socraticode сломался" correctly find memories.

- Migration 075: drops and recreates search_vector generated column
  as to_tsvector('english',...) || to_tsvector('simple',...); recreates
  GIN index as idx_observations_search_vector.
- SearchObservationsFTS, SearchObservationsFTSFiltered,
  SearchObservationsFTSScored: all @@ predicates and ts_rank calls
  now use (websearch_to_tsquery('english', ?) || websearch_to_tsquery('simple', ?));
  query param passed twice to match the two placeholders.

Co-authored-by: Kirill Turanskiy <thebtf@users.noreply.github.com>
thebtf added a commit that referenced this pull request Apr 18, 2026
Removes the per-project adaptive threshold infrastructure:

- Migration 097_drop_project_settings (DROP TABLE project_settings;
  per plan.md C3 rollback returns IRREVERSIBLE error — data was derived
  from learning signals)
- Delete internal/db/gorm/project_settings_store.go (ProjectSettings
  model + ProjectSettingsStore type + GetThreshold/AdjustThreshold/
  UpsertSettings methods)
- internal/search/manager.go: remove projectSettingsStore field and
  SetProjectSettingsStore method; GetProjectThreshold becomes a thin
  wrapper returning globalDefault (kept as a wrapper so callers in
  internal/worker don't need to change — remove together in a later
  US if wanted)
- internal/worker/service.go: remove projectSettingsStore field +
  init + SetProjectSettingsStore call (3 lines total)
- internal/worker/handlers_scoring.go: remove the adaptive threshold
  adjustment block in the utility-signal handler (it was the only
  caller of ProjectSettingsStore.AdjustThreshold)
- internal/worker/reaper/reaper.go: drop the project_settings entry
  from the ''tables related to projects.id'' comment

Verified:
  go build ./... — clean
  go vet ./... — clean
  go test -short -count=1 ./... — green

Per plan.md C7: CodeRabbit-only review.
Per plan.md C8: single coherent PR, no atomic-commit split.

Plan.md §Phase 4. Closes task #42.
thebtf added a commit that referenced this pull request Apr 18, 2026
Removes the per-project adaptive threshold infrastructure:

- Migration 097_drop_project_settings (DROP TABLE project_settings;
  per plan.md C3 rollback returns IRREVERSIBLE error — data was derived
  from learning signals)
- Delete internal/db/gorm/project_settings_store.go (ProjectSettings
  model + ProjectSettingsStore type + GetThreshold/AdjustThreshold/
  UpsertSettings methods)
- internal/search/manager.go: remove projectSettingsStore field and
  SetProjectSettingsStore method; GetProjectThreshold becomes a thin
  wrapper returning globalDefault (kept as a wrapper so callers in
  internal/worker don't need to change — remove together in a later
  US if wanted)
- internal/worker/service.go: remove projectSettingsStore field +
  init + SetProjectSettingsStore call (3 lines total)
- internal/worker/handlers_scoring.go: remove the adaptive threshold
  adjustment block in the utility-signal handler (it was the only
  caller of ProjectSettingsStore.AdjustThreshold)
- internal/worker/reaper/reaper.go: drop the project_settings entry
  from the ''tables related to projects.id'' comment

Verified:
  go build ./... — clean
  go vet ./... — clean
  go test -short -count=1 ./... — green

Per plan.md C7: CodeRabbit-only review.
Per plan.md C8: single coherent PR, no atomic-commit split.

Plan.md §Phase 4. Closes task #42.

Co-authored-by: Kirill Turanskiy <thebtf@users.noreply.github.com>
@thebtf thebtf deleted the worktree-tech-debt-sprint branch May 7, 2026 06:34
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant