chore: reinitialize project with vite architecture

This commit is contained in:
beabigegg
2026-02-08 08:30:48 +08:00
commit b56e80381b
264 changed files with 75752 additions and 0 deletions

View File

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

View File

@@ -0,0 +1,79 @@
## Context
`DashBoard_vite` 已完成第一批根目錄重構,但仍有部分頁面維持大量 inline script、部分計算在後端實作且缺乏前後一致性驗證、欄位命名規則未全面治理。`DashBoard/` 目前仍作為結構與行為參考來源。此變更目標是完成最終遷移:以 `DashBoard_vite` 根目錄作為唯一開發/部署主體,並建立可持續的前端模組化、欄位契約、快取可觀測性與遷移門檻。
## Goals / Non-Goals
**Goals:**
- 完成 root cutover執行與維護流程完全以 `DashBoard_vite` 為主。
- 將主要頁面前端腳本模組化至 Vite 管理,降低單檔模板複雜度。
- 將可前端化的展示/聚合計算前移,並建立與既有輸出一致性驗證。
- 建立 UI/API/Export 欄位契約與自動檢核機制。
- 強化分層快取的健康指標與退化觀測。
- 制定遷移驗收門檻、灰度與回退方案。
**Non-Goals:**
- 不重寫所有頁面的視覺設計。
- 不更換資料來源Oracle schema 與核心資料表不變)。
- 不改成前後端雙對外服務架構(維持單一 port
## Decisions
1. Canonical root ownership
- Decision: `DashBoard_vite` 為唯一可執行主工程;`DashBoard/` 僅保留為對照基準直到遷移結案。
- Why: 避免規格、程式碼、部署分散在不同根目錄。
- Alternative: 長期雙根並行;放棄,因維運成本與錯誤率高。
2. Page-by-page Vite modularization
- Decision: 以頁面為單位建立 Vite entry先抽共用 coreAPI、toast、table/tree、field contract再遷移頁面。
- Why: 風險可控,便於逐頁回歸驗證。
- Alternative: 一次性 SPA rewrite放棄風險高且不符合保持既有邏輯要求。
3. Compute-shift contract with parity checks
- Decision: 後端保留原始資料查詢與必要彙整,前端承接展示層聚合/格式化;每個前移計算需有 parity fixture。
- Why: 提升前端互動效率,同時避免行為偏移。
- Alternative: 全留後端;放棄,無法達成前移目標。
4. Field contract registry
- Decision: 建立欄位契約註冊檔UI label / API key / export header / semantic type頁面與匯出共用。
- Why: 消除欄位語義不一致與下載對不上畫面的問題。
- Alternative: 分頁分散維護;放棄,長期不可控。
5. Cache observability first-class
- Decision: 延續 L1 memory + L2 Redis新增命中率、資料新鮮度、降級狀態指標並在 health/deep-health 可見。
- Why: 快取是效能與穩定核心,需可觀測才能穩定運維。
- Alternative: 僅保留功能快取不加觀測;放棄,故障定位成本高。
## Risks / Trade-offs
- [Risk] 模組化拆分期間,舊 inline 與新 module 並存造成行為差異 → Mitigation: 對每頁保留 feature flag 或 fallback逐頁切換。
- [Risk] 前移計算造成數值差異(四捨五入、分母定義) → Mitigation: 建立固定測試資料與 snapshot 比對,未通過不得切換。
- [Risk] 欄位契約改名影響下游報表流程 → Mitigation: 提供 alias 過渡期與變更公告。
- [Risk] Redis/Oracle 不可用時測試訊號雜訊高 → Mitigation: 分離 unit/fallback 與 integration pipelines。
## Migration Plan
1. Baseline freeze
- 凍結基線 API payload、頁面主要互動、匯出欄位產生對照清單。
2. Cutover preparation
- 補齊根目錄執行文件、CI 與腳本,確保不再依賴 `DashBoard/`
3. Modularization waves
- Wave A: Portal、resource history、job query。
- Wave B: resource status、excel query、tables。
- 每波完成後執行頁面回歸與欄位一致性檢核。
4. Compute-shift waves
- 先移動展示層聚合與圖表資料整理,再評估進一步前移。
- 每項前移需 parity 測試與效能比較。
5. Final cutover and cleanup
- 滿足驗收門檻後將 `DashBoard/` 標記為 archived reference 或移除。
- 完成回退文件與操作手冊更新。
## Open Questions
- `DashBoard/` 在結案後保留多久(短期備援或立即封存)?
- 哪一頁的前移計算業務優先級最高resource_history vs job_query
- 是否要求在 cutover 前補齊端對端自動化下載欄位比對?

View File

@@ -0,0 +1,32 @@
## Why
目前已完成第一批根目錄重構,但仍存在「部分頁面與邏輯尚未完整遷移」的階段性狀態。需要建立完整遷移提案,將 `DashBoard_vite` 根目錄收斂為唯一開發與運行主體,並完成前端模組化與欄位契約治理,避免長期雙結構維運風險。
## What Changes
- 完成從參考結構到根目錄主工程的全面切換,消除對 `DashBoard/` 作為執行依賴。
- 以 Vite 完整模組化 Portal 與主要業務頁面前端腳本,逐步移除大型 inline scripts。
- 在不改變既有業務流程前提下,將可前端化的展示/聚合計算由後端移至前端。
- 建立 UI/API/Export 欄位契約機制,對報表與查詢頁進行一致性治理。
- 擴充快取與運維可觀測性,明確 Redis 與記憶體快取的行為、指標與退化策略。
- 建立完整遷移驗收與回退規則,作為 cutover 與後續清理依據。
## Capabilities
### New Capabilities
- `root-cutover-finalization`: 定義並完成根目錄主工程最終切換與遺留結構去依賴。
- `full-vite-page-modularization`: 完成主要頁面腳本的 Vite 模組化與資產輸出治理。
- `frontend-compute-shift`: 將展示層可前端化計算從後端搬移到前端,保持行為一致。
- `field-contract-governance`: 建立並執行欄位契約UI label / API key / export header一致性規範。
- `cache-observability-hardening`: 強化分層快取策略與健康指標,明確失效與退化行為。
- `migration-gates-and-rollout`: 定義完整遷移的驗收門檻、灰度與回退流程。
### Modified Capabilities
- None.
## Impact
- Affected code: root `src/`, `frontend/`, `scripts/`, `tests/`, `docs/`
- Runtime/deploy: Conda + Node(Vite) build pipeline、Flask/Gunicorn 單一對外 port 模式。
- APIs/pages: Portal、resource status、resource history、job query、excel query、tables 等頁面腳本與欄位輸出。
- Ops: Redis 快取、記憶體快取、health/deep health 指標與告警解讀。

View File

@@ -0,0 +1,15 @@
## ADDED Requirements
### Requirement: Layered Cache SHALL Expose Operational State
The route cache implementation SHALL expose layered cache operational state, including mode, freshness, and degradation status.
#### Scenario: Redis unavailable degradation state
- **WHEN** Redis is unavailable
- **THEN** health endpoints MUST indicate degraded cache mode while keeping L1 memory cache active
### Requirement: Cache Telemetry MUST be Queryable for Operations
The system MUST provide cache telemetry suitable for operations diagnostics.
#### Scenario: Telemetry inspection
- **WHEN** operators request deep health status
- **THEN** cache-related metrics/state SHALL be present and interpretable for troubleshooting

View File

@@ -0,0 +1,19 @@
## ADDED Requirements
### Requirement: Field Contract Registry SHALL Define UI/API/Export Mapping
The system SHALL maintain a field contract registry mapping UI labels, API keys, export headers, and semantic types.
#### Scenario: Contract lookup for page rendering
- **WHEN** a page renders table headers and values
- **THEN** it MUST resolve display labels and keys through the shared field contract definitions
#### Scenario: Contract lookup for export
- **WHEN** export headers are generated
- **THEN** header names MUST follow the same semantic mapping used by the page contract
### Requirement: Consistency Checks MUST Detect Contract Drift
The system MUST provide automated checks that detect mismatches between UI, API response keys, and export field definitions.
#### Scenario: Drift detection failure
- **WHEN** a page or export changes a field name without updating the contract
- **THEN** consistency checks MUST report a failing result before release

View File

@@ -0,0 +1,15 @@
## ADDED Requirements
### Requirement: Display-Layer Computation SHALL be Shifted to Frontend Safely
The system SHALL move eligible display-layer computations from backend to frontend while preserving existing business behavior.
#### Scenario: Equivalent metric output
- **WHEN** frontend-computed metrics are produced for a supported page
- **THEN** output values MUST match baseline backend results within defined rounding rules
### Requirement: Compute Shift MUST be Verifiable by Parity Fixtures
Each migrated computation MUST have parity fixtures comparing baseline and migrated outputs.
#### Scenario: Parity test gating
- **WHEN** a compute-shifted module is changed
- **THEN** parity checks MUST run and fail the migration gate if output differs beyond tolerance

View File

@@ -0,0 +1,19 @@
## ADDED Requirements
### Requirement: Major Pages SHALL be Managed by Vite Modules
The system SHALL provide Vite-managed module entries for major portal pages, replacing inline scripts in a phased manner.
#### Scenario: Portal module loading
- **WHEN** the portal page is rendered
- **THEN** it MUST load its behavior from a Vite-built module asset when available
#### Scenario: Page module fallback
- **WHEN** a required Vite asset is unavailable
- **THEN** the system MUST keep page behavior functional through explicit fallback logic
### Requirement: Build Pipeline SHALL Produce Backend-Served Assets
Vite build output MUST be emitted into backend static paths and served by Flask/Gunicorn on the same origin.
#### Scenario: Build artifact placement
- **WHEN** frontend build is executed
- **THEN** generated JS/CSS files SHALL be written to the configured backend static dist directory

View File

@@ -0,0 +1,15 @@
## ADDED Requirements
### Requirement: Migration Gates SHALL Define Cutover Readiness
The system SHALL define explicit migration gates for functional parity, build integrity, and operational health before final cutover.
#### Scenario: Gate evaluation before cutover
- **WHEN** release is prepared for final cutover
- **THEN** all required migration gates MUST pass or cutover SHALL be blocked
### Requirement: Rollout and Rollback Procedures MUST be Actionable
The system SHALL document actionable rollout and rollback procedures for root migration.
#### Scenario: Rollback execution
- **WHEN** post-cutover validation fails critical checks
- **THEN** operators MUST be able to execute documented rollback steps to restore previous stable behavior

View File

@@ -0,0 +1,19 @@
## ADDED Requirements
### Requirement: Root Project SHALL be the Single Execution Target
The system SHALL run all application startup, test, and deployment workflows from `DashBoard_vite` root without requiring nested `DashBoard/` paths.
#### Scenario: Root startup script execution
- **WHEN** an operator runs start/deploy scripts from `DashBoard_vite` root
- **THEN** all referenced source/config/script paths MUST resolve inside root project structure
#### Scenario: Root test execution
- **WHEN** CI or local developer runs test commands from root
- **THEN** tests SHALL execute against root source tree and root config files
### Requirement: Reference Directory MUST Remain Non-Authoritative
`DashBoard/` SHALL be treated as reference-only and MUST NOT be required for production runtime.
#### Scenario: Runtime independence
- **WHEN** root application is started in an environment without `DashBoard/`
- **THEN** the application MUST remain functional for the defined migration scope

View File

@@ -0,0 +1,42 @@
## 1. Root Cutover Finalization
- [x] 1.1 Inventory all remaining runtime/test/deploy references to nested `DashBoard/` paths.
- [x] 1.2 Remove or replace nested-path dependencies so root scripts and app startup are self-contained.
- [x] 1.3 Define and execute root-only smoke startup checks.
## 2. Vite Full Page Modularization
- [x] 2.1 Create/standardize Vite entries for Portal, Resource Status, Resource History, Job Query, Excel Query, and Tables.
- [x] 2.2 Extract shared frontend core modules (API wrappers, table/tree helpers, field contract helpers).
- [x] 2.3 Replace targeted inline scripts with module bootstraps while preserving fallback behavior.
- [x] 2.4 Update template asset resolution to support per-page Vite bundles.
## 3. Frontend Compute Shift
- [x] 3.1 Identify display-layer computations eligible for frontend migration and document parity rules.
- [x] 3.2 Migrate selected calculations page by page with deterministic helper functions.
- [x] 3.3 Add parity fixtures/tests comparing baseline backend vs migrated frontend outputs.
## 4. Field Contract Governance
- [x] 4.1 Introduce shared field contract registry for UI/API/Export mapping.
- [x] 4.2 Apply the registry to Job Query and Resource History completely (including headers and semantic types).
- [x] 4.3 Extend consistency checks to additional pages and exports.
## 5. Cache Observability Hardening
- [x] 5.1 Expand cache telemetry fields in health/deep-health outputs.
- [x] 5.2 Add explicit degraded-mode visibility when Redis is unavailable.
- [x] 5.3 Validate cache behavior and telemetry under L1-only and L1+L2 modes.
## 6. Migration Gates and Rollout
- [x] 6.1 Define gate checklist for cutover readiness (tests, parity, build, health).
- [x] 6.2 Document rollout steps and operator runbook for the final cutover.
- [x] 6.3 Document rollback procedure and rehearse rollback validation.
## 7. Validation and Documentation
- [x] 7.1 Run focused unit/integration checks in root project and record evidence.
- [x] 7.2 Record known environment-dependent gaps (Oracle/Redis) and mitigation plan.
- [x] 7.3 Update README/docs to declare final root-first workflow and migration status.

View File

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

View File

@@ -0,0 +1,64 @@
## Context
現有程式碼主體在 `DashBoard/` 子目錄OpenSpec/opsx 在 `DashBoard_vite` 根目錄,造成需求追蹤、實作與驗證分離。重構目標是以 `DashBoard/` 作為參考來源,將可執行專案落到根目錄,並在維持單一對外服務埠前提下導入 Vite 前端建置與模組化。
## Goals / Non-Goals
**Goals:**
-`DashBoard_vite` 根目錄建立可運行工程,與 OpenSpec artifacts 同層。
- 維持 Flask/Gunicorn 單一對外 port前端資產由 Flask static 提供。
- 導覽改為抽屜分組,保持既有頁面與 drill-down 操作語意。
- 導入分層快取L1 memory + L2 Redis取代 NoOp 預設。
- 建立畫面欄位、API key、下載欄位的一致性規範。
**Non-Goals:**
- 不在第一階段重寫所有頁面 UI。
- 不更動核心商業資料來源Oracle schema 與主要 SQL 邏輯)。
- 不在第一階段導入多服務或多 port 架構。
## Decisions
1. Root-first migration根目錄主工程
- Decision: 以 `DashBoard/` 為參考,將執行入口、`src/``scripts/`、前端建置等移到 `DashBoard_vite` 根目錄。
- Rationale: 使 OpenSpec 與可執行程式在同一工作根,避免流程分裂。
- Alternative considered: 繼續在 `DashBoard/` 開發,放棄;因與使用者要求衝突。
2. Single-port Vite integration
- Decision: 使用 Vite build 輸出到 Flask static僅在開發時可選擇 Vite dev server不作對外正式服務。
- Rationale: 保持現行部署模型與防火牆策略,降低切換風險。
- Alternative considered: 分離前後端雙服務;放棄以符合單一 port 約束。
3. Layered route cache
- Decision: 路由層快取採用 L1 memory TTL + L2 Redis JSONRedis 不可用時仍有 L1。
- Rationale: 改善響應速度與穩定性,避免 NoOp 導致的快取失效。
- Alternative considered: Redis-only放棄以避免 Redis 異常時退化過大。
4. Navigation IA by drawers
- Decision: 將 portal 導覽分為「報表類、查詢類、開發工具類」抽屜,頁面內容維持原路由/iframe lazy load。
- Rationale: 降低使用者認知負擔,同時避免一次性替換頁面內邏輯。
- Alternative considered: 直接改成 SPA router放棄以降低第一階段風險。
5. Field contract normalization
- Decision: 建立欄位契約字典UI label / API key / export header並先修正已知不一致。
- Rationale: 避免匯出與畫面解讀差異造成誤用。
- Alternative considered: 每頁分散維護;放棄因長期不可維護。
## Risks / Trade-offs
- [Risk] 根目錄遷移時檔案基線混亂(舊目錄與新目錄並存) → Mitigation: 明確標註 `DashBoard/` 為 reference新增 root 驗證與遷移清單。
- [Risk] Redis/Oracle 在本機測試環境不可用導致測試波動 → Mitigation: 分離「單元測試通過」與「環境依賴測試」兩條驗證報告。
- [Risk] Portal 抽屜調整影響既有 E2E selector → Mitigation: 保留原 tab class/data-target先兼容再逐步更新測試。
- [Risk] 欄位命名調整影響下游檔案流程 → Mitigation: 提供別名過渡期與欄位映射文件。
## Migration Plan
1. 建立根目錄主工程骨架(參照 `DashBoard/`),保留 `DashBoard/` 作為對照來源。
2. 導入 Vite build 流程並接入 `deploy/start` 腳本。
3. 套用 portal 抽屜導覽與快取 backend 重構。
4. 執行欄位一致性第一批修正job query / resource history
5. 補齊根目錄測試與操作文件,確認單一 port 運作。
## Open Questions
- 根目錄最終是否保留 `DashBoard/` 作為長期參考,或在完成驗收後移除?
- 第二階段前端運算前移的優先頁面順序(`resource_history` vs `job_query`)是否有業務優先級?

