Files
html-transform/PRD.md
T
2026-05-03 09:38:24 +08:00

362 lines
18 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Product Requirement Document
## HTML Transform
| 欄位 | 內容 |
|------|------|
| 版本 | v0.1 |
| 日期 | 2026-05-02 |
| 狀態 | Draft |
---
## 1. 背景與目標
HTML Transform 是一個安裝在 pnpm-workspace / monorepo 中的 prototype-driven orchestration framework。它讓工程師指定四個資料夾,由單一 coding agent 依序驅動完整 pipeline,將 HTML prototype 轉換為可運作、可維護的 Vuetify 前端實作,並用 backend API schema 對齊資料流。
**四個資料夾:**
| 識別子 | 說明 |
|--------|------|
| `prototype` | HTML prototype 來源 |
| `frontend` | 已預先建立的 Vuetify 前端專案 |
| `backend` | 已預先建立的 backend API 專案 |
| `output` | 生成結果的寫入目標 |
**核心設計原則:** pipeline 的每個 stage 都產出可被人工 review 的 artifactagent 的不確定性由結構化中間產物吸收,而非在最終輸出才暴露。HTML prototype 不是完整規格;rendered browser evidence、DOM/accessibility snapshot、`LayoutSpec`、project conventions、API contract、`TaskList` 才共同構成實作依據。
**成功標準:**
- 相同 prototype 執行兩次,`output` 資料夾的結果語意一致
- Diff report 的平均 similarity score 高於 75%
- `LayoutSpec``null` 欄位比率低於 30%
- Stage 7 的 quality gatestypecheck、lint、test、route smoke test)全部通過,或明確標示為環境缺失而非實作失敗
- 每次 run 都能回溯到對應的 screenshot、DOM snapshot、spec、plan、agent raw output 與 verification report
---
## 2. 系統架構
```
ht.config.ts
┌─────────────────────────────────────────────────────┐
│ Orchestrator │
│ (讀取 config,依序呼叫各 stage,傳遞中間產物) │
└──────┬──────────┬──────────┬──────────┬─────────────┘
│ │ │ │
▼ ▼ ▼ ▼
[Stage 1] [Stage 2] [Stage 3] [Stage 4]
Capture Decompose Extract Validate
│ │ │ │
└──────────┴──────────┴──────────┘
LayoutSpec
┌────────┴────────┐
▼ ▼
[Stage 5] [Stage 6]
Plan Run
TaskList coding agent
output/
[Stage 7]
Diff & Verify
reports + quality gates
```
**Agent 角色:** 單一 coding agent(由 `ht.config.ts` 中的 `agent` 欄位指定,支援 claude-code、codex、gemini)全程驅動所有 stage,包含 vision 截圖分析、spec 提取、程式碼實作、diff 評分。Orchestrator 負責呼叫順序與中間產物的序列化,agent 負責每個 stage 的實際執行。
---
## 3. 設定檔
```typescript
// ht.config.ts
import { defineConfig } from 'html-transform'
export default defineConfig({
prototype: './packages/prototype',
frontend: './packages/web',
backend: './packages/api',
output: './packages/result',
agent: 'claude-code', // 'claude-code' | 'codex' | 'gemini'
vision: {
viewport: { width: 1440, height: 900 },
captureStates: ['default', 'scrolled', 'mobile'],
includeDomSnapshot: true,
includeAccessibilityTree: true,
},
project: {
packageManager: 'pnpm',
frontendFramework: 'vue3',
uiLibrary: 'vuetify3',
qualityCommands: {
typecheck: 'pnpm typecheck',
lint: 'pnpm lint',
test: 'pnpm test',
},
},
plan: {
interactiveReview: true, // Stage 5 完成後暫停,等待人工確認 TaskList
requireApiContractMatch: true,
},
diff: {
scoreThreshold: 75, // 低於此分數的 region 在 report 中標示警告
requireDomChecks: true,
requireFlowChecks: true,
},
})
```
---
## 4. Pipeline 詳細需求
### Stage 1Capture
**目的:** 產出 prototype 的視覺真相,取代 agent 腦補的渲染結果。
| 需求 ID | 說明 |
|---------|------|
| F1-1 | 對每個 `.html` 檔案,以 desktop1440×900)、tablet768×1024)、mobile375×812)各截一張全頁截圖 |
| F1-2 | 以本地 static server 提供 prototype 檔案,避免 `file://` 協定的 CORS 問題 |
| F1-3 | 截圖前等待 `networkidle`,再額外等待 500ms,確保 CSS animation 穩定 |
| F1-4 | 以原始 `.html` 檔案的 SHA-256 hash 作為 cache keyhash 未變動時跳過截圖 |
| F1-5 | 截圖儲存至 `.ht/cache/prototype/{filename}/{viewport}-{state}.png` |
| F1-6 | 對每個 viewport/state 產出 DOM summary 與 accessibility tree snapshot,作為 Stage 25 的非視覺 evidence |
| F1-7 | 記錄外部資源載入失敗清單(font、image、script、stylesheet),寫入 capture metadata |
**產出物:** `.ht/cache/prototype/` 下的截圖、DOM snapshot、accessibility snapshot 與 capture metadata
---
### Stage 2Decompose
**目的:** 識別頁面的主要區域,為 Stage 3 的局部提取做準備。直接對整頁截圖做一次性提取,精度低且不穩定;分區後再提取可大幅降低錯誤率。
| 需求 ID | 說明 |
|---------|------|
| F2-1 | 以 desktop 截圖呼叫 agent(vision 模式),識別頁面主要區域 |
| F2-2 | 回傳 JSON array,每個 item 包含 `id``name``rough_position``element_count_estimate``semantic_role` |
| F2-3 | 依據 `rough_position`,用 Playwright `clip` 截取每個 region 的局部截圖 |
| F2-4 | Prompt 明確要求只回 JSON,不附任何說明文字 |
| F2-5 | 使用 Stage 1 的 DOM summary 與 accessibility tree 輔助確認 region 名稱、可互動元素與文字,不只依賴截圖 |
**產出物:** `PageDecomposition` JSON(含各 region 的局部截圖路徑)
---
### Stage 3Extract
**目的:** 從每個 region 截圖提取結構化的 `LayoutSpec`
| 需求 ID | 說明 |
|---------|------|
| F3-1 | 每個 region 獨立呼叫 agent,輸入該 region 的局部截圖 |
| F3-2 | Prompt 以填空題形式提供 `LayoutSpec` JSON 結構,要求 agent 填值而非自由生成 |
| F3-3 | `vuetifyComponent` 必須是 Vuetify 3 的真實 component 名稱(對照白名單驗證) |
| F3-4 | 不確定的欄位填 `null`Prompt 明確禁止猜測 |
| F3-5 | `colorPalette` 只填截圖中實際出現的色碼(hex 或 rgba) |
| F3-6 | `textSamples` 填截圖中可見的真實文字,最多 3 筆 |
| F3-7 | 對表單、列表、表格、導覽與 action button 產出 `uiContract` 欄位,描述 label、field type、required 狀態、主要/次要 action、可觀察互動 |
| F3-8 | 若 DOM/accessibility evidence 與 vision 判讀衝突,保留 `warnings`,不得任意合併成確定結論 |
**產出物:** 每個 region 的 `RegionSpec` JSON
---
### Stage 4Validate
**目的:** 確保 `LayoutSpec` 符合 schema,自動修復可修復的問題,標記需要人工介入的頁面。
| 需求 ID | 說明 |
|---------|------|
| F4-1 | 以 Zod schema 驗證每個 region 的 extract 結果 |
| F4-2 | `vuetifyComponent` 不合法時,查 Vuetify 3 白名單找最相近的名稱並自動修正 |
| F4-3 | 色碼格式不合法時,嘗試 normalize;無法修正時填 `null` |
| F4-4 | 產出 `ValidationReport`,記錄 `autoFixedCount``nullFieldCount``warnings` |
| F4-5 | `nullFieldCount` 超過 30% 時,將該頁標記為 `requiresHumanReview: true`,並在 CLI 輸出警告 |
| F4-6 | 語意驗證 region 數量、文字樣本、主要 action、表單欄位與 DOM/accessibility evidence 是否一致 |
| F4-7 | 產出人工可讀的 `ui-contract.md` 摘要,讓使用者可在實作前 review prototype contract |
**產出物:** 完整的 `LayoutSpec` JSON(儲存至 `.ht/spec/{filename}.spec.json`+ `ValidationReport` + `ui-contract.md`
---
### Stage 5Plan
**目的:**`LayoutSpec` 拆解為 agent 可逐一執行的 `TaskList`,讓 Stage 6 的執行單元保持小而可控。
| 需求 ID | 說明 |
|---------|------|
| F5-1 | 讀取 `LayoutSpec``frontend/` 的現有元件、`backend/` 的 API schema,產出 `TaskList` |
| F5-2 | 每個 Task 對應一個 page 或 component,包含:`id``type``targetFile``specReference``apiDependencies` |
| F5-3 | Task 之間的依賴關係以 `dependsOn` 陣列表示,Orchestrator 依此決定執行順序 |
| F5-4 | `ht.config.ts``plan.interactiveReview: true` 時,產出 TaskList 後暫停,輸出預覽並等待使用者輸入 `y` 繼續 |
| F5-5 | `TaskList` 儲存至 `.ht/plan/tasklist.json`,支援手動編輯後重新執行 Stage 6 |
| F5-6 | 掃描 `frontend/` 產出 `project-conventions.md`,至少包含 routing、Vuetify 使用方式、表單封裝、API client/composable、Pinia、validation、i18n、測試慣例 |
| F5-7 | 掃描 `backend/` 產出 `api-contract.md`;若存在 OpenAPI 優先使用,否則從 TypeScript interface、controller、route 或 markdown 抽象 endpoint contract |
| F5-8 | 產出 `component-mapping.json`,描述 prototype region/section 對應 Vuetify component 或既有自訂 wrapper 的映射 |
| F5-9 | `plan.requireApiContractMatch: true` 時,Task 不得引用 `api-contract.md` 未列出的 endpoint;缺口須產出 `contractProposal` 並標記需人工確認 |
**TaskList 結構(摘要):**
```typescript
interface Task {
id: string
type: 'page' | 'component' | 'api-integration'
targetFile: string // 相對於 output/ 的路徑
specReference: string // 對應 LayoutSpec 的 regionId
apiDependencies: string[] // backend API endpoint 清單
inputArtifacts: string[] // spec、contract、conventions、mapping 等 artifact 路徑
acceptanceChecks: string[] // 此 task 完成後必須通過的檢查
dependsOn: string[] // 其他 task id
status: 'pending' | 'running' | 'done' | 'error'
}
```
**產出物:** `.ht/plan/tasklist.json``.ht/plan/project-conventions.md``.ht/plan/api-contract.md``.ht/plan/component-mapping.json`
---
### Stage 6Run
**目的:** 讓 coding agent 依序執行 TaskList,將 Vuetify 元件與 API 整合寫入 `output/`
| 需求 ID | 說明 |
|---------|------|
| F6-1 | Orchestrator 依 `dependsOn` 拓撲排序,逐一將 task 交給 agent 執行 |
| F6-2 | 每個 task 的 prompt context 包含:對應的 `RegionSpec``ui-contract.md` 摘要、`project-conventions.md``component-mapping.json``targetFile` 的現有內容(若存在)、相關 API contract |
| F6-3 | Agent 的輸出直接寫入 `output/{targetFile}`;寫入前備份至 `.ht/backup/` |
| F6-4 | Task 執行失敗時標記 `status: 'error'`,記錄錯誤訊息,繼續執行無依賴的後續 task |
| F6-5 | 支援 `ht run --retry-failed` 指令,只重新執行 `status: 'error'` 的 task |
| F6-6 | 每個 task 完成後更新 `.ht/plan/tasklist.json``status` 欄位 |
| F6-7 | Agent invocation 必須限制 `allowedPaths`,預設只能寫入 `output/``.ht/`;不得修改 `prototype/``frontend/``backend/` 原始輸入資料夾 |
| F6-8 | 每次 agent raw output、changed files、exit code、stderr/stdout summary 寫入 `.ht/runs/{runId}/agent/` |
**產出物:** `output/` 資料夾中的 Vuetify 元件與整合程式碼
---
### Stage 7Diff & Verify
**目的:** 量化 `output/` 的結果與 prototype 的視覺相似度,並以 deterministic checks 優先驗證實作品質,讓工程師能快速判斷生成結果是否可交付。
| 需求 ID | 說明 |
|---------|------|
| F7-1 | 對 `output/` 中每個頁面以相同 viewport 截圖 |
| F7-2 | 將 output 截圖與 Stage 1 的 prototype 截圖交給 agent 評分(0–100),判斷視覺相似度 |
| F7-3 | 產出靜態 HTML report,每行並排顯示:prototype 截圖、output 截圖、similarity score |
| F7-4 | Score 低於 `ht.config.ts``diff.scoreThreshold`(預設 75)的項目以警告色標示 |
| F7-5 | Report 儲存至 `.ht/diff/{filename}.diff.html`,執行完畢後在 CLI 輸出 report 路徑 |
| F7-6 | 執行 `project.qualityCommands` 中設定的 typecheck、lint、test;缺少指令時記錄為 `skipped` 並說明原因 |
| F7-7 | 執行 DOM-level checks:主要文字、form label、table/list item、primary/secondary action 是否存在且可互動 |
| F7-8 | 執行 flow-level checks:可由 `LayoutSpec.interactions` 推導的 drawer、tab、modal、form submit、navigation 等互動 smoke test |
| F7-9 | 採 deterministic first, agent fallback second:固定檢查失敗時才呼叫 agent 協助分析原因,不讓 agent 取代可重跑驗證 |
| F7-10 | 產出 `VerificationReport`,彙整 quality commands、DOM checks、flow checks、visual diff 與人工需處理項目 |
**產出物:** `.ht/diff/` 下的靜態 HTML report + `.ht/verify/verification-report.json`
---
## 5. CLI 指令設計
| 指令 | 說明 |
|------|------|
| `ht scan` | 執行 Stage 14Capture → Validate),產出 `LayoutSpec` |
| `ht plan` | 執行 Stage 5,產出 `TaskList``interactiveReview: true` 時暫停等待確認 |
| `ht run` | 執行 Stage 6,依 `TaskList` 驅動 agent 寫入 `output/` |
| `ht run --retry-failed` | 只重新執行 `status: 'error'` 的 task |
| `ht diff` | 執行 Stage 7 的 visual diff,產出 similarity report |
| `ht verify` | 執行 Stage 7 的 quality commands、DOM checks 與 flow checks |
| `ht go` | 依序執行全部 stagescan → plan → run → diff → verify |
| `ht status` | 顯示目前 `TaskList` 的執行狀態摘要 |
| `ht doctor` | 檢查 pnpm workspace、Playwright、agent CLI、Vuetify component whitelist、quality commands 是否可用 |
---
## 6. 資料夾結構
```
monorepo/
├── ht.config.ts
├── packages/
│ ├── prototype/ ← 輸入:HTML prototype
│ ├── web/ ← 輸入:Vuetify 前端專案(預先建立)
│ ├── api/ ← 輸入:Backend API(預先建立)
│ └── result/ ← 輸出:生成結果
└── .ht/ ← 工具產出的所有中間產物與 cache
├── cache/prototype/ ← Stage 1 截圖
├── spec/ ← Stage 4 LayoutSpec JSON
├── plan/ ← Stage 5 TaskList JSON
├── runs/ ← 每次 run 的狀態、log、agent raw output、artifact 索引
├── backup/ ← Stage 6 寫入前的備份
├── verify/ ← Stage 7 verification report
└── diff/ ← Stage 7 similarity report
```
**Run artifact 結構:**
```
.ht/runs/
└── 2026-05-02-001/
├── run.json
├── screenshots/
├── dom-snapshots/
├── agent/
├── logs/
└── artifact-index.json
```
---
## 7. 非功能需求
| 類別 | 需求 |
|------|------|
| 效能 | 單一 HTML 頁面的 Stage 14 完整執行不超過 60 秒 |
| 可復現性 | Cache 命中時跳過截圖與 extract,相同輸入產出相同結果 |
| 可觀測性 | 每個 stage 完成後輸出 log,記錄耗時、agent call 次數、cache 命中狀態 |
| 錯誤隔離 | 單一 task 或 region 失敗不中斷整體流程,標記後繼續執行 |
| 可介入性 | `TaskList` 支援手動編輯;`interactiveReview` 模式允許人工在 Plan 後介入 |
| 可追溯性 | 每個輸出檔案都能追溯到 input artifact、agent invocation、task id 與 run id |
| 邊界控制 | Agent 預設只可寫入 `output/``.ht/`,所有輸入資料夾視為 read-only |
---
## 8. 風險與假設
| 風險 | 程度 | 緩解策略 |
|------|------|---------|
| Vision 分析精度不足,`null` 欄位過多 | 高 | Spike 驗證後調整 prompt;人工補充 spec |
| Prototype 引用外部資源,截圖不完整 | 中 | Local static server + `networkidle` 等待 |
| Agent 生成的程式碼不符合既有前端專案的規範 | 中 | Prompt context 包含現有元件與 coding styletask 單元保持小 |
| Backend API 不足以支援 prototype 行為 | 中 | Stage 5 產出 `contractProposal` 並要求人工確認,不讓 agent 自行發明 endpoint |
| 只靠 screenshot similarity 造成假陽性 | 中 | Stage 7 加入 DOM-level、flow-level 與 project quality checks |
| Vuetify component 白名單不完整,自動修正失敗 | 低 | 預先整理 Vuetify 3 全量 component 清單 |
**核心假設:**
- Prototype 在現代瀏覽器中能正確渲染
- `frontend/` 專案已有基本的 Vuetify 3 設定與 project structure
- `backend/` 專案有可讀的 API schemaOpenAPI 或 TypeScript interface
- 第一版 MVP 聚焦單一 HTML prototype → 單一 Vue page/component → 既有 API client → `output/` 結果,不追求一開始支援所有 monorepo 形態
---
## 9. 開發里程碑
| 里程碑 | 涵蓋 Stage | 完成條件 |
|--------|-----------|---------|
| M0Spike | Stage 13(手動) | 手動截圖 + 手動 prompt,驗證 `null` 欄位 < 30% |
| M1Vision Pipeline | Stage 14 | `ht scan` 可對一個 HTML 頁面產出完整 `LayoutSpec`、DOM snapshot 與 `ui-contract.md` |
| M2Plan | Stage 5 | `ht plan` 可產出 `TaskList``project-conventions.md``api-contract.md``component-mapping.json`interactive review 可運作 |
| M3Run | Stage 6 | `ht run` 可驅動 agent 對一個頁面完整執行並寫入 `output/` |
| M4Diff & Verify | Stage 7 | `ht diff` 可產出 similarity report`ht verify` 可執行 quality、DOM、flow checks |
| M5:整合 | 全部 | `ht go` 全流程可在真實 monorepo 中穩定執行 |