feat(query-tool): align lineage model and tighten timeline mapping

This commit is contained in:
egg
2026-02-22 17:36:47 +08:00
parent 6016c31e4d
commit 9890586191
29 changed files with 2090 additions and 299 deletions

View File

@@ -0,0 +1,2 @@
schema: spec-driven
created: 2026-02-22

View File

@@ -0,0 +1,152 @@
## Context
「批次追蹤工具」目前已拆成三個頁籤(正向/反向/設備),但 lineage 核心仍以 `SPLITFROMID``DW_MES_PJ_COMBINEDASSYLOTS` 為主,資料語意不足以完整表達現場流程:
- GC 並非 GA 的必經節點,且非 1:1部分批次只有 GC 抽點,部分完全不經 GC。
- Wafer LOT`DW_MES_CONTAINER.FIRSTNAME`)是 GA/GC 共同上游錨點,應獨立建模。
- GD 重工追溯主鏈在 `DW_MES_CONTAINER``ORIGINALCONTAINERID` + `FIRSTNAME` + `SPLITFROMID`,僅靠 COMBINED 表無法表達完整重工來源。
已驗證資料特徵(實查):
- GD lot 可由 `DW_MES_PJ_COMBINEDASSYLOTS.FINISHEDNAME` 反解至 `GDxxxx-Axx`
- 該 GD lot 在 `DW_MES_CONTAINER` 中可取得 `MFGORDERNAME=GD...``ORIGINALCONTAINERID``FIRSTNAME`
- `ORIGINALCONTAINERID` 對應來源 lot 可回接 Wafer LOT`FIRSTNAME`)。
約束條件:
- 需沿用現有 `/api/query-tool/*``/api/trace/*` 路由,不做破壞式移除。
- 需保留 staged trace 的快取與 rate limit 行為。
- 需維持查詢效能,避免以 Wafer LOT 為起點時產生不可控 fan-out。
## Goals / Non-Goals
**Goals:**
- 以「語意化節點/邊」重建 query-tool 的追溯模型,明確區分 split、merge、wafer-origin、gd-rework。
- 明確支持兩種入口集合:
- 正向Wafer LOT / GA-GC 工單 / GA-GC LOT
- 反向:成品流水號 / GD 工單 / GD LOT ID
- 前端樹圖可視化要能辨識「GA 無 GC」與「GD 重工分支」。
- 將 GD 追溯落在 lot/workorder 層級保證可追,並保留 serial 層級可得資訊。
**Non-Goals:**
- 不承諾舊成品流水號與新成品流水號 1:1 映射。
- 不調整設備頁籤功能。
- 不在本變更導入新資料來源(僅使用既有 DWH 表)。
## Decisions
### D1. 建立 Typed Lineage Graph節點/邊雙語意)
後端 lineage 輸出新增語意欄位,與現有欄位並存(過渡期兼容):
- `nodes`: 依 `container_id` 聚合節點屬性(`node_type`, `container_name`, `mfgorder_name`, `wafer_lot`
- `edges`: 邊列表(`from_cid`, `to_cid`, `edge_type`
- `edge_type` 固定枚舉:
- `split_from`
- `merge_source`
- `wafer_origin`
- `gd_rework_source`
`node_type` 判定優先順序:
1. `MFGORDERNAME LIKE 'GD%'``CONTAINERNAME LIKE 'GD%'``GD`
2. `MFGORDERNAME LIKE 'GC%'``CONTAINERNAME LIKE 'GC%'``GC`
3. `MFGORDERNAME LIKE 'GA%'``CONTAINERNAME LIKE 'GA%'``GA`
4. `OBJECTTYPE='LOT'` 且為 Wafer 錨點節點 → `WAFER`
5. COMBINED `FINISHEDNAME` 的虛擬節點 → `SERIAL`
保留現有 `children_map` / `parent_map` 等欄位,前端逐步切換到 typed graph。
### D2. 以 Profile 區分 seed-resolve 輸入語意
`/api/trace/seed-resolve` 改為 profile-aware 的 resolve type 規則:
- `query_tool`(正向)允許:`wafer_lot`, `lot_id`, `work_order`
- `query_tool_reverse`(反向)允許:`serial_number`, `gd_work_order`, `gd_lot_id`
其中:
- `wafer_lot`: 以 `DW_MES_CONTAINER.FIRSTNAME` 解析種子 lot 集合
- `gd_work_order`: 僅允許 `GD%` 前綴,對 `DW_MES_CONTAINER.MFGORDERNAME` 解析
- `gd_lot_id`: 以 `DW_MES_CONTAINER.CONTAINERNAME` 解析,且需同時符合 GD 規則(`CONTAINERNAME LIKE 'GD%'``MFGORDERNAME LIKE 'GD%'`
- `work_order`(正向)限定 GA/GC非 GD
此設計避免正反向模式語意混用,且可在 API 層即早回饋錯誤。
### D3. GD 反向追溯採「Container 主鏈 + Combined 輔鏈」
GD 反向演算法(三種起點共用):
1. 種子為 serial 時,先由 `DW_MES_PJ_COMBINEDASSYLOTS.FINISHEDNAME` 找到 lot常為 `GDxxxx-Axx`);種子為 `gd_lot_id` 時直接命中該 lot種子為 `gd_work_order` 時直接展開該工單 lot 群。
2. 對 serial 或 `gd_lot_id` 起點,讀取 lot 的 `MFGORDERNAME` 以展開同 GD 工單 lot 群。
3. 對每個 GD lot 取來源:
- 主來源:`ORIGINALCONTAINERID`
- 回退來源:`SPLITFROMID`(當 ORIGINAL 為空或無效)
4. 來源 lot 再透過 `FIRSTNAME` 接回 Wafer LOT 錨點。
5. COMBINED 僅負責「lot -> 成品流水號」映射,不作為 GD 來源主依據。
這可涵蓋「成品流水號 -> GD -> 來源 lot -> wafer」與「GD 工單 -> lot 群 -> 來源 lot」兩條路徑。
### D4. 前端改為語意化樹圖且保持明細過濾邊界
`LineageTreeChart` 調整為語意視覺:
- 節點顏色/形狀區分 `WAFER/GC/GA/GD/SERIAL`
- 邊樣式區分 `split/merge/wafer-origin/gd-rework`
- 無 GC 時強制顯示 `WAFER -> GA` 直接鏈路,不用「缺失」呈現
互動邊界:
- 點擊節點僅更新 detail panel 的 container scope
- 不重新過濾/改寫樹本身(避免「點樹即變樹」)
### D5. 效能策略:分段查詢 + 批次 + 快取
- lineage 查詢維持分段與批次IN clause batching策略。
- Wafer LOT 展開加入結果上限與分頁/裁切策略(避免單一查詢過大)。
- GD 關係查詢以 Redis/L2 做短期快取(可由 env 配置 TTL
- 監控新增 typed-edge 命中統計,觀察 `wafer_origin``gd_rework_source` 的覆蓋率。
### D6. 向後相容與漸進切換
- API contract 採「新增欄位」方式,不先移除舊欄位。
- 前端先讀新欄位,保留舊欄位 fallback 一個版本週期。
- 若生產異常可切回舊渲染路徑feature flag 或 runtime config
## Risks / Trade-offs
- [Risk] Wafer LOT fan-out 過大導致查詢壓力
Mitigation: 設定種子展開上限、分段查詢、UI 提示「僅顯示前 N 筆」。
- [Risk] `FIRSTNAME` 同名造成跨流程誤連
Mitigation: 邊生成時加上 `OBJECTTYPE='LOT'` 與工單/時間窗交叉約束;疑似多義連線以低信任度標記。
- [Risk] GD 舊/新 serial 無法 1:1 對映引發期待落差
Mitigation: 在規格與 UI 說明明確宣告 serial 層級的限制,保證 lot/workorder 層級完整可追。
- [Risk] 新舊欄位並存造成前後端邏輯複雜
Mitigation: 設定移除時程,待新前端穩定後再移除舊欄位讀取。
## Migration Plan
1. 後端先落地 typed lineage不改前端確認 API 回傳兼容。
2. 前端切換至 typed graph 視覺與新 resolve 類型。
3. 啟用 GD reverse 路徑與 GC-optional 顯示規則。
4. 以實例資料驗證三種主流程:
- WAFER -> GA無 GC
- WAFER -> GC -> GA
- SERIAL -> GD -> SOURCE LOT -> WAFER
5. 穩定後移除舊渲染相依欄位(若決議移除)。
Rollback
- 關閉 typed graph 功能開關,前端退回舊欄位渲染。
- 保留新 SQL/欄位但不被前端使用,避免熱修回滾需 DB 變更。
## Open Questions
- Wafer LOT 輸入值格式是否需要強制前綴或正則,以降低同名誤連?
- 正向 `work_order` 是否嚴格限制 GA/GC或允許 GD 但提示「請用反向頁籤」?
- `WAFER -> GA` 直接鏈路在視覺上要以虛線還是實線呈現(避免與 split 混淆)?

View File

@@ -0,0 +1,77 @@
## Why
目前「批次追蹤工具」雖已拆成正向/反向/設備三個頁籤,但追溯模型仍以 `SPLITFROMID + COMBINEDASSYLOTS` 為主,與實際 GA/GC/GD/WAFER LOT 關係不完全一致。已完成的資料探索也顯示GC→GA 常透過共同 `FIRSTNAME`Wafer LOT而非 split 直接可見GD 重工鏈也主要落在 `DW_MES_CONTAINER``ORIGINALCONTAINERID` / `FIRSTNAME` / `SPLITFROMID`),若不補齊模型,前端樹圖會持續出現「可顯示但語意不正確」的問題。
## What Changes
- 釐清並統一「批次追蹤」資料語意,將追溯關係分成可辨識的邊類型,而不只是一般 parent/child
- `split_from`(拆批)
- `merge_source`(併批)
- `wafer_origin``FIRSTNAME` 對應 Wafer LOT
- `gd_rework_source`GD 重工來源,依 `ORIGINALCONTAINERID`/`FIRSTNAME`
- 明確納入 GC 非必經站規則:
- GC 與 GA 非 1:1也不是必經關係可能僅抽點也可能完全不經 GC
- 追溯主錨點改為 Wafer LOTGC 視為「可選節點」,不存在時不視為斷鏈
- 前端需顯示 `WAFER -> GA` 直接鏈路(無 GC 時),讓使用者可視覺辨識「跳過 GC」情境
- 調整查詢入口,對齊你定義的使用情境:
- 正向頁籤支援Wafer LOT、GA/GC 工單、GA/GC LOT 作為起點
- 反向頁籤支援成品流水號、GD 工單、GD LOT ID 作為起點
- 讓正反向追溯輸出採同一份「語意化關係圖」資料結構,只在起點與展開方向不同,避免結果解讀不一致。
- 補齊 GA 無 GC 時的可視化語意:若無 GC 節點,仍須明確顯示 Wafer LOT 補充鏈路,不可隱性省略。
- 前端樹圖改為「節點類型 + 關係類型」雙重視覺表達(非僅 root/branch/leaf
- 節點至少區分WAFER、GC、GA、GD、SERIAL
- 關係邊樣式區分split、merge、wafer-origin、gd-rework
- 保留點選節點只過濾下方明細,不回頭過濾樹本身。
- 增加查詢效能與風險控制策略:
- 先做 seed resolve再按需分段展開關係避免一次全量 fan-out
- 對 GD 關係查詢加入快取策略(可配置 TTL預設使用既有 Redis 快取層)
- 補上追溯鏈路命中統計與慢查監控欄位,便於驗證模型是否正確覆蓋。
### GD 追溯策略(補充)
- 反向起點為「成品流水號」時:
1. 先用 `DW_MES_PJ_COMBINEDASSYLOTS.FINISHEDNAME` 解析到 GD lot例如 `GDxxxx-A01`
2. 取得 GD lot 對應 `MFGORDERNAME=GD...`
3.`DW_MES_CONTAINER` 展開同 GD 工單全部 lot
4. 每一個 GD lot 以 `ORIGINALCONTAINERID`(主)與 `FIRSTNAME`(輔)回溯來源 lot
5. 來源 lot 再透過 `FIRSTNAME` 連到 Wafer LOT 錨點
- 反向起點為「GD 工單」時:
- 直接從 `DW_MES_CONTAINER` 取 GD lot 群,後續同上回溯來源 lot 與 Wafer LOT
- 反向起點為「GD LOT ID」時
-`DW_MES_CONTAINER.CONTAINERNAME` 精準命中 GD lot需符合 GD 規則),再沿用同一條回溯鏈
- 適用「已知單顆/單批 GD lot未知整張 GD 工單」的快速反查情境
- 正向時,若查到來源 lot 存在 GD 再製分支,需額外顯示 `gd_rework_source` 邊,形成「原 lot -> GD lot -> 新成品」分支。
- 限制聲明:
- 目前資料可穩定追出「來源 lot 與 GD lot 關係」;
- 舊成品流水號與新成品流水號不保證存在 1:1 可直接映射,提案先保證 lot/workorder 層級完整可追。
### 現況/需求/整合比較
| 面向 | 目前實作 | 新需求 | 本提案整合方向 |
|---|---|---|---|
| 正向入口 | `lot_id` / `work_order` | Wafer LOT + GA/GC 工單 + GA/GC LOT | 擴充 resolve type 與正向查詢入口 |
| 反向入口 | 僅成品流水號 | 成品流水號 + GD 工單 + GD LOT ID | 反向 QueryBar 增加 GD 工單/GD LOT 模式 |
| GD 關聯 | 主要倚賴 COMBINED 映射 | 需追出重工來源與重測後新結果 | 改以 `DW_MES_CONTAINER` 欄位為 GD 主鏈COMBINED 僅作輔助 |
| GC 缺失情境 | 樹上不易看出補線來源 | GA 無 GC 時仍要看見 WAFER LOT | 新增 `wafer_origin` 邊與視覺標示 |
| 前端語意 | 泛化 root/branch/leaf | 要看得出流程語意 | 改成節點/邊語意化圖例與樣式 |
## Capabilities
### New Capabilities
- _(none)_
### Modified Capabilities
- `query-tool-lot-trace`: 查詢入口、正反向頁籤語意、樹圖互動與可視化規則更新。
- `lineage-engine-core`: 從單一 split/merge 模型擴充為可輸出 wafer/GD 關係的語意化關係圖。
- `trace-staged-api`: seed resolve 與 lineage response contract 擴充(新 resolve type、typed edges、節點分類欄位
- `progressive-trace-ux`: 正反向追溯在同一 UX 規則下顯示,並保持分段載入與快取策略一致。
## Impact
- **前端**`frontend/src/query-tool/App.vue``frontend/src/query-tool/components/QueryBar.vue``frontend/src/query-tool/components/LineageTreeChart.vue`、相關 composables`useLotResolve.js``useLotLineage.js``useReverseLineage.js`
- **後端 API**`src/mes_dashboard/routes/query_tool_routes.py``src/mes_dashboard/routes/trace_routes.py`
- **服務層**`src/mes_dashboard/services/query_tool_service.py``src/mes_dashboard/services/lineage_engine.py`
- **SQL/資料來源**`src/mes_dashboard/sql/lineage/*.sql``src/mes_dashboard/sql/query_tool/*resolve*.sql`(含 `DW_MES_CONTAINER` 欄位關聯補強)
- **快取/監控**:沿用既有 Redis/L2 cache 與 slow-query logger新增追溯關係命中統計欄位

View File

@@ -0,0 +1,42 @@
## MODIFIED Requirements
### Requirement: LineageEngine SHALL provide combined genealogy resolution
`LineageEngine.resolve_full_genealogy()` SHALL produce a semantic lineage graph that includes split, merge, wafer-origin, and GD-rework relationships.
#### Scenario: Combined genealogy includes typed edges
- **WHEN** `resolve_full_genealogy()` is called with seed container IDs
- **THEN** the response SHALL include lineage relationships with explicit edge types
- **THEN** split, merge, wafer-origin, and gd-rework edges SHALL be distinguishable
#### Scenario: GA without GC remains traceable by wafer origin
- **WHEN** seed lots have GA lineage without GC nodes
- **THEN** the engine SHALL still link GA lineage to wafer origin via `FIRSTNAME`
- **THEN** lineage output SHALL remain connected without synthetic GC nodes
#### Scenario: Backward compatibility fields preserved during migration
- **WHEN** callers still depend on legacy ancestry maps
- **THEN** the engine SHALL continue returning legacy-compatible fields during migration window
- **THEN** typed graph fields SHALL be additive, not replacing legacy fields immediately
## ADDED Requirements
### Requirement: LineageEngine SHALL resolve wafer-origin relationships from container data
The engine SHALL derive wafer-origin links using `DW_MES_CONTAINER.FIRSTNAME` and valid LOT nodes.
#### Scenario: Wafer-origin edge creation
- **WHEN** a lot node has a non-empty `FIRSTNAME` that maps to a wafer lot node
- **THEN** the engine SHALL create a `wafer_origin` edge between the lot and wafer nodes
- **THEN** wafer-origin resolution SHALL avoid duplicate edges per node pair
### Requirement: LineageEngine SHALL resolve GD rework source relationships from container data
The engine SHALL derive GD rework source links primarily from `ORIGINALCONTAINERID`, with `SPLITFROMID` as fallback.
#### Scenario: GD source via ORIGINALCONTAINERID
- **WHEN** a GD lot has a valid `ORIGINALCONTAINERID`
- **THEN** the engine SHALL create a `gd_rework_source` edge from source lot to GD lot
- **THEN** this edge SHALL be included in reverse and forward lineage outputs where applicable
#### Scenario: GD source fallback to SPLITFROMID
- **WHEN** `ORIGINALCONTAINERID` is null or invalid and `SPLITFROMID` is available
- **THEN** the engine SHALL fallback to `SPLITFROMID` for gd-rework source linkage
- **THEN** the fallback linkage SHALL be marked with edge type `gd_rework_source`

View File

@@ -0,0 +1,24 @@
## MODIFIED Requirements
### Requirement: query-tool lineage tab SHALL load on-demand
The query-tool lineage experience SHALL keep progressive loading behavior while supporting forward and reverse tracing semantics with independent caches.
#### Scenario: Forward resolve auto-fires lineage progressively
- **WHEN** forward seed resolution completes with N lots
- **THEN** lineage requests SHALL auto-fire with concurrency control
- **THEN** the tree SHALL progressively render as responses arrive
#### Scenario: Reverse resolve supports serial, GD work-order, and GD lot-id modes
- **WHEN** reverse tab resolves seeds using `serial_number`, `gd_work_order`, or `gd_lot_id`
- **THEN** lineage SHALL render upstream graph from resolved roots
- **THEN** reverse tab behavior SHALL not depend on forward tab state
#### Scenario: Cache isolation per tab context
- **WHEN** lineage data is fetched in forward tab
- **THEN** forward cache SHALL be reusable within forward context
- **THEN** reverse tab lineage cache SHALL be isolated from forward cache state
#### Scenario: Tree interaction does not mutate graph scope
- **WHEN** user clicks nodes to inspect details
- **THEN** detail panel scope SHALL update immediately
- **THEN** lineage graph visibility SHALL remain unchanged unless a new resolve is executed

View File

@@ -0,0 +1,65 @@
## MODIFIED Requirements
### Requirement: Query-tool page SHALL use tab-based layout separating LOT tracing from equipment queries
The query-tool page SHALL present three top-level tabs with independent state: `批次追蹤(正向)`, `流水批反查(反向)`, and `設備生產批次追蹤`.
#### Scenario: Tab switching preserves independent state
- **WHEN** the user switches between forward, reverse, and equipment tabs
- **THEN** each tab SHALL retain its own input values, resolved seeds, selected nodes, and detail sub-tab state
- **THEN** switching tabs SHALL NOT clear another tab's query context
#### Scenario: URL state reflects active tab and tab-local inputs
- **WHEN** the user is on a specific tab
- **THEN** the URL SHALL include `tab` and corresponding tab-local query parameters
- **THEN** reloading the page SHALL restore the active tab and its tab-local state
### Requirement: QueryBar SHALL resolve LOT/Serial/WorkOrder inputs
The query bar SHALL support profile-specific input types. Forward tracing SHALL support wafer/lot/work-order inputs, and reverse tracing SHALL support serial, GD work-order, and GD lot-id inputs.
#### Scenario: Forward query supports wafer-lot seeds
- **WHEN** the user selects `wafer_lot` in forward tab and submits values
- **THEN** the system SHALL call resolve API with `input_type=wafer_lot`
- **THEN** resolved lots under the wafer origin SHALL appear as forward tree roots
#### Scenario: Reverse query supports GD work-order seeds
- **WHEN** the user selects `gd_work_order` in reverse tab and submits `GD%` work orders
- **THEN** the system SHALL call resolve API with `input_type=gd_work_order`
- **THEN** resolved GD lots SHALL appear as reverse tree roots
#### Scenario: Reverse query supports GD lot-id seeds
- **WHEN** the user selects `gd_lot_id` in reverse tab and submits GD lot IDs
- **THEN** the system SHALL call resolve API with `input_type=gd_lot_id`
- **THEN** resolved GD lot roots SHALL be used for reverse lineage expansion
#### Scenario: Invalid GD work-order input is rejected
- **WHEN** reverse tab input type is `gd_work_order` and a value does not match `GD%`
- **THEN** the system SHALL return validation error without issuing lineage query
- **THEN** the UI SHALL keep user input and display actionable error text
#### Scenario: Invalid GD lot-id input is rejected
- **WHEN** reverse tab input type is `gd_lot_id` and a value does not match GD lot rules
- **THEN** the system SHALL return validation error without issuing lineage query
- **THEN** invalid values SHALL be reported in the UI without clearing user input
### Requirement: LineageTree SHALL display as a decomposition tree with progressive growth animation
The lineage tree SHALL render semantic node/edge relationships and SHALL preserve progressive loading behavior.
#### Scenario: GC is optional and wafer linkage remains visible
- **WHEN** a GA lot has no GC node in its upstream chain
- **THEN** the tree SHALL still render a direct `WAFER -> GA` relationship
- **THEN** this SHALL NOT be treated as a broken lineage
#### Scenario: GD rework branch is explicitly rendered
- **WHEN** lineage includes GD rework data
- **THEN** the tree SHALL render `source lot -> GD lot -> new serial/lot` using GD-specific node/edge style
- **THEN** users SHALL be able to distinguish GD rework edges from split/merge edges
#### Scenario: Auto-fire lineage after forward resolve
- **WHEN** forward lot resolution completes with N resolved lots
- **THEN** lineage SHALL be fetched automatically with concurrency-limited requests
- **THEN** the tree SHALL progressively grow as lineage responses arrive
#### Scenario: Node click only scopes detail panel
- **WHEN** the user clicks one or more nodes in the tree
- **THEN** only the detail panel query scope SHALL change
- **THEN** the tree structure and node visibility SHALL remain unchanged

View File

@@ -0,0 +1,42 @@
## MODIFIED Requirements
### Requirement: Staged trace API SHALL expose seed-resolve endpoint
`POST /api/trace/seed-resolve` SHALL resolve seed lots based on profile-specific resolve types.
#### Scenario: Forward profile resolve types
- **WHEN** request body contains `{ "profile": "query_tool", "params": { "resolve_type": "<type>", "values": [...] } }`
- **THEN** `<type>` SHALL be one of `wafer_lot`, `lot_id`, or `work_order`
- **THEN** non-supported types for this profile SHALL return HTTP 400 with `INVALID_PARAMS`
#### Scenario: Reverse profile resolve types
- **WHEN** request body contains `{ "profile": "query_tool_reverse", "params": { "resolve_type": "<type>", "values": [...] } }`
- **THEN** `<type>` SHALL be one of `serial_number`, `gd_work_order`, or `gd_lot_id`
- **THEN** invalid `gd_work_order` values not matching `GD%` SHALL return HTTP 400
#### Scenario: GD lot-id validation
- **WHEN** reverse profile uses `resolve_type=gd_lot_id`
- **THEN** each value SHALL be validated against GD lot rules before resolution
- **THEN** invalid values SHALL return HTTP 400 with `INVALID_PARAMS`
#### Scenario: Seed response payload compatibility
- **WHEN** seed resolution succeeds
- **THEN** response SHALL include `stage`, `seeds`, `seed_count`, and `cache_key`
- **THEN** each seed SHALL include `container_id` and displayable lot/container name fields
### Requirement: Staged trace API SHALL expose lineage endpoint
`POST /api/trace/lineage` SHALL return semantic lineage graph fields while preserving legacy-compatible fields during migration.
#### Scenario: Lineage response contains typed graph fields
- **WHEN** lineage is resolved for `query_tool` or `query_tool_reverse`
- **THEN** response SHALL include typed lineage fields (`nodes` and typed `edges`)
- **THEN** each edge SHALL declare edge type sufficient to distinguish split/merge/wafer/gd-rework
#### Scenario: Legacy compatibility during frontend migration
- **WHEN** existing clients still consume legacy lineage fields
- **THEN** lineage response SHALL continue to include existing compatibility fields for a migration period
- **THEN** typed fields SHALL be additive and not break current clients
#### Scenario: Profile-aware cache keys
- **WHEN** lineage requests have same container IDs but different profiles
- **THEN** cache keys SHALL remain profile-aware to prevent cross-profile response mixing
- **THEN** repeated requests with same profile and same sorted IDs SHALL hit cache

View File

@@ -0,0 +1,31 @@
## 1. Backend lineage model (typed graph)
- [x] 1.1 Extend `LineageEngine` output to include typed `nodes` and `edges` while keeping legacy-compatible fields
- [x] 1.2 Implement edge builders for `wafer_origin` (via `DW_MES_CONTAINER.FIRSTNAME`) and `gd_rework_source` (via `ORIGINALCONTAINERID`, fallback `SPLITFROMID`)
- [x] 1.3 Add node classification helper for `WAFER/GC/GA/GD/SERIAL` and ensure deterministic priority rules
- [x] 1.4 Add/adjust SQL fragments needed for wafer-origin and GD-source resolution with bind-safe `QueryBuilder` usage
## 2. Trace API and resolve contract updates
- [x] 2.1 Extend resolve service to support `wafer_lot`, `gd_work_order`, and `gd_lot_id` input types with profile-aware validation
- [x] 2.2 Update `/api/trace/seed-resolve` to enforce profile-specific resolve-type allowlists (`query_tool` vs `query_tool_reverse`)
- [x] 2.3 Update `/api/trace/lineage` response contract to return typed graph payload additively (no immediate legacy break)
- [x] 2.4 Verify lineage cache behavior remains profile-safe and does not mix forward/reverse responses
## 3. Query-tool frontend integration
- [x] 3.1 Update query bars and tab logic to expose forward types (`wafer_lot/lot_id/work_order`) and reverse types (`serial_number/gd_work_order/gd_lot_id`)
- [x] 3.2 Refactor lineage composables to consume typed graph fields and map them into rendering data structures
- [x] 3.3 Update `LineageTreeChart` to render semantic node styles and edge semantics for split/merge/wafer/gd-rework
- [x] 3.4 Implement explicit UI handling for GC-optional flow (`WAFER -> GA` visible when GC is absent)
- [x] 3.5 Ensure node click only updates detail scope and does not mutate tree visibility
## 4. Validation, regression, and documentation
- [x] 4.1 Add backend tests for resolve-type validation (`gd_work_order` + `gd_lot_id`), wafer-origin edges, and GD-source linkage
- [x] 4.2 Add API contract tests for typed lineage fields and backward-compatible fields
- [x] 4.3 Run manual data validation on representative scenarios:
- [x] 4.4 Validate `WAFER -> GA` path without GC
- [x] 4.5 Validate `WAFER -> GC -> GA` path
- [x] 4.6 Validate `SERIAL -> GD -> source lot -> WAFER` reverse path
- [x] 4.7 Update user-facing documentation/help text for new query modes and GD/GC interpretation rules