View File

@@ -0,0 +1,29 @@
## Why
目前可執行程式碼位於 `DashBoard/` 子目錄,與 `DashBoard_vite` 根目錄的 OpenSpec/opsx 工作流分離,導致規格、實作與驗證不在同一專案根。需要以 `DashBoard` 為參考,將重構主體統一到 `DashBoard_vite` 根目錄,並同時導入 Vite 以改善前端可維護性與體驗。
## What Changes
-`DashBoard_vite` 根目錄建立可執行的重構專案骨架,參照既有 `DashBoard` 功能與路由。
- 維持 Flask/Gunicorn 單一對外 port導入 Vite 作為前端建置工具build artifact 由 Flask 提供)。
- 導覽由平鋪 tab 重構為功能抽屜(報表類、查詢類、開發工具類),保持既有業務操作路徑。
- 快取策略改為可運作的分層快取L1 記憶體 + L2 Redis不再使用 NoOp 做為預設。
- 建立前端顯示欄位與下載欄位的一致性規範,先修正已知不一致案例。
## Capabilities
### New Capabilities
- `root-project-restructure`: 以 `DashBoard` 為參考,將可運行的重構工程落在 `DashBoard_vite` 根目錄。
- `vite-single-port-integration`: Vite 建置結果整合進 Flask static維持單一 server/port 對外。
- `portal-drawer-navigation`: Portal 導覽改為抽屜分類且維持原頁面邏輯。
- `layered-route-cache`: 路由層快取改為 L1 memory + L2 Redis 的可用實作。
- `field-name-consistency`: 統一畫面欄位、API key 與匯出欄位命名/語義。
### Modified Capabilities
- None.
## Impact
- Affected codebase root: `DashBoard_vite`(新主工程落點)
- Reference baseline: `DashBoard/`(保留作比對與遷移來源)
- Affected systems: Flask app factory, templates, frontend build pipeline, deployment/start scripts, cache layer, export SQL/headers

View File

@@ -0,0 +1,12 @@
## ADDED Requirements
### Requirement: UI and Export Fields SHALL Have a Consistent Contract
The system SHALL define and apply a consistent contract among UI column labels, API keys, and export headers for report/query pages.
#### Scenario: Job query export naming consistency
- **WHEN** job query exports include cause/repair/symptom values
- **THEN** exported field names SHALL reflect semantic value type consistently (e.g., code name vs status name)
#### Scenario: Resource history field alignment
- **WHEN** resource history detail table shows KPI columns
- **THEN** columns required by export semantics (including Availability%) SHALL be present or explicitly mapped

View File

@@ -0,0 +1,19 @@
## ADDED Requirements
### Requirement: Route Cache SHALL Use Layered Storage
The route cache SHALL use L1 in-memory TTL cache and L2 Redis JSON cache when Redis is available.
#### Scenario: L1 cache hit
- **WHEN** a cached key exists in L1 and is unexpired
- **THEN** the API response SHALL be returned from memory without querying Redis
#### Scenario: L2 fallback
- **WHEN** a cached key is missing in L1 but exists in Redis
- **THEN** the value SHALL be returned and warmed into L1
### Requirement: Cache SHALL Degrade Gracefully Without Redis
The route cache SHALL remain functional with L1 cache when Redis is unavailable.
#### Scenario: Redis unavailable at startup
- **WHEN** Redis health check fails during app initialization
- **THEN** route cache operations SHALL continue using L1 cache without application failure

View File

@@ -0,0 +1,15 @@
## ADDED Requirements
### Requirement: Portal Navigation SHALL Group Entries by Functional Drawers
The portal SHALL group navigation entries into functional drawers: reports, queries, and development tools.
#### Scenario: Drawer grouping visibility
- **WHEN** users open the portal
- **THEN** report pages and query pages SHALL appear in separate drawer groups
### Requirement: Existing Page Behavior SHALL Remain Compatible
The portal navigation refactor SHALL preserve existing target routes and lazy-load behavior for content frames.
#### Scenario: Route continuity
- **WHEN** a user selects an existing page entry from the new drawer
- **THEN** the corresponding original route SHALL be loaded without changing page business logic behavior

View File

@@ -0,0 +1,12 @@
## ADDED Requirements
### Requirement: Root Directory SHALL be the Primary Executable Project
The system SHALL treat `DashBoard_vite` root directory as the primary executable project, while `DashBoard/` remains reference-only during migration.
#### Scenario: Running app from root
- **WHEN** a developer runs project scripts from `DashBoard_vite` root
- **THEN** the application startup flow SHALL resolve code and config from root project files
#### Scenario: Reference directory preserved
- **WHEN** migration is in progress
- **THEN** `DashBoard/` SHALL remain available for structure comparison and behavior verification

View File

@@ -0,0 +1,15 @@
## ADDED Requirements
### Requirement: Frontend Build SHALL Use Vite With Flask Static Output
The system SHALL use Vite to build frontend assets and output artifacts into Flask static directories served by the backend.
#### Scenario: Build asset generation
- **WHEN** frontend build is executed
- **THEN** Vite SHALL generate portal-related JS/CSS artifacts into the backend static output path
### Requirement: Deployment SHALL Preserve Single External Port
The system SHALL preserve single-port external serving through Flask/Gunicorn.
#### Scenario: Production serving mode
- **WHEN** the system runs in deployment mode
- **THEN** frontend assets SHALL be served through Flask on the same external port as API/page routes

View File

@@ -0,0 +1,26 @@
## 1. Root Migration Baseline
- [x] 1.1 Build root project baseline in `DashBoard_vite` by referencing `DashBoard/` structure while preserving `DashBoard/` as comparison source.
- [x] 1.2 Ensure root-level Python entry/config/scripts can run without depending on nested `DashBoard/` paths.
- [x] 1.3 Update root README and environment setup notes to make root-first workflow explicit.
## 2. Vite + Single-Port Integration
- [x] 2.1 Add root frontend Vite project and configure build output to backend static assets.
- [x] 2.2 Integrate frontend build into deploy/start scripts with fallback behavior when npm build is unavailable.
- [x] 2.3 Verify root app serves Vite-built assets through Flask on the same external port.
## 3. Portal Navigation Refactor
- [x] 3.1 Refactor root portal navigation to drawer groups (reports/queries/dev-tools) while keeping existing route targets.
- [x] 3.2 Keep lazy-load frame behavior and health popup behavior compatible after navigation refactor.
## 4. Cache and Field Contract Updates
- [x] 4.1 Replace default NoOp route cache in root app with layered cache backend (L1 memory + optional Redis).
- [x] 4.2 Align known field-name inconsistencies between UI and export (job query and resource history first batch).
## 5. Validation and Documentation
- [x] 5.1 Run focused root tests for app factory/cache/query modules and record results.
- [x] 5.2 Document residual environment-dependent test gaps (Oracle/Redis dependent cases) and next actions.

View File

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

View File

