feat(search): align message result payloads
This commit is contained in:
@@ -49,11 +49,11 @@ Hermes task landing checklist:
|
||||
|
||||
## Current Baseline
|
||||
|
||||
- Current tracking checkpoint: 2026-06-07 tracker reconciliation, prepared as `docs: reconcile parity tracker`.
|
||||
- Latest implementation checkpoint: `0b47066 feat(search): align conversation result payloads` closes P3.85 search conversation payload parity.
|
||||
- Latest documentation/tooling checkpoint: this tracker update reconciles stale next-slice wording, adds the P3.84/P3.85 commit ledger rows, and keeps the executable queue pointed at Phase 2/3 drift audit, Phase 6 placeholder audit, or B12 live smoke. No route artifacts change.
|
||||
- Current tracking checkpoint: 2026-06-07 P3.86 search message payload parity, prepared as `feat(search): align message result payloads`.
|
||||
- Latest implementation checkpoint: this checkpoint, prepared as `feat(search): align message result payloads`.
|
||||
- Latest documentation/tooling checkpoint: this tracker update records Chatwoot search message Jbuilder payload parity for sender, attachments, and display-ID routing. No route artifacts change.
|
||||
- Plan landing status: complete for the current known Hermes plans and user-confirmed scope. Future work should update this file directly instead of opening a parallel tracker.
|
||||
- Worktree status at this implementation checkpoint: SearchAPI conversation results now include Chatwoot-compatible nested `message`, `contact`, `inbox`, `agent`, and `additional_attributes` payloads from DB fallback and Meilisearch documents, while retaining P3.84 agent-sender filter parity, P3.83 conversation ordering, P3.82 contact-conversation reindex fanout, P3.81 conversation identity search, P3.80 search time-bound parity, P3.79 advanced-search feature gates, P3.78 message recency, P3.77 current-user inbox access, and prior checkpoints. Live API/browser/enterprise smoke still needs the full PostgreSQL/Redis/Meilisearch/GoChat/Vite/Chrome stack.
|
||||
- Worktree status at this implementation checkpoint: SearchAPI message results now hydrate Chatwoot `_message` fields with conversation display IDs, sender push data, and attachment push data from DB-backed handlers plus Meilisearch document payloads, while retaining P3.85 conversation payloads, P3.84 agent-sender filter parity, P3.83 conversation ordering, P3.82 contact-conversation reindex fanout, P3.81 conversation identity search, P3.80 search time-bound parity, P3.79 advanced-search feature gates, P3.78 message recency, P3.77 current-user inbox access, and prior checkpoints. Live API/browser/enterprise smoke still needs the full PostgreSQL/Redis/Meilisearch/GoChat/Vite/Chrome stack.
|
||||
- Next executable implementation checkpoint: continue Phase 2/3 drift audit for the next reused-frontend mismatch, or run B12 live smoke when the full PostgreSQL/Redis/Meilisearch/GoChat/Vite/Chrome stack is available. Re-run Phase 6 placeholder audit after future route/smoke changes.
|
||||
- `go test ./...` passes when run outside the restricted socket sandbox for the latest implementation baseline; the latest docs/tooling checkpoint verified `scripts/parity_frontend_smoke.sh --check` with workspace-local temp/cache dirs after `/tmp` was full.
|
||||
- Route dump succeeds with `967` registered routes after profile MFA route tracking.
|
||||
@@ -156,6 +156,7 @@ This table is the shortest authoritative handoff view. If an older lower section
|
||||
|
||||
| Priority | Workstream | Current state | Next checkpoint | Commit close rule |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 0 | P3.86 search message payload parity | Implemented for reused SearchAPI message cards: DB-backed handlers now serialize message search hits through the Chatwoot `_message` contract with conversation display IDs, sender push data, and attachment push data; Meilisearch message documents and reindex/durable indexing paths now carry display-ID and attachment payload data when relations are loaded. | Keep in Review; reopen from B12 search smoke or fresh reference evidence for exact AgentBot sender push data, voice-call `call` payloads, or provider-specific attachment metadata beyond the inspected frontend card usage. | Focused SearchHandler, SearchRepo, DurableSearchIndexer, reindex, and document-builder tests passed; full `go test ./...` passed outside the restricted socket sandbox; `git diff --check` passed. No route artifacts change. |
|
||||
| 0 | P3.85 search conversation payload parity | Implemented for reused SearchAPI conversation cards: DB fallback results and Meilisearch documents now carry Chatwoot search Jbuilder fields `message`, `contact`, `inbox`, `agent`, and `additional_attributes`, with conversation indexing/reindexing preloading those display relations. | Keep in Review; reopen from B12 search smoke or fresh reference evidence for exact `api/v1/models/message` field drift, message attachment/sender serialization gaps, or Meilisearch document payload bloat/per-page tuning. | Focused SearchHandler, SearchRepo, and document-builder tests passed; full `go test ./...` passed outside the restricted socket sandbox; `git diff --check` passed. No route artifacts change. |
|
||||
| 0 | P3.84 search agent-sender filter parity | Implemented for reused SearchAPI message filters: frontend `from=agent:id` now matches GoChat's stored agent sender variants (`agent`, `user`, `User`) in both DB fallback and Meilisearch filters, while contact and bot sender filters also tolerate local/Rails-style casing. | Keep in Review; reopen from B12 search smoke or fresh reference evidence for additional polymorphic sender values, exact Searchkick sender-type indexing, or global `ChatwootApp.advanced_search_allowed?` differences. | Focused SearchFilter, Meilisearch engine, and SearchRepo sender-filter tests passed; full `go test ./...` passed outside the restricted socket sandbox; `git diff --check` passed. No route artifacts change. |
|
||||
| 0 | P3.83 search conversation ordering parity | Implemented for DB fallback conversation search: default ordering now matches Chatwoot `SearchService#filter_conversations` with newest `conversations.created_at` first instead of `last_activity_at`. | Keep in Review; reopen from B12 search smoke or fresh reference evidence for Meilisearch Searchkick ordering drift, tie-break behavior, or explicit sort param differences. | Focused SearchRepo ordering test passed; full `go test ./...` passed outside the restricted socket sandbox after retrying an unrelated `internal/worker` SQLite in-memory flake; `git diff --check` passed. No route artifacts change. |
|
||||
@@ -249,6 +250,7 @@ These rows are the executable development plan from this point forward. A checkp
|
||||
|
||||
| ID | Owner files | Reference files | Work to land | Exit gate |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| P3.86 search message payload parity | `internal/handler/api/v1/search_handler.go`, `internal/search/engine.go`, `internal/service/search_indexer_worker.go`, `cmd/reindex_search/main.go`, search handler/document/indexer tests | `reference/chatwoot/app/views/api/v1/models/_message.json.jbuilder`, `reference/chatwoot/app/models/message.rb#push_event_data`, `reference/chatwoot/app/models/attachment.rb#push_event_data`, `reference/chatwoot/app/javascript/dashboard/modules/search/components/SearchResultMessagesList.vue`, `SearchResultMessageItem.vue` | Message SearchAPI results now match the reused frontend card needs from Chatwoot's `_message` serializer: `conversation_id` is the conversation display ID for navigation, `sender` is hydrated from persisted contact/user rows for DB-backed handlers, attachments use Chatwoot-style push data, and Meilisearch message documents carry display-ID/attachment payload data when relations are preloaded by durable indexing and full reindex. | Review by `feat(search): align message result payloads`; focused SearchHandler, SearchRepo, DurableSearchIndexer, reindex, and document-builder tests prove DB-backed payload hydration plus Meilisearch nested payload shape; full `go test ./...` passed outside the restricted socket sandbox; `git diff --check` passed. No route artifacts change. |
|
||||
| P3.83 search conversation ordering parity | `internal/repository/search_repo.go`, `internal/repository/search_repo_test.go` | `reference/chatwoot/app/services/search_service.rb#filter_conversations` | Conversation DB fallback search default ordering now uses `conversations.created_at DESC, conversations.id DESC`, matching Chatwoot `@conversations = conversations_query.order('conversations.created_at DESC')`, instead of the older local `last_activity_at DESC` conversation-list default. | Review by `feat(search): align conversation search order`; focused test proves created-at ordering wins even when `last_activity_at` points the other way; full `go test ./...` passed outside the restricted socket sandbox after retrying an unrelated `internal/worker` SQLite in-memory flake; `git diff --check` passed. No route artifacts change. |
|
||||
| P3.82 search contact-conversation reindex parity | `internal/service/contact_service.go`, `internal/service/search_indexer_hooks_test.go` | `reference/chatwoot/app/services/search_service.rb#filter_conversations`, P3.81 Meilisearch conversation document contract | Contact search indexing now fans out to related account-scoped conversations after the contact document is indexed. Each related conversation is loaded with `Contact` preloaded and passed to `IndexConversation`, keeping Meilisearch conversation identity text aligned with contact direct updates and import merge updates. | Review by `feat(search): reindex contact conversations`; focused test proves contact update indexes both the contact and its conversation with the updated contact name; full `go test ./...` passed outside the restricted socket sandbox; `git diff --check` passed. No route artifacts change. |
|
||||
| P3.81 search conversation identity parity | `internal/repository/search_repo.go`, `internal/search/engine.go`, `internal/model/conversation.go`, `internal/service/search_indexer_worker.go`, `cmd/reindex_search/main.go`, repository/search/service tests | `reference/chatwoot/app/services/search_service.rb#filter_conversations`, `reference/chatwoot/app/javascript/dashboard/api/search.js`, `reference/chatwoot/app/javascript/dashboard/api/specs/search.spec.js` | Conversation global/entity search now matches Chatwoot's identity search contract: DB fallback matches `CAST(conversations.display_id AS TEXT)` plus joined contact `name`, `email`, `phone_number`, and `identifier`, while label and message-content text are not conversation-search matches. Meilisearch conversation documents use display/contact identity text in `title`/`content`; the conversation model exposes a `Contact` relation for preload; durable search indexing and full reindex preload contacts before indexing conversation documents. | Review by `feat(search): align conversation identity search`; focused tests cover DB display/contact matching, DB label/message exclusion, Meilisearch document content, and durable contact preload; full `go test ./...` passed outside the restricted socket sandbox; `git diff --check` passed. No route artifacts change. |
|
||||
@@ -358,6 +360,7 @@ This ledger records the committed parity checkpoints that future slices should b
|
||||
|
||||
| Commit | Scope | Verification summary | Follow-up state |
|
||||
| --- | --- | --- | --- |
|
||||
| `feat(search): align message result payloads` | Advances P3.86 with Chatwoot SearchAPI message result payload parity. Message search hits now route to conversation display IDs instead of DB IDs, expose `sender` push data for DB-backed results, expose attachment push data for DB-backed and Meilisearch document results, and index/reindex message documents with preloaded conversation/attachment display data where available. | `go test ./internal/handler/api/v1 ./internal/search ./internal/repository ./internal/service ./cmd/reindex_search -run 'TestSearchHandler_SearchMessages\|TestDocumentBuildersSetStableUIDAndType\|TestMessageDocumentCarriesChatwootPayloadData\|TestSearchRepo_SearchMessages\|TestDurableSearchIndexer' -count=1` passed with workspace-local temp/cache dirs; full `go test ./...` passed outside the restricted socket sandbox; `git diff --check` passed. No route artifacts change. | Move P3.86 to Review; continue Phase 2/3 drift audit, Phase 6 placeholder audit, or B12 live smoke. |
|
||||
| `feat(search): align conversation result payloads` | Advances P3.85 with Chatwoot search conversation-result payload parity. SearchAPI conversation hits now expose nested `message`, `contact`, `inbox`, `agent`, and `additional_attributes` data from both DB fallback rows and Meilisearch documents, and the indexing/reindexing paths preload the display relations needed by the reused frontend cards. | Focused SearchHandler, SearchRepo, and document-builder tests passed; full `go test ./...` passed outside the restricted socket sandbox; `git diff --check` passed. No route artifacts change. | Move P3.85 to Review; continue Phase 2/3 drift audit, Phase 6 placeholder audit, or B12 live smoke. |
|
||||
| `feat(search): align agent sender filters` | Advances P3.84 with Chatwoot SearchAPI sender filter parity. The reused frontend `from=agent:id` filter now matches locally persisted agent/user sender variants in DB fallback and Meilisearch filters, while contact and bot sender filters tolerate Rails/local casing drift. | Focused SearchFilter, Meilisearch engine, and SearchRepo sender-filter tests passed; full `go test ./...` passed outside the restricted socket sandbox; `git diff --check` passed. No route artifacts change. | Move P3.84 to Review; continue search payload smoke or the next Phase 2/3 drift slice. |
|
||||
| `feat(search): align conversation search order` | Advances P3.83 with Chatwoot `SearchService#filter_conversations` ordering parity. DB fallback conversation search now defaults to `conversations.created_at DESC` with deterministic `id DESC`, instead of reusing the normal conversation list `last_activity_at` ordering. | `go test ./internal/repository -run 'TestSearchRepo_SearchConversations_DefaultOrderUsesCreatedAt\|TestSearchRepo_SearchConversations_(DisplayAndContactMatch\|DoesNotMatchLabelsOrMessages)' -count=1`; full `go test ./...` passed outside the restricted socket sandbox after retrying an unrelated `internal/worker` SQLite in-memory flake; `git diff --check` passed. No route artifacts change. | Move P3.83 to Review; continue Phase 2/3 drift audit, Phase 6 placeholder audit, or B12 live smoke. |
|
||||
@@ -608,9 +611,9 @@ This ledger records the committed parity checkpoints that future slices should b
|
||||
|
||||
## Next Slice Contract
|
||||
|
||||
Committed implementation baseline: `0b47066 feat(search): align conversation result payloads` closes P3.85 SearchAPI conversation payload parity for the inspected `reference/chatwoot` search controller, Jbuilder views, and reused dashboard search result cards.
|
||||
Committed implementation baseline: the current checkpoint is prepared as `feat(search): align message result payloads`, closing P3.86 SearchAPI message payload parity for the inspected `reference/chatwoot` message serializer, push-event data, and reused dashboard message search result cards.
|
||||
|
||||
Completed documentation slice: this checkpoint keeps the plan self-contained for follow-up work. The user-confirmed scope, Hermes source-plan landing map, active route/search/enterprise contracts, current route-parity numbers, next executable queue, P3.84/P3.85 commit ledger rows, and progress log are all represented in this document.
|
||||
Completed documentation slice: this checkpoint keeps the plan self-contained for follow-up work. The user-confirmed scope, Hermes source-plan landing map, active route/search/enterprise contracts, current route-parity numbers, next executable queue, P3.86 commit ledger row, and progress log are all represented in this document.
|
||||
|
||||
Next implementation slice: do not start from older Hermes TODOs directly. Continue with one of these evidence-backed paths: Phase 2/3 route/controller/serializer drift audit, Phase 6 placeholder audit, or B12 live smoke when the full PostgreSQL/Redis/Meilisearch/GoChat/Vite/Chrome stack is available. Every discovered failure becomes a named row in the Active Remaining Work Board before implementation.
|
||||
|
||||
@@ -823,7 +826,7 @@ B6 request and payload matrix after `a16c23c`:
|
||||
| --- | --- | --- | --- |
|
||||
| `GET /api/v1/accounts/:account_id/search` | `q`, `page`, default 15 items, existing local filters, plus `since`, `until`, `from`, `inbox_id`. | `{ payload: { conversations, contacts, messages, articles } }`. | `TestSearchHandler_GlobalSearch_Success`, `TestParseSearchFilter_ChatwootSearchParams`. |
|
||||
| `GET /api/v1/accounts/:account_id/search/conversations` | `q`, `page`, status/priority/assignee/team/inbox/labels/date filters. | `{ payload: { conversations: [...] } }`. | `TestSearchHandler_SearchConversations_Success`. |
|
||||
| `GET /api/v1/accounts/:account_id/search/messages` | `q`, `page`, `message_type`, `sender_type`, `from`, `sender_id`, `content_type`, `private`, `inbox_id`, `since`, `until`. | `{ payload: { messages: [...] } }` with numeric Chatwoot `message_type` for model and Meilisearch hit data. | `TestSearchHandler_SearchMessages_Success`, `TestSearchHandler_SearchMessages_MeiliHitPayloadShape`, `TestMeiliSearchEngine_SearchSendsMessageSenderIDFilter`. |
|
||||
| `GET /api/v1/accounts/:account_id/search/messages` | `q`, `page`, `message_type`, `sender_type`, `from`, `sender_id`, `content_type`, `private`, `inbox_id`, `since`, `until`. | `{ payload: { messages: [...] } }` with numeric Chatwoot `message_type`, conversation display IDs, sender push data, and attachment push data for DB-backed and Meilisearch hit data. | `TestSearchHandler_SearchMessages_Success`, `TestSearchHandler_SearchMessages_MeiliHitPayloadShape`, `TestSearchHandler_SearchMessages_HydratesChatwootMessagePayload`, `TestMeiliSearchEngine_SearchSendsMessageSenderIDFilter`. |
|
||||
| `GET /api/v1/accounts/:account_id/search/contacts` | `q`, `page`, `contact_source`. | `{ payload: { contacts: [...] } }`. | `TestSearchHandler_SearchContacts_Success`. |
|
||||
| `GET /api/v1/accounts/:account_id/search/articles` | `q`, `page`, `portal_id`, `article_status`, `locale`. | `{ payload: { articles: [...] } }`. | `TestSearchHandler_SearchArticles_Success`. |
|
||||
|
||||
@@ -2720,3 +2723,4 @@ Verification milestone gates:
|
||||
- 2026-06-07: P3.84 search agent-sender filter checkpoint prepared as `feat(search): align agent sender filters`; audited Chatwoot `SearchService#parse_from_param`, `#apply_sender_filter`, and reused `SearchContactAgentSelector.vue`/SearchAPI message filter callers. GoChat DB fallback and Meilisearch message filters now treat `from=agent:id` as agent/user sender aliases (`agent`, `user`, `User`) and tolerate contact/bot casing aliases, so reused frontend agent filters find locally stored outgoing agent messages. Focused SearchFilter, Meilisearch engine, and SearchRepo sender-filter tests passed; full `go test ./...` passed outside the restricted socket sandbox; `git diff --check` passed. No route artifacts change.
|
||||
- 2026-06-07: P3.85 search conversation payload checkpoint prepared as `feat(search): align conversation result payloads`; audited Chatwoot search `conversations.json.jbuilder`, `_conversation_search_result`, `_message`, `_contact`, `_inbox`, `_agent`, and reused `SearchResultConversationsList.vue`. GoChat SearchAPI conversation results now include nested `message`, `contact`, `inbox`, `agent`, and `additional_attributes` payloads for DB fallback and Meilisearch hits; DB search, durable indexing, contact fanout reindexing, and `cmd/reindex_search` now preload the display relations needed to build those documents. Focused SearchHandler, SearchRepo, and document-builder tests passed; full `go test ./...` passed outside the restricted socket sandbox; `git diff --check` passed. No route artifacts change.
|
||||
- 2026-06-07: Documentation checkpoint prepared as `docs: reconcile parity tracker`; current baseline now points at `0b47066 feat(search): align conversation result payloads`, the stale P3.39 next-slice wording is replaced, and the Commit Ledger now includes P3.84/P3.85 so the plan can be followed from this document without reading older Hermes notes. Verification for this docs-only checkpoint: `git diff --check`; no Go code or route artifacts changed.
|
||||
- 2026-06-07: P3.86 search message payload checkpoint prepared as `feat(search): align message result payloads`; audited Chatwoot `_message.json.jbuilder`, `Message#push_event_data`, `Attachment#push_event_data`, and reused `SearchResultMessagesList.vue`/`SearchResultMessageItem.vue`. GoChat SearchAPI message results now hydrate DB-backed hits with conversation display IDs, sender push data, and attachment push data; Meilisearch hit serialization preserves nested sender/attachment payloads; message documents, durable index replay, and full `cmd/reindex_search` now preload or carry display/attachment data where available. Focused SearchHandler, SearchRepo, DurableSearchIndexer, reindex, and document-builder tests passed; full `go test ./...` passed outside the restricted socket sandbox; `git diff --check` passed. No route artifacts change.
|
||||
|
||||
Reference in New Issue
Block a user