Skip to main content

Task Breakdown — AI Agent Knowledge: Conversation History

Effort Summary

Phase / AreaFE daysBE daysQA daysTotal
Phase 1 — UI (mocked)6.02.08.0
Phase 2 — API integration1.016.05.522.5
Grand total7.016.07.530.5

Confidence: medium-low. Key assumptions: this breakdown incorporates conversation-history-review.md R2 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_id and 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

ActionFileWhat changes
extend/Users/mekari/workspace/work/chatbot-fe/components/AddKnowledgeDrawer.vueKeep/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.tsVerify 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.tsEnsure 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.tsKeep 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.tsAssert the action delegates to mainService.trainingSources.add_conversation_history() and resolves/rejects fetch status.

Implementation steps

  1. Open /Users/mekari/workspace/work/chatbot-fe/components/AddKnowledgeDrawer.vue and confirm how existing source entries are gated, displayed, and emitted; keep the Conversation history path consistent with those patterns.
  2. Write/update tests in /Users/mekari/workspace/work/chatbot-fe/tests/unit/store/training-source/actions.test.ts around ADD_CONVERSATION_HISTORY, using the existing mocked mainService.trainingSources.add_conversation_history.
  3. Verify /Users/mekari/workspace/work/chatbot-fe/common/services/main/endpoint.ts already points to the Grape create/detail endpoints; only adjust if the backend path changes.
  4. In /Users/mekari/workspace/work/chatbot-fe/common/services/main/v1/training-source.ts, keep body: payload intact so the future form can send { division_id, agents } without a second service refactor.
  5. Run pnpm test -- tests/unit/store/training-source/actions.test.ts.
  6. Run pnpm lint:ts and pnpm generate before closing the FE task, per repo guidance.

Acceptance criteria

  • Conversation history remains available only when the existing plan/subscription gate allows it.
  • ADD_CONVERSATION_HISTORY calls 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

DisciplineDays
Frontend1.0
Backend
QA0.5
Total1.5

Assumptions: reuses existing store/training-source and common/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

ActionFileWhat changes
create/Users/mekari/workspace/work/chatbot-fe/components/ai-knowledge/ConversationHistoryForm.vueDivision-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.vueRender the form when Conversation history is selected.
extend/Users/mekari/workspace/work/chatbot-fe/store/training-source/actions.tsLoad divisions/agents and submit { division_id, agents }.
create/Users/mekari/workspace/work/chatbot-fe/tests/unit/components/ai-knowledge/ConversationHistoryForm.test.tsCover division selection, cap validation, Save disabled/enabled, directory load failure, and submit payload.

Implementation steps

  1. Wait for REV-2 Figma frames; do not create the visual layout from prose alone.
  2. Open /Users/mekari/workspace/work/chatbot-fe/components/AddKnowledgeDrawer.vue and mirror existing source-flow state handling.
  3. Write failing tests in /Users/mekari/workspace/work/chatbot-fe/tests/unit/components/ai-knowledge/ConversationHistoryForm.test.ts.
  4. Create /Users/mekari/workspace/work/chatbot-fe/components/ai-knowledge/ConversationHistoryForm.vue using Pixel components verified against the delivered design.
  5. Wire directory load and submit through /Users/mekari/workspace/work/chatbot-fe/store/training-source/actions.ts.
  6. Run pnpm test -- tests/unit/components/ai-knowledge/ConversationHistoryForm.test.ts, then pnpm 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

DisciplineDays
Frontend3.0
Backend
QA1.0
Total4.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

ActionFileWhat changes
extend/Users/mekari/workspace/work/chatbot-fe/modules/ai-knowledge/views/training-source/knowledge-list.vueRender 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.vueShow Agent · Division detail rows for conversation sources.
extend/Users/mekari/workspace/work/chatbot-fe/modules/chat-panel/training-sources/views/training-sources-list.vueKeep 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.tsCover 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.tsCover detail rows and delete/in-use behavior.

Implementation steps

  1. Wait for REV-2 status-state design; use the qontak-designer prototype only as reference, not as source of truth.
  2. Open /Users/mekari/workspace/work/chatbot-fe/modules/ai-knowledge/views/training-source/knowledge-list.vue and mirror current table/status patterns.
  3. Write failing tests for IN_PROGRESS, ACTIVE, and FAILED/Error badge rendering.
  4. Extend the detail drawer to call the existing GET_TRAINING_SOURCE_CONVERSATION_HISTORY_DETAIL action and render Agent · Division rows after backend includes division data.
  5. Wire delete/in-use error display to Task 2.4 response behavior.
  6. Run targeted tests, pnpm lint:ts, and pnpm generate.