@@ -0,0 +1,50 @@
## Context
目前主要報表頁多已採 `frontend_asset(...) + Vite module + inline fallback` 模式,但 `hold_detail` 仍停留在純 inline script。這造成
- 例外頁面無法受益於共用模組治理與 build pipeline。
- 動態表格字串拼接保留 XSS 風險。
- 長期維護出現「主流程已模組化、單頁特例未遷移」的不一致。
## Goals / Non-Goals
**Goals:**
-`hold_detail` 與其他報表頁採同一套 Vite 載入模式。
- 保留既有功能語意(篩選、分頁、刷新、導航)與 MesApi 呼叫契約。
- 將高風險動態輸出改為 escape-safe 渲染。
- 加上模板整合測試覆蓋 module/fallback 分支。
**Non-Goals:**
- 不改後端資料模型與查詢邏輯。
- 不重設 UI 視覺樣式與互動流程。
- 不移除 fallback本次仍保留回退能力
## Decisions
### Decision 1: 以「抽取 inline script 到 Vite entry」完成遷移
- 選擇:新增 `frontend/src/hold-detail/main.js`,以既有邏輯為基礎遷移,模板改為 module 優先、fallback 次之。
- 理由:最小風險完成頁面納管,避免一次性重寫行為。
### Decision 2: 保持全域 handler 相容
- 選擇module 內維持 `window` 介面供既有 `onclick` 使用。
- 理由:降低模板 DOM 大改成本,優先保證 parity。
### Decision 3: 在 module 與 fallback 皆補 escape 防護
- 選擇:對 workcenter/package/lot 資料動態輸出加入 escape/quoted-string 保護。
- 理由:避免 fallback 成為安全漏洞旁路。
## Risks / Trade-offs
- [Risk] 複製遷移過程遺漏函式導致 runtime error → Mitigation: build + template test 覆蓋 module 路徑。
- [Risk] fallback 與 module 雙軌造成維護成本 → Mitigation: 保持語意對齊並在後續階段評估移除 fallback。
- [Risk] escape 導致個別顯示格式變化 → Mitigation: 僅防注入,不改原欄位值與排序/篩選語意。
## Migration Plan
1. 增加 `hold-detail` Vite entry 與 module 檔案。
2. 調整 `hold_detail.html` scripts block 為 module/fallback 雙軌。
3. 補強 module + fallback 的動態輸出 escape。
4. build 與 pytest 驗證,更新 tasks。
## Open Questions
- 是否在下一階段移除 `hold_detail` fallback inline script以降低雙路徑維運成本。

View File

@@ -0,0 +1,26 @@
## Why
`hold_detail` 目前仍是大型 inline script尚未納入 Vite 模組治理,且動態 HTML 字串拼接存在潛在注入風險。為了完成報表頁一致的現代化架構與安全基線,需要將該頁補齊至與其餘主要頁面相同的模組化與防護水位。
## What Changes
- 新增 `hold-detail` Vite entry 並由模板透過 `frontend_asset(...)` 優先載入 module。
- 保留現有 inline script 作為 asset 缺失時 fallback維持既有操作語意不變。
-`hold_detail` 的動態表格/篩選渲染改為 escape-safe 輸出,避免不受信字串直接注入 DOM。
- 補充模板整合測試,驗證 `hold_detail` 的 module/fallback 路徑。
## Capabilities
### New Capabilities
- None.
### Modified Capabilities
- `full-vite-page-modularization`: 擴展 major page 模組化覆蓋到 hold-detail 報表頁。
- `field-contract-governance`: 將動態渲染安全契約擴展到 hold-detail 報表內容。
- `report-effects-parity`: 明確要求 hold-detail 的篩選、分頁、分佈互動在遷移後維持等效。
## Impact
- Affected code: `frontend/src/`, `frontend/vite.config.js`, `src/mes_dashboard/templates/hold_detail.html`, `tests/test_template_integration.py`
- APIs/routes: `/hold-detail`, `/api/wip/hold-detail/*`(僅前端調用與渲染方式調整,不更動後端契約)。
- Runtime behavior: 單一 port 與既有 MesApi/retry 行為不變。

View File

@@ -0,0 +1,8 @@
## ADDED Requirements
### Requirement: Hold Detail Dynamic Rendering MUST Sanitize Untrusted Values
Dynamic table and distribution rendering in hold-detail SHALL sanitize untrusted text before injecting into HTML attributes or content.
#### Scenario: Hold reason distribution contains HTML-like payload
- **WHEN** workcenter/package/lot fields include HTML-like text from upstream data
- **THEN** the hold-detail page MUST render escaped text and MUST NOT execute embedded markup or scripts

View File

@@ -0,0 +1,12 @@
## ADDED Requirements
### Requirement: Hold Detail Page SHALL Be Served by a Vite Module
The system SHALL provide a dedicated Vite entry bundle for the hold-detail report page.
#### Scenario: Hold-detail module asset exists
- **WHEN** `/hold-detail` is rendered and `hold-detail.js` exists in static dist
- **THEN** the page MUST load behavior from the Vite module entry
#### Scenario: Hold-detail module asset missing
- **WHEN** `/hold-detail` is rendered and the module asset is unavailable
- **THEN** the page MUST remain operational through explicit inline fallback logic

View File

@@ -0,0 +1,8 @@
## ADDED Requirements
### Requirement: Hold Detail Interaction Semantics SHALL Remain Equivalent After Modularization
Migrating hold-detail to a Vite module SHALL preserve existing filter, pagination, and refresh behavior.
#### Scenario: User applies filters and paginates on hold-detail
- **WHEN** users toggle age/workcenter/package filters and navigate pages
- **THEN** returned lots, distribution highlights, and pagination state MUST remain behaviorally equivalent to baseline inline behavior

View File

@@ -0,0 +1,17 @@
## 1. Hold Detail Vite Modularization
- [x] 1.1 Add `hold-detail` entry to Vite build configuration.
- [x] 1.2 Create `frontend/src/hold-detail/main.js` by migrating existing page script while preserving behavior.
- [x] 1.3 Update `hold_detail.html` to prefer `frontend_asset('hold-detail.js')` with inline fallback retention.
## 2. Security and Parity Hardening
- [x] 2.1 Sanitize dynamic HTML/attribute interpolation in hold-detail module rendering paths.
- [x] 2.2 Apply equivalent sanitization in inline fallback logic to avoid security bypass.
- [x] 2.3 Preserve legacy global handler compatibility for existing inline event hooks.
## 3. Validation
- [x] 3.1 Build frontend and verify `hold-detail.js` output in static dist.
- [x] 3.2 Extend template integration tests for hold-detail module/fallback rendering.
- [x] 3.3 Run focused pytest suite for template/frontend regressions.

View File

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

View File

@@ -0,0 +1,101 @@
## Context
目前根目錄 `DashBoard_vite` 已完成單一埠 Vite 整合與主要頁面模組化,但運行層仍有三類風險:
1. 韌性參數未完全生效(例如 DB pool 參數在設定層存在、engine 層未完全採用)。
2. 故障語意未完全標準化pool 耗盡/熔斷開啟/降級回應仍有泛化 500
3. 效能優化尚未形成一致策略(快取資料結構與全量 merge 路徑可再降低 CPU 與記憶體負載)。
本設計在不改變業務邏輯與頁面流程前提下,推進 P0/P1/P2
- P0穩定性與退避
- P1查詢效率與資料結構
- P2運維一致性與自癒
約束條件:
- `resource`(設備主檔)與 `wip`(即時狀態)維持全表快取,因資料規模可接受且可換取查詢一致性與延遲穩定。
- Vite 架構持續以「前端可複用元件 + 前端運算前移」為核心方向。
## Goals / Non-Goals
**Goals:**
- 讓 DB pool / timeout / circuit breaker 形成可配置且可驗證的穩定性基線。
- 在 pool 耗盡與服務降級時提供可辨識錯誤碼、HTTP 狀態與前端退避策略。
- 保留全表快取前提下,優化快取資料形狀與索引路徑,降低每次請求全量合併成本。
- 對齊 conda + systemd + watchdog 運行模型,讓 worker 自癒與重啟流程可操作、可觀測。
- 持續擴大前端運算前移範圍,並以 parity 驗證保證結果一致。
**Non-Goals:**
- 不改變既有頁面資訊架構、分頁/鑽取邏輯與核心業務規則。
- 不將 `resource/wip` 改為分片快取或拆分多來源讀取。
- 不引入多埠部署或拆分為前後端不同網域。
- 不在本次變更中重寫所有歷史 SQL 或全面替換資料來源。
## Decisions
### Decision 1: 以「配置即行為」收斂 DB 連線與保護策略P0
- 決策:`database.py` 的 engine 建立必須直接採用 settings/.env 的 pool 與 timeout 參數,並在 `/health/deep` 輸出實際生效值。
- 原因:目前存在設定值與實際 engine 參數可能分離,導致調參無效。
- 替代方案:
- 保留硬編碼參數,僅調整 `.env.example`(拒絕,無法保證生效)。
- 完全改為每環境不同程式碼分支(拒絕,維運成本高)。
### Decision 2: 標準化「退避可判讀」錯誤語意P0
- 決策:新增/明確化 pool exhausted、circuit open、service degraded 的錯誤碼與 HTTP 映射,並在前端 `MesApi` 依狀態碼與錯誤碼進行退避。
- 原因:泛化 500 導致前端無法做差異化重試與提示。
- 替代方案:
- 維持所有 5xx 同一重試邏輯(拒絕,會加劇擁塞)。
- 僅靠文字訊息判斷(拒絕,不穩定且難國際化)。
### Decision 3: 在「全表快取不變」前提下做索引化與增量化P1
- 決策:保留 `resource/wip` 全表快取資料來源,但額外建立 process/redis 層索引(如 RESOURCEID → record index與預聚合中間結果減少每請求全量 merge。
- 原因:資料量雖不大,但高併發下重複全量轉換與合併會累積 CPU 成本。
- 替代方案:
- 改為分片快取(拒絕,破壞已確認的資料一致性策略)。
- 完全回 Oracle 即時計算(拒絕,增加 DB 壓力與延遲波動)。
### Decision 4: 前端運算前移採「可驗證前移」策略P1
- 決策:優先前移展示層聚合/比率/圖表資料整理,並為每個前移計算建立 parity fixture 與容差規則。
- 原因:符合 Vite 架構目的,減輕後端負擔,同時避免靜默偏差。
- 替代方案:
- 一次性大量前移(拒絕,驗證風險高)。
- 完全不前移(拒絕,無法達成改造目標)。
### Decision 5: 運維流程統一以 conda + systemd + watchdogP2
- 決策:部署與監控路徑統一到 conda 環境systemd 服務模板、啟停腳本、watchdog PID/flag 路徑統一;加入自癒與告警門檻。
- 原因:避免 `venv`/`conda` 混用造成重啟失效或定位困難。
- 替代方案:
- 保持雙系統共存(拒絕,長期不一致風險高)。
## Risks / Trade-offs
- [Risk] 調整錯誤碼與狀態碼可能影響既有前端假設 → Mitigation先以向後相容 envelope 保留既有 `success/error` 結構,再新增標準化 code/meta 欄位。
- [Risk] 啟用 circuit breaker 後短時間內可能增加 503 可見度 → Mitigation設定合理門檻與 recovery timeout並提供管理頁可觀測狀態與手動恢復流程。
- [Risk] 新索引/預聚合增加記憶體占用 → Mitigation設 TTL、大小監控與健康檢查輸出必要時可透過配置關閉特定索引層。
- [Risk] 前端運算前移可能出現精度差異 → Mitigation定義 rounding/tolerance 並在 CI gate 執行 parity 測試。
- [Risk] systemd 與腳本改動可能影響部署流程 → Mitigation提供 rollout/rollback 演練步驟與 smoke check。
## Migration Plan
1. P0 先行(穩定性)
- 讓 DB pool/call timeout/circuit breaker 參數化且生效。
- 新增 pool exhausted 與 degraded 錯誤語意;前端 `MesApi` 加入對應退避策略。
- 補充 health/deep 與 admin status 的可觀測欄位。
2. P1 續行(效率)
- 保留 `resource/wip` 全表快取資料源。
- 加入索引化/預聚合路徑與增量更新鉤子,降低全量 merge 次數。
- 擴充前端 compute-shift補 parity fixtures。
3. P2 收斂(運維)
- 統一 conda + systemd + watchdog 服務定義與文件。
- 設定 worker 自癒與告警門檻重啟頻率、pool 飽和、降級持續時間)。
- 完成壓測與重啟演練 gate 後放行。
4. Rollback
- 任一 gate 失敗即回退到前一穩定版本(腳本 + artifacts + 服務模板)。
- 保留向後相容錯誤回應欄位以降低回退期間前端風險。
## Open Questions
- pool exhausted 的最終 HTTP 語意是否固定為 `503`(含 `Retry-After`)或在部分查詢端點使用 `429`
- 告警通道是否先落地在 log + health gate或直接接既有監控平台若有
- 前端計算容差的全域預設值是否統一(如 1e-6 / 小數 1 位),或按指標分類?

