KnowledgeVault AI plan-module M-08
internal prototype · canonical JSON + Dreamborn Forge HTML
internal generated
plan-module · supabase_json

KnowledgeVault AI plan-module M-08

plan-module artifact · for KnowledgeVault AI · phase M-08 · status draft

Planning Surface

Use this to decide what happens next.

Status

draft

Phase

M-08

tasks
idrolebrieftitlecompletiondepends on
1developerCreate apps/knowledgevault/supabase/migrations/0008_field_queries_ve.sql — SQL migration ensuring field_queries has the columns needed for virtual expert query logging (answer, sources, field_verified_badge, virtual_expert_id, queried_at). IMPORTANT: Check if field_queries already exists from M-07 migration (0007_field_queries.sql). If it does: - Use ALTER TABLE field_queries ADD COLUMN IF NOT EXISTS for each missing column - Do NOT recreate the table If field_queries does NOT exist, create it fresh with CREATE TABLE IF NOT EXISTS. **Target schema (final state after both M-07 and Create field_queries virtual-expert columns migration- type: file - evaluate: SQL migration is fully idempotent using ADD COLUMN IF NOT EXISTS for columns that may already exist from M-07; final field_queries schema includes virtual_expert_id FK (NOT NULL, REFERENCES virtual_experts CASCADE), company_id FK, query_text NOT NULL, answer nullable with -- nullable comment, sources jsonb NOT NULL DEFAULT '[]', field_verified_badge boolean NOT NULL DEFAULT false, queried_at and created_at NOT NULL; RLS enabled with company SELECT policy; no existing migration files modified (POL-ARCH-001, POL-DATA-002, POL-SEC-001). - min length: 200
2developerCreate apps/knowledgevault/src/app/api/virtual-experts/route.ts — Next.js App Router API route listing all published virtual experts for company-authenticated field technicians. Auth: Company JWT required via companyAuthMiddleware from src/lib/auth/companyAuthMiddleware.ts (from M-07 — do not rewrite this middleware). Call it first per POL-SEC-002. Request: GET, no body, no query parameters. Success 200: ```json { "experts": [{ "id": "uuid", "name": "string", "role_type": "string", "description": "string|null", "session_count": "integer", "avg_accuracy_score": "float|null"Implement GET /api/virtual-experts route- type: file - evaluate: Route calls companyAuthMiddleware first per POL-SEC-002, returns 200 with experts array containing exactly 7 fields (id, name, role_type, description, session_count, avg_accuracy_score, knowledge_chunk_count), ordered by session_count DESC, filters to is_published=true only, returns 401 for missing/invalid JWT, returns 500 on DB error, no bare any (POL-STYLE-001). - min length: 100- 1
3developerCreate apps/knowledgevault/src/app/api/virtual-experts/[id]/query/route.ts — virtual expert query endpoint. Field technicians ask a named AI expert persona and receive a GPT-4o synthesised first-person answer. Auth: Company JWT required via companyAuthMiddleware from src/lib/auth/companyAuthMiddleware.ts (POL-SEC-002). Request: POST, URL param :id (virtual expert uuid), body { query: string (required, 1-500 chars) } Success 200: ```json { "answer": "string", "expert_name": "string", "role_type": "string", "sources": [{"chunk_id": "uuid", "content": "string", "chunk_typImplement POST /api/virtual-experts/[id]/query route- type: file - evaluate: Route performs all 12 steps in order (auth → validate → sanitize per POL-SEC-003 → fetch expert → embed → pgvector search → zero-chunk short-circuit without GPT-4o call → GPT-4o with 'Do not fabricate' in system prompt → field_verified_badge → field_queries INSERT via service role → return 200), correct HTTP codes for all error cases, typed catch on every async call (POL-STYLE-002), no bare any (POL-STYLE-001), POL-ARCH-003 for service key. - min length: 350- 1 - 2
4developerCreate apps/knowledgevault/src/app/(company)/experts/page.tsx — React page displaying published virtual experts for company-authenticated field technicians to select. Behavior: - Fetch GET /api/virtual-experts on mount - Render 4 ExpertCardSkeleton components (from src/components/experts/ExpertCardSkeleton.tsx) immediately while loading - On response: render ExpertCard components (from src/components/experts/ExpertCard.tsx) in a CSS grid: 2 columns at ≥768px, 1 column at <768px - On empty array: render empty state — icon + 'No experts available yet' headline + 'Check back soonImplement VirtualExpertSelection screen- type: file - evaluate: Page fetches GET /api/virtual-experts on mount, renders 4 ExpertCardSkeleton immediately, switches to ExpertCard grid (2-col ≥768px, 1-col <768px) on response, renders empty state ('No experts available yet') on empty array, PoweredByBadge always at bottom; ExpertCard has role=button and correct aria-label; companion components ExpertCard.tsx, ExpertCardSkeleton.tsx, PoweredByBadge.tsx exist in components/experts/; no bare any (POL-STYLE-001). - min length: 200- 2
5developerCreate apps/knowledgevault/src/app/(company)/experts/[id]/page.tsx — React Client Component for field technicians to query a specific virtual expert and read their synthesised first-person answer. On mount: Fetch expert detail (use GET /api/virtual-experts and filter by [id]). Render ExpertIdentityHeader skeleton immediately. ExpertIdentityHeader (component src/components/experts/ExpertIdentityHeader.tsx): - <h1> with expert name - Subtitle: role_type, formatted accuracy score - Back link to /experts QueryInput (component src/components/experts/QueryInput.tsx): -Implement VirtualExpertChat screen- type: file - evaluate: Page renders ExpertIdentityHeader skeleton on mount, QueryInput placeholder reads 'Ask <first_name> anything', submitting shows AnswerCard loading skeleton before response, 200 response renders answer with 'Based on N captured answers' expandable sources (content, chunk_type, sku, time-ago per source), field_verified_badge renders 'Field-verified N minutes ago' when true and is absent when false, 503 renders unavailable message with Try again button that re-submits last query, back link returns to /experts, companion components ExpertIdentityHeader/QueryInput/AnswerCar- 3
Agent Handoff
Start Here
idrolebrieftitlecompletiondepends on
1developerCreate apps/knowledgevault/supabase/migrations/0008_field_queries_ve.sql — SQL migration ensuring field_queries has the columns needed for virtual expert query logging (answer, sources, field_verified_badge, virtual_expert_id, queried_at). IMPORTANT: Check if field_queries already exists from M-07 migration (0007_field_queries.sql). If it does: - Use ALTER TABLE field_queries ADD COLUMN IF NOT EXISTS for each missing column - Do NOT recreate the table If field_queries does NOT exist, create it fresh with CREATE TABLE IF NOT EXISTS. **Target schema (final state after both M-07 and Create field_queries virtual-expert columns migration- type: file - evaluate: SQL migration is fully idempotent using ADD COLUMN IF NOT EXISTS for columns that may already exist from M-07; final field_queries schema includes virtual_expert_id FK (NOT NULL, REFERENCES virtual_experts CASCADE), company_id FK, query_text NOT NULL, answer nullable with -- nullable comment, sources jsonb NOT NULL DEFAULT '[]', field_verified_badge boolean NOT NULL DEFAULT false, queried_at and created_at NOT NULL; RLS enabled with company SELECT policy; no existing migration files modified (POL-ARCH-001, POL-DATA-002, POL-SEC-001). - min length: 200
2developerCreate apps/knowledgevault/src/app/api/virtual-experts/route.ts — Next.js App Router API route listing all published virtual experts for company-authenticated field technicians. Auth: Company JWT required via companyAuthMiddleware from src/lib/auth/companyAuthMiddleware.ts (from M-07 — do not rewrite this middleware). Call it first per POL-SEC-002. Request: GET, no body, no query parameters. Success 200: ```json { "experts": [{ "id": "uuid", "name": "string", "role_type": "string", "description": "string|null", "session_count": "integer", "avg_accuracy_score": "float|null"Implement GET /api/virtual-experts route- type: file - evaluate: Route calls companyAuthMiddleware first per POL-SEC-002, returns 200 with experts array containing exactly 7 fields (id, name, role_type, description, session_count, avg_accuracy_score, knowledge_chunk_count), ordered by session_count DESC, filters to is_published=true only, returns 401 for missing/invalid JWT, returns 500 on DB error, no bare any (POL-STYLE-001). - min length: 100- 1
3developerCreate apps/knowledgevault/src/app/api/virtual-experts/[id]/query/route.ts — virtual expert query endpoint. Field technicians ask a named AI expert persona and receive a GPT-4o synthesised first-person answer. Auth: Company JWT required via companyAuthMiddleware from src/lib/auth/companyAuthMiddleware.ts (POL-SEC-002). Request: POST, URL param :id (virtual expert uuid), body { query: string (required, 1-500 chars) } Success 200: ```json { "answer": "string", "expert_name": "string", "role_type": "string", "sources": [{"chunk_id": "uuid", "content": "string", "chunk_typImplement POST /api/virtual-experts/[id]/query route- type: file - evaluate: Route performs all 12 steps in order (auth → validate → sanitize per POL-SEC-003 → fetch expert → embed → pgvector search → zero-chunk short-circuit without GPT-4o call → GPT-4o with 'Do not fabricate' in system prompt → field_verified_badge → field_queries INSERT via service role → return 200), correct HTTP codes for all error cases, typed catch on every async call (POL-STYLE-002), no bare any (POL-STYLE-001), POL-ARCH-003 for service key. - min length: 350- 1 - 2
4developerCreate apps/knowledgevault/src/app/(company)/experts/page.tsx — React page displaying published virtual experts for company-authenticated field technicians to select. Behavior: - Fetch GET /api/virtual-experts on mount - Render 4 ExpertCardSkeleton components (from src/components/experts/ExpertCardSkeleton.tsx) immediately while loading - On response: render ExpertCard components (from src/components/experts/ExpertCard.tsx) in a CSS grid: 2 columns at ≥768px, 1 column at <768px - On empty array: render empty state — icon + 'No experts available yet' headline + 'Check back soonImplement VirtualExpertSelection screen- type: file - evaluate: Page fetches GET /api/virtual-experts on mount, renders 4 ExpertCardSkeleton immediately, switches to ExpertCard grid (2-col ≥768px, 1-col <768px) on response, renders empty state ('No experts available yet') on empty array, PoweredByBadge always at bottom; ExpertCard has role=button and correct aria-label; companion components ExpertCard.tsx, ExpertCardSkeleton.tsx, PoweredByBadge.tsx exist in components/experts/; no bare any (POL-STYLE-001). - min length: 200- 2
5developerCreate apps/knowledgevault/src/app/(company)/experts/[id]/page.tsx — React Client Component for field technicians to query a specific virtual expert and read their synthesised first-person answer. On mount: Fetch expert detail (use GET /api/virtual-experts and filter by [id]). Render ExpertIdentityHeader skeleton immediately. ExpertIdentityHeader (component src/components/experts/ExpertIdentityHeader.tsx): - <h1> with expert name - Subtitle: role_type, formatted accuracy score - Back link to /experts QueryInput (component src/components/experts/QueryInput.tsx): -Implement VirtualExpertChat screen- type: file - evaluate: Page renders ExpertIdentityHeader skeleton on mount, QueryInput placeholder reads 'Ask <first_name> anything', submitting shows AnswerCard loading skeleton before response, 200 response renders answer with 'Based on N captured answers' expandable sources (content, chunk_type, sku, time-ago per source), field_verified_badge renders 'Field-verified N minutes ago' when true and is absent when false, 503 renders unavailable message with Try again button that re-submits last query, back link returns to /experts, companion components ExpertIdentityHeader/QueryInput/AnswerCar- 3
Completion Evidence

No explicit evidence field yet. Require tests, screenshots, linked PRs, or reviewed outputs before marking complete.

Artifact Shape
  • notes: Reuses companyAuthMiddleware from M-07 (src/lib/auth/companyAuthMiddleware.ts). D-08-01 creates a field_queries migration with additional columns for virtual expert query context (answer, sources, field_verified_badge) — if field_queries already exists from M-07, this migration should ALTER TABLE to add the missing columns rather than CREATE TABLE. Quinn must check M-07 migration state before applying.
  • tasks: 5 items
  • module id: M-08
  • module name: Virtual Expert Query
  • schema version: 1.0
  • depends on modules: 2 items
Structured Payload

Machine-readable source fields

notes

Reuses companyAuthMiddleware from M-07 (src/lib/auth/companyAuthMiddleware.ts). D-08-01 creates a field_queries migration with additional columns for virtual expert query context (answer, sources, field_verified_badge) — if field_queries already exists from M-07, this migration should ALTER TABLE to add the missing columns rather than CREATE TABLE. Quinn must check M-07 migration state before applying.

tasks
idrolebrieftitlecompletiondepends on
1developerCreate apps/knowledgevault/supabase/migrations/0008_field_queries_ve.sql — SQL migration ensuring field_queries has the columns needed for virtual expert query logging (answer, sources, field_verified_badge, virtual_expert_id, queried_at). IMPORTANT: Check if field_queries already exists from M-07 migration (0007_field_queries.sql). If it does: - Use ALTER TABLE field_queries ADD COLUMN IF NOT EXISTS for each missing column - Do NOT recreate the table If field_queries does NOT exist, create it fresh with CREATE TABLE IF NOT EXISTS. **Target schema (final state after both M-07 and Create field_queries virtual-expert columns migration- type: file - evaluate: SQL migration is fully idempotent using ADD COLUMN IF NOT EXISTS for columns that may already exist from M-07; final field_queries schema includes virtual_expert_id FK (NOT NULL, REFERENCES virtual_experts CASCADE), company_id FK, query_text NOT NULL, answer nullable with -- nullable comment, sources jsonb NOT NULL DEFAULT '[]', field_verified_badge boolean NOT NULL DEFAULT false, queried_at and created_at NOT NULL; RLS enabled with company SELECT policy; no existing migration files modified (POL-ARCH-001, POL-DATA-002, POL-SEC-001). - min length: 200
2developerCreate apps/knowledgevault/src/app/api/virtual-experts/route.ts — Next.js App Router API route listing all published virtual experts for company-authenticated field technicians. Auth: Company JWT required via companyAuthMiddleware from src/lib/auth/companyAuthMiddleware.ts (from M-07 — do not rewrite this middleware). Call it first per POL-SEC-002. Request: GET, no body, no query parameters. Success 200: ```json { "experts": [{ "id": "uuid", "name": "string", "role_type": "string", "description": "string|null", "session_count": "integer", "avg_accuracy_score": "float|null"Implement GET /api/virtual-experts route- type: file - evaluate: Route calls companyAuthMiddleware first per POL-SEC-002, returns 200 with experts array containing exactly 7 fields (id, name, role_type, description, session_count, avg_accuracy_score, knowledge_chunk_count), ordered by session_count DESC, filters to is_published=true only, returns 401 for missing/invalid JWT, returns 500 on DB error, no bare any (POL-STYLE-001). - min length: 100- 1
3developerCreate apps/knowledgevault/src/app/api/virtual-experts/[id]/query/route.ts — virtual expert query endpoint. Field technicians ask a named AI expert persona and receive a GPT-4o synthesised first-person answer. Auth: Company JWT required via companyAuthMiddleware from src/lib/auth/companyAuthMiddleware.ts (POL-SEC-002). Request: POST, URL param :id (virtual expert uuid), body { query: string (required, 1-500 chars) } Success 200: ```json { "answer": "string", "expert_name": "string", "role_type": "string", "sources": [{"chunk_id": "uuid", "content": "string", "chunk_typImplement POST /api/virtual-experts/[id]/query route- type: file - evaluate: Route performs all 12 steps in order (auth → validate → sanitize per POL-SEC-003 → fetch expert → embed → pgvector search → zero-chunk short-circuit without GPT-4o call → GPT-4o with 'Do not fabricate' in system prompt → field_verified_badge → field_queries INSERT via service role → return 200), correct HTTP codes for all error cases, typed catch on every async call (POL-STYLE-002), no bare any (POL-STYLE-001), POL-ARCH-003 for service key. - min length: 350- 1 - 2
4developerCreate apps/knowledgevault/src/app/(company)/experts/page.tsx — React page displaying published virtual experts for company-authenticated field technicians to select. Behavior: - Fetch GET /api/virtual-experts on mount - Render 4 ExpertCardSkeleton components (from src/components/experts/ExpertCardSkeleton.tsx) immediately while loading - On response: render ExpertCard components (from src/components/experts/ExpertCard.tsx) in a CSS grid: 2 columns at ≥768px, 1 column at <768px - On empty array: render empty state — icon + 'No experts available yet' headline + 'Check back soonImplement VirtualExpertSelection screen- type: file - evaluate: Page fetches GET /api/virtual-experts on mount, renders 4 ExpertCardSkeleton immediately, switches to ExpertCard grid (2-col ≥768px, 1-col <768px) on response, renders empty state ('No experts available yet') on empty array, PoweredByBadge always at bottom; ExpertCard has role=button and correct aria-label; companion components ExpertCard.tsx, ExpertCardSkeleton.tsx, PoweredByBadge.tsx exist in components/experts/; no bare any (POL-STYLE-001). - min length: 200- 2
5developerCreate apps/knowledgevault/src/app/(company)/experts/[id]/page.tsx — React Client Component for field technicians to query a specific virtual expert and read their synthesised first-person answer. On mount: Fetch expert detail (use GET /api/virtual-experts and filter by [id]). Render ExpertIdentityHeader skeleton immediately. ExpertIdentityHeader (component src/components/experts/ExpertIdentityHeader.tsx): - <h1> with expert name - Subtitle: role_type, formatted accuracy score - Back link to /experts QueryInput (component src/components/experts/QueryInput.tsx): -Implement VirtualExpertChat screen- type: file - evaluate: Page renders ExpertIdentityHeader skeleton on mount, QueryInput placeholder reads 'Ask <first_name> anything', submitting shows AnswerCard loading skeleton before response, 200 response renders answer with 'Based on N captured answers' expandable sources (content, chunk_type, sku, time-ago per source), field_verified_badge renders 'Field-verified N minutes ago' when true and is absent when false, 503 renders unavailable message with Try again button that re-submits last query, back link returns to /experts, companion components ExpertIdentityHeader/QueryInput/AnswerCar- 3
module id

M-08

module name

Virtual Expert Query

schema version

1.0

depends on modules
  • M-05
  • M-07