# Kế hoạch tổng thể: integration và E2E verification cho DSCons

## Mục tiêu

Thiết kế một lớp kiểm chứng xuyên tầng đủ thực dụng để DSCons không chỉ có unit test cho từng service, mà còn chứng minh được các luồng nghiệp vụ chính đang chạy đúng qua:

- FastAPI route
- service orchestration
- PostgreSQL persistence
- Qdrant retrieval
- MLX/agent runtime
- SSE streaming
- degraded/fallback path

Tài liệu này không sửa code. Mục tiêu là chốt kiến trúc verification, thứ tự triển khai, tiêu chí chấp nhận và cách rollout ít rủi ro cho codebase hiện tại.

---

## 1. Gap map hiện tại

## 1.1 Coverage hiện có

Từ suite hiện tại, DSCons đã có nền tảng ban đầu:

- `tests/test_dossier_review_routes.py`
  - kiểm tra route-level lifecycle dossier review
  - nhưng chủ yếu bằng fake `PostgresClient` và fake `WorkflowPersistenceService`
- `tests/test_workflow_persistence_service.py`
  - kiểm tra logic service ở mức đơn lẻ
- `tests/test_company_operational_state_service.py`
  - kiểm tra aggregate/fallback ở mức service
- `tests/test_remediation_planning_service.py`
  - kiểm tra build/list logic ở mức service
- `tests/test_dossier_report_service.py`
  - kiểm tra dossier reporting ở mức service/schema
- `docs/verification-strategy-workflow-and-operational-state.md`
  - có vài smoke script thủ công trong `tmp/`
  - hữu ích để verify live server nhưng chưa thành chiến lược verification chính thức

## 1.2 Gaps theo lớp

| Lớp | Hiện trạng | Gap chính |
| --- | --- | --- |
| Schema/model | Có một phần test schema | Chưa có contract test khóa shape response cho nhiều endpoint trọng yếu |
| Service | Có nhiều unit test | Chưa chứng minh wiring thật giữa service với DB/Qdrant/runtime |
| Route | Có route test cho dossier review | Chưa phủ remediation, operational state, knowledge, readiness, health |
| Integration với Postgres | Chủ yếu fake | Chưa có suite chạy với Postgres thật |
| Integration với Qdrant | Hầu như chưa có | Chưa có ingestion/search verification thật |
| Integration với MLX/agent | Hầu như chưa có | Chưa có chiến lược fake-vs-real rõ ràng để test ổn định |
| SSE | Chưa thấy test chính thức | Chưa verify event framing, reconnect semantics, payload contract |
| Error path | Có một số fallback test service | Chưa có matrix lỗi ở API level và dependency level |
| E2E đa bước | Có script ad-hoc trong `tmp/` | Chưa có suite deterministic, repeatable trong CI |
| CI staging | Chưa thấy phân tầng rõ | Chưa phân biệt smoke / integration / E2E / nightly |

## 1.3 Gaps theo luồng nghiệp vụ

### Luồng 1: persisted dossier review workflow
Có test route lifecycle giả lập, nhưng chưa có:
- luồng đi thật qua Postgres
- xác minh review start → list/get → finding → assignment → submission → verify → close
- xác minh side-effect sang company operational state / operations / remediation
- error-path khi step giữa fail hoặc dữ liệu partial

### Luồng 2: company operational state aggregate
Có test service fallback, nhưng chưa có:
- integration test API với dữ liệu persisted thật
- contract test cho `source_status`, `used_fallback`, `message`
- SSE parity test giữa snapshot route và stream event payload

### Luồng 3: remediation planning
Có service tests tốt, nhưng chưa có:
- integration từ persisted review finding sang remediation endpoint
- contract test build/list/gaps ở route level
- error-path khi manifest thiếu/sai định dạng qua API thật

### Luồng 4: knowledge/agent routing
README xác nhận có:
- `/v1/knowledge/ingest`
- `/v1/knowledge/search`
- `/v1/knowledge/review-memory/ingest`
- `/v1/knowledge/project-memory/ingest`
- `/route-task`
- `/v1/agents/...`

Nhưng hiện chưa thấy lớp verification chính thức cho:
- ingest → search → route-task
- review memory ingestion từ review session thật
- fallback khi Qdrant unavailable
- fake LLM vs real MLX behavior