View File

@@ -0,0 +1,39 @@
## Why
目前根目錄遷移與 Vite 架構已完成可用性與功能對齊,但「穩定性、退避、自癒、查詢效率」仍未被完整定義為可驗收的規格。現在需要在不改變既有業務邏輯的前提下,將運行韌性與前端運算前移策略正式化,避免 cutover 後在高負載或故障情境下出現不一致行為。
## What Changes
- 以三階段推進非破壞式優化:
- P0先救穩定讓 DB pool 參數真正生效、在生產基線啟用 circuit breaker、補齊 pool exhausted 的專用錯誤語意與前後端退避行為。
- P1再拚效率重整快取資料結構與查詢路徑索引化/增量化),降低每次請求的全量 merge 成本。
- P2運維收斂統一 conda + systemd 執行模型,補齊 worker 自癒與告警門檻,讓 watchdog/restart 流程可操作且可觀測。
- 明確保留既有架構原則:
- `resource`(設備基礎資料)與 `wip`(線上即時狀況)維持全表快取策略,不改成分片或拆表快取。
- Vite 架構持續以「元件複用(圖表/查詢/抽屜)」與「運算前移至瀏覽器」為主軸,前端承接可前移的聚合與呈現計算。
## Capabilities
### New Capabilities
- `runtime-resilience-recovery`: 定義 DB pool 耗盡、worker 異常、服務降級時的標準退避、恢復與熱重啟流程。
- `conda-systemd-runtime-alignment`: 定義 conda 環境、systemd 服務、watchdog 與啟停腳本的一致部署契約與驗收門檻。
### Modified Capabilities
- `frontend-compute-shift`: 擴充前端運算前移邊界與 parity 驗證,確保前端計算結果與後端契約一致。
- `full-vite-page-modularization`: 強化跨頁可複用元件與共用核心模組(圖表、查詢、抽屜、欄位契約)的要求。
- `layered-route-cache`: 明確要求保留 `resource/wip` 全表快取,並在此基礎上優化索引與資料形狀。
- `cache-observability-hardening`: 擴充快取/連線池/熔斷器的可觀測欄位、降級訊號與告警閾值。
- `migration-gates-and-rollout`: 新增穩定性壓測、pool 壓力、worker 重啟演練等遷移門檻。
## Impact
- Affected code:
- Backend: `src/mes_dashboard/core/database.py`, `src/mes_dashboard/core/circuit_breaker.py`, `src/mes_dashboard/core/cache.py`, `src/mes_dashboard/routes/*.py`, `src/mes_dashboard/services/resource_cache.py`, `src/mes_dashboard/services/realtime_equipment_cache.py`
- Frontend: `frontend/src/core/*` 與各頁 entry 模組,持續抽取可複用圖表/查詢邏輯。
- Ops: `scripts/start_server.sh`, `scripts/worker_watchdog.py`, `deploy/mes-dashboard-watchdog.service`, `.env.example`, `README.md`
- API/behavior:
- 新增或標準化故障語意(含 pool exhausted / circuit open / degraded與對應退避策略。
- Dependencies/systems:
- 維持單一埠服務模型;持續使用 conda + gunicorn + redis + systemd/watchdog。
- Validation:
- 增加 resilience/performance 測試與 rollout gate驗證降級、恢復、快取一致性與前後端計算一致性。

View File

@@ -0,0 +1,22 @@
## ADDED Requirements
### Requirement: Health Endpoints SHALL Expose Pool Saturation and Degradation Reason Codes
Operational health endpoints MUST report connection pool saturation indicators and explicit degradation reason codes.
#### Scenario: Pool saturation observed
- **WHEN** checked-out connections and overflow approach configured limits
- **THEN** deep health output MUST expose saturation metrics and degraded reason classification
### Requirement: Degraded Responses MUST Be Correlatable Across API and Health Telemetry
Error responses for degraded states SHALL include stable codes that can be mapped to health telemetry and operational dashboards.
#### Scenario: Degraded API response correlation
- **WHEN** an API request fails due to circuit-open or pool-exhausted conditions
- **THEN** operators MUST be able to match the response code to current health telemetry state
### Requirement: Operational Alert Thresholds SHALL Be Explicitly Defined
The system MUST define alert thresholds for sustained degraded state, repeated worker recovery, and abnormal retry pressure.
#### Scenario: Sustained degradation threshold exceeded
- **WHEN** degraded status persists beyond configured duration
- **THEN** the monitoring contract MUST classify the service as alert-worthy with actionable context

View File

@@ -0,0 +1,22 @@
## ADDED Requirements
### Requirement: Production Service Runtime SHALL Use Conda-Aligned Execution Paths
Service units and operational scripts MUST run with a consistent conda-managed Python runtime.
#### Scenario: Service unit starts application
- **WHEN** systemd starts the dashboard service and watchdog
- **THEN** both processes MUST execute using the configured conda environment binaries and paths
### Requirement: Watchdog and Runtime Paths MUST Be Operationally Consistent
PID files, restart flag paths, state files, and worker control interfaces SHALL be consistent across scripts, environment variables, and systemd units.
#### Scenario: Watchdog handles restart flag
- **WHEN** a restart flag is written by admin control endpoints
- **THEN** watchdog MUST read the same configured path set and signal the correct Gunicorn master process
### Requirement: Deployment Documentation MUST Match Runtime Contract
Runbooks and deployment documentation MUST describe the same conda/systemd/watchdog contract used by the deployed system.
#### Scenario: Operator follows deployment runbook
- **WHEN** an operator performs deploy, health check, and rollback from documentation
- **THEN** documented commands and paths MUST work without requiring venv-specific assumptions

View File

@@ -0,0 +1,22 @@
## ADDED Requirements
### Requirement: Compute-Shifted Logic SHALL Be Exposed as Reusable Frontend Core Modules
Frontend-computed metrics and transformations MUST be implemented as reusable, testable modules instead of page-local inline logic.
#### Scenario: Multiple pages consume shared compute logic
- **WHEN** two or more pages require the same metric transformation or aggregation
- **THEN** they MUST import a shared frontend core module and produce consistent outputs
### Requirement: Frontend Compute Parity MUST Include Tolerance Contracts Per Metric
Parity verification SHALL define explicit tolerance and rounding contracts per migrated metric.
#### Scenario: Parity check for migrated metric
- **WHEN** migrated frontend computation is validated against baseline output
- **THEN** parity tests MUST evaluate the metric against its declared tolerance and fail when outside bounds
### Requirement: Compute Shift MUST Preserve Existing User-Facing Logic
Frontend compute migration MUST preserve existing filter semantics, drill-down behavior, and displayed totals.
#### Scenario: Existing dashboard interactions after compute shift
- **WHEN** users apply filters and navigate drill-down flows on migrated pages
- **THEN** interaction results MUST remain behaviorally equivalent to the pre-shift baseline

View File

@@ -0,0 +1,22 @@
## ADDED Requirements
### Requirement: Vite Page Modules SHALL Reuse Shared Chart and Query Building Blocks
Page entry modules MUST consume shared chart/query/drawer utilities for common behaviors.
#### Scenario: Common chart behavior across pages
- **WHEN** multiple report pages render equivalent chart interactions
- **THEN** the behavior MUST be provided by shared Vite modules rather than duplicated page-local implementations
### Requirement: Modularization MUST Preserve Established Navigation and Drill-Down Semantics
Refactoring into Vite modules SHALL not alter existing page transitions, independent tabs, and drill-down entry points.
#### Scenario: User follows existing drill-down path
- **WHEN** the user navigates from summary page to detail views
- **THEN** the resulting flow and parameter semantics MUST match the established baseline behavior
### Requirement: Module Boundaries SHALL Support Frontend Compute Expansion
Vite module structure MUST keep compute logic decoupled from DOM wiring so additional backend-to-frontend computation shifts can be added safely.
#### Scenario: Adding a new frontend-computed metric
- **WHEN** a new metric is migrated from backend to frontend
- **THEN** the metric logic MUST be integrated through shared compute modules without rewriting page routing structure

View File

@@ -0,0 +1,22 @@
## ADDED Requirements
### Requirement: Resource and WIP Full-Table Cache SHALL Remain the Authoritative Cached Dataset
The system MUST keep `resource` and `wip` full-table cache datasets as the canonical cached source for downstream route queries.
#### Scenario: Route query reads cached baseline
- **WHEN** an endpoint requires resource or wip data
- **THEN** it MUST read from the corresponding full-table cache baseline before applying derived filters or aggregations
### Requirement: Cache Access Paths SHALL Support Index-Based Lookup and Derived Views
The caching layer SHALL support index and derived-view access paths to reduce per-request full-table merge and transformation overhead.
#### Scenario: Lookup by key under concurrent load
- **WHEN** requests query by high-cardinality keys such as RESOURCEID
- **THEN** the system MUST serve lookups via indexed cache access instead of repeated full-array scans
### Requirement: Full-Table Cache Refresh MUST Support Incremental Derivation Updates
Derived cache indices and aggregates MUST be refreshed consistently when the underlying full-table cache version changes.
#### Scenario: Cache version update
- **WHEN** full-table cache is refreshed to a new version
- **THEN** dependent indices and derived views MUST be rebuilt or updated before being exposed for reads

View File

@@ -0,0 +1,22 @@
## ADDED Requirements
### Requirement: Migration Gates SHALL Include Runtime Resilience Validation
Cutover readiness gates MUST include resilience checks for pool exhaustion handling, circuit-breaker fail-fast behavior, and recovery flow.
#### Scenario: Resilience gate evaluation
- **WHEN** migration gates are executed before release
- **THEN** resilience tests MUST pass for degraded-response semantics and recovery path validation
### Requirement: Migration Gates SHALL Include Frontend Compute Parity Validation
Cutover readiness MUST include parity validation for metrics shifted from backend to frontend computation.
#### Scenario: Compute parity gate
- **WHEN** a release includes additional frontend-computed metrics
- **THEN** gate execution MUST verify parity fixtures and fail if tolerance contracts are violated
### Requirement: Rollout Procedure MUST Include Conda-Systemd-Watchdog Rehearsal
Rollout and rollback runbooks SHALL include an operational rehearsal for service start, watchdog-triggered reload, and post-restart health checks under the conda/systemd runtime contract.
#### Scenario: Pre-cutover rehearsal
- **WHEN** operators execute pre-cutover rehearsal
- **THEN** they MUST successfully complete conda-based start, worker reload, and health verification steps documented in the runbook

View File

@@ -0,0 +1,29 @@
## ADDED Requirements
### Requirement: Database Pool Runtime Configuration SHALL Be Enforced
The system SHALL apply database pool and timeout parameters from runtime configuration to the active SQLAlchemy engine used by request handling.
#### Scenario: Runtime pool configuration takes effect
- **WHEN** operators set pool and timeout values via environment configuration and start the service
- **THEN** the active engine MUST use those values for pool size, overflow, wait timeout, and query call timeout
### Requirement: Pool Exhaustion MUST Return Retry-Aware Degraded Responses
The system MUST return explicit degraded responses for connection pool exhaustion and include machine-readable metadata for retry/backoff behavior.
#### Scenario: Pool exhausted under load
- **WHEN** concurrent requests exceed available database connections and pool wait timeout is reached
- **THEN** the API MUST return a dedicated error code and retry guidance instead of a generic 500 failure
### Requirement: Runtime Degradation MUST Integrate Circuit Breaker State
Database-facing API behavior SHALL distinguish circuit-breaker-open degradation from transient query failures.
#### Scenario: Circuit breaker is open
- **WHEN** the circuit breaker transitions to OPEN state
- **THEN** database-backed endpoints MUST fail fast with a stable degradation response contract
### Requirement: Worker Recovery SHALL Support Hot Reload and Watchdog-Assisted Recovery
The runtime MUST support graceful worker hot reload and watchdog-triggered recovery without requiring a port change or full system reboot.
#### Scenario: Worker restart requested
- **WHEN** an authorized operator requests worker restart during degraded operation
- **THEN** the service MUST trigger graceful reload and preserve single-port availability

View File

@@ -0,0 +1,36 @@
## 1. P0 Runtime Resilience Baseline
- [x] 1.1 Make `database.py` read and enforce runtime pool/timeouts from settings/env instead of hardcoded constants.
- [x] 1.2 Add explicit degraded error mapping for pool exhaustion and circuit-open states (stable error codes + retry metadata).
- [x] 1.3 Update API response handling so degraded errors are returned consistently across WIP/Resource/Dashboard endpoints.
- [x] 1.4 Extend frontend `MesApi` retry/backoff policy to respect degraded error codes and avoid aggressive retries under pool exhaustion.
## 2. P0 Observability and Recovery Controls
- [x] 2.1 Extend `/health` and `/health/deep` payloads with pool configuration, saturation indicators, and degradation reason classification.
- [x] 2.2 Expose runtime-resilience diagnostics in admin status API for operations triage.
- [x] 2.3 Ensure hot-reload/restart controls preserve single-port availability and return actionable status for watchdog-driven recovery.
## 3. P1 Cache and Query Efficiency (Keep Full-Table Cache)
- [x] 3.1 Preserve `resource/wip` full-table cache as authoritative baseline while introducing indexed lookup helpers for high-frequency access paths.
- [x] 3.2 Reduce repeated full-array merge cost in resource status composition by using prebuilt lookup/index structures.
- [x] 3.3 Add cache version-coupled rebuild/update flow for derived indices and expose telemetry for index freshness.
## 4. P1 Frontend Compute Shift Expansion
- [x] 4.1 Refactor compute-heavy display transformations into reusable frontend core modules.
- [x] 4.2 Add parity fixtures/tests for newly shifted computations with explicit tolerance contracts.
- [x] 4.3 Ensure migrated pages preserve existing tab/drill-down behavior while consuming shared Vite modules.
## 5. P2 Conda/Systemd/Watchdog Runtime Alignment
- [x] 5.1 Align systemd service templates and runtime paths with conda-based execution model.
- [x] 5.2 Align startup/deploy scripts, watchdog config, and documentation to a single runtime contract.
- [x] 5.3 Define and document alert thresholds for sustained degraded state, restart churn, and retry pressure.
## 6. Validation and Migration Gates
- [x] 6.1 Add/extend tests for pool exhaustion semantics, circuit-breaker fail-fast behavior, and degraded response contracts.
- [x] 6.2 Add/extend tests for indexed cache access and frontend compute parity.
- [x] 6.3 Update migration gate/runbook docs to include resilience checks, conda-systemd rehearsal, and rollback verification.

View File

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

View File

@@ -0,0 +1,65 @@
## Context
`DashBoard_vite` 已完成主體搬遷,但報表頁仍處於混合狀態:
- `resource-status``resource-history` 等頁面已有 Vite 版本,卻存在實際行為缺陷。
- `wip_overview``wip_detail` 仍以 inline script 為主,尚未納入 Vite entry 與共用模組治理。
- 部分頁面仍有直接字串拼接輸出與原生 `fetch` 路徑,無法完整承接既有 `MesApi` 的降級重試契約。
此變更是「遷移後硬化」階段:不改變既有業務操作語意,但將效果對齊、模組化覆蓋與前端複用一起完成。
## Goals / Non-Goals
**Goals:**
- 讓 WIP 報表頁進入 Vite entry 管理,並保留目前 tab/drill-down 與 `onclick` 操作語意。
- 修復已遷移模組中會影響報表可用性的缺陷初始化、KPI、矩陣選取、API 呼叫路徑)。
- 強化共用路徑escape、欄位契約、MesApi/backoff以支撐後續前端運算擴展。
- 用測試明確覆蓋「asset exists -> module」、「asset missing -> fallback」的模板行為。
**Non-Goals:**
- 不改動後端路由設計與單一 port 服務模型。
- 不重寫 UI 視覺風格或更動既有商業邏輯判斷規則。
- 不在本次引入新的大型前端框架(維持 Vanilla + Vite entry 模式)。
## Decisions
### Decision 1: 採用「模板雙軌載入」完成 WIP 遷移
- 選擇:在 `wip_overview.html``wip_detail.html` 加入 `frontend_asset()` module 載入,保留既有 inline script 作 fallback。
- 理由:可在不破壞現場可用性的前提下,讓 Vite bundle 成為預設執行路徑,符合先前頁面遷移模式。
- 替代方案:直接刪除 inline script。
- 未採用原因:回退能力不足,且無法快速比對 parity。
### Decision 2: 模組保持全域 handler 相容層
- 選擇Vite entry 內對舊有 `onclick` 所需函式維持 `window` 綁定,避免模板同步大改。
- 理由:降低一次性改動範圍,先確保行為完全對齊,再逐步收斂事件綁定方式。
- 替代方案:全面改為 addEventListener 並移除 inline `onclick`
- 未採用原因:本次目標是 parity hardening不是互動模型重寫。
### Decision 3: 前端 API 路徑統一走 MesApi
- 選擇JSON API 優先走 `MesApi.get/post`(或 core api bridge僅 blob/download 等必要場景保留原生 fetch。
- 理由:沿用既有降級錯誤碼與 retry/backoff 策略,避免 pool exhausted 時前端重試失控。
- 替代方案:維持頁面各自 `fetch`
- 未採用原因:會破壞 resilience contract一致性不足。
### Decision 4: 字串輸出與欄位命名同步納入治理
- 選擇:針對動態 HTML 內容補 escape並對照 field contract 驗證表格欄位與下載標頭語意一致。
- 理由:遷移期間常見 XSS/欄位漂移問題,必須和模組化同時收斂。
## Risks / Trade-offs
- [Risk] 大型 inline script 搬入 module 時可能出現作用域差異 → Mitigation: 先保留 fallback並針對 `window` handler 做顯式綁定。
- [Risk] 模組與 fallback 並存造成測試分支增加 → Mitigation: 以 template integration 測試固定兩條路徑行為。
- [Risk] escape 補強可能改變少數欄位原始顯示格式 → Mitigation: 僅針對 HTML 注入風險欄位處理,保留 NULL/日期等既有顯示語意。
- [Risk] 前端改走 MesApi 使錯誤提示型態改變 → Mitigation: 保持原錯誤訊息文案,僅替換底層請求路徑。
## Migration Plan
1. 先完成 OpenSpec task 分解與可執行順序。
2. 新增 WIP Vite entries更新 vite config模板加上 module/fallback 雙軌。
3. 修復 `resource-history``resource-status` 關鍵缺陷並補安全性修正。
4. Build + pytest 驗證,更新 task 勾選。
5. 交付變更摘要與剩餘風險,供後續 archive。
## Open Questions
- 是否需要在下一階段移除 WIP fallback inline script目前先保留作為回退機制
- 是否要擴充前端單元測試Vitest覆蓋更多 DOM 互動,而不只依賴後端模板整合測試。

View File

@@ -0,0 +1,28 @@
## Why
目前仍有部分報表頁維持大型 inline script且已遷移的 Vite 模組存在實際行為缺口(例如 KPI 0% 呈現、矩陣篩選選取、模組作用域匯出失敗)。這造成「舊版 Jinja 報表效果」與「新架構模組化」之間存在落差,無法完全發揮 Vite 在複用、可維護性與前端運算轉移的優勢。
## What Changes
- 將 WIP Overview / WIP Detail 的報表互動完整納入 Vite entry保留既有頁面操作語意與 drill-down 路徑。
- 修復已遷移頁面的核心行為缺陷Resource History 模組初始化、Resource Status KPI 與矩陣交互)。
- 統一報表前端 API 呼叫路徑,優先透過 `MesApi` 以承接既有 retry/backoff 與降級錯誤契約。
- 補強報表頁字串輸出安全與欄位契約一致性,確保畫面欄位、查詢結果與下載欄位名稱一致。
- 新增/調整模板整合驗證,確保 Vite 模組載入與 fallback 行為在報表頁完整覆蓋。
## Capabilities
### New Capabilities
- `report-effects-parity`: 定義舊版 Jinja 報表在新 Vite 架構下的效果對齊要求圖表、篩選、表格、KPI、互動與下載語意
### Modified Capabilities
- `full-vite-page-modularization`: 擴展到 WIP 報表頁完整模組化與 fallback 覆蓋。
- `frontend-compute-shift`: 擴大前端運算承載並修復前端計算與呈現邏輯缺陷。
- `field-contract-governance`: 強化欄位名稱與匯出標頭一致性及頁面渲染安全。
- `runtime-resilience-recovery`: 明確要求前端呼叫在降級/壓力情境下遵循退避契約。
## Impact
- Affected code: `frontend/src/`, `frontend/vite.config.js`, `src/mes_dashboard/templates/`, `tests/test_template_integration.py`
- Affected runtime behavior: 報表頁 JS 載入模式、矩陣/篩選互動、KPI 顯示與下載欄位對齊。
- Affected operations: 單一對外 port 架構不變,仍由 Flask/Gunicorn 提供頁面與 Vite build 輸出資產。