Acceptance criteria

  • Conversation history rows show approved Training in Progress, Active, and Error states.
  • Last Updated advances from updated_at and 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

DisciplineDays
Frontend2.0
Backend
QA0.5
Total2.5

Assumptions: status labels map directly from existing backend IN_PROGRESS/ACTIVE/FAILED values.

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

ActionFileWhat changes
create/Users/mekari/workspace/work/chatbot/db/chatbot_gpt_migrate/2026XXXX_add_division_id_to_ai_knowledge_sources.rbAdd 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.rbSchema output after chatbot_gpt migration.
extend/Users/mekari/workspace/work/chatbot/app/models/chatbot_gpt/ai_knowledge_source.rbDocument/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.rbCover duplicate division behavior after Task 2.3 wires the create guard.

Implementation steps

  1. Open /Users/mekari/workspace/work/chatbot/db/chatbot_gpt_migrate/20240724144048_unique_knowledge_store.rb and mirror its partial-index style.
  2. Create /Users/mekari/workspace/work/chatbot/db/chatbot_gpt_migrate/2026XXXX_add_division_id_to_ai_knowledge_sources.rb with # frozen_string_literal: true.
  3. Run migration, rollback, then migration again against the chatbot_gpt DB as the repo supports it.
  4. Confirm /Users/mekari/workspace/work/chatbot/db/chatbot_gpt_schema.rb includes division_id and the partial unique index.
  5. 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.rb once Task 2.3 wires the create guard.

Acceptance criteria

  • ai_knowledge_sources.division_id exists 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

DisciplineDays
Frontend
Backend1.0
QA0.5
Total1.5

Assumptions: no backfill is needed for existing non-division-scoped sources; division_id remains 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

ActionFileWhat changes
create/Users/mekari/workspace/work/chatbot/app/api/frontend_service/v1/divisions.rbAdd 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.rbReturn company/organization-scoped divisions with nested agents, following APIAbstractUseCase.
create/Users/mekari/workspace/work/chatbot/app/core/entities/frontend_services/division.rbEntity for { division_id, name, agents:[{id,name}] }.
create/Users/mekari/workspace/work/chatbot/app/core/builders/frontend_services/division.rbBuilder if entity conversion follows local pattern.
extend/Users/mekari/workspace/work/chatbot/app/api/frontend_service/v1.rbMount the new divisions resource if needed.
create/Users/mekari/workspace/work/chatbot/spec/api/frontend_service/v1/divisions/get_spec.rbAPI specs for 200, role enforcement, and tenant scoping.

Implementation steps

  1. Open /Users/mekari/workspace/work/chatbot/app/models/division.rb and /Users/mekari/workspace/work/chatbot/app/models/agents_division.rb; use the existing associations division.agents.
  2. Write failing API specs in /Users/mekari/workspace/work/chatbot/spec/api/frontend_service/v1/divisions/get_spec.rb for owner/supervisor/admin access, forbidden roles, and cross-company exclusion.
  3. Create /Users/mekari/workspace/work/chatbot/app/core/use_cases/api/frontend_service/v1/division/get.rb with a dry contract requiring company_id and optionally organization_id / division_id.
  4. Create the Grape resource in /Users/mekari/workspace/work/chatbot/app/api/frontend_service/v1/divisions.rb, using Dry::Matcher::ResultMatcher.call() and success_response.
  5. Add entity/builder files only if the response needs Grape entity shaping; otherwise return a plain success payload consistently with nearby API use cases.
  6. Go green with bundle exec rspec /Users/mekari/workspace/work/chatbot/spec/api/frontend_service/v1/divisions/get_spec.rb.
  7. Run bundle exec rubocop for touched files.

Acceptance criteria

  • GET /v1/divisions returns only divisions for the current user's company/organization.
  • GET /v1/divisions/:id/agents returns 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

DisciplineDays
Frontend
Backend2.0
QA0.5
Total2.5

Assumptions: Division and AgentsDivision are 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

ActionFileWhat changes
extend/Users/mekari/workspace/work/chatbot/app/api/frontend_service/v1/gpt/ai_knowledge_sources.rbAdd 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.rbValidate 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.rbPersist source division_id on ChatbotGpt::AiKnowledgeSource.
extend/Users/mekari/workspace/work/chatbot/app/core/repositories/gpt/ai_service/post_knowledge_sources.rbEnsure 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.rbUnit 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.rbRequest coverage for params, 202 shape, and 422 messages.