### Luồng 5: health/readiness/degraded signaling
Có smoke script và endpoint hiện tại, nhưng thiếu:
- contract test cho readiness payload
- negative test khi Postgres down hoặc static asset thiếu
- thống nhất expectation giữa health endpoint và degraded service responses

---

## 2. Root cause của việc thiếu integration/E2E verification

## 2.1 Test suite đang nghiêng mạnh về isolated logic
Phần lớn test hiện tại dùng:
- fake clients
- stub services
- in-memory payloads

Điều này tốt cho tốc độ, nhưng che mất lỗi integration thực tế như:
- schema persistence mismatch
- wiring sai giữa route và service
- lỗi serialization/deserialization
- assumption sai về dependency availability

## 2.2 Chưa có dependency strategy thống nhất
DSCons có 3 dependency khó test ổn định:
- PostgreSQL
- Qdrant
- MLX local LLM

Hiện chưa có ma trận chính thức xác định:
- test nào dùng fake
- test nào dùng service thật
- test nào được chạy trong CI thường xuyên
- test nào chỉ chạy nightly/manual

## 2.3 Thiếu fixture và seed chuẩn hóa
Các luồng dossier review, remediation, operational state đều cần seed data liên quan lẫn nhau. Nếu không có:
- fixture tạo project/review/findings chuẩn
- manifest fixture
- knowledge chunks fixture
- cleanup strategy

thì integration test sẽ khó viết, khó lặp lại và dễ flaky.

## 2.4 Chưa có contract layer ổn định ở API biên
Nhiều endpoint đang có hành vi fail-soft/degraded. Nếu không có contract test rõ:
- field nào luôn phải có
- field nào optional
- khi degraded thì status code thế nào
- `used_fallback`, `message`, `source_status` phải ra sao

thì rất dễ “pass bằng cảm tính” nhưng hỏng ngầm.

## 2.5 SSE và async path chưa được đưa vào verification architecture
`GET /v1/company/operational-state/stream` là endpoint đặc thù:
- async
- streaming
- lặp vô hạn
- phụ thuộc timing

Nếu không thiết kế test harness riêng, SSE thường bị bỏ trống trong suite.

---

## 3. Target verification architecture

## 3.1 Test pyramid đề xuất cho DSCons

### Tầng A. Unit + schema tests
Mục tiêu:
- validate logic cục bộ, nhanh, deterministic

Bao gồm:
- model/schema validation
- helper/assembler/policy mapping
- service logic thuần với fake dependency

Tỷ trọng đề xuất: 55-60%

### Tầng B. Slice tests / route-contract tests
Mục tiêu:
- test FastAPI endpoint với dependency override hoặc fake có kiểm soát
- khóa API contract ở response layer

Bao gồm:
- route-level response shape
- status code mapping
- error contract
- degraded flags contract

Tỷ trọng đề xuất: 20-25%

### Tầng C. Integration tests với dependency thật có chọn lọc
Mục tiêu:
- test wiring thật với Postgres/Qdrant
- xác minh persistence, query, serialization, side-effect

Bao gồm:
- Postgres-backed integration
- Qdrant-backed integration
- SSE integration tại ASGI/HTTP level

Tỷ trọng đề xuất: 15-20%

### Tầng D. E2E business-flow tests
Mục tiêu:
- chứng minh một số luồng nghiệp vụ ưu tiên chạy xuyên lớp

Bao gồm:
- dossier review full lifecycle
- review → operational state → remediation
- knowledge ingest → search → route-task

Tỷ trọng đề xuất: 5-10%

### Tầng E. Manual/live smoke scripts
Giữ lại `tmp/` script cho:
- live environment diagnostics
- smoke ngoài CI
- hỗ trợ debug production-like

Không coi đây là source-of-truth chính.

---

## 3.2 Fake vs real dependency matrix

| Verification layer | Postgres | Qdrant | MLX / LLM |
| --- | --- | --- | --- |
| Unit service tests | Fake / stub | Fake / stub | Fake / stub |
| Route-contract tests | Fake / override | Fake / override | Fake / override |
| Postgres integration | Real | Fake | Fake |
| Qdrant integration | Fake hoặc real tùy flow | Real | Fake |
| Retrieval + route-task integration | Fake hoặc real tối thiểu | Real | Fake deterministic |
| Full E2E core business flow | Real | Fake nếu flow không cần retrieval | Fake deterministic |
| Nightly retrieval E2E | Real nếu cần | Real | Real hoặc smoke-real có quota thấp |

