# 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 的 artifact,agent 的不確定性由結構化中間產物吸收,而非在最終輸出才暴露。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 gates(typecheck、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 1:Capture
**目的:** 產出 prototype 的視覺真相,取代 agent 腦補的渲染結果。
| 需求 ID | 說明 |
|---------|------|
| F1-1 | 對每個 `.html` 檔案,以 desktop(1440×900)、tablet(768×1024)、mobile(375×812)各截一張全頁截圖 |
| F1-2 | 以本地 static server 提供 prototype 檔案,避免 `file://` 協定的 CORS 問題 |
| F1-3 | 截圖前等待 `networkidle`,再額外等待 500ms,確保 CSS animation 穩定 |
| F1-4 | 以原始 `.html` 檔案的 SHA-256 hash 作為 cache key;hash 未變動時跳過截圖 |
| F1-5 | 截圖儲存至 `.ht/cache/prototype/{filename}/{viewport}-{state}.png` |
| F1-6 | 對每個 viewport/state 產出 DOM summary 與 accessibility tree snapshot,作為 Stage 2–5 的非視覺 evidence |
| F1-7 | 記錄外部資源載入失敗清單(font、image、script、stylesheet),寫入 capture metadata |
**產出物:** `.ht/cache/prototype/` 下的截圖、DOM snapshot、accessibility snapshot 與 capture metadata
---
### Stage 2:Decompose
**目的:** 識別頁面的主要區域,為 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 3:Extract
**目的:** 從每個 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 4:Validate
**目的:** 確保 `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 5:Plan
**目的:** 將 `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 6:Run
**目的:** 讓 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 7:Diff & 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 1–4(Capture → 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` | 依序執行全部 stage(scan → 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 1–4 完整執行不超過 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 style;task 單元保持小 |
| 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 schema(OpenAPI 或 TypeScript interface)
- 第一版 MVP 聚焦單一 HTML prototype → 單一 Vue page/component → 既有 API client → `output/` 結果,不追求一開始支援所有 monorepo 形態
---
## 9. 開發里程碑
| 里程碑 | 涵蓋 Stage | 完成條件 |
|--------|-----------|---------|
| M0:Spike | Stage 1–3(手動) | 手動截圖 + 手動 prompt,驗證 `null` 欄位 < 30% |
| M1:Vision Pipeline | Stage 1–4 | `ht scan` 可對一個 HTML 頁面產出完整 `LayoutSpec`、DOM snapshot 與 `ui-contract.md` |
| M2:Plan | Stage 5 | `ht plan` 可產出 `TaskList`、`project-conventions.md`、`api-contract.md`、`component-mapping.json`,interactive review 可運作 |
| M3:Run | Stage 6 | `ht run` 可驅動 agent 對一個頁面完整執行並寫入 `output/` |
| M4:Diff & Verify | Stage 7 | `ht diff` 可產出 similarity report,`ht verify` 可執行 quality、DOM、flow checks |
| M5:整合 | 全部 | `ht go` 全流程可在真實 monorepo 中穩定執行 |