Implementation steps

  1. 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.
  2. Write failing specs in both create spec files for division_id, 16 selected agents, duplicate division, and successful 202 response.
  3. Extend the Grape params in /Users/mekari/workspace/work/chatbot/app/api/frontend_service/v1/gpt/ai_knowledge_sources.rb to require division_id.
  4. Update the use-case contract and guard to query by company_id, ai_knowledge_source_type_id, and division_id.
  5. Update /Users/mekari/workspace/work/chatbot/app/core/repositories/gpt/ai_knowledge_source_omnichannel_agent_conversations/create.rb so the created source row stores division_id.
  6. Review /Users/mekari/workspace/work/chatbot/app/core/repositories/gpt/ai_service/post_knowledge_sources.rb; if it currently uses find_by for a single conversation source, change it to post all active division-scoped conversation sources for the company.
  7. 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.
  8. 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

DisciplineDays
Frontend
Backend2.0
QA0.5
Total2.5

Assumptions: backend does not echo division_id in 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

ActionFileWhat changes
extend/Users/mekari/workspace/work/chatbot/app/core/use_cases/api/frontend_service/v1/gpt/ai_knowledge_source/delete.rbAdd in-use guard before destroy and keep tenant authorization.
extend/Users/mekari/workspace/work/chatbot/app/core/repositories/gpt/ai_knowledge_sources/destroy.rbEnsure destroy only removes the right agent-conversation rows/source.
extend/Users/mekari/workspace/work/chatbot/app/api/frontend_service/v1/gpt/ai_knowledge_sources.rbKeep 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.rbAdd in-use blocked and unused vector-delete cases.
extend/Users/mekari/workspace/work/chatbot/spec/core/repositories/gpt/ai_knowledge_sources/destroy_spec.rbCover source-row and agent-row deletion behavior if repository specs exist for this path.

Implementation steps

  1. 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.
  2. 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.rb for in-use 422 and unused delete success.
  3. Identify the "in use by agent" relationship (ai_agent_knowledges per RFC) and query it before Repositories::Gpt::AiKnowledgeSources::Destroy.
  4. For unused sources, call vector deletion with entity type conversation; for unlink-only behavior, soft-delete only the join/unlink record.
  5. Assert delete_vector_db is not called when the source is only removed from an agent.
  6. 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

DisciplineDays
Frontend
Backend1.5
QA0.5
Total2.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

ActionFileWhat changes
create/Users/mekari/workspace/work/chatbot/app/workers/conversation_history_daily_sync_worker.rbNew worker with sidekiq_options queue: :application_maintenance, retry: 3.
extend/Users/mekari/workspace/work/chatbot/config/schedule.ymlAdd daily cron entry for the worker.
extend/Users/mekari/workspace/work/chatbot/app/core/repositories/gpt/ai_service/post_knowledge_sources.rbReuse 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.rbAssert active sources are processed, failures are isolated, and inactive/deleted sources are skipped.

Implementation steps

  1. Open /Users/mekari/workspace/work/chatbot/config/schedule.yml and mirror the application_maintenance cron style used by PartitionChatbotGptMaintenanceWorker.
  2. Write failing specs in /Users/mekari/workspace/work/chatbot/spec/workers/conversation_history_daily_sync_worker_spec.rb for active source processing and failure isolation.
  3. Create /Users/mekari/workspace/work/chatbot/app/workers/conversation_history_daily_sync_worker.rb with # frozen_string_literal: true.
  4. Query active, non-deleted agent_conversation_history sources and post each source or company via Repositories::Gpt::AiService::PostKnowledgeSources.
  5. Rescue per source, send Rollbar.error, and continue processing remaining sources.
  6. Add the conversation_history_daily_sync_job cron entry to /Users/mekari/workspace/work/chatbot/config/schedule.yml.
  7. Run worker specs and bundle exec rubocop.

Acceptance criteria

  • Worker runs from application_maintenance at 0 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

DisciplineDays
Frontend
Backend1.5
QA0.5
Total2.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

ActionFileWhat changes
extend/Users/mekari/workspace/work/chatbot-fe/common/services/main/endpoint.tsAdd division.get and division.agents endpoint constants for Task 2.2.
extend/Users/mekari/workspace/work/chatbot-fe/common/services/main/v1/training-source.tsAdd 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.tsAdd 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.tsAssert directory action states and create payload delegation.