## 3.3 Quy tắc chọn real dependency

### PostgreSQL
Dùng thật cho:
- workflow persistence lifecycle
- review list/get/filter
- operations case derivation từ review data
- remediation derivation từ persisted findings
- readiness/health dependency check

Không cần thật cho:
- pure schema validation
- route contract đơn giản không phụ thuộc DB

### Qdrant
Dùng thật cho:
- knowledge ingest/search contract
- review-memory/project-memory ingestion path
- retrieval filtering correctness tối thiểu

Không bắt buộc thật cho:
- dossier workflow persistence
- company operational state nếu không dùng retrieval

### MLX / LLM
Mặc định fake ở đa số test vì:
- chậm
- nondeterministic
- phụ thuộc model local/cache
- dễ flaky trên CI

Chỉ dùng real cho:
- smoke-nightly rất hẹp
- benchmark/regression thủ công
- một vài health check phi chức năng, không assert nội dung text quá chặt

---

## 4. Priority E2E flows cần có

## 4.1 P0 — Dossier review persisted lifecycle
Luồng:
1. `POST /v1/workflows/dossier-review/start`
2. `GET /v1/dossiers/reviews`
3. `GET /v1/dossiers/reviews/{review_id}`
4. `POST /v1/dossiers/reviews/{review_id}/findings`
5. `POST /.../assignments`
6. `POST /.../submissions`
7. `POST /.../verify`
8. `POST /v1/dossiers/reviews/{review_id}/close`

Assert chính:
- session persisted thật trong Postgres
- review status chuyển đúng qua từng bước
- finding/assignment/submission/action records nhất quán
- list/get phản ánh state mới nhất
- close không làm mất action history

Giá trị:
- là flow nghiệp vụ lõi nhất của DSCons hiện tại
- trực tiếp giảm rủi ro cho issue #1, #4, #5

## 4.2 P0 — Review-derived operational projection flow
Chuẩn bị bằng persisted review data, rồi gọi:
- `GET /v1/company/operational-state`
- `GET /v1/operations/cases`
- `GET /v1/operations/actions`
- `GET /v1/operations/blockers`
- `GET /v1/remediation/plans`
- `GET /v1/remediation/gaps`

Assert chính:
- cùng một finding mở tạo ra signals nhất quán ở nhiều endpoint
- resolved finding biến mất hoặc đổi trạng thái nhất quán
- counts ở aggregate không lệch với queue endpoints
- `used_fallback`, `source_status`, `message` phản ánh đúng dependency health

Giá trị:
- phát hiện semantic drift xuyên service
- gắn trực tiếp với issue #3 và #4

## 4.3 P0 — SSE operational-state parity flow
Luồng:
1. seed dữ liệu review/project
2. gọi snapshot `GET /v1/company/operational-state`
3. mở stream `GET /v1/company/operational-state/stream`
4. đọc event đầu tiên

Assert chính:
- HTTP headers đúng cho SSE
- event name là `operational_state`
- payload JSON parse được
- payload stream có shape tương thích snapshot route
- các field quan trọng (`summary`, `projects`, `source_status`, `used_fallback`) tồn tại

Giá trị:
- phủ phần async/streaming dễ bị bỏ sót
- giúp dashboard không gãy ngầm

## 4.4 P1 — Knowledge ingestion and retrieval flow
Luồng:
1. `POST /v1/knowledge/ingest`
2. `POST /v1/knowledge/search`
3. `POST /route-task` hoặc `/v1/agents/{task_type}/run` với LLM fake deterministic

Assert chính:
- chunk ingest thành công
- search trả về metadata/filter đúng
- routing gọi retrieval path đúng và trả response contract hợp lệ

## 4.5 P1 — Review memory ingestion flow
Luồng:
1. tạo review session thật
2. ingest review memory qua `/v1/knowledge/review-memory/ingest`
3. search theo review metadata
4. route-task dùng retrieval filters liên quan review

Assert chính:
- review persisted được chuyển thành memory chunks
- metadata truy hồi đúng `review_id`, `project_code`

## 4.6 P1 — Readiness/degraded flow
Luồng:
- chạy readiness khi Postgres bật
- chạy readiness khi Postgres bị disable/unavailable bằng config test harness
- gọi operational/remediation endpoints trong mode degraded

Assert chính:
- status code 200/503 đúng contract
- payload không đánh tráo “ready” thành success giả
- degraded state được surfacing nhất quán

