Files
lcbp3/specs/200-fullstacks/238-ocr-ai-prompt-separation/code-review-report.md
T
admin 09e304de84
CI / CD Pipeline / build (push) Successful in 7m5s
CI / CD Pipeline / deploy (push) Failing after 20m14s
690618:1444 237 #02
2026-06-18 14:44:46 +07:00

4.8 KiB

Code Review Report

Date: 2026-06-18 13:48 Asia/Bangkok Scope: specs/200-fullstacks/238-ocr-ai-prompt-separation, related backend/frontend/sidecar changes for Feature 238 Overall: REQUEST CHANGES

Summary

Severity Count
Critical 0
High 3
Medium 2
Low 0
Suggestions 1

Findings

HIGH: OCR prompt UI is not reachable from the actual admin page

File: frontend/app/(admin)/admin/ai/prompt-management/page.tsx:21

The real prompt-management page still uses the old dropdown/editor flow and never imports or renders PromptManagementTabs. The dropdown type list also excludes ocr_system (frontend/lib/types/ai-prompts.ts:5, frontend/components/admin/ai/PromptTypeDropdown.tsx:50), so admins cannot select or edit the OCR system prompt from the shipped page.

This blocks FR-006/FR-007 and the core acceptance scenario for "OCR System Prompt". The task list marks T021/T022/T057 complete, but the implementation is currently dead UI.

Fix: Wire the Feature 238 UI into prompt-management/page.tsx, or extend the existing page's PromptType/dropdown/editor flow to include ocr_system with the required separation. Add a component test that renders the actual page and asserts both OCR System Prompt and AI Extraction Prompt are available.

HIGH: New prompt service builds /api/api/... URLs

File: frontend/lib/services/admin-ai-prompt.service.ts:28

frontend/lib/api/client.ts already sets baseURL to http://localhost:3001/api. The new service calls paths like /api/ai/prompts/${promptType}, which resolve to /api/api/ai/prompts/.... If PromptManagementTabs is wired into the page, all prompt list/create/activate/delete calls from these new tabs will fail.

Fix: Match the existing adminAiService pattern and call /ai/prompts/..., or remove this duplicate service and reuse adminAiService.

HIGH: Sidecar fallback path crashes with NameError

File: specs/04-Infrastructure-OPS/04-00-docker-compose/Desk-5439/ocr-sidecar/app.py:179

After renaming typhoon_options to ocr_options, the unknown-engine fallback still calls:

process_ocr(..., options_override=typhoon_options, ...)

typhoon_options is undefined in _process_pdf_doc(), so any direct sidecar request with a legacy/unknown engine value crashes instead of falling back to np-dms-ocr. This is especially risky because prior clients and docs still mention legacy engine aliases.

Fix: Use ocr_options in the fallback branch and add a sidecar test for engine=typhoon-np-dms-ocr and an unknown engine.

MEDIUM: Activate request body bypasses DTO validation

File: backend/src/modules/ai/prompts/ai-prompts.controller.ts:135

The new expectedVersion body is typed inline as { expectedVersion?: number } rather than a DTO. Runtime validation will not enforce integer typing, so "1" from a client compares unequal to numeric 1 and returns a false 409 conflict.

Fix: Add an ActivatePromptDto with @IsOptional(), @Type(() => Number), @IsInt(), @Min(1), and use it in the controller. Add a controller/service test for string numeric input and invalid input.

MEDIUM: Feature tasks are marked complete beyond implemented UI behavior

File: specs/200-fullstacks/238-ocr-ai-prompt-separation/tasks.md:175

T057-T068 are checked as complete, but the new PromptManagementTabs has only two tabs and no Sandbox tab, while the real page still uses the older SandboxTabs path. The E2E file that passed is mostly data/format assertions and does not exercise the rendered admin page or backend endpoints end-to-end.

Fix: Uncheck incomplete tasks or finish the actual wiring/tests. Add a UI test for the real page's 3-step sandbox and a backend/sidecar integration test proving Step 1 sends systemPrompt.

What's Good

  • Backend prompt validation now recognizes ocr_system as a free-form prompt type while preserving required placeholders for ocr_extraction, rag_prep_prompt, and related types.
  • SandboxOcrEngineService fetches the active ocr_system prompt and appends it as systemPrompt for sidecar calls.
  • Existing backend and frontend type checks currently pass.

Verification

  • pnpm --filter backend test -- sandbox-ocr-engine.service.spec.ts passed, but Jest ran the broader backend suite: 98 passed, 2 skipped, 855 tests passed.
  • pnpm --filter lcbp3-frontend exec tsc --noEmit passed with no output.
  1. Must fix before merge: wire OCR prompt management into the real page, correct frontend service URLs, and fix the sidecar typhoon_options runtime crash.
  2. Should address: replace inline activate body typing with a validated DTO and align tasks.md with verified behavior.
  3. Consider later: consolidate duplicate prompt services/components to avoid two admin prompt-management implementations drifting apart.