View File

@@ -0,0 +1,15 @@
## ADDED Requirements
### Requirement: Dynamic Report Rendering MUST Sanitize Untrusted Values
Dynamic table/list rendering in report and query pages SHALL sanitize untrusted text before injecting HTML.
#### Scenario: HTML-like payload in query result
- **WHEN** an API result field contains HTML-like text payload
- **THEN** the rendered page MUST display escaped text and MUST NOT execute embedded script content
### Requirement: UI Table and Download Headers SHALL Follow the Same Field Contract
Page table headers and exported file headers SHALL map to the same field contract definition for the same dataset.
#### Scenario: Header consistency check
- **WHEN** users view a report table and then export the corresponding data
- **THEN** header labels MUST remain semantically aligned and avoid conflicting naming for identical fields

View File

@@ -0,0 +1,15 @@
## ADDED Requirements
### Requirement: Frontend Compute Paths MUST Handle Zero and Boundary Values Correctly
Frontend-computed report metrics SHALL preserve valid zero values and boundary conditions in user-visible KPI and summary components.
#### Scenario: Zero-value KPI rendering
- **WHEN** OU% or availability metrics are computed as `0`
- **THEN** the page MUST render `0%` (or configured numeric format) instead of placeholder values
### Requirement: Hierarchical Filter Compute Logic SHALL Be Deterministic Across Levels
Frontend matrix/filter computations SHALL produce deterministic selection and filtering outcomes for group, family, and resource levels.
#### Scenario: Matrix selection at multiple hierarchy levels
- **WHEN** users toggle matrix cells across group, family, and resource rows
- **THEN** selected-state rendering and filtered equipment result sets MUST remain level-correct and reversible

View File

@@ -0,0 +1,19 @@
## ADDED Requirements
### Requirement: WIP Report Pages SHALL Be Served by Vite Modules
The system SHALL provide Vite entry bundles for WIP overview and WIP detail pages, with template-level asset resolution.
#### Scenario: WIP module asset available
- **WHEN** the built asset exists in backend static dist
- **THEN** the page MUST load behavior from the corresponding Vite module entry
#### Scenario: WIP module asset unavailable
- **WHEN** the built asset is not present
- **THEN** the page MUST retain equivalent behavior through explicit inline fallback logic
### Requirement: Vite Modules MUST Preserve Legacy Handler Compatibility
Vite report modules SHALL expose required global handlers for existing inline entry points until event wiring is fully migrated.
#### Scenario: Inline-triggered handler compatibility
- **WHEN** a template control invokes existing global handler names
- **THEN** the migrated module MUST provide compatible callable handlers without runtime scope errors

View File

@@ -0,0 +1,19 @@
## ADDED Requirements
### Requirement: Report Effect Parity SHALL Be Preserved During Vite Migration
The system SHALL preserve existing Jinja-era report interactions when report pages are served by Vite modules.
#### Scenario: WIP overview interactions remain equivalent
- **WHEN** users operate WIP overview filters, KPI cards, chart refresh, and drill-down entry
- **THEN** the resulting state transitions and navigation parameters MUST remain behaviorally equivalent to the baseline page logic
#### Scenario: WIP detail interactions remain equivalent
- **WHEN** users operate WIP detail filters, pagination, lot detail popup, and back-to-overview transitions
- **THEN** the resulting data scope and interaction behavior MUST match baseline semantics
### Requirement: Report Visual Semantics MUST Remain Consistent
Report pages SHALL keep established status color semantics, KPI display rules, and table/chart synchronization behavior after migration.
#### Scenario: KPI and matrix state consistency
- **WHEN** metric values are zero or filters target specific matrix levels
- **THEN** KPI values and selected-state highlights MUST render correctly without collapsing valid zero values or losing selection state