---

## 5. Contract test strategy

## 5.1 Endpoint families cần contract test

### Family A: health/readiness
- `/health`
- `/health/readiness`

Khóa:
- field bắt buộc
- status code semantics
- `checks.application`, `checks.postgres`, `checks.static_assets`

### Family B: dossier workflow
- `/v1/workflows/dossier-review/start`
- `/v1/dossiers/reviews`
- `/v1/dossiers/reviews/{review_id}`
- nested finding/assignment/submission/verify/close endpoints

Khóa:
- response schema đầy đủ
- status transition semantics tối thiểu
- error payload khi invalid review/finding/assignment

### Family C: operational aggregate
- `/v1/company/operational-state`
- `/v1/company/operational-state/stream`
- `/v1/operations/cases`
- `/v1/operations/actions`
- `/v1/operations/blockers`

Khóa:
- top-level fields
- degraded metadata
- queue item minimum fields
- cross-endpoint count invariants

### Family D: remediation
- `/v1/remediation/plans`
- `/v1/remediation/plans/build`
- `/v1/remediation/gaps`
- `/v1/dossiers/{project_code}/coverage`
- `/v1/dossiers/{project_code}/readiness`

Khóa:
- fallback-safe responses vẫn schema-compatible
- `used_fallback` contract
- build/list/gaps selector semantics

### Family E: knowledge/agent
- `/v1/knowledge/ingest`
- `/v1/knowledge/search`
- `/v1/knowledge/review-memory/ingest`
- `/v1/knowledge/project-memory/ingest`
- `/route-task`
- `/v1/agents/...`

Khóa:
- request/response shape
- filter contract
- metadata propagation
- deterministic fake-LLM answer envelope

## 5.2 Contract style
Nên khóa ở mức:
- field presence
- field type
- enum/status invariant chính
- relational invariant ngắn gọn

Không nên khóa:
- timestamp exact value
- natural-language message toàn phần nếu không thật sự cần
- thứ tự list khi business không cam kết

---

## 6. Error-path coverage matrix

## 6.1 Dossier workflow
Phải có test cho:
- `review_id` không tồn tại → 404 hoặc 400 đúng contract
- `finding_id` sai
- verify khi chưa có submission
- close khi còn open finding nếu business rule cấm
- payload thiếu field required
- persistence layer ném `ValueError` → route mapping đúng

## 6.2 Operational state
Phải có test cho:
- project source fail
- dossier review source fail
- operations case service fail
- remediation service fail
- nhiều optional builder cùng fail

Assert:
- endpoint không crash nếu policy là fail-soft
- `used_fallback=True`
- `source_status` phản ánh source unavailable
- `message` mang tín hiệu đủ để debug

## 6.3 Remediation
Phải có test cho:
- manifest missing
- manifest invalid JSON
- project code không có trong manifest
- finding selector không match
- generic document type fallback path

## 6.4 Knowledge/Qdrant
Phải có test cho:
- collection unavailable
- ingest payload invalid
- filter key không hợp lệ
- search khi collection rỗng
- review-memory ingest khi review không tồn tại

## 6.5 Health/readiness
Phải có test cho:
- Postgres disabled
- Postgres enabled nhưng query fail
- static asset thiếu file
- readiness degraded nhưng app còn sống

## 6.6 SSE
Phải có test cho:
- response media type đúng
- event format parse được
- event đầu tiên trả về trong timeout xác định
- stream không nhả malformed JSON

---

## 7. SSE coverage strategy

## 7.1 Mục tiêu
Không cần test loop vô hạn. Chỉ cần chứng minh:
- route mở stream được
- frame đầu tiên hợp lệ
- payload shape đúng contract

## 7.2 Cách test đề xuất
Dùng HTTP client test ở ASGI layer hoặc local server harness để:
- mở connection tới `/v1/company/operational-state/stream`
- đọc tới `\n\n` đầu tiên
- parse `event:` và `data:`
- decode JSON

## 7.3 Assertions tối thiểu
- status 200
- `content-type` chứa `text/event-stream`
- `Cache-Control: no-cache`
- event name = `operational_state`
- `data` parse thành JSON object
- object có:
  - `summary`
  - `projects`
  - `source_status`
  - `used_fallback`

## 7.4 Anti-flake cho SSE
- chỉ đọc event đầu tiên
- timeout cố định ngắn nhưng đủ rộng, ví dụ 8-10s
- không assert số lượng event
- không sleep chờ event thứ hai

