chore: reinitialize project with vite architecture
This commit is contained in:
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-02-07
|
||||
@@ -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,先抽共用 core(API、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 前補齊端對端自動化下載欄位比對?
|
||||
@@ -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 指標與告警解讀。
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-02-07
|
||||
@@ -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 JSON;Redis 不可用時仍有 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`)是否有業務優先級?
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-02-07
|
||||
@@ -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,以降低雙路徑維運成本。
|
||||
@@ -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 行為不變。
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-02-07
|
||||
@@ -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 + watchdog(P2)
|
||||
- 決策:部署與監控路徑統一到 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 位),或按指標分類?
|
||||
@@ -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,驗證降級、恢復、快取一致性與前後端計算一致性。
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-02-07
|
||||
@@ -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 互動,而不只依賴後端模板整合測試。
|
||||
@@ -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 輸出資產。
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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.
|
||||
@@ -0,0 +1,2 @@
|
||||
schema: spec-driven
|
||||
created: 2026-02-07
|
||||
@@ -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 diagnostics(thresholds/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 與告警 webhook(Slack/Teams)直接整合?
|
||||
- 是否要把 restart churn 門檻與 UI 告警顏色標準化到 admin/performance 頁?
|
||||
@@ -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 與既有手動重啟流程;新增觀測與建議,不預設啟用自動重啟風暴風險。
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
|
||||
@@ -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
20
openspec/config.yaml
Normal 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
|
||||
38
openspec/specs/cache-observability-hardening/spec.md
Normal file
38
openspec/specs/cache-observability-hardening/spec.md
Normal 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
|
||||
|
||||
26
openspec/specs/conda-systemd-runtime-alignment/spec.md
Normal file
26
openspec/specs/conda-systemd-runtime-alignment/spec.md
Normal 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
|
||||
|
||||
42
openspec/specs/field-contract-governance/spec.md
Normal file
42
openspec/specs/field-contract-governance/spec.md
Normal 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
|
||||
|
||||
16
openspec/specs/field-name-consistency/spec.md
Normal file
16
openspec/specs/field-name-consistency/spec.md
Normal 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
|
||||
52
openspec/specs/frontend-compute-shift/spec.md
Normal file
52
openspec/specs/frontend-compute-shift/spec.md
Normal 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
|
||||
|
||||
81
openspec/specs/full-vite-page-modularization/spec.md
Normal file
81
openspec/specs/full-vite-page-modularization/spec.md
Normal 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
|
||||
42
openspec/specs/layered-route-cache/spec.md
Normal file
42
openspec/specs/layered-route-cache/spec.md
Normal 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
|
||||
|
||||
48
openspec/specs/migration-gates-and-rollout/spec.md
Normal file
48
openspec/specs/migration-gates-and-rollout/spec.md
Normal 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
|
||||
19
openspec/specs/portal-drawer-navigation/spec.md
Normal file
19
openspec/specs/portal-drawer-navigation/spec.md
Normal 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
|
||||
30
openspec/specs/report-effects-parity/spec.md
Normal file
30
openspec/specs/report-effects-parity/spec.md
Normal 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
|
||||
|
||||
23
openspec/specs/root-cutover-finalization/spec.md
Normal file
23
openspec/specs/root-cutover-finalization/spec.md
Normal 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
|
||||
16
openspec/specs/root-project-restructure/spec.md
Normal file
16
openspec/specs/root-project-restructure/spec.md
Normal 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
|
||||
50
openspec/specs/runtime-resilience-recovery/spec.md
Normal file
50
openspec/specs/runtime-resilience-recovery/spec.md
Normal 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
|
||||
19
openspec/specs/vite-single-port-integration/spec.md
Normal file
19
openspec/specs/vite-single-port-integration/spec.md
Normal 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
|
||||
Reference in New Issue
Block a user