View File

@@ -0,0 +1,8 @@
## ADDED Requirements
### Requirement: Report Frontend API Access SHALL Honor Degraded Retry Contracts
Report pages SHALL use retry-aware API access paths for JSON endpoints so degraded backend responses propagate retry metadata to UI behavior.
#### Scenario: Pool exhaustion or circuit-open response
- **WHEN** report API endpoints return degraded error codes with retry hints
- **THEN** frontend calls MUST flow through MesApi-compatible behavior and avoid aggressive uncontrolled retry loops

View File

@@ -0,0 +1,28 @@
## 1. OpenSpec Scope and Parity Baseline
- [x] 1.1 Confirm report parity target pages and interaction scope (WIP overview/detail, resource status/history, query pages).
- [x] 1.2 Capture concrete parity defects in current Vite modules (runtime errors, KPI/matrix mismatch, API path inconsistency).
## 2. WIP Pages Vite Modularization
- [x] 2.1 Add Vite entries for `wip-overview` and `wip-detail`.
- [x] 2.2 Update templates to load `frontend_asset(...)` module bundles with inline fallback retention.
- [x] 2.3 Preserve legacy global handler compatibility for existing inline-triggered actions.
## 3. Report Behavior and Compute Fixes
- [x] 3.1 Fix `resource-history` module initialization/export scope error.
- [x] 3.2 Fix `resource-status` matrix selection logic and KPI zero-value rendering parity.
- [x] 3.3 Align report JSON API calls to MesApi-compatible paths for degraded retry behavior.
## 4. Field Contract and Rendering Hardening
- [x] 4.1 Patch dynamic table/query rendering to escape untrusted values.
- [x] 4.2 Verify UI table headers and export header naming consistency for touched report flows.
- [x] 4.3 Fix missing report style tokens affecting visual consistency.
## 5. Validation and Regression Guard
- [x] 5.1 Build frontend bundles and ensure new entries are emitted into backend static dist.
- [x] 5.2 Extend/update template integration tests for WIP module/fallback behavior.
- [x] 5.3 Run focused pytest suite for template/frontend/report regressions and record outcomes.

View File

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

View File

@@ -0,0 +1,67 @@
## Context
`DashBoard_vite` 已完成單一 port 的 Flask + Vite 架構整併並具備降級回應、circuit breaker、watchdog 熱重啟與多層快取。
目前主要缺口不是功能不存在,而是「運維可操作性」與「前端治理粒度」:
1. health/admin 雖有狀態,但缺少門檻與建議動作,值班時仍需人工判讀。
2. watchdog 僅保留最後一次重啟紀錄,無法直接判斷短時間 churn。
3. WIP overview/detail 仍有 autocomplete/filter 搜尋邏輯重複,後續擴展成本高。
4. README 需要明確反映最新架構契約與改善策略,避免文件落後於實作。
## Goals / Non-Goals
**Goals:**
- 提供可操作的韌性診斷輸出thresholds、churn、recovery recommendation
- 保持既有單 port 與手動重啟控制模型,不引入高風險自動重啟風暴。
- 抽離 WIP 頁面共用 autocomplete/filter 查詢邏輯到 Vite core降低重複。
- 新增對應測試與文件更新,讓 gate 與 README 可驗證。
**Non-Goals:**
- 不做整站 SPA rewrite。
- 不改動既有 drill-down 路徑與使用者操作語意。
- 不預設啟用「條件達成即自動重啟 worker」的強制策略。
## Decisions
1. 韌性診斷採「可觀測 + 建議」而非預設自動重啟
- Decision: 在 `/health``/health/deep``/admin/api/system-status``/admin/api/worker/status` 增加 thresholds/churn/recommendation。
- Rationale: 目前已具備 degraded response + backoff + admin restart先提升判讀與操作性避免未設防的自動重啟造成抖動。
- Alternative considered: 直接在 pool exhausted 時自動重啟 worker未採用因 root cause 多為慢查詢/瞬時壅塞,重啟治標不治本且有風暴風險。
2. watchdog state 擴充最近重啟歷史
- Decision: 在 state 檔保留 bounded restart history 並計算 churn summary。
- Rationale: 提供運維端可觀測的重啟密度訊號,支援告警與 runbook 決策。
- Alternative considered: 僅依日誌分析;未採用,因 API 需要機器可讀狀態。
3. WIP autocomplete/filter 抽共用核心模組
- Decision: 新增 `frontend/src/core/autocomplete.js`,由 `wip-overview` / `wip-detail` 共用。
- Rationale: 保留既有 API 與頁面互動語意,同時降低重複與 bug 修補成本。
- Alternative considered: 全量頁面元件化框架重寫;未採用,因超出本次風險與範圍。
4. README 架構契約同步
- Decision: 更新 README並提供 `README.mdj` 鏡像)記錄新的韌性診斷與前端共用模組策略。
- Rationale: 交付後文件應可直接支援運維與交接。
## Risks / Trade-offs
- [Risk] 韌性輸出欄位增加可能影響依賴固定 schema 的外部腳本
- Mitigation: 採向後相容擴充,不移除既有欄位。
- [Risk] 共用 autocomplete 模組抽離後可能引入搜尋參數差異
- Mitigation: 保持原有欄位映射與 cross-filter 規則,並補單元測試覆蓋。
- [Risk] restart history 持久化不當可能造成 state 膨脹
- Mitigation: 使用 bounded history固定上限與窗口彙總。
## Migration Plan
1. 實作 resilience diagnosticsthresholds/churn/recommendation與 watchdog state 擴充。
2. 更新 health/admin API 輸出並補測試。
3. 抽離前端 autocomplete 共用模組,更新 WIP 頁面引用並執行 Vite build。
4. 更新 README/README.mdj 與 runbook 對應段落。
5. 執行 focused pytest + frontend build 驗證,確認單 port 契約不變。
## Open Questions
- 是否在下一階段將 recommendation 與告警 webhookSlack/Teams直接整合
- 是否要把 restart churn 門檻與 UI 告警顏色標準化到 admin/performance 頁?

View File