Implementation steps

  1. 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.
  2. Write/update failing tests in /Users/mekari/workspace/work/chatbot-fe/tests/unit/store/training-source/actions.test.ts for the directory load action and create payload delegation.
  3. Extend /Users/mekari/workspace/work/chatbot-fe/common/services/main/v1/training-source.ts with a GET wrapper using $apiMain, AbortController, and lazy, matching neighboring methods.
  4. Add the action in /Users/mekari/workspace/work/chatbot-fe/store/training-source/actions.ts only if the form needs store-owned request state.
  5. Leave /Users/mekari/workspace/work/chatbot-fe/components/AddKnowledgeDrawer.vue form rendering unchanged until REV-2 design is resolved.
  6. Run the targeted Vitest file, pnpm lint:ts, and pnpm 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

DisciplineDays
Frontend0.5
Backend
QA0.5
Total1.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

ActionFileWhat changes
create/Users/mekari/workspace/work/chatbot/app/api/internal_service/v1/gpt/conversation_history_status_webhooks.rbInbound 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.rbValidate payload, authorize service caller, map status, update source.
extend/Users/mekari/workspace/work/chatbot/app/core/repositories/gpt/ai_knowledge_sources/update_status.rbReuse/align status mapping with poll path.
create/Users/mekari/workspace/work/chatbot/spec/api/internal_service/v1/gpt/conversation_history_status_webhooks_spec.rbContract, auth, retry/idempotency, and status mapping specs.

Implementation steps

  1. Wait for REV-3 contract; do not infer payload fields or auth from the RFC prose.
  2. Open /Users/mekari/workspace/work/chatbot/app/core/repositories/gpt/ai_knowledge_sources/update_status.rb and reuse the existing poll status mapping where possible.
  3. Write failing specs in /Users/mekari/workspace/work/chatbot/spec/api/internal_service/v1/gpt/conversation_history_status_webhooks_spec.rb from the published contract.
  4. Create the internal API resource and use case using existing internal-service response patterns.
  5. Add idempotency handling for duplicate webhook delivery if the contract requires retries.
  6. Run targeted specs and bundle exec rubocop.

Acceptance criteria

  • Webhook rejects unauthenticated or malformed requests.
  • in_progress, completed, and failed contract 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

DisciplineDays
Frontend
Backend2.0
QA0.5
Total2.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

ActionFileWhat changes
extendData & AI ingestion pipeline [unverified — check owning repo]Mask standard phone/email before indexing; emit failed status on masking failure.
extendData & AI conversation filtering [unverified — check owning repo]Exclude rooms with fewer than 5 customer-facing messages and exclude whispers.
extendData & AI vector ranking [unverified — check owning repo]Prioritize recent resolved conversations and deterministic tie-break behavior.
extendData & AI content parser [unverified — check owning repo]Index text-only content and skip image/file/voice payloads.
createData & AI pipeline tests [unverified — check owning repo]Coverage for PII masking, low-message skip, whisper skip, recency, and non-text exclusion.

Implementation steps

  1. Locate the Data & AI ingestion repository and replace the unverified file placeholders above with real paths.
  2. Write failing pipeline tests for phone/email masking, 3-message skip, ≥5-message inclusion, whisper exclusion, recency order, and non-text exclusion.
  3. Implement masking before vector write; ensure raw PII is not persisted post-processing.
  4. Implement the room/message filters before indexing.
  5. Emit failure status back through the poll/webhook contract when masking/indexing fails.
  6. 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

DisciplineDays
Frontend
Backend5.0
QA1.5
Total6.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

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

ActionFileWhat changes
extend/Users/mekari/workspace/work/chatbot/app/core/use_cases/api/frontend_service/v1/gpt/ai_knowledge_source/predict.rbInclude 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.rbMap 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.rbAuthorized 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.vueRender reference link only when backend supplies an authorized URL/id.

Implementation steps

  1. Re-read the room authorization path in /Users/mekari/workspace/work/chatbot and identify the exact service/use case that owns room-view permission.
  2. Replace the provisional test file name with the repo's established spec location once the authorization path is identified.
  3. Write failing specs for authorized same-division access and unauthorized cross-division access.
  4. Add backend reference metadata only after permission passes.
  5. Update FE rendering to hide or disable links when permission metadata is absent.
  6. Run targeted RSpec, targeted Vitest, bundle exec rubocop, and pnpm 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

DisciplineDays
Frontend0.5
Backend1.0
QA0.5
Total2.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

StoryReason
NoneNo 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.