Files
lcbp3/specs/200-fullstacks/237-unified-prompt-management-ux-ui/validation-report.md
T
admin db16c95019
CI / CD Pipeline / build (push) Failing after 7m26s
CI / CD Pipeline / deploy (push) Has been skipped
690617:1443 237 #01.3
2026-06-17 14:43:30 +07:00

12 KiB
Raw Blame History

Validation Report: Unified Prompt Management UX/UI (ADR-037)

Date: 2026-06-15 Status: PARTIAL — 3 gaps require action before sign-off Feature: 237-unified-prompt-management-ux-ui Validated Against: spec.md, tasks.md, plan.md, ADR-037


Coverage Summary

Metric Count Percentage
Functional Requirements 25/29 86%
Acceptance Criteria Met 16/18 89%
Edge Cases Handled 9/12 75%
Tests Present 8/10 80%

Verified — Implemented Correctly

Phase 1 — Database Setup

Task File Status
T001 deltas/2026-06-14-create-ai-execution-profiles.sql
T002 deltas/2026-06-14-seed-execution-profiles.sql
T003 deltas/2026-06-14-seed-additional-prompt-types.sql

Phase 2 — Foundational

  • AiExecutionProfile entity — correct columns, no @VersionColumn needed (not required)
  • AiPrompt entity — @VersionColumn added (T066)
  • ContextConfigDto, SandboxRagPrepDto, CreateExecutionProfileDto, UpdateExecutionProfileDto all present
  • AiModule registered AiExecutionProfile

Phase 3 — User Story 1 (Multi-Type Prompt Management)

  • AiPromptsService.create() validates placeholders for all 4 types; increments version per promptType
  • PromptTypeDropdown component — exists
  • VersionHistory component — showAllTypes prop, grouped view, pagination (20/page)
  • PromptEditor component — live placeholder validation via PLACEHOLDER_REQUIREMENTS
  • prompt-management/page.tsx 2-column responsive layout (Tailwind lg:col-span-4/8)
  • i18n keys for th and en present in ai.json / common.json

Phase 4 — User Story 2 (Context Config Management)

  • GET /api/ai/prompts/:type/:version/context-config implemented with CASL guard
  • PUT /api/ai/prompts/:type/:version/context-config with Idempotency-Key + CASL + audit
  • AiPromptsService.getContextConfig() / updateContextConfig()
  • Context config validation: pageSize (11000), language required, project/contract UUID existence —
  • Optimistic locking (@VersionColumn) + error mapping to BusinessException
  • ContextConfigEditor component —

Phase 5 — User Story 3 (3-Step Sandbox)

  • POST /api/ai/admin/sandbox/ocr (Step 1)
  • POST /api/ai/admin/sandbox/extract (Step 2, maps to "sandbox-extract" job)
  • POST /api/ai/admin/sandbox/rag-prep added 2026-06-14 (Step 3)
  • GET /api/ai/admin/sandbox/job/:id with 300 req/min throttle
  • SandboxTabs 3-step sequential flow: OCR → Extract → RAG Prep with step guards
  • "Activate This Version" button in sandbox results — (handleActivate wired to onActivateVersion)

Phase 6 — User Story 4 (Runtime Parameters Separation)

  • AiExecutionProfilesService
  • GET/POST/PUT/DELETE /api/ai/execution-profiles with CASL guards
  • RuntimeParametersPanel component — labelled "Runtime Parameters (Global - Applies to All AI Jobs)"
  • Integrated into Sandbox tab (separate from Context Config) —

Phase 7 — Polish

  • ADR-007 layered error handling in page mutations — (toast with userMessage + recoveryAction)
  • CASL guard on all mutation endpoints —
  • Redis cache invalidation on activation — (both active:type and versions:type keys deleted)
  • Block deletion of active version — (CANNOT_DELETE_ACTIVE_PROMPT BusinessException)
  • SELECT FOR UPDATE concurrent activation —

Phase 8 — Grilling Session Resolutions

  • "All Types" option in PromptTypeDropdown
  • "All Types" grouped view in VersionHistory
  • @VersionColumn on AiPrompt entity — (T066)
  • Context config field validation backend — (T068)
  • Responsive design breakpoints in page — (grid-cols-1 lg:grid-cols-12)
  • "Runtime Parameters (Global...)" label —
  • ADR-007 layered Toast/Inline errors in page —
  • Redis cache (60s TTL) for version history — (setex(cacheKey, 60, ...))
  • Pagination (20 versions/page) in VersionHistory
  • Database SELECT FOR UPDATE for activation —
  • Block active version deletion —
  • Redis TTL (60m) for sandbox results — to be confirmed (see gap below)

⚠️ Gaps Identified

GAP-1: Placeholder Validation Mismatch — Backend vs Spec [MEDIUM]

FR-023 / FR-024 / FR-026 violation

Prompt Type Spec Required Placeholders Backend Checks Frontend Checks
ocr_extraction {{ocr_text}} (req), {{master_data_context}} (opt) {{ocr_text}} only {{ocr_text}}, {{master_data_context}} both required
rag_query_prompt {{user_query}} (req), {{retrieved_chunks}} (req) {{query}} + {{context}} {{query}} + {{context}}
rag_prep_prompt {{document_text}} (req) {{text}} {{text}}
classification_prompt {{document_metadata}} (req), {{document_text}} (opt) {{document_text}} only {{document_text}} only