@@ -0,0 +1,40 @@
## Why
Vite migration已完成主要功能遷移但目前仍有兩個可見風險一是運維端缺少「可操作」的韌性判斷僅有狀態缺少建議動作與重啟 churn 訊號);二是前端主要報表頁仍存在可抽離的重複互動邏輯,會增加後續維護成本。現在補齊這兩塊,可在不改變既有使用流程下提高穩定性與可演進性。
## What Changes
- 擴充 runtime resilience 診斷契約:在 health/admin payload 提供門檻設定、重啟 churn 與可行動建議。
- 強化 watchdog state保留最近重啟歷史支持 churn 計算與觀測。
- 將 WIP overview/detail 重複的 autocomplete/filter 查詢邏輯抽成共用 Vite core 模組。
- 增加前端核心模組與韌性診斷的測試覆蓋。
- 更新專案說明文件README反映最新架構、治理策略與操作準則。
## Capabilities
### New Capabilities
- None.
### Modified Capabilities
- `runtime-resilience-recovery`: 新增重啟 churn 與復原建議契約,讓降級狀態具備可操作的 runbook 訊號。
- `full-vite-page-modularization`: 新增 WIP 報表共用 autocomplete/filter building blocks 要求,降低頁面重複實作。
- `migration-gates-and-rollout`: 新增文件與前端治理 gate確保架構說明與實際部署契約一致。
## Impact
- Affected code:
- `src/mes_dashboard/routes/health_routes.py`
- `src/mes_dashboard/routes/admin_routes.py`
- `scripts/worker_watchdog.py`
- `frontend/src/core/`
- `frontend/src/wip-overview/main.js`
- `frontend/src/wip-detail/main.js`
- `tests/`
- `README.md`(以及使用者要求的 README.mdj
- APIs:
- `/health`
- `/health/deep`
- `/admin/api/system-status`
- `/admin/api/worker/status`
- Operational behavior:
- 保持單一 port 與既有手動重啟流程;新增觀測與建議,不預設啟用自動重啟風暴風險。

View File

@@ -0,0 +1,12 @@
## ADDED Requirements
### Requirement: WIP Modules SHALL Reuse Shared Autocomplete and Filter Query Utilities
WIP overview and WIP detail Vite entry modules SHALL use shared frontend core utilities for autocomplete request construction and cross-filter behavior.
#### Scenario: Cross-filter autocomplete parity across WIP pages
- **WHEN** users type in workorder/lot/package/type filters on either WIP overview or WIP detail pages
- **THEN** both pages MUST generate equivalent autocomplete request parameters and return behaviorally consistent dropdown results
#### Scenario: Shared utility change propagates across both pages
- **WHEN** autocomplete mapping rules are updated in the shared core module
- **THEN** both WIP overview and WIP detail modules MUST consume the updated behavior without duplicated page-local logic edits

View File

@@ -0,0 +1,12 @@
## ADDED Requirements
### Requirement: Migration Gates SHALL Enforce Architecture Documentation Consistency
Cutover governance MUST include verification that runtime architecture contracts documented for operators match implemented deployment and resilience behavior.
#### Scenario: Documentation gate before release
- **WHEN** release gates are executed for a migration or hardening change
- **THEN** project README artifacts MUST be updated to reflect current single-port runtime contract, resilience diagnostics, and frontend modularization strategy
#### Scenario: Gate fails on stale architecture contract
- **WHEN** implementation introduces resilience or module-governance changes but README architecture section remains outdated
- **THEN** release governance MUST treat the gate as failed until documentation is aligned

View File

@@ -0,0 +1,12 @@
## ADDED Requirements
### Requirement: Runtime Resilience Diagnostics MUST Expose Actionable Signals
The system MUST expose machine-readable resilience thresholds, restart-churn indicators, and operator action recommendations so degraded states can be triaged consistently.
#### Scenario: Health payload includes resilience diagnostics
- **WHEN** clients call `/health` or `/health/deep`
- **THEN** responses MUST include resilience thresholds and a recommendation field describing whether to observe, throttle, or trigger controlled worker recovery
#### Scenario: Admin status includes restart churn summary
- **WHEN** operators call `/admin/api/system-status` or `/admin/api/worker/status`
- **THEN** responses MUST include bounded restart history summary within a configured time window and indicate whether churn threshold is exceeded

View File

@@ -0,0 +1,23 @@
## 1. Runtime Resilience Diagnostics Hardening
- [x] 1.1 Add shared resilience threshold/recommendation helpers for health/admin payloads.
- [x] 1.2 Extend watchdog restart state to include bounded restart history and churn summary.
- [x] 1.3 Expose thresholds/churn/recommendation fields in `/health`, `/health/deep`, `/admin/api/system-status`, and `/admin/api/worker/status`.
## 2. Frontend WIP Module Reuse
- [x] 2.1 Add shared Vite core autocomplete/filter utility module.
- [x] 2.2 Refactor WIP overview/detail modules to consume shared autocomplete utilities while preserving behavior.
- [x] 2.3 Verify Vite build output remains valid for single-port backend delivery.
## 3. Validation Coverage
- [x] 3.1 Add backend tests for resilience diagnostics and restart churn telemetry contracts.
- [x] 3.2 Add frontend tests for shared autocomplete request parameter behavior.
- [x] 3.3 Run focused backend/frontend validation commands and record pass results.
## 4. Documentation Alignment
- [x] 4.1 Update `README.md` architecture/operations sections to reflect latest resilience and frontend-governance model.
- [x] 4.2 Add/update `README.mdj` to mirror latest architecture contract for your requested documentation path.
- [x] 4.3 Update migration runbook notes to include documentation-alignment gate.

20
openspec/config.yaml Normal file
View File

@@ -0,0 +1,20 @@
schema: spec-driven
# Project context (optional)
# This is shown to AI when creating artifacts.
# Add your tech stack, conventions, style guides, domain knowledge, etc.
# Example:
# context: |
# Tech stack: TypeScript, React, Node.js
# We use conventional commits
# Domain: e-commerce platform
# Per-artifact rules (optional)
# Add custom rules for specific artifacts.
# Example:
# rules:
# proposal:
# - Keep proposals under 500 words
# - Always include a "Non-goals" section
# tasks:
# - Break tasks into chunks of max 2 hours

View File

@@ -0,0 +1,38 @@
## Purpose
Define stable requirements for cache-observability-hardening.
## Requirements
### Requirement: Layered Cache SHALL Expose Operational State
The route cache implementation SHALL expose layered cache operational state, including mode, freshness, and degradation status.
#### Scenario: Redis unavailable degradation state
- **WHEN** Redis is unavailable
- **THEN** health endpoints MUST indicate degraded cache mode while keeping L1 memory cache active
### Requirement: Cache Telemetry MUST be Queryable for Operations
The system MUST provide cache telemetry suitable for operations diagnostics.
#### Scenario: Telemetry inspection
- **WHEN** operators request deep health status
- **THEN** cache-related metrics/state SHALL be present and interpretable for troubleshooting
### Requirement: Health Endpoints SHALL Expose Pool Saturation and Degradation Reason Codes
Operational health endpoints MUST report connection pool saturation indicators and explicit degradation reason codes.
#### Scenario: Pool saturation observed
- **WHEN** checked-out connections and overflow approach configured limits
- **THEN** deep health output MUST expose saturation metrics and degraded reason classification
### Requirement: Degraded Responses MUST Be Correlatable Across API and Health Telemetry
Error responses for degraded states SHALL include stable codes that can be mapped to health telemetry and operational dashboards.
#### Scenario: Degraded API response correlation
- **WHEN** an API request fails due to circuit-open or pool-exhausted conditions
- **THEN** operators MUST be able to match the response code to current health telemetry state
### Requirement: Operational Alert Thresholds SHALL Be Explicitly Defined
The system MUST define alert thresholds for sustained degraded state, repeated worker recovery, and abnormal retry pressure.
#### Scenario: Sustained degradation threshold exceeded
- **WHEN** degraded status persists beyond configured duration
- **THEN** the monitoring contract MUST classify the service as alert-worthy with actionable context

View File

@@ -0,0 +1,26 @@
# conda-systemd-runtime-alignment Specification
## Purpose
TBD - created by archiving change stability-and-frontend-compute-shift. Update Purpose after archive.
## Requirements
### Requirement: Production Service Runtime SHALL Use Conda-Aligned Execution Paths
Service units and operational scripts MUST run with a consistent conda-managed Python runtime.
#### Scenario: Service unit starts application
- **WHEN** systemd starts the dashboard service and watchdog
- **THEN** both processes MUST execute using the configured conda environment binaries and paths
### Requirement: Watchdog and Runtime Paths MUST Be Operationally Consistent
PID files, restart flag paths, state files, and worker control interfaces SHALL be consistent across scripts, environment variables, and systemd units.
#### Scenario: Watchdog handles restart flag
- **WHEN** a restart flag is written by admin control endpoints
- **THEN** watchdog MUST read the same configured path set and signal the correct Gunicorn master process
### Requirement: Deployment Documentation MUST Match Runtime Contract
Runbooks and deployment documentation MUST describe the same conda/systemd/watchdog contract used by the deployed system.
#### Scenario: Operator follows deployment runbook
- **WHEN** an operator performs deploy, health check, and rollback from documentation
- **THEN** documented commands and paths MUST work without requiring venv-specific assumptions

View File

@@ -0,0 +1,42 @@
## Purpose
Define stable requirements for field-contract-governance.
## Requirements
### Requirement: Field Contract Registry SHALL Define UI/API/Export Mapping
The system SHALL maintain a field contract registry mapping UI labels, API keys, export headers, and semantic types.
#### Scenario: Contract lookup for page rendering
- **WHEN** a page renders table headers and values
- **THEN** it MUST resolve display labels and keys through the shared field contract definitions
#### Scenario: Contract lookup for export
- **WHEN** export headers are generated
- **THEN** header names MUST follow the same semantic mapping used by the page contract
### Requirement: Consistency Checks MUST Detect Contract Drift
The system MUST provide automated checks that detect mismatches between UI, API response keys, and export field definitions.
#### Scenario: Drift detection failure
- **WHEN** a page or export changes a field name without updating the contract
- **THEN** consistency checks MUST report a failing result before release
### Requirement: Dynamic Report Rendering MUST Sanitize Untrusted Values
Dynamic table/list rendering in report and query pages SHALL sanitize untrusted text before injecting HTML.
#### Scenario: HTML-like payload in query result
- **WHEN** an API result field contains HTML-like text payload
- **THEN** the rendered page MUST display escaped text and MUST NOT execute embedded script content
### Requirement: UI Table and Download Headers SHALL Follow the Same Field Contract
Page table headers and exported file headers SHALL map to the same field contract definition for the same dataset.
#### Scenario: Header consistency check
- **WHEN** users view a report table and then export the corresponding data
- **THEN** header labels MUST remain semantically aligned and avoid conflicting naming for identical fields
### Requirement: Hold Detail Dynamic Rendering MUST Sanitize Untrusted Values
Dynamic table and distribution rendering in hold-detail SHALL sanitize untrusted text before injecting into HTML attributes or content.
#### Scenario: Hold reason distribution contains HTML-like payload
- **WHEN** workcenter/package/lot fields include HTML-like text from upstream data
- **THEN** the hold-detail page MUST render escaped text and MUST NOT execute embedded markup or scripts

View File

@@ -0,0 +1,16 @@
## Purpose
Define stable requirements for field-name-consistency.
## Requirements
### Requirement: UI and Export Fields SHALL Have a Consistent Contract
The system SHALL define and apply a consistent contract among UI column labels, API keys, and export headers for report/query pages.
#### Scenario: Job query export naming consistency
- **WHEN** job query exports include cause/repair/symptom values
- **THEN** exported field names SHALL reflect semantic value type consistently (e.g., code name vs status name)
#### Scenario: Resource history field alignment
- **WHEN** resource history detail table shows KPI columns
- **THEN** columns required by export semantics (including Availability%) SHALL be present or explicitly mapped

View File

@@ -0,0 +1,52 @@
## Purpose
Define stable requirements for frontend-compute-shift.
## Requirements
### Requirement: Display-Layer Computation SHALL be Shifted to Frontend Safely
The system SHALL move eligible display-layer computations from backend to frontend while preserving existing business behavior.
#### Scenario: Equivalent metric output
- **WHEN** frontend-computed metrics are produced for a supported page
- **THEN** output values MUST match baseline backend results within defined rounding rules
### Requirement: Compute Shift MUST be Verifiable by Parity Fixtures
Each migrated computation MUST have parity fixtures comparing baseline and migrated outputs.
#### Scenario: Parity test gating
- **WHEN** a compute-shifted module is changed
- **THEN** parity checks MUST run and fail the migration gate if output differs beyond tolerance
### Requirement: Compute-Shifted Logic SHALL Be Exposed as Reusable Frontend Core Modules
Frontend-computed metrics and transformations MUST be implemented as reusable, testable modules instead of page-local inline logic.
#### Scenario: Multiple pages consume shared compute logic
- **WHEN** two or more pages require the same metric transformation or aggregation
- **THEN** they MUST import a shared frontend core module and produce consistent outputs
### Requirement: Frontend Compute Parity MUST Include Tolerance Contracts Per Metric
Parity verification SHALL define explicit tolerance and rounding contracts per migrated metric.
#### Scenario: Parity check for migrated metric
- **WHEN** migrated frontend computation is validated against baseline output
- **THEN** parity tests MUST evaluate the metric against its declared tolerance and fail when outside bounds
### Requirement: Compute Shift MUST Preserve Existing User-Facing Logic
Frontend compute migration MUST preserve existing filter semantics, drill-down behavior, and displayed totals.
#### Scenario: Existing dashboard interactions after compute shift
- **WHEN** users apply filters and navigate drill-down flows on migrated pages
- **THEN** interaction results MUST remain behaviorally equivalent to the pre-shift baseline
### Requirement: Frontend Compute Paths MUST Handle Zero and Boundary Values Correctly
Frontend-computed report metrics SHALL preserve valid zero values and boundary conditions in user-visible KPI and summary components.
#### Scenario: Zero-value KPI rendering
- **WHEN** OU% or availability metrics are computed as `0`
- **THEN** the page MUST render `0%` (or configured numeric format) instead of placeholder values
### Requirement: Hierarchical Filter Compute Logic SHALL Be Deterministic Across Levels
Frontend matrix/filter computations SHALL produce deterministic selection and filtering outcomes for group, family, and resource levels.
#### Scenario: Matrix selection at multiple hierarchy levels
- **WHEN** users toggle matrix cells across group, family, and resource rows
- **THEN** selected-state rendering and filtered equipment result sets MUST remain level-correct and reversible

View File

@@ -0,0 +1,81 @@
## Purpose
Define stable requirements for full-vite-page-modularization.
## Requirements
### Requirement: Major Pages SHALL be Managed by Vite Modules
The system SHALL provide Vite-managed module entries for major portal pages, replacing inline scripts in a phased manner.
#### Scenario: Portal module loading
- **WHEN** the portal page is rendered
- **THEN** it MUST load its behavior from a Vite-built module asset when available
#### Scenario: Page module fallback
- **WHEN** a required Vite asset is unavailable
- **THEN** the system MUST keep page behavior functional through explicit fallback logic
### Requirement: Build Pipeline SHALL Produce Backend-Served Assets
Vite build output MUST be emitted into backend static paths and served by Flask/Gunicorn on the same origin.
#### Scenario: Build artifact placement
- **WHEN** frontend build is executed
- **THEN** generated JS/CSS files SHALL be written to the configured backend static dist directory
### Requirement: Vite Page Modules SHALL Reuse Shared Chart and Query Building Blocks
Page entry modules MUST consume shared chart/query/drawer utilities for common behaviors.
#### Scenario: Common chart behavior across pages
- **WHEN** multiple report pages render equivalent chart interactions
- **THEN** the behavior MUST be provided by shared Vite modules rather than duplicated page-local implementations
### Requirement: Modularization MUST Preserve Established Navigation and Drill-Down Semantics
Refactoring into Vite modules SHALL not alter existing page transitions, independent tabs, and drill-down entry points.
#### Scenario: User follows existing drill-down path
- **WHEN** the user navigates from summary page to detail views
- **THEN** the resulting flow and parameter semantics MUST match the established baseline behavior
### Requirement: Module Boundaries SHALL Support Frontend Compute Expansion
Vite module structure MUST keep compute logic decoupled from DOM wiring so additional backend-to-frontend computation shifts can be added safely.
#### Scenario: Adding a new frontend-computed metric
- **WHEN** a new metric is migrated from backend to frontend
- **THEN** the metric logic MUST be integrated through shared compute modules without rewriting page routing structure
### Requirement: WIP Report Pages SHALL Be Served by Vite Modules
The system SHALL provide Vite entry bundles for WIP overview and WIP detail pages, with template-level asset resolution.
#### Scenario: WIP module asset available
- **WHEN** the built asset exists in backend static dist
- **THEN** the page MUST load behavior from the corresponding Vite module entry
#### Scenario: WIP module asset unavailable
- **WHEN** the built asset is not present
- **THEN** the page MUST retain equivalent behavior through explicit inline fallback logic
### Requirement: Vite Modules MUST Preserve Legacy Handler Compatibility
Vite report modules SHALL expose required global handlers for existing inline entry points until event wiring is fully migrated.
#### Scenario: Inline-triggered handler compatibility
- **WHEN** a template control invokes existing global handler names
- **THEN** the migrated module MUST provide compatible callable handlers without runtime scope errors
### Requirement: Hold Detail Page SHALL Be Served by a Vite Module
The system SHALL provide a dedicated Vite entry bundle for the hold-detail report page.
#### Scenario: Hold-detail module asset exists
- **WHEN** `/hold-detail` is rendered and `hold-detail.js` exists in static dist
- **THEN** the page MUST load behavior from the Vite module entry
#### Scenario: Hold-detail module asset missing
- **WHEN** `/hold-detail` is rendered and the module asset is unavailable
- **THEN** the page MUST remain operational through explicit inline fallback logic
### Requirement: WIP Modules SHALL Reuse Shared Autocomplete and Filter Query Utilities
WIP overview and WIP detail Vite entry modules SHALL use shared frontend core utilities for autocomplete request construction and cross-filter behavior.
#### Scenario: Cross-filter autocomplete parity across WIP pages
- **WHEN** users type in workorder/lot/package/type filters on either WIP overview or WIP detail pages
- **THEN** both pages MUST generate equivalent autocomplete request parameters and return behaviorally consistent dropdown results
#### Scenario: Shared utility change propagates across both pages
- **WHEN** autocomplete mapping rules are updated in the shared core module
- **THEN** both WIP overview and WIP detail modules MUST consume the updated behavior without duplicated page-local logic edits

View File

@@ -0,0 +1,42 @@
## Purpose
Define stable requirements for layered-route-cache.
## Requirements
### Requirement: Route Cache SHALL Use Layered Storage
The route cache SHALL use L1 in-memory TTL cache and L2 Redis JSON cache when Redis is available.
#### Scenario: L1 cache hit
- **WHEN** a cached key exists in L1 and is unexpired
- **THEN** the API response SHALL be returned from memory without querying Redis
#### Scenario: L2 fallback
- **WHEN** a cached key is missing in L1 but exists in Redis
- **THEN** the value SHALL be returned and warmed into L1
### Requirement: Cache SHALL Degrade Gracefully Without Redis
The route cache SHALL remain functional with L1 cache when Redis is unavailable.
#### Scenario: Redis unavailable at startup
- **WHEN** Redis health check fails during app initialization
- **THEN** route cache operations SHALL continue using L1 cache without application failure
### Requirement: Resource and WIP Full-Table Cache SHALL Remain the Authoritative Cached Dataset
The system MUST keep `resource` and `wip` full-table cache datasets as the canonical cached source for downstream route queries.
#### Scenario: Route query reads cached baseline
- **WHEN** an endpoint requires resource or wip data
- **THEN** it MUST read from the corresponding full-table cache baseline before applying derived filters or aggregations
### Requirement: Cache Access Paths SHALL Support Index-Based Lookup and Derived Views
The caching layer SHALL support index and derived-view access paths to reduce per-request full-table merge and transformation overhead.
#### Scenario: Lookup by key under concurrent load
- **WHEN** requests query by high-cardinality keys such as RESOURCEID
- **THEN** the system MUST serve lookups via indexed cache access instead of repeated full-array scans
### Requirement: Full-Table Cache Refresh MUST Support Incremental Derivation Updates
Derived cache indices and aggregates MUST be refreshed consistently when the underlying full-table cache version changes.
#### Scenario: Cache version update
- **WHEN** full-table cache is refreshed to a new version
- **THEN** dependent indices and derived views MUST be rebuilt or updated before being exposed for reads

View File

@@ -0,0 +1,48 @@
## Purpose
Define stable requirements for migration-gates-and-rollout.
## Requirements
### Requirement: Migration Gates SHALL Define Cutover Readiness
The system SHALL define explicit migration gates for functional parity, build integrity, and operational health before final cutover.
#### Scenario: Gate evaluation before cutover
- **WHEN** release is prepared for final cutover
- **THEN** all required migration gates MUST pass or cutover SHALL be blocked
### Requirement: Rollout and Rollback Procedures MUST be Actionable
The system SHALL document actionable rollout and rollback procedures for root migration.
#### Scenario: Rollback execution
- **WHEN** post-cutover validation fails critical checks
- **THEN** operators MUST be able to execute documented rollback steps to restore previous stable behavior
### Requirement: Migration Gates SHALL Include Runtime Resilience Validation
Cutover readiness gates MUST include resilience checks for pool exhaustion handling, circuit-breaker fail-fast behavior, and recovery flow.
#### Scenario: Resilience gate evaluation
- **WHEN** migration gates are executed before release
- **THEN** resilience tests MUST pass for degraded-response semantics and recovery path validation
### Requirement: Migration Gates SHALL Include Frontend Compute Parity Validation
Cutover readiness MUST include parity validation for metrics shifted from backend to frontend computation.
#### Scenario: Compute parity gate
- **WHEN** a release includes additional frontend-computed metrics
- **THEN** gate execution MUST verify parity fixtures and fail if tolerance contracts are violated
### Requirement: Rollout Procedure MUST Include Conda-Systemd-Watchdog Rehearsal
Rollout and rollback runbooks SHALL include an operational rehearsal for service start, watchdog-triggered reload, and post-restart health checks under the conda/systemd runtime contract.
#### Scenario: Pre-cutover rehearsal
- **WHEN** operators execute pre-cutover rehearsal
- **THEN** they MUST successfully complete conda-based start, worker reload, and health verification steps documented in the runbook
### Requirement: Migration Gates SHALL Enforce Architecture Documentation Consistency
Cutover governance MUST include verification that runtime architecture contracts documented for operators match implemented deployment and resilience behavior.
#### Scenario: Documentation gate before release
- **WHEN** release gates are executed for a migration or hardening change
- **THEN** project README artifacts MUST be updated to reflect current single-port runtime contract, resilience diagnostics, and frontend modularization strategy
#### Scenario: Gate fails on stale architecture contract
- **WHEN** implementation introduces resilience or module-governance changes but README architecture section remains outdated
- **THEN** release governance MUST treat the gate as failed until documentation is aligned

View File

@@ -0,0 +1,19 @@
## Purpose
Define stable requirements for portal-drawer-navigation.
## Requirements
### Requirement: Portal Navigation SHALL Group Entries by Functional Drawers
The portal SHALL group navigation entries into functional drawers: reports, queries, and development tools.
#### Scenario: Drawer grouping visibility
- **WHEN** users open the portal
- **THEN** report pages and query pages SHALL appear in separate drawer groups
### Requirement: Existing Page Behavior SHALL Remain Compatible
The portal navigation refactor SHALL preserve existing target routes and lazy-load behavior for content frames.
#### Scenario: Route continuity
- **WHEN** a user selects an existing page entry from the new drawer
- **THEN** the corresponding original route SHALL be loaded without changing page business logic behavior

View File

@@ -0,0 +1,30 @@
# report-effects-parity Specification
## Purpose
TBD - created by archiving change vite-jinja-report-parity-hardening. Update Purpose after archive.
## Requirements
### Requirement: Report Effect Parity SHALL Be Preserved During Vite Migration
The system SHALL preserve existing Jinja-era report interactions when report pages are served by Vite modules.
#### Scenario: WIP overview interactions remain equivalent
- **WHEN** users operate WIP overview filters, KPI cards, chart refresh, and drill-down entry
- **THEN** the resulting state transitions and navigation parameters MUST remain behaviorally equivalent to the baseline page logic
#### Scenario: WIP detail interactions remain equivalent
- **WHEN** users operate WIP detail filters, pagination, lot detail popup, and back-to-overview transitions
- **THEN** the resulting data scope and interaction behavior MUST match baseline semantics
### Requirement: Report Visual Semantics MUST Remain Consistent
Report pages SHALL keep established status color semantics, KPI display rules, and table/chart synchronization behavior after migration.
#### Scenario: KPI and matrix state consistency
- **WHEN** metric values are zero or filters target specific matrix levels
- **THEN** KPI values and selected-state highlights MUST render correctly without collapsing valid zero values or losing selection state
### Requirement: Hold Detail Interaction Semantics SHALL Remain Equivalent After Modularization
Migrating hold-detail to a Vite module SHALL preserve existing filter, pagination, and refresh behavior.
#### Scenario: User applies filters and paginates on hold-detail
- **WHEN** users toggle age/workcenter/package filters and navigate pages
- **THEN** returned lots, distribution highlights, and pagination state MUST remain behaviorally equivalent to baseline inline behavior

View File

@@ -0,0 +1,23 @@
## Purpose
Define stable requirements for root-cutover-finalization.
## Requirements
### Requirement: Root Project SHALL be the Single Execution Target
The system SHALL run all application startup, test, and deployment workflows from `DashBoard_vite` root without requiring nested `DashBoard/` paths.
#### Scenario: Root startup script execution
- **WHEN** an operator runs start/deploy scripts from `DashBoard_vite` root
- **THEN** all referenced source/config/script paths MUST resolve inside root project structure
#### Scenario: Root test execution
- **WHEN** CI or local developer runs test commands from root
- **THEN** tests SHALL execute against root source tree and root config files
### Requirement: Reference Directory MUST Remain Non-Authoritative
`DashBoard/` SHALL be treated as reference-only and MUST NOT be required for production runtime.
#### Scenario: Runtime independence
- **WHEN** root application is started in an environment without `DashBoard/`
- **THEN** the application MUST remain functional for the defined migration scope

View File

@@ -0,0 +1,16 @@
## Purpose
Define stable requirements for root-project-restructure.
## Requirements
### Requirement: Root Directory SHALL be the Primary Executable Project
The system SHALL treat `DashBoard_vite` root directory as the primary executable project, while `DashBoard/` remains reference-only during migration.
#### Scenario: Running app from root
- **WHEN** a developer runs project scripts from `DashBoard_vite` root
- **THEN** the application startup flow SHALL resolve code and config from root project files
#### Scenario: Reference directory preserved
- **WHEN** migration is in progress
- **THEN** `DashBoard/` SHALL remain available for structure comparison and behavior verification

View File

@@ -0,0 +1,50 @@
# runtime-resilience-recovery Specification
## Purpose
TBD - created by archiving change stability-and-frontend-compute-shift. Update Purpose after archive.
## Requirements
### Requirement: Database Pool Runtime Configuration SHALL Be Enforced
The system SHALL apply database pool and timeout parameters from runtime configuration to the active SQLAlchemy engine used by request handling.
#### Scenario: Runtime pool configuration takes effect
- **WHEN** operators set pool and timeout values via environment configuration and start the service
- **THEN** the active engine MUST use those values for pool size, overflow, wait timeout, and query call timeout
### Requirement: Pool Exhaustion MUST Return Retry-Aware Degraded Responses
The system MUST return explicit degraded responses for connection pool exhaustion and include machine-readable metadata for retry/backoff behavior.
#### Scenario: Pool exhausted under load
- **WHEN** concurrent requests exceed available database connections and pool wait timeout is reached
- **THEN** the API MUST return a dedicated error code and retry guidance instead of a generic 500 failure
### Requirement: Runtime Degradation MUST Integrate Circuit Breaker State
Database-facing API behavior SHALL distinguish circuit-breaker-open degradation from transient query failures.
#### Scenario: Circuit breaker is open
- **WHEN** the circuit breaker transitions to OPEN state
- **THEN** database-backed endpoints MUST fail fast with a stable degradation response contract
### Requirement: Worker Recovery SHALL Support Hot Reload and Watchdog-Assisted Recovery
The runtime MUST support graceful worker hot reload and watchdog-triggered recovery without requiring a port change or full system reboot.
#### Scenario: Worker restart requested
- **WHEN** an authorized operator requests worker restart during degraded operation
- **THEN** the service MUST trigger graceful reload and preserve single-port availability
### Requirement: Report Frontend API Access SHALL Honor Degraded Retry Contracts
Report pages SHALL use retry-aware API access paths for JSON endpoints so degraded backend responses propagate retry metadata to UI behavior.
#### Scenario: Pool exhaustion or circuit-open response
- **WHEN** report API endpoints return degraded error codes with retry hints
- **THEN** frontend calls MUST flow through MesApi-compatible behavior and avoid aggressive uncontrolled retry loops
### Requirement: Runtime Resilience Diagnostics MUST Expose Actionable Signals
The system MUST expose machine-readable resilience thresholds, restart-churn indicators, and operator action recommendations so degraded states can be triaged consistently.
#### Scenario: Health payload includes resilience diagnostics
- **WHEN** clients call `/health` or `/health/deep`
- **THEN** responses MUST include resilience thresholds and a recommendation field describing whether to observe, throttle, or trigger controlled worker recovery
#### Scenario: Admin status includes restart churn summary
- **WHEN** operators call `/admin/api/system-status` or `/admin/api/worker/status`
- **THEN** responses MUST include bounded restart history summary within a configured time window and indicate whether churn threshold is exceeded

View File

@@ -0,0 +1,19 @@
## Purpose
Define stable requirements for vite-single-port-integration.
## Requirements
### Requirement: Frontend Build SHALL Use Vite With Flask Static Output
The system SHALL use Vite to build frontend assets and output artifacts into Flask static directories served by the backend.
#### Scenario: Build asset generation
- **WHEN** frontend build is executed
- **THEN** Vite SHALL generate portal-related JS/CSS artifacts into the backend static output path
### Requirement: Deployment SHALL Preserve Single External Port
The system SHALL preserve single-port external serving through Flask/Gunicorn.
#### Scenario: Production serving mode
- **WHEN** the system runs in deployment mode
- **THEN** frontend assets SHALL be served through Flask on the same external port as API/page routes