Task Breakdown — AI Agent Knowledge: Conversation History
Effort Summary
| Phase / Area | FE days | BE days | QA days | Total |
|---|---|---|---|---|
| Phase 1 — UI (mocked) | 6.0 | — | 2.0 | 8.0 |
| Phase 2 — API integration | 1.0 | 16.0 | 5.5 | 22.5 |
| Grand total | 7.0 | 16.0 | 7.5 | 30.5 |
Confidence: medium-low. Key assumptions: this breakdown incorporates
conversation-history-review.mdR2 and includes blocked work in the main task list for full planning visibility. Blocked external work is estimated at planning level because the owning Data & AI implementation repo/contract was not available locally.
Phase 1 — UI (mocked)
Task 1.1: [FE] Wire Conversation History Entry and Existing Service Contract (CONVHIST-S01, NEG-1)
An Admin can select Conversation history from the add-source entry point and the frontend has a typed service/store path ready to submit a mocked
division_idand agent list.
Status: ✅ Actionable
Design reference: Bot - AI Add source flow · DS version: @mekari/pixel3@^1.0.12 · Frame: Add source flow · Design QA: Wulan Febyazzahra Putri
What to build
Keep this narrowly to the source-type entry and client contract. Do not build the division-first form yet; that is design-blocked by REV-2.
Implementation Plan
| Action | File | What changes |
|---|---|---|
| extend | /Users/mekari/workspace/work/chatbot-fe/components/AddKnowledgeDrawer.vue | Keep/enable the conversation-history source entry behind the existing plan/subscription gate and route it to the conversation-history flow shell. |
| extend | /Users/mekari/workspace/work/chatbot-fe/common/services/main/endpoint.ts | Verify conversation_history.add and conversation_history.get_id paths remain aligned to /v1/gpt/ai_knowledge_sources/omnichannel-agent-conversations. |
| extend | /Users/mekari/workspace/work/chatbot-fe/common/services/main/v1/training-source.ts | Ensure add_conversation_history() sends division_id plus agents[] in the body once the form supplies them. |
| extend | /Users/mekari/workspace/work/chatbot-fe/store/training-source/actions.ts | Keep ADD_CONVERSATION_HISTORY fetch-state transitions and response handling ready for the new form. |
| extend | /Users/mekari/workspace/work/chatbot-fe/tests/unit/store/training-source/actions.test.ts | Assert the action delegates to mainService.trainingSources.add_conversation_history() and resolves/rejects fetch status. |
Implementation steps
- Open
/Users/mekari/workspace/work/chatbot-fe/components/AddKnowledgeDrawer.vueand confirm how existing source entries are gated, displayed, and emitted; keep the Conversation history path consistent with those patterns. - Write/update tests in
/Users/mekari/workspace/work/chatbot-fe/tests/unit/store/training-source/actions.test.tsaroundADD_CONVERSATION_HISTORY, using the existing mockedmainService.trainingSources.add_conversation_history. - Verify
/Users/mekari/workspace/work/chatbot-fe/common/services/main/endpoint.tsalready points to the Grape create/detail endpoints; only adjust if the backend path changes. - In
/Users/mekari/workspace/work/chatbot-fe/common/services/main/v1/training-source.ts, keepbody: payloadintact so the future form can send{ division_id, agents }without a second service refactor. - Run
pnpm test -- tests/unit/store/training-source/actions.test.ts. - Run
pnpm lint:tsandpnpm generatebefore closing the FE task, per repo guidance.
Acceptance criteria
- Conversation history remains available only when the existing plan/subscription gate allows it.
-
ADD_CONVERSATION_HISTORYcalls the existing service method and manages pending/resolved/rejected states. - No division-first form, 15-cap interaction, or status-badge redesign is introduced before REV-2 design frames land.
Test strategy
Unit tests mock mainService.trainingSources.add_conversation_history and assert the Pinia action returns { fetch, request } while updating fetch status on resolve/reject.
Effort estimate
| Discipline | Days |
|---|---|
| Frontend | 1.0 |
| Backend | — |
| QA | 0.5 |
| Total | 1.5 |
Assumptions: reuses existing
store/training-sourceandcommon/services/main/v1/training-source.ts; no new component UX is built in this task.
Run to verify
pnpm test -- tests/unit/store/training-source/actions.test.ts && pnpm lint:ts && pnpm generate
Depends on
- None
Task 1.2: [FE] Build Conversation History Configuration Form (CONVHIST-S01, CONVHIST-S04, CONVHIST-S05)
An Admin can choose one division, select up to 15 expert agents, see the cap counter/tooltip, and submit the source for training.
Status: 🚫 Blocked — REV-2: the Figma frame for the division-first multiselect, 15-cap validation, and expertise tooltip is missing; building now would invent UX.
Design reference: n/a — design pending REV-2 · DS version: @mekari/pixel3@^1.0.12 · Frame: division-first multiselect pending · Design QA: Wulan Febyazzahra Putri
What to build
Create the actual form UI once design lands, using the directory endpoint from Task 2.2 and the create contract from Task 2.3.
Implementation Plan
| Action | File | What changes |
|---|---|---|
| create | /Users/mekari/workspace/work/chatbot-fe/components/ai-knowledge/ConversationHistoryForm.vue | Division-first form, agent checkboxes/multiselect, 15-agent cap counter, tooltip, disabled Save states, and inline errors. |
| extend | /Users/mekari/workspace/work/chatbot-fe/components/AddKnowledgeDrawer.vue | Render the form when Conversation history is selected. |
| extend | /Users/mekari/workspace/work/chatbot-fe/store/training-source/actions.ts | Load divisions/agents and submit { division_id, agents }. |
| create | /Users/mekari/workspace/work/chatbot-fe/tests/unit/components/ai-knowledge/ConversationHistoryForm.test.ts | Cover division selection, cap validation, Save disabled/enabled, directory load failure, and submit payload. |
Implementation steps
- Wait for REV-2 Figma frames; do not create the visual layout from prose alone.
- Open
/Users/mekari/workspace/work/chatbot-fe/components/AddKnowledgeDrawer.vueand mirror existing source-flow state handling. - Write failing tests in
/Users/mekari/workspace/work/chatbot-fe/tests/unit/components/ai-knowledge/ConversationHistoryForm.test.ts. - Create
/Users/mekari/workspace/work/chatbot-fe/components/ai-knowledge/ConversationHistoryForm.vueusing Pixel components verified against the delivered design. - Wire directory load and submit through
/Users/mekari/workspace/work/chatbot-fe/store/training-source/actions.ts. - Run
pnpm test -- tests/unit/components/ai-knowledge/ConversationHistoryForm.test.ts, thenpnpm lint:ts && pnpm generate.
Acceptance criteria
- Division must be selected before agents can be submitted.
- Save is disabled at 0 agents and at >15 agents.
- The 16th selected agent shows the approved validation state and message.
- Submit sends
{ division_id, agents:[{id,name}] }and shows Training in Progress on success.
Test strategy
Vitest mounts the form with mocked directory/create actions and asserts state transitions, validation, and submitted payload.
Effort estimate
| Discipline | Days |
|---|---|
| Frontend | 3.0 |
| Backend | — |
| QA | 1.0 |
| Total | 4.0 |
Assumptions: form reuses existing Pinia/store patterns and Pixel components; estimate may move after final Figma details.
Run to verify
pnpm test -- tests/unit/components/ai-knowledge/ConversationHistoryForm.test.ts && pnpm lint:ts && pnpm generate
Depends on
- Task 2.2
- Task 2.3
- External: REV-2 config-form Figma frames
Task 1.3: [FE] Add Training Status States and Source Detail UI (CONVHIST-S02, CONVHIST-S03, CONVHIST-S10)
An Admin can see Training in Progress, Active, and Error states, inspect the Agent · Division detail table, and use remove/delete actions with the correct confirmations.
Status: 🚫 Blocked — REV-2: Training in Progress/Error list states and final source-detail/status designs are missing.
Design reference: AI Resources source detail · DS version: @mekari/pixel3@^1.0.12 · Frame: Source detail; status states pending · Design QA: Wulan Febyazzahra Putri
What to build
Extend the resources list/detail drawer with Conversation history status states, Last Updated display, Agent · Division rows, and remove/delete affordances.
Implementation Plan
| Action | File | What changes |
|---|---|---|
| extend | /Users/mekari/workspace/work/chatbot-fe/modules/ai-knowledge/views/training-source/knowledge-list.vue | Render Conversation history status badges and Last Updated behavior. |
| extend | /Users/mekari/workspace/work/chatbot-fe/modules/chat-panel/training-sources/drawer/training-source-detail-drawer.vue | Show Agent · Division detail rows for conversation sources. |
| extend | /Users/mekari/workspace/work/chatbot-fe/modules/chat-panel/training-sources/views/training-sources-list.vue | Keep chat-panel list behavior aligned if this surface remains canonical. |
| extend | /Users/mekari/workspace/work/chatbot-fe/tests/unit/modules/ai-knowledge/views/training-source/knowledge-list.test.ts | Cover status badges and date rendering. |
| extend | /Users/mekari/workspace/work/chatbot-fe/tests/unit/modules/chat-panel/training-sources/drawer/training-source-detail-drawer.test.ts | Cover detail rows and delete/in-use behavior. |
Implementation steps
- Wait for REV-2 status-state design; use the
qontak-designerprototype only as reference, not as source of truth. - Open
/Users/mekari/workspace/work/chatbot-fe/modules/ai-knowledge/views/training-source/knowledge-list.vueand mirror current table/status patterns. - Write failing tests for
IN_PROGRESS,ACTIVE, andFAILED/Errorbadge rendering. - Extend the detail drawer to call the existing
GET_TRAINING_SOURCE_CONVERSATION_HISTORY_DETAILaction and render Agent · Division rows after backend includes division data. - Wire delete/in-use error display to Task 2.4 response behavior.
- Run targeted tests,
pnpm lint:ts, andpnpm generate.
Acceptance criteria
- Conversation history rows show approved Training in Progress, Active, and Error states.
- Last Updated advances from
updated_atand handles empty/missing values. - Detail drawer shows selected agents and division.
- In-use delete errors are shown without removing the row locally.
Test strategy
Unit tests mock list/detail payloads and assert the UI renders each status, date, detail row, and delete error state.
Effort estimate
| Discipline | Days |
|---|---|
| Frontend | 2.0 |
| Backend | — |
| QA | 0.5 |
| Total | 2.5 |
Assumptions: status labels map directly from existing backend
IN_PROGRESS/ACTIVE/FAILEDvalues.
Run to verify
pnpm test -- tests/unit/modules/ai-knowledge/views/training-source/knowledge-list.test.ts tests/unit/modules/chat-panel/training-sources/drawer/training-source-detail-drawer.test.ts && pnpm lint:ts && pnpm generate
Depends on
- Task 2.4
- External: REV-2 status/detail Figma frames
Phase 2 — API integration
Task 2.1: [BE] Add Division Scope to Conversation History Sources (CONVHIST-S05, NEG-3)
An Admin can create one Conversation history source per division, with the uniqueness rule backed by the chatbot_gpt database.
Status: ⚠️ Partially blocked — PM+eng must confirm the division-scoping decision (REV-5), but the migration is fully specified and can be prepared behind that sign-off.
What to build
Add nullable division_id to ai_knowledge_sources and a paranoid-safe partial unique index on (company_id, division_id, ai_knowledge_source_type_id) for non-deleted rows.
Implementation Plan
| Action | File | What changes |
|---|---|---|
| create | /Users/mekari/workspace/work/chatbot/db/chatbot_gpt_migrate/2026XXXX_add_division_id_to_ai_knowledge_sources.rb | Add division_id :string and index_ai_knowledge_sources_on_company_division_type with where: 'deleted_at IS NULL AND division_id IS NOT NULL'. |
| update | /Users/mekari/workspace/work/chatbot/db/chatbot_gpt_schema.rb | Schema output after chatbot_gpt migration. |
| extend | /Users/mekari/workspace/work/chatbot/app/models/chatbot_gpt/ai_knowledge_source.rb | Document/allow the new source-level division_id if model-level behavior is needed. |
| extend | /Users/mekari/workspace/work/chatbot/spec/core/use_cases/api/frontend_service/v1/gpt/ai_knowledge_source/create_omnichannel_agent_conversation_knowledge_source_spec.rb | Cover duplicate division behavior after Task 2.3 wires the create guard. |
Implementation steps
- Open
/Users/mekari/workspace/work/chatbot/db/chatbot_gpt_migrate/20240724144048_unique_knowledge_store.rband mirror its partial-index style. - Create
/Users/mekari/workspace/work/chatbot/db/chatbot_gpt_migrate/2026XXXX_add_division_id_to_ai_knowledge_sources.rbwith# frozen_string_literal: true. - Run migration, rollback, then migration again against the chatbot_gpt DB as the repo supports it.
- Confirm
/Users/mekari/workspace/work/chatbot/db/chatbot_gpt_schema.rbincludesdivision_idand the partial unique index. - Defer user-facing uniqueness behavior assertions to
/Users/mekari/workspace/work/chatbot/spec/core/use_cases/api/frontend_service/v1/gpt/ai_knowledge_source/create_omnichannel_agent_conversation_knowledge_source_spec.rbonce Task 2.3 wires the create guard.
Acceptance criteria
-
ai_knowledge_sources.division_idexists and is nullable. - Duplicate active Conversation history sources for the same
(company_id, division_id, type)are blocked by the DB. - Soft-deleted rows do not block a replacement source for the same division.
- Rollback removes the column/index cleanly.
Test strategy
Migration or use-case specs create two active sources for the same division and assert the second fails, then soft-delete the first and assert a replacement can be created.
Effort estimate
| Discipline | Days |
|---|---|
| Frontend | — |
| Backend | 1.0 |
| QA | 0.5 |
| Total | 1.5 |
Assumptions: no backfill is needed for existing non-division-scoped sources;
division_idremains null outside Conversation history.
Run to verify
bundle exec rails db:migrate && bundle exec rails db:rollback && bundle exec rails db:migrate
Depends on
- External: PM+eng division-scoping sign-off (REV-5)
Task 2.2: [BE] Create Divisions + Agents Directory Endpoint (CONVHIST-S05)
An Admin can load company-scoped divisions and eligible agents for the Conversation history configuration form.
Status: ✅ Actionable
What to build
Add a frontend-service directory read endpoint using the existing Division and AgentsDivision models. This unblocks the future FE multiselect without depending on its final design.
Implementation Plan
| Action | File | What changes |
|---|---|---|
| create | /Users/mekari/workspace/work/chatbot/app/api/frontend_service/v1/divisions.rb | Add GET /v1/divisions and GET /v1/divisions/:id/agents with set_role(%w[owner supervisor admin]). |
| create | /Users/mekari/workspace/work/chatbot/app/core/use_cases/api/frontend_service/v1/division/get.rb | Return company/organization-scoped divisions with nested agents, following APIAbstractUseCase. |
| create | /Users/mekari/workspace/work/chatbot/app/core/entities/frontend_services/division.rb | Entity for { division_id, name, agents:[{id,name}] }. |
| create | /Users/mekari/workspace/work/chatbot/app/core/builders/frontend_services/division.rb | Builder if entity conversion follows local pattern. |
| extend | /Users/mekari/workspace/work/chatbot/app/api/frontend_service/v1.rb | Mount the new divisions resource if needed. |
| create | /Users/mekari/workspace/work/chatbot/spec/api/frontend_service/v1/divisions/get_spec.rb | API specs for 200, role enforcement, and tenant scoping. |
Implementation steps
- Open
/Users/mekari/workspace/work/chatbot/app/models/division.rband/Users/mekari/workspace/work/chatbot/app/models/agents_division.rb; use the existing associationsdivision.agents. - Write failing API specs in
/Users/mekari/workspace/work/chatbot/spec/api/frontend_service/v1/divisions/get_spec.rbfor owner/supervisor/admin access, forbidden roles, and cross-company exclusion. - Create
/Users/mekari/workspace/work/chatbot/app/core/use_cases/api/frontend_service/v1/division/get.rbwith a dry contract requiringcompany_idand optionallyorganization_id/division_id. - Create the Grape resource in
/Users/mekari/workspace/work/chatbot/app/api/frontend_service/v1/divisions.rb, usingDry::Matcher::ResultMatcher.call()andsuccess_response. - Add entity/builder files only if the response needs Grape entity shaping; otherwise return a plain success payload consistently with nearby API use cases.
- Go green with
bundle exec rspec /Users/mekari/workspace/work/chatbot/spec/api/frontend_service/v1/divisions/get_spec.rb. - Run
bundle exec rubocopfor touched files.
Acceptance criteria
-
GET /v1/divisionsreturns only divisions for the current user's company/organization. -
GET /v1/divisions/:id/agentsreturns agents for that division only. - Unauthorized roles cannot read the directory.
- Empty division/agent results return
data: []rather than a 500.
Test strategy
API specs seed two companies, divisions, agents, and AgentsDivision rows; assertions prove tenant scoping and nested agent shape.
Effort estimate
| Discipline | Days |
|---|---|
| Frontend | — |
| Backend | 2.0 |
| QA | 0.5 |
| Total | 2.5 |
Assumptions:
DivisionandAgentsDivisionare the source of truth; no proxy to Omnichannel directory is required.
Run to verify
bundle exec rspec spec/api/frontend_service/v1/divisions/get_spec.rb && bundle exec rubocop
Depends on
- None
Task 2.3: [BE] Extend Conversation History Create Contract (CONVHIST-S01, CONVHIST-S04, CONVHIST-S05, NEG-3)
An Admin can create a division-scoped Conversation history source with 1 to 15 selected agents and receive clear 422 errors for invalid selections.
Status: ⚠️ Partially blocked — implementation should land after REV-5 scoping sign-off and Task 2.1 migration; tests and code shape are otherwise actionable.
What to build
Extend the existing create use case and API params to accept division_id, enforce the 15-agent cap, use the division-aware uniqueness guard, and keep the AI-Service post behavior compatible with type: 'conversation'.
Implementation Plan
| Action | File | What changes |
|---|---|---|
| extend | /Users/mekari/workspace/work/chatbot/app/api/frontend_service/v1/gpt/ai_knowledge_sources.rb | Add division_id param to POST /omnichannel-agent-conversations and pass it into the use case. |
| extend | /Users/mekari/workspace/work/chatbot/app/core/use_cases/api/frontend_service/v1/gpt/ai_knowledge_source/create_omnichannel_agent_conversation_knowledge_source.rb | Validate division_id, enforce agents.size <= 15, and query existing source by company/type/division. |
| extend | /Users/mekari/workspace/work/chatbot/app/core/repositories/gpt/ai_knowledge_source_omnichannel_agent_conversations/create.rb | Persist source division_id on ChatbotGpt::AiKnowledgeSource. |
| extend | /Users/mekari/workspace/work/chatbot/app/core/repositories/gpt/ai_service/post_knowledge_sources.rb | Ensure conversation source lookup remains correct after multiple division-scoped sources exist. |
| extend | /Users/mekari/workspace/work/chatbot/spec/core/use_cases/api/frontend_service/v1/gpt/ai_knowledge_source/create_omnichannel_agent_conversation_knowledge_source_spec.rb | Unit coverage for valid create, 16-agent cap, missing division, and duplicate division. |
| extend | /Users/mekari/workspace/work/chatbot/spec/api/frontend_service/v1/gpt/ai_knowledge_sources/create_omnichannel_agent_conversation_knowledge_source_spec.rb | Request coverage for params, 202 shape, and 422 messages. |
Implementation steps
- Open
/Users/mekari/workspace/work/chatbot/app/core/use_cases/api/frontend_service/v1/gpt/ai_knowledge_source/create_omnichannel_agent_conversation_knowledge_source.rb; note the current one-per-company guard and the transaction around repository create +PostKnowledgeSources. - Write failing specs in both create spec files for
division_id, 16 selected agents, duplicate division, and successful 202 response. - Extend the Grape params in
/Users/mekari/workspace/work/chatbot/app/api/frontend_service/v1/gpt/ai_knowledge_sources.rbto requiredivision_id. - Update the use-case contract and guard to query by
company_id,ai_knowledge_source_type_id, anddivision_id. - Update
/Users/mekari/workspace/work/chatbot/app/core/repositories/gpt/ai_knowledge_source_omnichannel_agent_conversations/create.rbso the created source row storesdivision_id. - Review
/Users/mekari/workspace/work/chatbot/app/core/repositories/gpt/ai_service/post_knowledge_sources.rb; if it currently usesfind_byfor a single conversation source, change it to post all active division-scoped conversation sources for the company. - Add a comment or follow-up ticket for REV-11 if the team chooses not to add an immediate retry after a failed AI-Service post.
- Run the targeted RSpec files and
bundle exec rubocop.
Acceptance criteria
- Valid
{ division_id, agents:[1..15] }creates the source and agent rows and returns 202. - 16 agents returns a 422 with a stable
agent_limit_exceeded-style message/code. - A second active source for the same company/division/type returns 422
already_exist. - AI-Service post includes each division-scoped conversation source rather than silently posting only the first source.
Test strategy
Use-case specs cover business rules and repository persistence; API specs cover request parsing and response envelope. Mock PostKnowledgeSources to isolate the create tests, then add one repository spec for multi-source posting behavior if needed.
Effort estimate
| Discipline | Days |
|---|---|
| Frontend | — |
| Backend | 2.0 |
| QA | 0.5 |
| Total | 2.5 |
Assumptions: backend does not echo
division_idin the create response, matching the reviewed entity shape; FE keeps local division context.
Run to verify
bundle exec rspec spec/core/use_cases/api/frontend_service/v1/gpt/ai_knowledge_source/create_omnichannel_agent_conversation_knowledge_source_spec.rb spec/api/frontend_service/v1/gpt/ai_knowledge_sources/create_omnichannel_agent_conversation_knowledge_source_spec.rb && bundle exec rubocop
Depends on
- Task 2.1
- External: PM+eng division-scoping sign-off (REV-5)
Task 2.4: [BE] Add Delete In-Use Guard and Conditional Vector Delete (CONVHIST-S02, CONVHIST-S03)
An Admin can unlink a Conversation history source from an agent without deleting vectors, and can hard-delete the source only when it is not in use.
Status: ✅ Actionable
What to build
Extend delete behavior so in-use sources return 422, unused sources soft-delete locally and delete vectors, and unlink/remove-from-agent semantics do not purge shared vectors.
Implementation Plan
| Action | File | What changes |
|---|---|---|
| extend | /Users/mekari/workspace/work/chatbot/app/core/use_cases/api/frontend_service/v1/gpt/ai_knowledge_source/delete.rb | Add in-use guard before destroy and keep tenant authorization. |
| extend | /Users/mekari/workspace/work/chatbot/app/core/repositories/gpt/ai_knowledge_sources/destroy.rb | Ensure destroy only removes the right agent-conversation rows/source. |
| extend | /Users/mekari/workspace/work/chatbot/app/api/frontend_service/v1/gpt/ai_knowledge_sources.rb | Keep DELETE response envelope and 422 handling aligned. |
| extend | /Users/mekari/workspace/work/chatbot/spec/api/frontend_service/v1/gpt/ai_knowledge_sources/delete_omnichannel_agent_conversation_knowledge_source_spec.rb | Add in-use blocked and unused vector-delete cases. |
| extend | /Users/mekari/workspace/work/chatbot/spec/core/repositories/gpt/ai_knowledge_sources/destroy_spec.rb | Cover source-row and agent-row deletion behavior if repository specs exist for this path. |
Implementation steps
- Open
/Users/mekari/workspace/work/chatbot/app/core/use_cases/api/frontend_service/v1/gpt/ai_knowledge_source/delete.rb; preserve the existing company ownership check. - Write failing API specs in
/Users/mekari/workspace/work/chatbot/spec/api/frontend_service/v1/gpt/ai_knowledge_sources/delete_omnichannel_agent_conversation_knowledge_source_spec.rbfor in-use 422 and unused delete success. - Identify the "in use by agent" relationship (
ai_agent_knowledgesper RFC) and query it beforeRepositories::Gpt::AiKnowledgeSources::Destroy. - For unused sources, call vector deletion with entity type
conversation; for unlink-only behavior, soft-delete only the join/unlink record. - Assert
delete_vector_dbis not called when the source is only removed from an agent. - Run targeted specs and
bundle exec rubocop.
Acceptance criteria
- In-use source delete returns 422 and does not destroy rows or vectors.
- Unused source delete soft-deletes the source and agent-conversation rows.
- Vector delete is called only for hard source delete.
- Cross-company delete remains forbidden.
Test strategy
API specs mock the AI-Service client and assert call/no-call behavior for delete_vector_db; repository specs cover DB side effects.
Effort estimate
| Discipline | Days |
|---|---|
| Frontend | — |
| Backend | 1.5 |
| QA | 0.5 |
| Total | 2.0 |
Assumptions: existing DELETE route stays unchanged; this task only tightens behavior for Conversation history.
Run to verify
bundle exec rspec spec/api/frontend_service/v1/gpt/ai_knowledge_sources/delete_omnichannel_agent_conversation_knowledge_source_spec.rb && bundle exec rubocop
Depends on
- None
Task 2.5: [BE] Daily Conversation History Sync Worker (CONVHIST-S10, CONVHIST-S12)
Active Conversation history sources are re-posted to AI-Service daily so the 90-day window stays fresh and deactivated agents stop contributing new data.
Status: ✅ Actionable
What to build
Create a Sidekiq worker scheduled at 01:00 Asia/Jakarta on application_maintenance to iterate active Conversation history sources and re-post them to AI-Service with isolated failure handling.
Implementation Plan
| Action | File | What changes |
|---|---|---|
| create | /Users/mekari/workspace/work/chatbot/app/workers/conversation_history_daily_sync_worker.rb | New worker with sidekiq_options queue: :application_maintenance, retry: 3. |
| extend | /Users/mekari/workspace/work/chatbot/config/schedule.yml | Add daily cron entry for the worker. |
| extend | /Users/mekari/workspace/work/chatbot/app/core/repositories/gpt/ai_service/post_knowledge_sources.rb | Reuse or expose a call path that can post a specific source/company safely. |
| create | /Users/mekari/workspace/work/chatbot/spec/workers/conversation_history_daily_sync_worker_spec.rb | Assert active sources are processed, failures are isolated, and inactive/deleted sources are skipped. |
Implementation steps
- Open
/Users/mekari/workspace/work/chatbot/config/schedule.ymland mirror theapplication_maintenancecron style used byPartitionChatbotGptMaintenanceWorker. - Write failing specs in
/Users/mekari/workspace/work/chatbot/spec/workers/conversation_history_daily_sync_worker_spec.rbfor active source processing and failure isolation. - Create
/Users/mekari/workspace/work/chatbot/app/workers/conversation_history_daily_sync_worker.rbwith# frozen_string_literal: true. - Query active, non-deleted
agent_conversation_historysources and post each source or company viaRepositories::Gpt::AiService::PostKnowledgeSources. - Rescue per source, send
Rollbar.error, and continue processing remaining sources. - Add the
conversation_history_daily_sync_jobcron entry to/Users/mekari/workspace/work/chatbot/config/schedule.yml. - Run worker specs and
bundle exec rubocop.
Acceptance criteria
- Worker runs from
application_maintenanceat0 1 * * * Asia/Jakarta. - Active Conversation history sources are re-posted to AI-Service.
- Deleted/inactive sources and deactivated agents do not create new ingest payloads.
- One failed source does not stop the rest of the batch.
Test strategy
Worker specs stub PostKnowledgeSources and Rollbar.error, then assert per-source processing and failure isolation.
Effort estimate
| Discipline | Days |
|---|---|
| Frontend | — |
| Backend | 1.5 |
| QA | 0.5 |
| Total | 2.0 |
Assumptions: Data & AI owns the actual 90-day purge; chatbot only re-triggers the source sync.
Run to verify
bundle exec rspec spec/workers/conversation_history_daily_sync_worker_spec.rb && bundle exec rubocop
Depends on
- Task 2.3
Task 2.6: [FE] Wire Real Directory/Create Calls Into the Future Form Contract (CONVHIST-S01, CONVHIST-S04, CONVHIST-S05)
Once the form design is approved, the Conversation history UI can call the real directory and create endpoints without another service-layer refactor.
Status: ⚠️ Partially blocked — real UI work is blocked by REV-2, but the service endpoint wiring can be prepared after Task 2.2.
Design reference: n/a — design pending REV-2 · DS version: @mekari/pixel3@^1.0.12 · Frame: division-first multiselect pending · Design QA: Wulan Febyazzahra Putri
What to build
Add the FE service/store method for the new divisions directory and update the existing create service tests for the real { division_id, agents } payload. Do not implement the visual form until Figma frames are delivered.
Implementation Plan
| Action | File | What changes |
|---|---|---|
| extend | /Users/mekari/workspace/work/chatbot-fe/common/services/main/endpoint.ts | Add division.get and division.agents endpoint constants for Task 2.2. |
| extend | /Users/mekari/workspace/work/chatbot-fe/common/services/main/v1/training-source.ts | Add directory fetch method or place it in the local service module that owns training source dependencies. |
| extend | /Users/mekari/workspace/work/chatbot-fe/store/training-source/actions.ts | Add action for loading divisions/agents if the form will consume Pinia rather than direct service calls. |
| extend | /Users/mekari/workspace/work/chatbot-fe/tests/unit/store/training-source/actions.test.ts | Assert directory action states and create payload delegation. |
Implementation steps
- Open
/Users/mekari/workspace/work/chatbot-fe/common/services/main/endpoint.ts; add directory paths only after Task 2.2 confirms final backend route names. - Write/update failing tests in
/Users/mekari/workspace/work/chatbot-fe/tests/unit/store/training-source/actions.test.tsfor the directory load action and create payload delegation. - Extend
/Users/mekari/workspace/work/chatbot-fe/common/services/main/v1/training-source.tswith a GET wrapper using$apiMain,AbortController, andlazy, matching neighboring methods. - Add the action in
/Users/mekari/workspace/work/chatbot-fe/store/training-source/actions.tsonly if the form needs store-owned request state. - Leave
/Users/mekari/workspace/work/chatbot-fe/components/AddKnowledgeDrawer.vueform rendering unchanged until REV-2 design is resolved. - Run the targeted Vitest file,
pnpm lint:ts, andpnpm generate.
Acceptance criteria
- FE has a tested client method for the divisions+agents endpoint.
- Create service passes
{ division_id, agents }unchanged to the backend. - No unapproved form layout or status-state UI is introduced.
Test strategy
Vitest mocks $apiMain / service wrappers and asserts endpoint, method, payload, and fetch-state transitions.
Effort estimate
| Discipline | Days |
|---|---|
| Frontend | 0.5 |
| Backend | — |
| QA | 0.5 |
| Total | 1.0 |
Assumptions: final directory endpoint matches the RFC shape; if backend route names change, update endpoint constants before implementing the visual form.
Run to verify
pnpm test -- tests/unit/store/training-source/actions.test.ts && pnpm lint:ts && pnpm generate
Depends on
- Task 2.2
- External: REV-2 before any visual form work
Task 2.7: [BE] Training Status Webhook Consumer (CONVHIST-S06, CONVHIST-S10)
Conversation history training status can update from Data & AI webhook events instead of relying only on polling.
Status: 🚫 Blocked — REV-3: Data & AI has not published the webhook states, payload, retry semantics, or auth contract.
What to build
Add the inbound webhook endpoint, validation, status mapping, idempotency guard, and tests once the external contract is available. Poll-based status remains the baseline until then.
Implementation Plan
| Action | File | What changes |
|---|---|---|
| create | /Users/mekari/workspace/work/chatbot/app/api/internal_service/v1/gpt/conversation_history_status_webhooks.rb | Inbound status webhook endpoint after contract is published. |
| create | /Users/mekari/workspace/work/chatbot/app/core/use_cases/api/internal_service/v1/gpt/conversation_history_status_webhook/update.rb | Validate payload, authorize service caller, map status, update source. |
| extend | /Users/mekari/workspace/work/chatbot/app/core/repositories/gpt/ai_knowledge_sources/update_status.rb | Reuse/align status mapping with poll path. |
| create | /Users/mekari/workspace/work/chatbot/spec/api/internal_service/v1/gpt/conversation_history_status_webhooks_spec.rb | Contract, auth, retry/idempotency, and status mapping specs. |
Implementation steps
- Wait for REV-3 contract; do not infer payload fields or auth from the RFC prose.
- Open
/Users/mekari/workspace/work/chatbot/app/core/repositories/gpt/ai_knowledge_sources/update_status.rband reuse the existing poll status mapping where possible. - Write failing specs in
/Users/mekari/workspace/work/chatbot/spec/api/internal_service/v1/gpt/conversation_history_status_webhooks_spec.rbfrom the published contract. - Create the internal API resource and use case using existing internal-service response patterns.
- Add idempotency handling for duplicate webhook delivery if the contract requires retries.
- Run targeted specs and
bundle exec rubocop.
Acceptance criteria
- Webhook rejects unauthenticated or malformed requests.
-
in_progress,completed, andfailedcontract statuses map to chatbot source statuses. - Duplicate webhook deliveries do not corrupt status or timestamps.
- Poll baseline still works if webhook delivery fails.
Test strategy
API specs replay valid, invalid, unauthorized, duplicate, and out-of-order webhook payloads. Repository/use-case specs assert final source status and updated_at behavior.
Effort estimate
| Discipline | Days |
|---|---|
| Frontend | — |
| Backend | 2.0 |
| QA | 0.5 |
| Total | 2.5 |
Assumptions: webhook is additive; no migration required unless the published contract adds idempotency keys that must be persisted.
Run to verify
bundle exec rspec spec/api/internal_service/v1/gpt/conversation_history_status_webhooks_spec.rb && bundle exec rubocop
Depends on
- External: REV-3 webhook contract from Data & AI
Task 2.8: [BE] Data & AI Masking, Quality Gate, Recency, Whisper, and Text-Only Filters (CONVHIST-S06, CONVHIST-S07, CONVHIST-S08, CONVHIST-S09, CONVHIST-S13)
Conversation history training only indexes qualified, customer-facing, text conversation content after standard phone/email PII is masked.
Status: 🚫 Blocked — REV-4: Data & AI masking SLA/entity coverage and pipeline contract are not published; the owning implementation repo was not available in the provided local references.
What to build
In the Data & AI-owned ingestion/vector pipeline, enforce masking, ≥5-message quality gate, whisper exclusion, recency ranking, and text-only filtering. Chatbot consumes only status and does not implement the masking pipeline.
Implementation Plan
| Action | File | What changes |
|---|---|---|
| extend | Data & AI ingestion pipeline [unverified — check owning repo] | Mask standard phone/email before indexing; emit failed status on masking failure. |
| extend | Data & AI conversation filtering [unverified — check owning repo] | Exclude rooms with fewer than 5 customer-facing messages and exclude whispers. |
| extend | Data & AI vector ranking [unverified — check owning repo] | Prioritize recent resolved conversations and deterministic tie-break behavior. |
| extend | Data & AI content parser [unverified — check owning repo] | Index text-only content and skip image/file/voice payloads. |
| create | Data & AI pipeline tests [unverified — check owning repo] | Coverage for PII masking, low-message skip, whisper skip, recency, and non-text exclusion. |
Implementation steps
- Locate the Data & AI ingestion repository and replace the unverified file placeholders above with real paths.
- Write failing pipeline tests for phone/email masking, 3-message skip, ≥5-message inclusion, whisper exclusion, recency order, and non-text exclusion.
- Implement masking before vector write; ensure raw PII is not persisted post-processing.
- Implement the room/message filters before indexing.
- Emit failure status back through the poll/webhook contract when masking/indexing fails.
- Run the owning repo's unit/integration test suite and provide sample masked payload evidence for InfoSec.
Acceptance criteria
- Standard phone and email formats are masked 100% before indexing.
- Rooms with fewer than 5 qualifying customer-facing messages are skipped.
- Whisper/internal-only messages are excluded.
- Recent resolved conversations rank ahead of older ones with deterministic tie-breaks.
- Non-text payloads are excluded from vectors.
Test strategy
Pipeline tests use fixture conversations containing phone/email PII, whispers, short rooms, mixed media, and same-score recency cases; assertions inspect the masked/vectorized payload, not only the final status.
Effort estimate
| Discipline | Days |
|---|---|
| Frontend | — |
| Backend | 5.0 |
| QA | 1.5 |
| Total | 6.5 |
Assumptions: estimate is for the external Data & AI service, not the chatbot repo; it may change once the owning repo and SLA are available.
Run to verify
# Run the owning Data & AI repo's unit/integration pipeline tests once the repo is identified.
Depends on
- External: REV-4 masking SLA and Data & AI ingestion contract
Task 2.9: [BE] Permission-Scoped Reference Room Link Contract (CONVHIST-S11)
An Agent can open a cited source conversation only when they are authorized to view that room.
Status: ⚠️ Partially blocked — the RFC marks this as Could-Have and the review says the room-permission mechanism is not file-grounded enough yet.
What to build
Ground the room authorization path, add a permission check for reference opens, and expose enough response data for the FE to render a safe link.
Implementation Plan
| Action | File | What changes |
|---|---|---|
| extend | /Users/mekari/workspace/work/chatbot/app/core/use_cases/api/frontend_service/v1/gpt/ai_knowledge_source/predict.rb | Include permission-scoped reference metadata only when the source is a room reference. |
| extend | /Users/mekari/workspace/work/chatbot/app/core/repositories/gpt/ai_knowledge_sources/mapping_related_source.rb | Map conversation source references to room ids if available. |
| create | /Users/mekari/workspace/work/chatbot/spec/core/use_cases/api/frontend_service/v1/gpt/ai_knowledge_source/reference_room_permission_spec.rb | Authorized room opens succeed; cross-division/unauthorized opens return 403. |
| extend | /Users/mekari/workspace/work/chatbot-fe/modules/chat-panel/training-sources/drawer/training-source-detail-drawer.vue | Render reference link only when backend supplies an authorized URL/id. |
Implementation steps
- Re-read the room authorization path in
/Users/mekari/workspace/work/chatbotand identify the exact service/use case that owns room-view permission. - Replace the provisional test file name with the repo's established spec location once the authorization path is identified.
- Write failing specs for authorized same-division access and unauthorized cross-division access.
- Add backend reference metadata only after permission passes.
- Update FE rendering to hide or disable links when permission metadata is absent.
- Run targeted RSpec, targeted Vitest,
bundle exec rubocop, andpnpm lint:ts.
Acceptance criteria
- Authorized users can open the referenced room.
- Unauthorized/cross-division users receive 403 and no usable link.
- FE does not render unsafe room links from raw reference ids.
Test strategy
Backend specs exercise the permission decision; FE unit tests assert link visibility for allowed and denied payloads.
Effort estimate
| Discipline | Days |
|---|---|
| Frontend | 0.5 |
| Backend | 1.0 |
| QA | 0.5 |
| Total | 2.0 |
Assumptions: room authorization can reuse existing session/company/division checks once the exact path is identified.
Run to verify
bundle exec rspec spec/core/use_cases/api/frontend_service/v1/gpt/ai_knowledge_source/reference_room_permission_spec.rb && pnpm test -- tests/unit/modules/chat-panel/training-sources/drawer/training-source-detail-drawer.test.ts
Depends on
- Codebase grounding for the room authorization path
Ordering rationale
- Start with Task 1.1 because it is low-risk FE plumbing and prevents later form work from needing a service/store cleanup pass.
- Task 2.2 can proceed independently and unblocks the future form; it is the cleanest BE task to start while scoping sign-off is pending.
- Tasks 2.1 and 2.3 should wait for PM+eng sign-off on division scoping, because they encode the product rule in schema and create behavior.
- Task 2.5 depends on the create/post path understanding multiple division-scoped sources; doing it after Task 2.3 avoids a second worker rewrite.
- Keep Tasks 1.2, 1.3, 2.7, and 2.8 visible even though blocked, because they represent required work for the full PRD/RFC scope.
- Push externally on REV-2 first for frontend delivery, and on REV-3/REV-4 for launch readiness; they should not block the BOT-owned backend baseline.
Skipped stories
| Story | Reason |
|---|---|
| None | No blocked stories are omitted from the main task list. Out-of-scope items remain excluded per the RFC: automated/CSAT-based agent selection, real-time ingestion, multimedia indexing, cross-division pooling, and new reporting dashboards. |