Spec FR-023FR-026 defines exact placeholder names that differ from what was implemented. Additionally, {{master_data_context}} is marked "optional" in the spec but PLACEHOLDER_REQUIREMENTS requires it (making it a required validation that blocks save).

Impact: Incorrect placeholder names mean production prompts using spec-defined names ({{user_query}}, {{retrieved_chunks}}, {{document_text}} for rag_prep, {{document_metadata}}) will fail validation and cannot be saved.

Recommendation: Decide canonical placeholder names — align spec or align code. Suggested: update spec FR-023FR-026 to reflect implemented names ({{query}}, {{context}}, {{text}}) since these are used in actual production seed data. Also remove {{master_data_context}} from required list in PLACEHOLDER_REQUIREMENTS (mark as optional per spec).


GAP-2: Mobile Collapsible Accordion (T071) — Not Implemented [LOW]

FR-021 / T071: Spec requires "collapsible Left Panel accordion for mobile". The VersionHistory component has no <Accordion> or collapse-on-mobile logic. It renders the same <Card> on all screen sizes.

Impact: On mobile (<768px) the Left Panel is not collapsible — it stacks vertically (technically responsive) but without the accordion UX defined in T071.

Recommendation: Wrap VersionHistory content in a shadcn/ui <Collapsible> or <Accordion> gated by a md:hidden toggle button.


GAP-3: Integration Test (T032) Marked describe.skip [LOW]

T032 (Integration test for 3-step sandbox workflow in backend/tests/integration/ai/sandbox-workflow.spec.ts) is implemented but marked describe.skip due to missing e2e infrastructure (UserModule, CacheModule, etc.).

Impact: The 3-step sandbox workflow is not covered by automated tests at integration level. Unit tests for individual steps exist.

Recommendation: Either un-skip with a proper test module setup, or document as a known deferred test requiring e2e infrastructure setup. Update tasks.md T032 status to reflect this.


Uncovered Requirements

Requirement Status Notes
FR-023 ⚠️ Partial Backend checks {{ocr_text}} only; spec also defines {{master_data_context}} as optional (frontend wrongly requires it)
FR-024 ⚠️ Mismatch Spec: {{user_query}}, {{retrieved_chunks}}; implemented: {{query}}, {{context}}
FR-025 ⚠️ Mismatch Spec: {{document_text}}; implemented: {{text}}
FR-026 ⚠️ Partial Spec: {{document_metadata}} required; implemented: checks {{document_text}} (wrong placeholder)
FR-021 (mobile accordion) ⚠️ Partial Responsive breakpoints exist but Left Panel is not collapsible accordion
T032 integration test ⚠️ Skipped Valid test structure but describe.skip — no CI coverage

ADR Compliance Check

ADR Check Status
ADR-019 No parseInt on UUID; publicId only Pass — controller uses ParseIntPipe on versionNumber (INT), not UUID
ADR-009 No TypeORM migrations; SQL deltas used Pass — 3 SQL deltas created
ADR-016 CASL guards on all mutations Pass — @RequirePermission('system.manage_all') on every mutation
ADR-016 Idempotency-Key on POST/PUT Pass — POST :type, POST activate, PUT context-config all require it
ADR-007 Layered error handling Pass — BusinessException/ValidationException + Toast/Inline in frontend
ADR-008 Sandbox jobs via BullMQ (no inline AI) Pass — all sandbox steps enqueue via aiQueueService.enqueueSandboxJob()
ADR-023/A AI boundary — no direct Ollama access Pass — BullMQ queues used for all AI calls
ADR-029 Redis cache TTL 60s for active prompts Pass — setex(cacheKey, 60, ...)
ADR-037 Single page layout; 3-step sandbox Pass
TypeScript Zero any, zero console.log Pass — reviewed ai-prompts.service.ts, controller, page.tsx
i18n No hardcoded Thai/English strings ⚠️ Partial — SandboxTabs contains several hardcoded Thai strings (e.g., "กรุณาเลือกไฟล์ PDF", "ทำ OCR สำเร็จแล้ว")

Recommendations (Priority Order)

  1. [HIGH — FR-023FR-026] Align placeholder names between spec and code. Recommended approach: update spec to use implemented names ({{query}}, {{context}}, {{text}}). Fix PLACEHOLDER_REQUIREMENTS to mark {{master_data_context}} as optional (not blocking save).
  2. [MEDIUM — i18n] Extract hardcoded Thai strings in SandboxTabs.tsx to i18n keys (pre-existing ai.json or common.json).
  3. [LOW — T071] Add collapsible accordion to VersionHistory for mobile screens.
  4. [LOW — T032] Un-skip integration test or create a tracking issue for e2e infrastructure setup.

Sign-off Readiness

Area Ready?
Backend API endpoints Yes
Frontend page & components Yes
Database schema / seed data Yes
RBAC / Security (ADR-016) Yes
Error handling (ADR-007) Yes
Redis cache (ADR-029) Yes
AI boundary (ADR-023/A) Yes
Placeholder validation accuracy No (GAP-1)
Mobile UX (collapsible panel) ⚠️ Partial (GAP-2)
Test coverage (T032 skipped) ⚠️ Partial (GAP-3)
i18n completeness ⚠️ Partial

Conclusion: Core architecture and business logic are correctly implemented. The feature is functionally complete but requires a placeholder naming decision (GAP-1) before production sign-off.