---

## 8. Fixture strategy

## 8.1 Nguyên tắc
Fixture phải:
- deterministic
- nhỏ gọn
- phục vụ được nhiều flow
- dễ cleanup
- tách seed Postgres, Qdrant, manifest, fake-LLM

## 8.2 Bộ fixture đề xuất

### A. Postgres business fixtures
Một bộ seed nhỏ cho:
- project `PRJ-VERIFY-001`
- review session `review-verify-001`
- 1 finding blocking
- 1 assignment pending
- 1 submission
- 1 resolved review variant

Dùng để cover:
- lifecycle
- operational aggregate
- remediation derivation

### B. Manifest fixtures
File coverage manifest tối thiểu cho:
- project đủ dữ liệu
- project thiếu critical docs
- manifest invalid
- manifest missing project

### C. Qdrant knowledge fixtures
Chunks nhỏ có metadata rõ:
- `project_code`
- `review_id`
- `task_type`
- `document_type`

### D. Fake LLM fixtures
Adapter deterministic trả:
- answer cố định theo `task_type`
- hoặc template dựa trên retrieved metadata

Mục tiêu:
- verify orchestration contract mà không phụ thuộc model thật

### E. SSE payload fixture expectation
Không cần file riêng nếu đã seed Postgres. Chỉ cần snapshot invariant để đối chiếu.

## 8.3 Isolation và cleanup
- mỗi integration test dùng namespace/ID riêng, ví dụ suffix theo test name
- cleanup Postgres theo `project_code` hoặc `review_id`
- cleanup Qdrant theo collection test hoặc metadata filter
- tránh dùng dữ liệu dùng chung toàn suite

## 8.4 Shared fixtures giữa các suite
Nên tái sử dụng:
- `make_review_start_payload()`
- `make_finding_payload()`
- `make_assignment_payload()`
- `make_submission_payload()`
- `make_manifest_payload()`
- `make_knowledge_chunks()`

Điều này giảm drift giữa test route, integration và E2E.

---

## 9. CI stages đề xuất

## 9.1 Stage 1 — fast unit + contract
Chạy trên mọi PR.

Bao gồm:
- unit tests hiện có
- route-contract tests dùng fake dependency
- schema tests
- error mapping tests không cần infra thật

Thời gian mục tiêu:
- dưới 2-3 phút

## 9.2 Stage 2 — Postgres integration
Chạy trên PR chính hoặc label liên quan backend persistence/API.

Bao gồm:
- review lifecycle với Postgres thật
- operational/remediation integration từ review persisted
- readiness với Postgres available/unavailable

Thời gian mục tiêu:
- dưới 5-7 phút

## 9.3 Stage 3 — Qdrant integration
Chạy trên PR chạm knowledge/agent/retrieval hoặc nightly.

Bao gồm:
- ingest/search contract
- review-memory/project-memory ingestion
- retrieval filter semantics

## 9.4 Stage 4 — Core E2E smoke
Chạy trên merge vào main và nightly.

Bao gồm:
- P0 dossier lifecycle
- review-derived operational projection
- SSE first-event parity

## 9.5 Stage 5 — Nightly extended / optional-real-MLX
Chạy nightly hoặc manual.

Bao gồm:
- route-task với retrieval thật
- smoke gọi MLX thật
- performance envelope nhẹ
- long-running diagnostics scripts trong `tmp/` nếu cần

---

## 10. Cách giảm flaky test

## 10.1 Không dùng MLX thật trong PR CI
Đây là nguồn flaky lớn nhất vì:
- tải model
- warm-up chậm
- phụ thuộc tài nguyên máy
- output không ổn định

Giải pháp:
- fake deterministic ở PR
- chỉ real-MLX cho nightly/manual smoke

## 10.2 Không assert text tự do quá chặt
Chỉ assert:
- field tồn tại
- substring quan trọng
- enum/status
- count/invariant

## 10.3 Seed dữ liệu tối thiểu và tách biệt
Mỗi test:
- tạo ID riêng
- cleanup riêng
- không dựa vào state cũ từ test khác

## 10.4 Giới hạn phạm vi SSE
Chỉ đọc event đầu tiên.
Không test thời gian dài.

## 10.5 Timeout rõ ràng
Thiết lập timeout cho:
- DB connect
- SSE first event
- knowledge search
- route-task

