feat(contacts): initiate voice calls
This commit is contained in:
@@ -37,14 +37,14 @@ Hermes plan landing map:
|
||||
|
||||
## Current Baseline
|
||||
|
||||
- Current tracking checkpoint: 2026-06-06 on `5a3da22 feat(help-center): queue article translations`.
|
||||
- Latest implementation checkpoint: `5a3da22 feat(help-center): queue article translations`.
|
||||
- Current tracking checkpoint: 2026-06-06 after this implementation checkpoint, prepared as `feat(contacts): initiate voice calls`.
|
||||
- Latest implementation checkpoint: this checkpoint, prepared as `feat(contacts): initiate voice calls`.
|
||||
- Latest documentation/tooling checkpoint: `docs: land parity execution tracker`; this document is now the active follow-up plan and supersedes `.hermes/plans/*`.
|
||||
- Worktree status at this implementation checkpoint: P3.7d enterprise help-center article translation now matches the reused dashboard `bulkTranslate` route and Chatwoot enterprise `Articles::BulkActionsController#translate`/`Captain::Articles::TranslateJob` boundary: `POST /articles/bulk_actions/translate` validates `captain_tasks`, allowed portal locale, optional locale-scoped category, and article IDs; returns `409 { duplicate_articles }` unless `force` is true; enqueues durable low-priority `captain:article_translate` jobs; and replays translation through an LLM backend using Chatwoot's title/content prompts before creating or updating draft translated articles. P6.5 inbox agent-bot member actions, P6 message retry parity, P6 conversation custom-attribute response parity, and P3.7a-P3.7c help center portal/category/article payload parity remain in Review. Campaign create/update already mirrors Chatwoot `Campaign#ensure_correct_campaign_attributes`; account campaign CRUD already matches the reused dashboard `campaigns` store and Chatwoot Jbuilder contract. Agent/settings/profile/notification/contact/custom-field/report enterprise drifts listed below remain at their prior checkpoint states. The fresh placeholder audit found remaining `chatwootParityStub` routes only in webhook handler-not-injected fallbacks, not in the reused dashboard account/contact/conversation/message/inbox critical path. P3.6 custom filters/custom attribute definitions and label CRUD are already in Review. B11.1a-B11.3e Captain/Copilot slices remain in Review; B12.1/B12.2/B12.3 smoke harnesses remain in Review; P5 durable job work through P5.13b is in Review. Next active implementation slice is another Phase 6 placeholder burn-down item or a new Phase 2/3 drift slice from fresh reference/smoke evidence.
|
||||
- Worktree status at this implementation checkpoint: P6.8 contact outbound voice call parity is now implemented for the reused dashboard `ContactAPI.initiateCall`/voice client route and Chatwoot enterprise `Contacts::CallsController#create` plus `Voice::OutboundCallBuilder` boundary. `POST /contacts/:contact_id/call` validates the account contact, current user's assigned Twilio voice inbox, `voice_enabled` channel config, and contact phone number; reuses only matching open display-ID conversations; otherwise creates a ContactInbox and open conversation; persists Twilio outgoing call metadata plus a `voice_call` message payload; and returns `{ conversation_id, inbox_id, call_sid, conference_sid }`. P3.7d enterprise help-center article translation, P6.5 inbox agent-bot member actions, P6 message retry parity, P6 conversation custom-attribute response parity, and P3.7a-P3.7c help-center payload parity remain in Review. The fresh placeholder audit found remaining `chatwootParityStub` routes only in webhook handler-not-injected fallbacks, not in the reused dashboard account/contact/conversation/message/inbox critical path. P3.6 custom filters/custom attribute definitions and label CRUD are already in Review. B11.1a-B11.3e Captain/Copilot slices remain in Review; B12.1/B12.2/B12.3 smoke harnesses remain in Review; P5 durable job work through P5.13b is in Review. Next active implementation slice is another Phase 6 placeholder burn-down item or a new Phase 2/3 drift slice from fresh reference/smoke evidence.
|
||||
- `go test ./...` passes.
|
||||
- Route dump succeeds with `TOTAL: 860` after adding no-trailing-slash article index/create aliases, frontend-used article PATCH update route, and frontend article bulk-action routes.
|
||||
- Route dump succeeds with `TOTAL: 861` after adding the enterprise contact outbound voice call route.
|
||||
- Route parity artifacts now exist under `docs/parity/` and are generated by `cmd/route_parity`.
|
||||
- Tracked frontend-critical route audit covers 305 Chatwoot routes: 298 exact, 0 method-compatible, 7 parameter-compatible, 0 missing. The 7 parameter-compatible routes are Gin-internal parameter-name differences for nested AgentCapacityPolicy users/inbox limits; the external URL shape is equivalent.
|
||||
- Tracked frontend-critical route audit covers 306 Chatwoot routes: 299 exact, 0 method-compatible, 7 parameter-compatible, 0 missing. The 7 parameter-compatible routes are Gin-internal parameter-name differences for nested AgentCapacityPolicy users/inbox limits; the external URL shape is equivalent.
|
||||
- `/api/v1/widget` stubs are burned down and public inbox/contact/conversation/message core flows are backed by real handlers.
|
||||
- Handler test stability fixes are committed into the baseline before feature parity work continues.
|
||||
- `.codegraph/` is generated indexing output and is not part of tracked product code.
|
||||
@@ -74,10 +74,9 @@ Execution queue for the next agent turn:
|
||||
|
||||
| Order | Slice ID | Why now | Required commit contents |
|
||||
| --- | --- | --- | --- |
|
||||
| 1 | P6.8 contact outbound voice call parity | The reused Chatwoot dashboard calls `POST /api/v1/accounts/:account_id/contacts/:contact_id/call`, and GoChat does not register or implement it yet. | Route, handler/service behavior, tests, route artifacts, this tracker, and commit `feat(contacts): initiate voice calls`. |
|
||||
| 2 | Phase 2/3 drift audit | Route parity is currently green for the tracked set, but only fresh reference/frontend inspection proves the next missing reused-frontend path. | Named drift rows with inspected reference files, fixture tests where behavior is known, regenerated route artifacts if the route set changes. |
|
||||
| 3 | Phase 6 placeholder audit | `chatwootParityStub` remains only as webhook nil-handler fallback, but every audit result must stay recorded so no frontend-critical stub becomes ownerless. | `rg` audit result, either a burn-down implementation or explicit non-frontend fallback classification, focused tests if code changes. |
|
||||
| 4 | B12 live smoke | The harness is checked in; live pass/fail still needs the full PostgreSQL/Redis/Meilisearch/Vite/Chrome stack. | Updated smoke report with command, environment, failures, and linked owner rows. |
|
||||
| 1 | Phase 2/3 drift audit | Route parity is currently green for the tracked set, but only fresh reference/frontend inspection proves the next missing reused-frontend path. | Named drift rows with inspected reference files, fixture tests where behavior is known, regenerated route artifacts if the route set changes. |
|
||||
| 2 | Phase 6 placeholder audit | `chatwootParityStub` remains only as webhook nil-handler fallback, but every audit result must stay recorded so no frontend-critical stub becomes ownerless. | `rg` audit result, either a burn-down implementation or explicit non-frontend fallback classification, focused tests if code changes. |
|
||||
| 3 | B12 live smoke | The harness is checked in; live pass/fail still needs the full PostgreSQL/Redis/Meilisearch/Vite/Chrome stack. | Updated smoke report with command, environment, failures, and linked owner rows. |
|
||||
|
||||
Slice lifecycle:
|
||||
|
||||
@@ -127,9 +126,9 @@ This table is the shortest authoritative handoff view. If an older lower section
|
||||
|
||||
| Priority | Workstream | Current state | Next checkpoint | Commit close rule |
|
||||
| --- | --- | --- | --- | --- |
|
||||
| 1 | Phase 2/3 drift | Tracked route parity is 0 missing for the current 305-route critical set; help-center portal/category/article routes from `routes.rb:385-404` are now explicitly tracked. Notification list/action serializers, user notification-settings raw payloads, campaigns raw payload/display-id routes, Devise password reset/confirmation payloads, CRM shared attachment payloads plus fixed 100-row attachment pagination, account/settings payloads, assignable-agent payloads, agent index full-list behavior, agent create/update/delete defaults/errors/scope, label CRUD payloads, custom filters, custom attribute definitions, and help-center portal/category/article payloads now match the inspected Chatwoot frontend contract. | Run the next evidence-backed route/controller/serializer drift audit. | Regenerate parity artifacts when routes change and add endpoint-family fixture tests. |
|
||||
| 1 | Phase 2/3 drift | Tracked route parity is 0 missing for the current 306-route critical set; help-center portal/category/article routes from `routes.rb:385-404` and enterprise contact outbound voice call from `routes.rb:216` are now explicitly tracked. Notification list/action serializers, user notification-settings raw payloads, campaigns raw payload/display-id routes, Devise password reset/confirmation payloads, CRM shared attachment payloads plus fixed 100-row attachment pagination, account/settings payloads, assignable-agent payloads, agent index full-list behavior, agent create/update/delete defaults/errors/scope, label CRUD payloads, custom filters, custom attribute definitions, contact outbound voice calls, and help-center portal/category/article payloads now match the inspected Chatwoot frontend contract. | Run the next evidence-backed route/controller/serializer drift audit. | Regenerate parity artifacts when routes change and add endpoint-family fixture tests. |
|
||||
| 2 | Phase 6 placeholder audit | Widget/public/webhook critical placeholders are burned down; inbox WhatsApp health/register-webhook and sync-template drift are closed; fresh `rg` audit shows only webhook nil-handler fallbacks still call `chatwootParityStub`; dashboard conversation transcript/custom-attribute response drift and message retry status drift are closed. | Continue targeted account/contact/conversation/message/inbox drift from reference/smoke evidence. | `rg` placeholder audit is recorded and no reused-frontend blocker is ownerless. |
|
||||
| 3 | P6.8 contact outbound voice call | Reference enterprise route exists at `contacts#call`; reused dashboard invokes it from contacts/voice clients; GoChat has no matching route/handler. | Implement `POST /contacts/:contact_id/call` with Twilio voice-enabled inbox validation, assigned-inbox check, open-conversation reuse, call/message persistence, and Chatwoot response shape. | Focused contact call tests, route dump/parity regeneration, full `go test ./...`, and `git diff --check`. |
|
||||
| 3 | P6.8 contact outbound voice call | Implemented for the reused dashboard route with Twilio voice-enabled inbox validation, assigned-inbox check, open-conversation reuse, ContactInbox/conversation/call/message persistence, and Chatwoot response shape. | Keep in Review; reopen only if live smoke exposes provider initiation/status-update drift beyond the fakeable persisted boundary. | Focused contact call tests, route dump/parity regeneration, full `go test ./...`, and `git diff --check` passed. |
|
||||
| 4 | B12 optional live smoke | API/browser/enterprise smoke commands are checked in; live runs need PostgreSQL, Redis, Meilisearch, Vite, and Chrome. | Run full live smoke when environment is available and map failures to the board. | `docs/parity/frontend_smoke_report.md` records pass/fail and linked owners. |
|
||||
| 5 | B9.3 delayed automation actions | Current reference exposes no delayed automation action params; scheduled-item work is already P5.12; `send_email_to_team` is durable and `add_sla` mutates conversation/applied SLA state. | Keep automation drift closed if future reference/smoke exposes delayed params or unsupported action shapes. | Automation worker/action fixtures verify queued team email replay, retry visibility through worker jobs, and SLA action idempotency. |
|
||||
| 6 | P5.13 reports/analytics | P5.13a derives visible report aggregates from persisted rows; P5.13b adds lazy rollup freshness, durable day rollup jobs, and `/reports` metric timeseries. | Keep report drift closed as frontend smoke or reference inspection exposes additional metrics. | Report fixtures verify timeseries values, cache/freshness behavior, and no hidden placeholder JSON. |
|
||||
@@ -151,7 +150,7 @@ These rows are the executable development plan from this point forward. A checkp
|
||||
| P3.7b help center category route/payload parity | `internal/router/router.go`, `internal/handler/api/v1/category_handler.go`, `internal/service/category_service.go`, `internal/repository/category_repo.go`, category tests | `reference/chatwoot/app/controllers/api/v1/accounts/categories_controller.rb`, `app/views/api/v1/accounts/categories/*.json.jbuilder`, dashboard `api/helpCenter/categories.js` | Category APIs now resolve portal slugs account-scoped for `/portals/:portal_id/categories`, accept raw category bodies plus wrappers, expose frontend no-trailing-slash and `PATCH` routes, return Chatwoot `{ payload, meta }` and `{ payload: category }` serializers with locale filtering and article counts, make delete/reorder empty `200 OK`, accept Chatwoot `positions_hash`, and keep category mutations scoped to the resolved portal. | Review by `feat(help-center): align category payloads`; focused category handler/service/repository tests, route dump/parity regeneration, full `go test ./...`, and `git diff --check` passed. |
|
||||
| P3.7c help center article and bulk-action parity | `internal/router/router.go`, `internal/handler/api/v1/article_handler.go`, `internal/service/article_service.go`, `internal/repository/article_repo.go`, article tests | `reference/chatwoot/app/controllers/api/v1/accounts/articles_controller.rb`, `app/controllers/api/v1/accounts/articles/bulk_actions_controller.rb`, `app/views/api/v1/accounts/articles/*.json.jbuilder`, dashboard `api/helpCenter/articles.js` | Article APIs now resolve portal slugs account-scoped with numeric fallback, accept raw article bodies plus wrappers, expose no-trailing-slash index/create plus frontend `PATCH`, return Chatwoot `{ payload, meta }` list/search payloads and `{ payload: article }` show/create/update/edit payloads, serialize category/author/views/Unix updated-at/meta/associated articles, make delete/reorder/bulk actions empty `200 OK`, accept Chatwoot `positions_hash`, scope mutations to the resolved portal, and implement frontend bulk update-status/update-category/delete routes. | Review by `feat(help-center): align article payloads`; focused article handler tests, service/repository article tests, router test, route dump/parity regeneration, escalated full `go test ./...`, and `git diff --check` passed. |
|
||||
| P3.7d enterprise article bulk translation | `internal/handler/api/v1/article_handler.go`, `internal/service/article_service.go`, `internal/repository/article_repo.go`, `internal/app/bootstrap.go`, article handler/service tests | `reference/chatwoot/enterprise/app/controllers/enterprise/api/v1/accounts/articles/bulk_actions_controller.rb`, `enterprise/app/jobs/captain/articles/translate_job.rb`, `enterprise/app/services/captain/llm/article_translation_service.rb`, dashboard `api/helpCenter/articles.js`, `BulkTranslateDialog.vue` | Article bulk translate now validates `captain_tasks`, portal allowed locales, optional target-locale category, and selected articles; detects existing root-article translations and returns `409 { duplicate_articles }` unless `force` is true; queues durable low-priority `captain:article_translate` jobs; maps locale codes to English language names; and creates or updates draft translated articles through the wired LLM translation backend using Chatwoot's title/content prompts. | Review by `feat(help-center): queue article translations`; focused service/handler tests, combined service/handler/repository/app tests, full `go test ./...`, and `git diff --check` passed. No route changes. |
|
||||
| P6.8 contact outbound voice call parity | `internal/router/router.go`, `internal/handler/api/v1/contact_handler.go`, contact service/conversation/contact-inbox/call/message boundaries, contact handler tests | `reference/chatwoot/config/routes.rb:216`, `reference/chatwoot/enterprise/app/controllers/api/v1/accounts/contacts/calls_controller.rb`, `reference/chatwoot/enterprise/app/services/voice/outbound_call_builder.rb`, dashboard `api/contacts.js`, `store/modules/contacts/actions.js`, `api/channel/voice/voiceAPIClient.js` | Implement Chatwoot enterprise `POST /api/v1/accounts/:account_id/contacts/:contact_id/call`: authorize the contact and current user's assigned Twilio voice inbox, require a contact phone number and `voice_enabled` channel config, reuse only an open conversation whose display ID matches the same contact/inbox, otherwise create contact inbox plus open conversation, initiate or fakeably boundary the provider call, persist call/message side effects, and return `{ conversation_id, inbox_id, call_sid, conference_sid }`. | Todo. Close with focused contact call tests for success/reuse/mismatched-conversation/new-conversation/no-phone/non-voice/unassigned cases; regenerate route artifacts; run full `go test ./...`; run `git diff --check`; commit as `feat(contacts): initiate voice calls`. |
|
||||
| P6.8 contact outbound voice call parity | `internal/router/router.go`, `internal/handler/api/v1/contact_handler.go`, `internal/service/contact_service.go`, `internal/model/call.go`, contact handler tests | `reference/chatwoot/config/routes.rb:216`, `reference/chatwoot/enterprise/app/controllers/api/v1/accounts/contacts/calls_controller.rb`, `reference/chatwoot/enterprise/app/services/voice/outbound_call_builder.rb`, `reference/chatwoot/enterprise/app/services/voice/call_message_builder.rb`, `reference/chatwoot/enterprise/app/models/call.rb`, dashboard `api/contacts.js`, `store/modules/contacts/actions.js`, `api/channel/voice/voiceAPIClient.js` | Contact outbound calls now match the Chatwoot enterprise route boundary: account contact lookup, current user's assigned `Channel::TwilioSms` inbox lookup, `voice_enabled` guard, phone-number guard, open display-ID conversation reuse only for same inbox/contact, new ContactInbox/open conversation creation when needed, persisted outgoing Twilio call metadata, linked `voice_call` message content attributes, and raw `{ conversation_id, inbox_id, call_sid, conference_sid }` response. | Review by `feat(contacts): initiate voice calls`; focused contact call tests cover success/reuse/resolved-hint ignored/no-phone/non-voice/unassigned cases; route dump/parity regenerated to `TOTAL: 861` and `299 exact, 7 parameter-compatible, 0 missing out of 306`; full `go test ./...` and `git diff --check` passed. |
|
||||
| P6 conversation transcript response parity | `internal/handler/api/v1/conversation_handler.go`, conversation handler tests | `reference/chatwoot/app/controllers/api/v1/accounts/conversations_controller.rb`, dashboard `api/inbox/conversation.js` | Account conversation transcript now follows Chatwoot's controller contract: missing email returns `422 { error: "email param missing" }`, nonblank email schedules through the existing service boundary and returns empty `200 OK`, and invalid-looking but nonblank email values are not rejected by local email format validation. | Review by `feat(conversations): align transcript responses`; focused transcript handler/service tests, combined handler/service/router tests, full `go test ./...`, and `git diff --check` must pass. |
|
||||
| P6 conversation custom attributes response parity | `internal/handler/api/v1/conversation_handler.go`, conversation handler tests | `reference/chatwoot/app/controllers/api/v1/accounts/conversations_controller.rb`, `app/views/api/v1/accounts/conversations/custom_attributes.json.jbuilder`, dashboard `api/inbox/conversation.js`, conversation store action | Account conversation custom attribute updates now return Chatwoot `{ custom_attributes: ... }` only, matching the store action that reads `response.data.custom_attributes`, instead of returning the full conversation serializer with unrelated fields. Empty/null JSON serializes as `{}`. | Review by `feat(conversations): align custom attribute response`; focused handler tests, combined handler/service/router tests, full `go test ./...`, and `git diff --check` passed. |
|
||||
| P6 message retry status parity | `internal/service/message_service.go`, `internal/handler/api/v1/message_handler.go`, message service/handler tests | `reference/chatwoot/app/controllers/api/v1/accounts/conversations/messages_controller.rb`, `app/views/api/v1/accounts/conversations/messages/retry.json.jbuilder`, dashboard `api/inbox/message.js` | Account message retry now follows Chatwoot: status resets to `sent`, `content_attributes` is cleared to `{}`, response returns the message serializer, and the existing durable SendReplyJob path is queued when a worker pool is configured. | Review by `feat(messages): align retry status parity`; focused retry service/handler tests, combined handler/service tests, full `go test ./...`, and `git diff --check` must pass. |
|
||||
@@ -190,6 +189,7 @@ This ledger records the committed parity checkpoints that future slices should b
|
||||
|
||||
| Commit | Scope | Verification summary | Follow-up state |
|
||||
| --- | --- | --- | --- |
|
||||
| `feat(contacts): initiate voice calls` | Advances P6.8 contact outbound voice call parity by matching Chatwoot enterprise `Contacts::CallsController#create`, `Voice::OutboundCallBuilder`, `Voice::CallMessageBuilder`, `Call`, and the reused dashboard `ContactAPI.initiateCall`/voice client path. GoChat now registers `POST /api/v1/accounts/:account_id/contacts/:contact_id/call`, requires an assigned `Channel::TwilioSms` inbox with `voice_enabled`, requires a contact phone number, reuses only matching open display-ID conversations, creates ContactInbox/open conversation records when needed, persists Twilio outgoing call metadata and a linked `voice_call` message payload, and returns `{ conversation_id, inbox_id, call_sid, conference_sid }`. | `go test ./internal/handler/api/v1 -run 'ContactHandlerCRUDTestSuite/TestInitiateCall' -count=1`; `go test ./internal/service ./internal/handler/api/v1 ./internal/router -run 'Contact\|Router' -count=1`; `go run ./cmd/dump_routes > docs/parity/gochat_routes.txt`; `go run ./cmd/route_parity`; `go test ./cmd/route_parity -count=1`; `go test ./...`; `git diff --check`. Route dump is `TOTAL: 861`; tracked route parity is `299 exact, 0 method-compatible, 7 parameter-compatible, 0 missing out of 306`. | P6.8 moves to Review; continue Phase 2/3 drift audit, Phase 6 placeholder audit, or B12 live smoke. |
|
||||
| `docs: land parity execution tracker` | Documentation-only checkpoint that turns the Hermes-era search and automation/macro/CSAT notes, user-confirmed enterprise scope, latest help-center baseline, and fresh contact voice-call drift into one executable queue. Adds lifecycle rules, ordered next slices, explicit P6.8 contact outbound voice-call contract, and updates the active board so future work can be tracked without reopening `.hermes/plans/*`. | `git diff --check`. No Go code changed and no route artifacts changed. | Start P6.8 contact outbound voice-call parity, or run the next Phase 2/3 plus Phase 6 evidence audit before implementation. |
|
||||
| `feat(help-center): queue article translations` | Advances P3.7d enterprise help-center parity by matching Chatwoot enterprise `Articles::BulkActionsController#translate`, `Captain::Articles::TranslateJob`, `Captain::Llm::ArticleTranslationService`, and the reused dashboard `bulkTranslate` flow. Bulk translate now enforces `captain_tasks`, portal allowed locales, optional locale-matched categories, and article selection; returns `409 { duplicate_articles }` for existing translations unless `force` is true; enqueues low-priority durable `captain:article_translate` jobs; registers replay in bootstrap; and uses a wired LLM-backed article translator with Chatwoot title/content prompts and locale-to-English target language names before creating or updating draft translated articles. | `go test ./internal/service -run 'ArticleService_.*Translate\|LLMArticleTranslationBackend\|ArticleService_BulkActions\|ArticleService_BulkUpdateStatus\|ArticleService_BulkDelete' -count=1`; `go test ./internal/handler/api/v1 -run 'ArticleHandlerSuite/TestBulkTranslate\|ArticleHandlerSuite/TestBulkActions' -count=1`; `go test ./internal/service ./internal/handler/api/v1 ./internal/repository ./internal/app -run 'Article\|Bootstrap\|App' -count=1`; `go test ./...`; `git diff --check`. No route changes. | P3.7d moves to Review; continue Phase 6 placeholder burn-down or the next evidence-backed Phase 2/3 drift slice. |
|
||||
| `feat(inboxes): align agent bot member actions` | Advances P6.5 inbox API parity by aligning `GET /inboxes/:id/agent_bot` and `POST /inboxes/:id/set_agent_bot` with Chatwoot `InboxesController#agent_bot`/`#set_agent_bot`, `inboxes/agent_bot.json.jbuilder`, `_agent_bot.json.jbuilder`, and the reused dashboard `agentBots` store/API path. The setter accepts Chatwoot `{ agent_bot: id|null }` bodies, keeps legacy `{ agent_bot_id }` compatibility, treats omitted/null params as disconnect, returns empty `200 OK`, destroys disconnected bindings instead of leaving inactive local rows, and updates the inbox's single binding on reassignment. The getter now returns `{ agent_bot: {} }` when disconnected and serializes assigned bots with Chatwoot fields such as `thumbnail`, `bot_type`, `bot_config`, and `outgoing_url`. | `go test ./internal/service -run 'InboxService_SetAgentBot' -count=1`; `go test ./internal/handler/api/v1 -run 'InboxHandler_Set.*AgentBot\|InboxHandler_GetAgentBot\|InboxSetAgentBot' -count=1`; `go test ./internal/handler/api/v1 ./internal/service -run 'Inbox.*AgentBot\|SetAgentBot' -count=1`; `go test ./...`; `git diff --check`. No route changes. | P6.5 remains Doing for additional inbox/channel drift; continue Phase 6 placeholder audit or the next evidence-backed inbox member action gap. |
|
||||
@@ -2147,6 +2147,7 @@ Verification milestone gates:
|
||||
|
||||
## Progress Log
|
||||
|
||||
- 2026-06-06: P6.8 contact outbound voice call checkpoint prepared as `feat(contacts): initiate voice calls`; audited Chatwoot `routes.rb:216`, enterprise `Contacts::CallsController#create`, `Voice::OutboundCallBuilder`, `Voice::CallMessageBuilder`, `Call`, and reused dashboard `api/contacts.js`, contact store action, and voice API client. GoChat now registers `POST /api/v1/accounts/:account_id/contacts/:contact_id/call`, validates account contact scope, current user's assigned Twilio voice inbox, `voice_enabled`, and contact phone number, reuses only matching open display-ID conversations, creates ContactInbox/open conversation rows when needed, persists outgoing Twilio call metadata and linked `voice_call` message content attributes, and returns `{ conversation_id, inbox_id, call_sid, conference_sid }`. Focused contact-call tests, combined service/handler/router tests, route dump/parity regeneration, `go test ./cmd/route_parity -count=1`, full `go test ./...`, and `git diff --check` passed; route dump is `TOTAL: 861` and tracked route parity is `299 exact, 0 method-compatible, 7 parameter-compatible, 0 missing out of 306`.
|
||||
- 2026-06-06: Documentation checkpoint prepared as `docs: land parity execution tracker`; consolidated the active execution queue so future work can be followed from `docs/CHATWOOT_PARITY_DEVELOPMENT_PLAN.md` alone. The tracker now pins current baseline commits, maps Hermes source plans to active sections, defines slice lifecycle states, records the ordered next queue, and opens P6.8 for Chatwoot enterprise contact outbound voice calls after inspecting `reference/chatwoot/config/routes.rb:216`, `enterprise/app/controllers/api/v1/accounts/contacts/calls_controller.rb`, `enterprise/app/services/voice/outbound_call_builder.rb`, and reused dashboard contact/voice API clients. Verification for this docs-only checkpoint: `git diff --check`; no Go code or route artifacts changed.
|
||||
- 2026-06-06: P3.7d enterprise article translation checkpoint prepared as `feat(help-center): queue article translations`; audited Chatwoot enterprise `Articles::BulkActionsController#translate`, `Captain::Articles::TranslateJob`, `Captain::Llm::ArticleTranslationService`, reused dashboard `api/helpCenter/articles.js`, and `BulkTranslateDialog.vue`. Account article bulk translate now validates `captain_tasks`, allowed portal locale, optional locale-scoped category, and selected articles; detects existing root-article translations and returns `409 { duplicate_articles }` unless `force` is true; queues durable low-priority `captain:article_translate` jobs; replays jobs by creating or updating draft translated articles; and wires an LLM-backed translation backend in bootstrap with Chatwoot title/content prompts and English target language names. Focused service/handler tests, combined service/handler/repository/app tests, full `go test ./...`, and `git diff --check` passed; no route artifacts changed.
|
||||
- 2026-06-06: P6.5 inbox agent-bot checkpoint prepared as `feat(inboxes): align agent bot member actions`; audited Chatwoot `InboxesController#agent_bot`, `InboxesController#set_agent_bot`, `inboxes/agent_bot.json.jbuilder`, `_agent_bot.json.jbuilder`, and the reused dashboard `agentBots` store/API. `POST /inboxes/:id/set_agent_bot` now accepts the frontend `{ agent_bot: id|null }` body, keeps legacy `{ agent_bot_id }` compatibility, treats omitted/null bodies as disconnect, returns empty `200 OK`, destroys disconnected bindings like Chatwoot `@inbox.agent_bot_inbox.destroy!`, and updates the inbox's single binding when reassigning bots. `GET /inboxes/:id/agent_bot` now returns `{ agent_bot: {} }` when disconnected and Chatwoot partial fields such as `thumbnail`, `bot_type`, `bot_config`, and `outgoing_url` when assigned. Focused inbox service/handler tests, combined handler/service tests, full `go test ./...`, and `git diff --check` passed; continue Phase 6 placeholder burn-down or the next evidence-backed inbox drift.
|
||||
|
||||
@@ -574,6 +574,7 @@ POST /api/v1/accounts/:account_id/companies/:company_id/destroy_custom_attribute
|
||||
POST /api/v1/accounts/:account_id/companies/:company_id/notes
|
||||
POST /api/v1/accounts/:account_id/contact_merge
|
||||
POST /api/v1/accounts/:account_id/contacts/
|
||||
POST /api/v1/accounts/:account_id/contacts/:contact_id/call
|
||||
POST /api/v1/accounts/:account_id/contacts/:contact_id/contact_inboxes
|
||||
POST /api/v1/accounts/:account_id/contacts/:contact_id/contact_inboxes/
|
||||
POST /api/v1/accounts/:account_id/contacts/:contact_id/custom_attributes/
|
||||
@@ -858,4 +859,4 @@ PUT /public/api/v1/csat_survey/:id
|
||||
PUT /public/api/v1/inboxes/:inbox_id/contacts/:contact_id
|
||||
PUT /public/api/v1/inboxes/:inbox_id/contacts/:contact_id/conversations/:conversation_id/messages/:message_id
|
||||
PUT /widget/direct_uploads/:upload_uuid
|
||||
TOTAL: 860
|
||||
TOTAL: 861
|
||||
|
||||
@@ -7,7 +7,7 @@ Generated from:
|
||||
|
||||
This report covers tracked frontend-critical Chatwoot routes from `reference/chatwoot/config/routes.rb`, including API v1 account routes, Captain/Copilot, assignment policies, widget/public APIs, and API v2 reports. Ruby is not installed in the workspace, so Chatwoot routes are sourced from static route declarations instead of `bin/rails routes`.
|
||||
|
||||
Summary: 298 exact, 0 method-compatible, 7 parameter-compatible, 0 missing out of 305 tracked critical routes.
|
||||
Summary: 299 exact, 0 method-compatible, 7 parameter-compatible, 0 missing out of 306 tracked critical routes.
|
||||
|
||||
## Missing Critical Routes
|
||||
|
||||
@@ -243,6 +243,7 @@ These routes exist with equivalent method and path shape but different parameter
|
||||
| POST | `/api/v1/accounts/:account_id/companies/:company_id/contacts` | `/api/v1/accounts/:account_id/companies/:company_id/contacts` | `api/v1/accounts/companies/contacts#create` | `routes.rb:188` | exact |
|
||||
| POST | `/api/v1/accounts/:account_id/companies/:company_id/destroy_custom_attributes` | `/api/v1/accounts/:account_id/companies/:company_id/destroy_custom_attributes` | `api/v1/accounts/companies#destroy_custom_attributes` | `routes.rb:184` | exact |
|
||||
| POST | `/api/v1/accounts/:account_id/contacts/` | `/api/v1/accounts/:account_id/contacts/` | `api/v1/accounts/contacts#create` | `routes.rb:197` | exact |
|
||||
| POST | `/api/v1/accounts/:account_id/contacts/:contact_id/call` | `/api/v1/accounts/:account_id/contacts/:contact_id/call` | `api/v1/accounts/contacts/calls#create` | `routes.rb:216` | exact |
|
||||
| POST | `/api/v1/accounts/:account_id/contacts/:contact_id/contact_inboxes/` | `/api/v1/accounts/:account_id/contacts/:contact_id/contact_inboxes/` | `api/v1/accounts/contacts/contact_inboxes#create` | `routes.rb:212` | exact |
|
||||
| POST | `/api/v1/accounts/:account_id/contacts/:contact_id/destroy_custom_attributes` | `/api/v1/accounts/:account_id/contacts/:contact_id/destroy_custom_attributes` | `api/v1/accounts/contacts#destroy_custom_attributes` | `routes.rb:207` | exact |
|
||||
| POST | `/api/v1/accounts/:account_id/contacts/:contact_id/labels/` | `/api/v1/accounts/:account_id/contacts/:contact_id/labels/` | `api/v1/accounts/contacts/labels#create` | `routes.rb:213` | exact |
|
||||
|
||||
Reference in New Issue
Block a user