Tránh để test treo vô hạn.

## 10.6 Tránh dependency mạng ngoài
- Qdrant dùng local/container trong CI
- MLX fake
- không gọi external hosted model/api

## 10.7 Tách “contract deterministic” khỏi “live diagnostics”
Script trong `tmp/` giữ cho mục tiêu chẩn đoán.
Suite CI chính chỉ dùng test deterministic.

---

## 11. Phased rollout plan

## Phase 0 — Chuẩn hóa baseline verification
Mục tiêu:
- phân loại suite hiện có
- chốt naming, marker, thư mục, fixture conventions
- chuyển `tmp` scripts quan trọng thành input cho kế hoạch chính thức

Deliverables:
- test inventory map
- dependency matrix
- naming convention cho fast / integration / e2e / nightly

Acceptance:
- mọi test mới sau đó biết đang thuộc lớp nào
- parent/master plan có thể map với workstream khác

## Phase 1 — Route contract + error-path hardening
Ưu tiên endpoint lõi:
- health/readiness
- dossier workflow endpoints
- operational state endpoints
- remediation endpoints

Deliverables:
- contract tests cho payload shape
- negative tests cho invalid IDs/payloads
- degraded response assertions

Acceptance:
- các endpoint lõi đều có route-level verification không cần infra thật
- fail-soft/fallback path được khóa contract

## Phase 2 — Postgres integration suite
Ưu tiên:
- dossier lifecycle thật
- review → operations/remediation projection thật

Deliverables:
- fixtures seed/cleanup cho Postgres
- integration tests dùng DB thật
- cross-endpoint invariant tests

Acceptance:
- thay đổi schema/persistence dễ bị bắt lỗi ngay ở CI integration
- semantic mismatch giữa review state và aggregate endpoints bị phát hiện

## Phase 3 — SSE + readiness integration
Deliverables:
- SSE first-event contract tests
- readiness test matrix với Postgres available/unavailable
- snapshot-vs-stream parity checks

Acceptance:
- dashboard-facing stream route được bảo vệ tối thiểu
- readiness semantics không regress ngầm

## Phase 4 — Qdrant + knowledge/agent integration
Deliverables:
- ingest/search integration tests với Qdrant thật
- review-memory/project-memory tests
- route-task tests dùng fake LLM deterministic

Acceptance:
- retrieval stack có kiểm chứng xuyên route → orchestrator → store

## Phase 5 — Core E2E orchestration suite
Deliverables:
- P0 E2E flows chạy ổn định
- suite smoke trên merge/main
- nightly extended suite

Acceptance:
- DSCons có thể chứng minh vài luồng business thật chạy xuyên tầng end-to-end

## Phase 6 — Nightly real-runtime smoke
Deliverables:
- smoke route-task với MLX thật
- optional benchmark/health runtime scripts

Acceptance:
- không block PR thường ngày
- vẫn có tín hiệu sớm khi runtime local model bị hỏng

---

## 12. Execution order tối ưu và phụ thuộc

## Thứ tự tối ưu

### Bước 1. Chốt contract tests cho route và degraded behavior
Lý do:
- nhanh nhất
- ít phụ thuộc infra
- khóa bề mặt API trước khi làm integration

### Bước 2. Dựng Postgres integration cho dossier lifecycle
Lý do:
- đây là trục dữ liệu cốt lõi
- đồng thời hỗ trợ kiểm chứng issue #1 và #2

### Bước 3. Dùng cùng seed Postgres để verify operational/remediation projection
Lý do:
- tận dụng fixture đã có
- phát hiện semantic drift issue #3 và #4

### Bước 4. Thêm SSE parity tests
Lý do:
- phụ thuộc trực tiếp vào operational-state route đã ổn định

### Bước 5. Dựng Qdrant integration + knowledge tests
Lý do:
- tách khỏi workflow core để giảm độ phức tạp rollout
- cần dependency riêng

### Bước 6. Dựng route-task/agent tests với fake LLM
Lý do:
- phụ thuộc Qdrant integration và orchestration contract

### Bước 7. Chỉ sau cùng mới thêm nightly real MLX smoke
Lý do:
- chi phí cao nhất
- ít deterministic nhất

## Phụ thuộc với 4 workstream còn lại

- Phụ thuộc workstream #1:
  - khi transaction boundary thay đổi, P0 lifecycle integration sẽ là suite chính để xác thực không còn partial state
- Phụ thuộc workstream #2:
  - Postgres integration phải chạy sau hoặc song song với việc chốt schema governance
- Phụ thuộc workstream #3:
  - contract test degraded-state sẽ là nơi khóa response flags và readiness semantics
- Phụ thuộc workstream #4:
  - cross-endpoint invariant tests sẽ là công cụ đo semantic drift trước/sau shared projection layer

---

## 13. Tradeoff chính

## 13.1 Fake LLM mặc định thay vì real LLM
Ưu điểm:
- nhanh
- deterministic
- CI ổn định

Nhược:
- không bắt được lỗi runtime model thật

Giải pháp cân bằng:
- fake cho PR
- real cho nightly/manual

## 13.2 Không cố E2E hóa mọi endpoint ngay
Ưu điểm:
- tập trung vào luồng có giá trị cao nhất
- giảm thời gian build suite

Nhược:
- một số endpoint phụ chưa được phủ ngay

Giải pháp:
- P0/P1 flow list rõ ràng
- rollout theo phase

## 13.3 Contract test chỉ khóa invariant tối thiểu
Ưu điểm:
- ít brittle
- dễ refactor nội bộ

Nhược:
- không khóa toàn bộ nội dung response

Giải pháp:
- chỉ tăng độ chặt ở field nào thật sự là public contract

---

## 14. Definition of Done cho lớp verification

DSCons được coi là hoàn tất lớp verification cho vấn đề #5 khi đạt đồng thời các điều kiện sau:

### 14.1 Về cấu trúc suite
- có test pyramid rõ: unit, route-contract, integration, E2E, nightly
- mỗi test mới được phân loại vào đúng tầng
- có fixture strategy và cleanup strategy chuẩn hóa

### 14.2 Về coverage nghiệp vụ lõi
- dossier review lifecycle có integration/E2E verification với Postgres thật
- review-derived operational/remediation flow có cross-endpoint verification
- SSE operational-state stream có contract coverage tối thiểu
- knowledge ingest/search và route-task có integration coverage với Qdrant thật và fake LLM

### 14.3 Về error-path
- health/readiness có negative coverage
- degraded/fallback behavior của operational/remediation được assert ở route/integration level
- invalid selector/ID/payload paths quan trọng đều có coverage

### 14.4 Về CI
- PR pipeline có fast deterministic stage
- có stage integration cho Postgres
- có stage integration cho Qdrant
- có core E2E smoke trên merge/main
- có nightly/manual stage cho MLX thật

### 14.5 Về chất lượng tín hiệu
- suite deterministic, tỷ lệ flaky thấp
- test fail chỉ ra đúng lớp lỗi: contract, persistence, retrieval, stream, hoặc runtime
- `tmp/` scripts vẫn tồn tại như live diagnostics bổ trợ, nhưng không thay thế suite chính thức

---

## 15. Acceptance criteria gợi ý theo phase

| Phase | Acceptance criteria |
| --- | --- |
| Phase 1 | Endpoint lõi có contract tests cho success + degraded/error paths |
| Phase 2 | Review lifecycle chạy với Postgres thật và assert persistence invariants |
| Phase 3 | Operational/remediation/SSE parity được verify từ cùng persisted dataset |
| Phase 4 | Knowledge ingest/search/review-memory có integration với Qdrant thật |
| Phase 5 | Có ít nhất 2 P0 E2E flow chạy ổn định trong CI merge/main |
| Phase 6 | Có nightly smoke dùng MLX thật, không block PR thường |

---

## 16. Khuyến nghị thực thi ngắn gọn cho parent plan

Nếu cần xếp ưu tiên liên-team, nên đi theo thứ tự:

1. route contract + degraded contract
2. Postgres integration cho dossier lifecycle
3. cross-endpoint invariant cho operational/remediation
4. SSE first-event parity
5. Qdrant integration
6. route-task/agent integration với fake LLM
7. nightly real MLX smoke

Đây là thứ tự cho hiệu quả cao nhất trên DSCons hiện tại vì:
- bám vào API và service đã tồn tại trong `app/api/routes.py`
- tận dụng test suite sẵn có thay vì thay kiến trúc lớn ngay
- hỗ trợ trực tiếp việc xác thực các workstream transaction/schema/degraded/projection còn lại
- giảm rủi ro flaky và tránh biến verification thành một hệ riêng quá đắt đỏ