From 7cb0985b1228dcb69f33c865827658605a843cac Mon Sep 17 00:00:00 2001 From: egg Date: Thu, 12 Feb 2026 11:26:02 +0800 Subject: [PATCH] feat(modernization): full architecture blueprint with hardening follow-up Implement phased modernization infrastructure for transitioning from multi-page legacy routing to SPA portal-shell architecture, plus post-delivery hardening fixes for policy loading, fallback consistency, and governance drift detection. Key changes: - Add route contract enrichment with scope/visibility/compatibility policies - Canonical 302 redirects from legacy direct-entry to /portal-shell/ routes - Asset readiness enforcement and runtime fallback retirement for in-scope routes - Shared feature-flag helpers (env > config > default) replacing duplicated _to_bool - Defensive copy for lru_cached policy payloads preventing mutation corruption - Unified retired-fallback response helper across app and blueprint routes - Frontend/backend route-contract cross-validation in governance gates - Shell CSS token fallback values for routes rendered outside shell scope - Local-safe .env.example defaults with production recommendation comments - Legacy contract fallback warning logging and single-hop redirect optimization Co-Authored-By: Claude Opus 4.6 --- .env.example | 35 +- .../workflows/full-modernization-gates.yml | 57 +++ README.md | 10 + data/modernization_feature_flags.json | 21 + data/page_status.json | 2 +- .../README.md | 27 + .../asset_readiness_manifest.json | 22 + .../bug_revalidation_records.json | 12 + .../canonical_routing_policy.json | 24 + .../deferred_route_handoff.md | 40 ++ .../exception_registry.json | 42 ++ .../governance_milestones.md | 30 ++ .../interaction_parity_checks.json | 17 + .../known_bug_baseline.json | 58 +++ .../manual_acceptance_records.json | 5 + .../observability_checkpoints.md | 32 ++ ...age_content_manual_acceptance_checklist.md | 28 ++ .../parity_golden_fixtures.json | 17 + .../performance_budgets.json | 13 + .../quality_gate_policy.json | 21 + .../quality_gate_report.json | 7 + .../rollback_controls.md | 26 + .../rollout_runbook.md | 33 ++ .../route_content_contracts.json | 77 +++ .../route_contracts.json | 166 +++++++ .../route_scope_matrix.json | 113 +++++ .../style_inventory.json | 30 ++ .../baseline_drawer_visibility.json | 19 +- .../baseline_drawer_visibility.json | 20 +- .../hold-overview/components/FilterBar.vue | 65 ++- frontend/src/hold-overview/style.css | 70 ++- frontend/src/job-query/style.css | 8 +- frontend/src/portal-shell/navigationState.js | 10 +- frontend/src/portal-shell/routeContracts.js | 281 +++++++++-- frontend/src/portal-shell/router.js | 4 + .../portal-shell/views/NativeRouteView.vue | 14 +- frontend/src/qc-gate/style.css | 24 +- frontend/src/tmtt-defect/style.css | 10 +- .../tests/portal-shell-app-contract.test.js | 8 +- .../tests/portal-shell-health-summary.test.js | 8 +- .../tests/portal-shell-navigation.test.js | 23 + frontend/tests/portal-shell-no-iframe.test.js | 8 +- ...al-shell-parity-table-chart-matrix.test.js | 8 +- ...al-shell-route-contract-governance.test.js | 83 ++++ frontend/tests/portal-shell-sidebar.test.js | 8 +- ...ortal-shell-wave-a-chart-lifecycle.test.js | 8 +- .../.openspec.yaml | 2 + .../design.md | 146 ++++++ .../proposal.md | 46 ++ .../spec.md | 25 + .../spec.md | 26 + .../spec.md | 25 + .../full-vite-page-modularization/spec.md | 24 + .../page-content-modernization-safety/spec.md | 54 ++ .../specs/spa-shell-navigation/spec.md | 28 ++ .../spec.md | 25 + .../specs/tailwind-design-system/spec.md | 24 + .../unified-shell-route-coverage/spec.md | 29 ++ .../specs/vue-vite-page-architecture/spec.md | 20 + .../tasks.md | 78 +++ .../.openspec.yaml | 2 + .../design.md | 108 ++++ .../proposal.md | 34 ++ .../spec.md | 12 + .../spec.md | 19 + .../spec.md | 19 + .../specs/spa-shell-navigation/spec.md | 20 + .../spec.md | 12 + .../unified-shell-route-coverage/spec.md | 19 + .../tasks.md | 50 ++ .../.openspec.yaml | 2 + .../design.md | 60 +++ .../proposal.md | 33 ++ .../spec.md | 18 + .../page-content-modernization-safety/spec.md | 26 + .../unified-shell-route-coverage/spec.md | 14 + .../tasks.md | 38 ++ .../spec.md | 40 ++ .../spec.md | 48 ++ .../spec.md | 29 ++ .../full-vite-page-modularization/spec.md | 28 +- .../spec.md | 18 + .../page-content-modernization-safety/spec.md | 58 +++ openspec/specs/spa-shell-navigation/spec.md | 70 +-- .../spec.md | 40 ++ openspec/specs/tailwind-design-system/spec.md | 32 +- .../unified-shell-route-coverage/spec.md | 51 ++ .../specs/vue-vite-page-architecture/spec.md | 274 ++++++----- scripts/check_full_modernization_gates.py | 460 ++++++++++++++++++ scripts/start_server.sh | 116 +++-- src/mes_dashboard/app.py | 193 ++++++-- src/mes_dashboard/core/feature_flags.py | 49 ++ .../core/modernization_policy.py | 167 +++++++ src/mes_dashboard/core/runtime_contract.py | 15 +- .../routes/hold_history_routes.py | 12 +- .../routes/hold_overview_routes.py | 12 +- src/mes_dashboard/routes/hold_routes.py | 25 +- src/mes_dashboard/routes/job_query_routes.py | 20 +- tests/conftest.py | 17 +- tests/e2e/test_wip_hold_pages_e2e.py | 11 +- tests/test_asset_readiness_policy.py | 72 +++ tests/test_feature_flags.py | 25 + tests/test_full_modernization_gates.py | 97 ++++ tests/test_hold_history_routes.py | 17 +- tests/test_hold_overview_routes.py | 17 +- tests/test_hold_routes.py | 55 ++- tests/test_job_query_routes.py | 16 +- tests/test_modernization_policy_hardening.py | 45 ++ tests/test_portal_shell_routes.py | 173 ++++++- tests/test_qc_gate_routes.py | 17 +- tests/test_template_integration.py | 97 +++- tests/test_wip_hold_pages_integration.py | 24 +- tests/test_wip_routes.py | 37 +- 113 files changed, 4577 insertions(+), 582 deletions(-) create mode 100644 .github/workflows/full-modernization-gates.yml create mode 100644 data/modernization_feature_flags.json create mode 100644 docs/migration/full-modernization-architecture-blueprint/README.md create mode 100644 docs/migration/full-modernization-architecture-blueprint/asset_readiness_manifest.json create mode 100644 docs/migration/full-modernization-architecture-blueprint/bug_revalidation_records.json create mode 100644 docs/migration/full-modernization-architecture-blueprint/canonical_routing_policy.json create mode 100644 docs/migration/full-modernization-architecture-blueprint/deferred_route_handoff.md create mode 100644 docs/migration/full-modernization-architecture-blueprint/exception_registry.json create mode 100644 docs/migration/full-modernization-architecture-blueprint/governance_milestones.md create mode 100644 docs/migration/full-modernization-architecture-blueprint/interaction_parity_checks.json create mode 100644 docs/migration/full-modernization-architecture-blueprint/known_bug_baseline.json create mode 100644 docs/migration/full-modernization-architecture-blueprint/manual_acceptance_records.json create mode 100644 docs/migration/full-modernization-architecture-blueprint/observability_checkpoints.md create mode 100644 docs/migration/full-modernization-architecture-blueprint/page_content_manual_acceptance_checklist.md create mode 100644 docs/migration/full-modernization-architecture-blueprint/parity_golden_fixtures.json create mode 100644 docs/migration/full-modernization-architecture-blueprint/performance_budgets.json create mode 100644 docs/migration/full-modernization-architecture-blueprint/quality_gate_policy.json create mode 100644 docs/migration/full-modernization-architecture-blueprint/quality_gate_report.json create mode 100644 docs/migration/full-modernization-architecture-blueprint/rollback_controls.md create mode 100644 docs/migration/full-modernization-architecture-blueprint/rollout_runbook.md create mode 100644 docs/migration/full-modernization-architecture-blueprint/route_content_contracts.json create mode 100644 docs/migration/full-modernization-architecture-blueprint/route_contracts.json create mode 100644 docs/migration/full-modernization-architecture-blueprint/route_scope_matrix.json create mode 100644 docs/migration/full-modernization-architecture-blueprint/style_inventory.json create mode 100644 frontend/tests/portal-shell-route-contract-governance.test.js create mode 100644 openspec/changes/archive/2026-02-12-full-modernization-architecture-blueprint/.openspec.yaml create mode 100644 openspec/changes/archive/2026-02-12-full-modernization-architecture-blueprint/design.md create mode 100644 openspec/changes/archive/2026-02-12-full-modernization-architecture-blueprint/proposal.md create mode 100644 openspec/changes/archive/2026-02-12-full-modernization-architecture-blueprint/specs/asset-readiness-and-fallback-retirement/spec.md create mode 100644 openspec/changes/archive/2026-02-12-full-modernization-architecture-blueprint/specs/frontend-platform-modernization-governance/spec.md create mode 100644 openspec/changes/archive/2026-02-12-full-modernization-architecture-blueprint/specs/frontend-quality-gate-modernization/spec.md create mode 100644 openspec/changes/archive/2026-02-12-full-modernization-architecture-blueprint/specs/full-vite-page-modularization/spec.md create mode 100644 openspec/changes/archive/2026-02-12-full-modernization-architecture-blueprint/specs/page-content-modernization-safety/spec.md create mode 100644 openspec/changes/archive/2026-02-12-full-modernization-architecture-blueprint/specs/spa-shell-navigation/spec.md create mode 100644 openspec/changes/archive/2026-02-12-full-modernization-architecture-blueprint/specs/style-isolation-and-token-enforcement/spec.md create mode 100644 openspec/changes/archive/2026-02-12-full-modernization-architecture-blueprint/specs/tailwind-design-system/spec.md create mode 100644 openspec/changes/archive/2026-02-12-full-modernization-architecture-blueprint/specs/unified-shell-route-coverage/spec.md create mode 100644 openspec/changes/archive/2026-02-12-full-modernization-architecture-blueprint/specs/vue-vite-page-architecture/spec.md create mode 100644 openspec/changes/archive/2026-02-12-full-modernization-architecture-blueprint/tasks.md create mode 100644 openspec/changes/archive/2026-02-12-modernization-hardening-follow-up/.openspec.yaml create mode 100644 openspec/changes/archive/2026-02-12-modernization-hardening-follow-up/design.md create mode 100644 openspec/changes/archive/2026-02-12-modernization-hardening-follow-up/proposal.md create mode 100644 openspec/changes/archive/2026-02-12-modernization-hardening-follow-up/specs/asset-readiness-and-fallback-retirement/spec.md create mode 100644 openspec/changes/archive/2026-02-12-modernization-hardening-follow-up/specs/frontend-platform-modernization-governance/spec.md create mode 100644 openspec/changes/archive/2026-02-12-modernization-hardening-follow-up/specs/maintainability-type-and-constant-hygiene/spec.md create mode 100644 openspec/changes/archive/2026-02-12-modernization-hardening-follow-up/specs/spa-shell-navigation/spec.md create mode 100644 openspec/changes/archive/2026-02-12-modernization-hardening-follow-up/specs/style-isolation-and-token-enforcement/spec.md create mode 100644 openspec/changes/archive/2026-02-12-modernization-hardening-follow-up/specs/unified-shell-route-coverage/spec.md create mode 100644 openspec/changes/archive/2026-02-12-modernization-hardening-follow-up/tasks.md create mode 100644 openspec/changes/deferred-route-modernization-follow-up/.openspec.yaml create mode 100644 openspec/changes/deferred-route-modernization-follow-up/design.md create mode 100644 openspec/changes/deferred-route-modernization-follow-up/proposal.md create mode 100644 openspec/changes/deferred-route-modernization-follow-up/specs/asset-readiness-and-fallback-retirement/spec.md create mode 100644 openspec/changes/deferred-route-modernization-follow-up/specs/page-content-modernization-safety/spec.md create mode 100644 openspec/changes/deferred-route-modernization-follow-up/specs/unified-shell-route-coverage/spec.md create mode 100644 openspec/changes/deferred-route-modernization-follow-up/tasks.md create mode 100644 openspec/specs/asset-readiness-and-fallback-retirement/spec.md create mode 100644 openspec/specs/frontend-platform-modernization-governance/spec.md create mode 100644 openspec/specs/frontend-quality-gate-modernization/spec.md create mode 100644 openspec/specs/page-content-modernization-safety/spec.md create mode 100644 openspec/specs/style-isolation-and-token-enforcement/spec.md create mode 100644 openspec/specs/unified-shell-route-coverage/spec.md create mode 100755 scripts/check_full_modernization_gates.py create mode 100644 src/mes_dashboard/core/feature_flags.py create mode 100644 src/mes_dashboard/core/modernization_policy.py create mode 100644 tests/test_asset_readiness_policy.py create mode 100644 tests/test_feature_flags.py create mode 100644 tests/test_full_modernization_gates.py create mode 100644 tests/test_modernization_policy_hardening.py diff --git a/.env.example b/.env.example index 92a6a7c..e4a75bc 100644 --- a/.env.example +++ b/.env.example @@ -181,9 +181,41 @@ WORKER_RESTART_COOLDOWN=60 # Watchdog loop check interval in seconds WATCHDOG_CHECK_INTERVAL=5 +# ============================================================ +# Portal Shell / Full Modernization Flags +# ============================================================ +# Frontend build mode: auto | always | never +# - auto: build only when dist is missing/stale +# - always: force build on every start/restart +# - never: skip build entirely +FRONTEND_BUILD_MODE=always + +# Fail startup when frontend build fails (recommended in production) +FRONTEND_BUILD_FAIL_ON_ERROR=true + +# Shell-first SPA navigation +# Local default: false (avoid coupling first boot to shell-first cutover behavior) +# Production recommendation: set true after shell cutover verification is complete +PORTAL_SPA_ENABLED=false + +# Fail-fast readiness gate for in-scope dist assets +# Local default: false (allow startup when dist artifacts are intentionally absent) +# Production recommendation: set true to enforce release readiness at boot +MODERNIZATION_ENFORCE_ASSET_READINESS=false + +# Retire in-scope runtime fallback behavior +# Local default: false (retain compatibility fallback while developing) +# Production recommendation: set true only after all in-scope dist assets are verified +MODERNIZATION_RETIRE_IN_SCOPE_RUNTIME_FALLBACK=false + # Runtime contract strict validation toggle +# Local default: false (avoid strict conda/runtime checks on onboarding machines) +# Production recommendation: set true to fail fast on contract drift RUNTIME_CONTRACT_ENFORCE=false +# Health endpoint memo cache TTL in seconds +HEALTH_MEMO_TTL_SECONDS=5 + # ============================================================ # Runtime Resilience Diagnostics Thresholds # ============================================================ @@ -205,6 +237,3 @@ RESILIENCE_RESTART_CHURN_THRESHOLD=3 # Example: https://example.com,https://app.example.com # Set to * for development (not recommended for production) CORS_ALLOWED_ORIGINS= - -# Health endpoint memo cache TTL in seconds -HEALTH_MEMO_TTL_SECONDS=5 diff --git a/.github/workflows/full-modernization-gates.yml b/.github/workflows/full-modernization-gates.yml new file mode 100644 index 0000000..114faf9 --- /dev/null +++ b/.github/workflows/full-modernization-gates.yml @@ -0,0 +1,57 @@ +name: full-modernization-gates + +on: + pull_request: + paths: + - "frontend/src/portal-shell/**" + - "frontend/src/qc-gate/**" + - "frontend/tests/portal-shell-*.test.js" + - "src/mes_dashboard/**" + - "tests/test_portal_shell_routes.py" + - "tests/test_full_modernization_gates.py" + - "tests/test_asset_readiness_policy.py" + - "scripts/check_full_modernization_gates.py" + - "docs/migration/full-modernization-architecture-blueprint/**" + - "openspec/changes/full-modernization-architecture-blueprint/**" + - ".github/workflows/full-modernization-gates.yml" + push: + branches: [ main ] + paths: + - "frontend/src/portal-shell/**" + - "frontend/src/qc-gate/**" + - "frontend/tests/portal-shell-*.test.js" + - "src/mes_dashboard/**" + - "tests/test_portal_shell_routes.py" + - "tests/test_full_modernization_gates.py" + - "tests/test_asset_readiness_policy.py" + - "scripts/check_full_modernization_gates.py" + - "docs/migration/full-modernization-architecture-blueprint/**" + - "openspec/changes/full-modernization-architecture-blueprint/**" + - ".github/workflows/full-modernization-gates.yml" + +jobs: + frontend-route-governance: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-node@v4 + with: + node-version: "20" + - name: Run shell governance tests + run: node --test frontend/tests/portal-shell-navigation.test.js frontend/tests/portal-shell-route-contract-governance.test.js + + backend-modernization-gates: + runs-on: ubuntu-latest + steps: + - uses: actions/checkout@v4 + - uses: actions/setup-python@v5 + with: + python-version: "3.13" + - name: Install test dependencies + run: | + python -m pip install --upgrade pip + python -m pip install -e . pytest + - name: Run modernization governance gate script + run: python scripts/check_full_modernization_gates.py --mode block + - name: Run backend canonical/fallback gate tests + run: python -m pytest tests/test_portal_shell_routes.py tests/test_full_modernization_gates.py tests/test_asset_readiness_policy.py -q diff --git a/README.md b/README.md index 6828f5d..5a03745 100644 --- a/README.md +++ b/README.md @@ -5,6 +5,7 @@ > 專案主執行根目錄:`DashBoard_vite/` > 目前已移除舊版 `DashBoard/` 代碼,僅保留新架構。 > 2026-02-11:`portal-shell-route-view-integration` 已完成並封存,Portal Shell 全面採用 no-iframe 的 SPA route-view 架構。 +> 2026-02-12:`full-modernization-architecture-blueprint` 已完成並封存(Phase 1),目前僅剩 `deferred-route-modernization-follow-up` 進行中(`/tables`、`/excel-query`、`/query-tool`、`/mid-section-defect`)。 --- @@ -46,6 +47,8 @@ | QC-GATE 即時狀態報表(Vue 3 + Vite) | ✅ 已完成 | | 數據表查詢頁面 Vue 3 遷移 | ✅ 已完成 | | WIP 三頁 Vue 3 遷移(Overview/Detail/Hold Detail) | ✅ 已完成 | +| 全站現代化治理 Phase 1(路由治理/品質門檻/資產就緒/手動驗收) | ✅ 已完成(已封存) | +| Deferred routes 現代化(`/tables`、`/excel-query`、`/query-tool`、`/mid-section-defect`) | ⏳ 進行中(follow-up 提案) | | WIP Overview/Detail 篩選條件保留 | ✅ 已完成 | | 設備雙頁 Vue 3 遷移(Status/History) | ✅ 已完成 | | 設備快取 DataFrame TTL 一致性修復 | ✅ 已完成 | @@ -55,6 +58,7 @@ ## 開發歷史(Vite 重構後) +- 2026-02-12:完成並封存 `full-modernization-architecture-blueprint`(Phase 1)— in-scope 報表路由全面採 canonical shell entry(`/portal-shell/...`)、補齊 admin 路由治理(`/admin/pages`、`/admin/performance`)、建立資產就緒 fail-fast 政策與前端品質門檻治理;並建立 deferred follow-up 提案承接 `/tables`、`/excel-query`、`/query-tool`、`/mid-section-defect`。 - 2026-02-11:完成 Portal Shell route-view 全遷移(`portal-shell-route-view-integration`)— 全站移除 iframe 內容嵌入、導入 Vue Router 動態註冊與 fallback guard、補齊 Wave A/Wave B page parity 測試、健康檢查 summary/detail UX 與 `/health/frontend-shell` 契約,並完成 pre/post parity 與 smoke 證據彙整。 - 2026-02-11:完成 table query API `table_name` 白名單驗證(`/api/query_table`、`/api/get_table_columns`)— 拒絕未註冊資料表,補上整合測試,避免 SQL injection 入口。 - 2026-02-11:完成設備雙頁級聯篩選(`/resource`、`/resource-history`)— 新增 Group/Family/Machine 多層篩選聯動,前後端支援 `resource_ids` 條件,矩陣與明細篩選一致。 @@ -116,6 +120,7 @@ - 頁面架構與抽屜分類:`docs/page_architecture_map.md` - 前端計算前移與 parity 規則:`docs/frontend_compute_shift_plan.md` - Portal Shell route-view 遷移基線與驗收:`docs/migration/portal-shell-route-view-integration/` +- 全站現代化架構 Phase 1 治理文件:`docs/migration/full-modernization-architecture-blueprint/` - Hold 歷史頁資料口徑說明:`docs/hold_history.md` - Cutover gates / rollout / rollback:`docs/migration_gates_and_runbook.md` - 環境依賴缺口與對策:`docs/environment_gaps_and_mitigation.md` @@ -163,6 +168,11 @@ - LDAP API URL 啟動驗證:僅允許 `https` + host allowlist。 - 全域 security headers:CSP/X-Frame-Options/X-Content-Type-Options/Referrer-Policy(production 含 HSTS)。 +8. 現階段仍保留部分相容路徑(非 bug,屬於分期策略) +- in-scope 報表路由已改為 canonical shell redirect(直接進入 `/portal-shell/...`)。 +- `portal-shell` 為目前主路由容器,尚不可移除。 +- deferred scope(`/tables`、`/excel-query`、`/query-tool`、`/mid-section-defect`)與其相容模板/入口會保留到 follow-up 提案完成。 + --- ## 快速開始 diff --git a/data/modernization_feature_flags.json b/data/modernization_feature_flags.json new file mode 100644 index 0000000..49f66a9 --- /dev/null +++ b/data/modernization_feature_flags.json @@ -0,0 +1,21 @@ +{ + "change": "full-modernization-architecture-blueprint", + "route_flags": { + "/wip-overview": {"content_cutover_enabled": true}, + "/wip-detail": {"content_cutover_enabled": true}, + "/hold-overview": {"content_cutover_enabled": true}, + "/hold-detail": {"content_cutover_enabled": true}, + "/hold-history": {"content_cutover_enabled": true}, + "/resource": {"content_cutover_enabled": true}, + "/resource-history": {"content_cutover_enabled": true}, + "/qc-gate": {"content_cutover_enabled": true}, + "/job-query": {"content_cutover_enabled": true}, + "/tmtt-defect": {"content_cutover_enabled": true}, + "/admin/pages": {"content_cutover_enabled": true}, + "/admin/performance": {"content_cutover_enabled": true}, + "/tables": {"content_cutover_enabled": false}, + "/excel-query": {"content_cutover_enabled": false}, + "/query-tool": {"content_cutover_enabled": false}, + "/mid-section-defect": {"content_cutover_enabled": false} + } +} diff --git a/data/page_status.json b/data/page_status.json index 8e74e46..f1c3021 100644 --- a/data/page_status.json +++ b/data/page_status.json @@ -88,7 +88,7 @@ { "route": "/tmtt-defect", "name": "TMTT印字腳型不良分析", - "status": "released", + "status": "dev", "drawer_id": "dev-tools", "order": 5 }, diff --git a/docs/migration/full-modernization-architecture-blueprint/README.md b/docs/migration/full-modernization-architecture-blueprint/README.md new file mode 100644 index 0000000..b7b5165 --- /dev/null +++ b/docs/migration/full-modernization-architecture-blueprint/README.md @@ -0,0 +1,27 @@ +# Full Modernization Architecture Blueprint Artifacts + +This directory stores execution artifacts for `full-modernization-architecture-blueprint`. + +## Core Governance + +- `route_scope_matrix.json`: frozen in-scope/deferred route contract matrix. +- `governance_milestones.md`: completion and deprecation milestones. +- `exception_registry.json`: approved temporary exceptions with owner and milestone. +- Policy artifact runtime cache model: + - `src/mes_dashboard/core/modernization_policy.py` caches `route_scope_matrix.json` and + `asset_readiness_manifest.json` in-process with `lru_cache`. + - Runtime behavior is restart-refresh by default: JSON edits take effect after worker restart. + - Controlled refresh is available through `clear_modernization_policy_cache()` for tests or + explicit maintenance hooks; no automatic file watcher/hot reload is active in production. + +## Content Modernization Safety + +- `page_content_manual_acceptance_checklist.md`: mandatory manual sign-off checklist. +- `known_bug_baseline.json`: route-level known bug baseline and replay blocking policy. + +## Rollout Operations + +- `rollout_runbook.md`: phase steps and hold points. +- `rollback_controls.md`: rollback and false-positive gate handling. +- `observability_checkpoints.md`: route/gate/rollback observability contract. +- `deferred_route_handoff.md`: explicit handoff package to deferred-route follow-up change. diff --git a/docs/migration/full-modernization-architecture-blueprint/asset_readiness_manifest.json b/docs/migration/full-modernization-architecture-blueprint/asset_readiness_manifest.json new file mode 100644 index 0000000..ec0e806 --- /dev/null +++ b/docs/migration/full-modernization-architecture-blueprint/asset_readiness_manifest.json @@ -0,0 +1,22 @@ +{ + "change": "full-modernization-architecture-blueprint", + "in_scope_required_assets": { + "/portal-shell": ["portal-shell.html", "portal-shell.js", "portal-shell.css", "tailwind.css"], + "/wip-overview": ["wip-overview.html", "wip-overview.js"], + "/wip-detail": ["wip-detail.html", "wip-detail.js"], + "/hold-overview": ["hold-overview.html", "hold-overview.js"], + "/hold-detail": ["hold-detail.html", "hold-detail.js"], + "/hold-history": ["hold-history.html", "hold-history.js"], + "/resource": ["resource-status.html", "resource-status.js"], + "/resource-history": ["resource-history.html", "resource-history.js"], + "/qc-gate": ["qc-gate.html", "qc-gate.js"], + "/job-query": ["job-query.js"], + "/tmtt-defect": ["tmtt-defect.js"] + }, + "deferred_routes": [ + "/tables", + "/excel-query", + "/query-tool", + "/mid-section-defect" + ] +} diff --git a/docs/migration/full-modernization-architecture-blueprint/bug_revalidation_records.json b/docs/migration/full-modernization-architecture-blueprint/bug_revalidation_records.json new file mode 100644 index 0000000..f5c45eb --- /dev/null +++ b/docs/migration/full-modernization-architecture-blueprint/bug_revalidation_records.json @@ -0,0 +1,12 @@ +{ + "change": "full-modernization-architecture-blueprint", + "records": [], + "schema": { + "route": "string", + "known_bug_id": "string", + "replay_date": "YYYY-MM-DD", + "result": "pass|fail", + "notes": "string", + "signoff_owner": "string" + } +} diff --git a/docs/migration/full-modernization-architecture-blueprint/canonical_routing_policy.json b/docs/migration/full-modernization-architecture-blueprint/canonical_routing_policy.json new file mode 100644 index 0000000..99a29d2 --- /dev/null +++ b/docs/migration/full-modernization-architecture-blueprint/canonical_routing_policy.json @@ -0,0 +1,24 @@ +{ + "change": "full-modernization-architecture-blueprint", + "canonical_policy": { + "applies_when": "PORTAL_SPA_ENABLED=true", + "report_routes": "redirect direct route entry to /portal-shell/", + "admin_routes": "shell target redirects to backend /admin/* while backend keeps auth authority" + }, + "direct_entry_compatibility": { + "query_semantics_must_be_preserved": true, + "redirect_status_code": 302 + }, + "in_scope_report_routes": [ + "/wip-overview", + "/wip-detail", + "/hold-overview", + "/hold-detail", + "/hold-history", + "/resource", + "/resource-history", + "/qc-gate", + "/job-query", + "/tmtt-defect" + ] +} diff --git a/docs/migration/full-modernization-architecture-blueprint/deferred_route_handoff.md b/docs/migration/full-modernization-architecture-blueprint/deferred_route_handoff.md new file mode 100644 index 0000000..a0cc6cd --- /dev/null +++ b/docs/migration/full-modernization-architecture-blueprint/deferred_route_handoff.md @@ -0,0 +1,40 @@ +# Deferred Route Handoff (Phase 1 -> Follow-up) + +## Source Change + +- `openspec/changes/full-modernization-architecture-blueprint/` + +## Deferred Routes (Not in Phase 1 Blocking Scope) + +- `/tables` +- `/excel-query` +- `/query-tool` +- `/mid-section-defect` + +## Follow-up Change + +- `openspec/changes/deferred-route-modernization-follow-up/` + +## Handoff Content + +1. Scope boundary contract: +- Source: `docs/migration/full-modernization-architecture-blueprint/route_scope_matrix.json` + +2. Required acceptance model to carry forward: +- Parity fixtures/checks: + - `docs/migration/full-modernization-architecture-blueprint/parity_golden_fixtures.json` + - `docs/migration/full-modernization-architecture-blueprint/interaction_parity_checks.json` +- Manual acceptance + bug replay: + - `docs/migration/full-modernization-architecture-blueprint/page_content_manual_acceptance_checklist.md` + - `docs/migration/full-modernization-architecture-blueprint/known_bug_baseline.json` + - `docs/migration/full-modernization-architecture-blueprint/bug_revalidation_records.json` + +3. Governance policy to carry forward: +- `docs/migration/full-modernization-architecture-blueprint/quality_gate_policy.json` +- `docs/migration/full-modernization-architecture-blueprint/governance_milestones.md` +- `docs/migration/full-modernization-architecture-blueprint/asset_readiness_manifest.json` + +## Transfer Rule + +- Deferred routes remain excluded from phase-1 blocking criteria. +- Follow-up change MUST promote these routes to in-scope and apply equivalent parity/manual-acceptance/bug-revalidation gates before legacy retirement. diff --git a/docs/migration/full-modernization-architecture-blueprint/exception_registry.json b/docs/migration/full-modernization-architecture-blueprint/exception_registry.json new file mode 100644 index 0000000..2b0fd71 --- /dev/null +++ b/docs/migration/full-modernization-architecture-blueprint/exception_registry.json @@ -0,0 +1,42 @@ +{ + "version": 1, + "change": "full-modernization-architecture-blueprint", + "fields": [ + "id", + "type", + "scope", + "owner", + "introduced_by", + "reason", + "mitigation", + "status", + "milestone", + "tracking_issue" + ], + "entries": [ + { + "id": "style-admin-pages-inline-css", + "type": "style", + "scope": "/admin/pages", + "owner": "frontend-platform-admin", + "introduced_by": "legacy-template", + "reason": "admin pages remain backend-rendered in this phase", + "mitigation": "enforce shell contract governance while retaining backend auth authority", + "status": "approved-temporary", + "milestone": "2026-03-19", + "tracking_issue": "deferred-route-modernization-follow-up/admin-template-modernization" + }, + { + "id": "style-admin-performance-inline-css", + "type": "style", + "scope": "/admin/performance", + "owner": "frontend-platform-admin", + "introduced_by": "legacy-template", + "reason": "admin performance remains backend-rendered in this phase", + "mitigation": "governed navigation + route-level fallback controls", + "status": "approved-temporary", + "milestone": "2026-03-19", + "tracking_issue": "deferred-route-modernization-follow-up/admin-template-modernization" + } + ] +} diff --git a/docs/migration/full-modernization-architecture-blueprint/governance_milestones.md b/docs/migration/full-modernization-architecture-blueprint/governance_milestones.md new file mode 100644 index 0000000..a9f2d52 --- /dev/null +++ b/docs/migration/full-modernization-architecture-blueprint/governance_milestones.md @@ -0,0 +1,30 @@ +# Full Modernization Governance Milestones + +## Phase Completion Criteria + +A phase is complete only when all criteria below are true: + +1. Route governance: 100% of in-scope routes in `route_scope_matrix.json` have valid shell contract metadata and ownership. +2. Style governance: in-scope route-local styles do not introduce page-global selectors (`:root`, `body`) unless recorded in exception registry. +3. Quality governance: functional parity, visual checkpoints, accessibility checks, and performance budgets pass at configured gate severity. +4. Content safety governance: page-content parity evidence + manual acceptance sign-off exist for each migrated in-scope route. +5. Bug carry-over governance: known-bug replay checks for migrated scope do not reproduce legacy defects. + +## Legacy Deprecation Milestones + +- 2026-02-20: route contract CI completeness gate enabled in `warn` mode. +- 2026-02-27: route contract CI completeness gate promoted to `block` mode. +- 2026-03-05: in-scope asset readiness gate promoted to `block` mode. +- 2026-03-12: runtime fallback posture retired for in-scope routes in production policy. +- 2026-03-19: unresolved style exceptions past milestone fail modernization review. + +## Deferred Route Linkage + +Deferred routes are not pass/fail criteria in this phase and are handed over to a follow-up change: + +- `/tables` +- `/excel-query` +- `/query-tool` +- `/mid-section-defect` + +Follow-up change handoff is recorded in `openspec/changes/deferred-route-modernization-follow-up/`. diff --git a/docs/migration/full-modernization-architecture-blueprint/interaction_parity_checks.json b/docs/migration/full-modernization-architecture-blueprint/interaction_parity_checks.json new file mode 100644 index 0000000..dc7a5ee --- /dev/null +++ b/docs/migration/full-modernization-architecture-blueprint/interaction_parity_checks.json @@ -0,0 +1,17 @@ +{ + "change": "full-modernization-architecture-blueprint", + "required_flows": { + "/wip-overview": ["filter_apply", "filter_reset", "status_card_drill"], + "/wip-detail": ["list_detail_continuity", "pagination", "filter_reset"], + "/hold-overview": ["reason_toggle", "matrix_selection", "lot_scope_sync"], + "/hold-detail": ["reason_required_redirect", "distribution_toggle", "lot_scope_sync"], + "/hold-history": ["date_range_query", "pareto_selection", "duration_bucket_selection"], + "/resource": ["status_filter", "workcenter_family_filter", "tooltip_open_close"], + "/resource-history": ["query_submit", "export_csv", "chart_detail_sync"], + "/qc-gate": ["chart_bucket_selection", "table_filter_sync", "filter_clear"], + "/job-query": ["resource_select", "query_submit", "export_csv"], + "/tmtt-defect": ["date_range_query", "chart_filter_link", "detail_sort"], + "/admin/pages": ["drawer_crud", "page_status_update", "admin_visibility"], + "/admin/performance": ["admin_auth_access", "performance_view_load"] + } +} diff --git a/docs/migration/full-modernization-architecture-blueprint/known_bug_baseline.json b/docs/migration/full-modernization-architecture-blueprint/known_bug_baseline.json new file mode 100644 index 0000000..220c0fa --- /dev/null +++ b/docs/migration/full-modernization-architecture-blueprint/known_bug_baseline.json @@ -0,0 +1,58 @@ +{ + "change": "full-modernization-architecture-blueprint", + "scope": "in-scope-routes-only", + "routes": { + "/wip-overview": { + "baseline_status": "initialized", + "known_bugs": [] + }, + "/wip-detail": { + "baseline_status": "initialized", + "known_bugs": [] + }, + "/hold-overview": { + "baseline_status": "initialized", + "known_bugs": [] + }, + "/hold-detail": { + "baseline_status": "initialized", + "known_bugs": [] + }, + "/hold-history": { + "baseline_status": "initialized", + "known_bugs": [] + }, + "/resource": { + "baseline_status": "initialized", + "known_bugs": [] + }, + "/resource-history": { + "baseline_status": "initialized", + "known_bugs": [] + }, + "/qc-gate": { + "baseline_status": "initialized", + "known_bugs": [] + }, + "/job-query": { + "baseline_status": "initialized", + "known_bugs": [] + }, + "/tmtt-defect": { + "baseline_status": "initialized", + "known_bugs": [] + }, + "/admin/pages": { + "baseline_status": "initialized", + "known_bugs": [] + }, + "/admin/performance": { + "baseline_status": "initialized", + "known_bugs": [] + } + }, + "revalidation_rule": { + "reproduced_legacy_bug_blocks_signoff": true, + "reproduced_legacy_bug_blocks_legacy_retirement": true + } +} diff --git a/docs/migration/full-modernization-architecture-blueprint/manual_acceptance_records.json b/docs/migration/full-modernization-architecture-blueprint/manual_acceptance_records.json new file mode 100644 index 0000000..f74bbde --- /dev/null +++ b/docs/migration/full-modernization-architecture-blueprint/manual_acceptance_records.json @@ -0,0 +1,5 @@ +{ + "change": "full-modernization-architecture-blueprint", + "records": [], + "rule": "next route cutover is blocked until current route has approved manual sign-off" +} diff --git a/docs/migration/full-modernization-architecture-blueprint/observability_checkpoints.md b/docs/migration/full-modernization-architecture-blueprint/observability_checkpoints.md new file mode 100644 index 0000000..69c0e72 --- /dev/null +++ b/docs/migration/full-modernization-architecture-blueprint/observability_checkpoints.md @@ -0,0 +1,32 @@ +# Modernization Observability Checkpoints + +## Route Governance Signals + +1. `navigation_contract_mismatch_total` +- Source: `/api/portal/navigation` diagnostics. +- Alert condition: non-zero for in-scope routes. + +2. `route_contract_missing_metadata_total` +- Source: route governance CI script. +- Alert condition: >0 in block mode. + +## Quality Gate Signals + +1. `quality_gate_failed_total{gate_id}` +- Source: quality gate report. +- Alert condition: any mandatory gate failed. + +2. `manual_acceptance_pending_routes` +- Source: manual acceptance records. +- Alert condition: cutover attempted with pending sign-off. + +## Fallback and Rollback Signals + +1. `in_scope_runtime_fallback_served_total` +- Should remain zero after fallback retirement milestone. + +2. `content_cutover_flag_rollbacks_total` +- Track frequency and route impact. + +3. `legacy_bug_replay_failures_total` +- Any non-zero indicates carry-over risk and blocks sign-off. diff --git a/docs/migration/full-modernization-architecture-blueprint/page_content_manual_acceptance_checklist.md b/docs/migration/full-modernization-architecture-blueprint/page_content_manual_acceptance_checklist.md new file mode 100644 index 0000000..43dc5e4 --- /dev/null +++ b/docs/migration/full-modernization-architecture-blueprint/page_content_manual_acceptance_checklist.md @@ -0,0 +1,28 @@ +# Page Content Manual Acceptance Checklist + +## Rule + +- Route cutover proceeds one route at a time. +- Next route cutover is blocked until current route is manually signed off. +- Legacy code retirement is blocked until parity checks and manual sign-off are both complete. + +## Mandatory Checks Per Route + +1. Filter semantics match baseline (apply, reset, URL/query continuity). +2. Chart interactions match baseline (drill/selection/clear behavior). +3. Empty/loading/error/success states are correct and non-overlapping. +4. Table/chart linked interactions remain deterministic. +5. Accessibility: keyboard flow, focus visibility, `aria-*` semantics, reduced-motion behavior. +6. Known-bug replay checks completed (see `known_bug_baseline.json`). +7. No reproduced legacy bug in migrated scope. + +## Sign-Off Template + +- Route: +- Owner: +- Reviewer: +- Date: +- Parity evidence links: +- Known-bug replay result: +- Blocking defects: +- Decision: `approved` | `rework-required` diff --git a/docs/migration/full-modernization-architecture-blueprint/parity_golden_fixtures.json b/docs/migration/full-modernization-architecture-blueprint/parity_golden_fixtures.json new file mode 100644 index 0000000..fa5a438 --- /dev/null +++ b/docs/migration/full-modernization-architecture-blueprint/parity_golden_fixtures.json @@ -0,0 +1,17 @@ +{ + "change": "full-modernization-architecture-blueprint", + "fixtures": { + "/wip-overview": ["tests/fixtures/frontend_compute_parity.json"], + "/wip-detail": ["docs/migration/portal-shell-route-view-integration/wave-b-parity-evidence.json"], + "/hold-overview": ["docs/migration/portal-shell-route-view-integration/baseline_interaction_evidence.json"], + "/hold-detail": ["docs/migration/portal-shell-route-view-integration/baseline_interaction_evidence.json"], + "/hold-history": ["docs/migration/portal-shell-route-view-integration/baseline_interaction_evidence.json"], + "/resource": ["docs/migration/portal-shell-route-view-integration/baseline_api_payload_contracts.json"], + "/resource-history": ["docs/migration/portal-shell-route-view-integration/baseline_api_payload_contracts.json"], + "/qc-gate": ["docs/migration/portal-shell-route-view-integration/visual-regression-snapshots.json"], + "/job-query": ["docs/migration/portal-shell-route-view-integration/wave-b-parity-evidence.json"], + "/tmtt-defect": ["docs/migration/portal-shell-route-view-integration/wave-b-parity-evidence.json"], + "/admin/pages": ["tests/test_portal_shell_routes.py"], + "/admin/performance": ["tests/test_performance_integration.py"] + } +} diff --git a/docs/migration/full-modernization-architecture-blueprint/performance_budgets.json b/docs/migration/full-modernization-architecture-blueprint/performance_budgets.json new file mode 100644 index 0000000..7767a8d --- /dev/null +++ b/docs/migration/full-modernization-architecture-blueprint/performance_budgets.json @@ -0,0 +1,13 @@ +{ + "change": "full-modernization-architecture-blueprint", + "targets": { + "shell_navigation_api_avg_ms": 150, + "shell_navigation_api_p95_ms": 350, + "portal_shell_entry_avg_ms": 200, + "portal_shell_entry_p95_ms": 450 + }, + "source_baselines": [ + "docs/migration/portal-no-iframe/performance_baseline_spa.json", + "docs/migration/portal-no-iframe/performance_baseline_legacy.json" + ] +} diff --git a/docs/migration/full-modernization-architecture-blueprint/quality_gate_policy.json b/docs/migration/full-modernization-architecture-blueprint/quality_gate_policy.json new file mode 100644 index 0000000..67ccf00 --- /dev/null +++ b/docs/migration/full-modernization-architecture-blueprint/quality_gate_policy.json @@ -0,0 +1,21 @@ +{ + "change": "full-modernization-architecture-blueprint", + "severity_mode": { + "current": "warn", + "promotion_target": "block", + "promotion_milestone": "2026-02-27" + }, + "gates": [ + {"id": "Q1", "name": "functional-parity", "required": true}, + {"id": "Q2", "name": "visual-regression", "required": true}, + {"id": "Q3", "name": "accessibility-keyboard-aria-motion", "required": true}, + {"id": "Q4", "name": "performance-budget", "required": true}, + {"id": "Q5", "name": "manual-acceptance-and-bug-revalidation", "required": true} + ], + "deferred_routes_excluded": [ + "/tables", + "/excel-query", + "/query-tool", + "/mid-section-defect" + ] +} diff --git a/docs/migration/full-modernization-architecture-blueprint/quality_gate_report.json b/docs/migration/full-modernization-architecture-blueprint/quality_gate_report.json new file mode 100644 index 0000000..9c97008 --- /dev/null +++ b/docs/migration/full-modernization-architecture-blueprint/quality_gate_report.json @@ -0,0 +1,7 @@ +{ + "mode": "block", + "errors": [], + "warnings": [], + "info": [], + "passed": true +} diff --git a/docs/migration/full-modernization-architecture-blueprint/rollback_controls.md b/docs/migration/full-modernization-architecture-blueprint/rollback_controls.md new file mode 100644 index 0000000..b9539cf --- /dev/null +++ b/docs/migration/full-modernization-architecture-blueprint/rollback_controls.md @@ -0,0 +1,26 @@ +# Full Modernization Rollback Controls + +## Route-Level Reversion Controls + +- `PORTAL_SPA_ENABLED=false`: + Disable shell-first navigation runtime globally. +- Route-scoped contract fallback: + Mark route contract with fallback strategy and redeploy shell assets. +- Content cutover feature flag: + Disable route-level modernized content path while keeping shell runtime up. + +## False-Positive Gate Handling + +1. Capture failing gate output and route impact. +2. Confirm whether failure is test flake or product defect. +3. If false-positive and production risk is high: +- Temporarily switch gate severity from `block` to `warn`. +- Record waiver with owner, reason, expiry. +4. Restore `block` mode after corrective action. + +## Required Rollback Evidence + +- Incident timestamp and impacted routes. +- Gate IDs that triggered rollback. +- Route contract state before/after rollback. +- Manual acceptance and known-bug replay references. diff --git a/docs/migration/full-modernization-architecture-blueprint/rollout_runbook.md b/docs/migration/full-modernization-architecture-blueprint/rollout_runbook.md new file mode 100644 index 0000000..eeab681 --- /dev/null +++ b/docs/migration/full-modernization-architecture-blueprint/rollout_runbook.md @@ -0,0 +1,33 @@ +# Full Modernization Rollout Runbook + +## Phase Sequence + +1. Governance freeze +- Confirm `route_scope_matrix.json` has no pending route-scope changes. +- Confirm exception registry entries include owner + milestone. + +2. Route governance enforcement +- Run route contract completeness checks in warn mode. +- Fix all in-scope metadata gaps. +- Promote route governance checks to block mode. + +3. Style/content hardening +- Apply style isolation checks for in-scope routes. +- Execute parity checks and manual acceptance route-by-route. +- Run known-bug replay checks per route. + +4. Asset/gate enforcement +- Validate in-scope asset readiness. +- Run quality gate suite (functional, visual, accessibility, performance). +- Promote gate severity from warn to block according to policy. + +## Hold Points + +- Hold-1: Any in-scope route missing contract metadata. +- Hold-2: Any unresolved style exception past milestone. +- Hold-3: Any parity failure or known-bug replay failure. +- Hold-4: Any mandatory quality gate failure in block mode. + +## Promotion Rule + +Promotion is allowed only when all hold points are clear and no deferred-route checks were incorrectly included as blockers. diff --git a/docs/migration/full-modernization-architecture-blueprint/route_content_contracts.json b/docs/migration/full-modernization-architecture-blueprint/route_content_contracts.json new file mode 100644 index 0000000..7a13411 --- /dev/null +++ b/docs/migration/full-modernization-architecture-blueprint/route_content_contracts.json @@ -0,0 +1,77 @@ +{ + "change": "full-modernization-architecture-blueprint", + "in_scope_routes": { + "/wip-overview": { + "filter_input_semantics": ["workorder", "lotid", "package", "type", "status"], + "query_payload_contract": ["workorder", "lotid", "package", "type", "status"], + "chart_data_shape": ["status_cards", "matrix", "pareto"], + "state_contract": ["loading", "empty", "error", "success"] + }, + "/wip-detail": { + "filter_input_semantics": ["workcenter", "workorder", "lotid", "package", "type", "status", "page"], + "query_payload_contract": ["workcenter", "workorder", "lotid", "package", "type", "status", "page"], + "chart_data_shape": ["summary_cards", "lot_table"], + "state_contract": ["loading", "empty", "error", "success"] + }, + "/hold-overview": { + "filter_input_semantics": ["hold_type", "reason", "workcenter", "package", "age_range", "page"], + "query_payload_contract": ["hold_type", "reason", "workcenter", "package", "age_range", "page"], + "chart_data_shape": ["summary_cards", "matrix", "treemap", "lot_table"], + "state_contract": ["loading", "empty", "error", "success"] + }, + "/hold-detail": { + "filter_input_semantics": ["reason", "workcenter", "package", "age_range", "page"], + "query_payload_contract": ["reason", "workcenter", "package", "age_range", "page"], + "chart_data_shape": ["summary_cards", "distribution", "lot_table"], + "state_contract": ["loading", "empty", "error", "success"] + }, + "/hold-history": { + "filter_input_semantics": ["start_date", "end_date", "hold_type", "record_type", "reason", "duration_range", "page"], + "query_payload_contract": ["start_date", "end_date", "hold_type", "record_type", "reason", "duration_range", "page"], + "chart_data_shape": ["trend", "reason_pareto", "duration", "detail_table"], + "state_contract": ["loading", "empty", "error", "success"] + }, + "/resource": { + "filter_input_semantics": ["workcenter_groups", "families", "resource_ids", "statuses"], + "query_payload_contract": ["workcenter_groups", "families", "resource_ids", "statuses"], + "chart_data_shape": ["summary_cards", "status_matrix", "equipment_grid"], + "state_contract": ["loading", "empty", "error", "success"] + }, + "/resource-history": { + "filter_input_semantics": ["start_date", "end_date", "granularity", "workcenter_groups", "families", "resource_ids", "is_production", "is_key", "is_monitor"], + "query_payload_contract": ["start_date", "end_date", "granularity", "workcenter_groups", "families", "resource_ids", "is_production", "is_key", "is_monitor"], + "chart_data_shape": ["kpi", "trend", "heatmap", "workcenter_comparison", "detail"], + "state_contract": ["loading", "empty", "error", "success"] + }, + "/qc-gate": { + "filter_input_semantics": ["chart_bucket_selection", "table_sort"], + "query_payload_contract": ["summary", "table", "pareto"], + "chart_data_shape": ["station_stack_chart", "linked_lot_table"], + "state_contract": ["loading", "empty", "error", "success"] + }, + "/job-query": { + "filter_input_semantics": ["resource_ids", "start_date", "end_date"], + "query_payload_contract": ["resource_ids", "start_date", "end_date"], + "chart_data_shape": ["job_table", "txn_table"], + "state_contract": ["loading", "empty", "error", "success"] + }, + "/tmtt-defect": { + "filter_input_semantics": ["start_date", "end_date", "sort", "page"], + "query_payload_contract": ["start_date", "end_date"], + "chart_data_shape": ["kpi", "pareto", "trend", "detail_table"], + "state_contract": ["loading", "empty", "error", "success"] + }, + "/admin/pages": { + "filter_input_semantics": ["drawer_crud", "page_status_edit", "order_updates"], + "query_payload_contract": ["drawers", "pages", "status"], + "chart_data_shape": ["n/a"], + "state_contract": ["loading", "empty", "error", "success"] + }, + "/admin/performance": { + "filter_input_semantics": ["date_range", "severity", "search"], + "query_payload_contract": ["performance_summary", "log_stream"], + "chart_data_shape": ["timeline", "status_summary"], + "state_contract": ["loading", "empty", "error", "success"] + } + } +} diff --git a/docs/migration/full-modernization-architecture-blueprint/route_contracts.json b/docs/migration/full-modernization-architecture-blueprint/route_contracts.json new file mode 100644 index 0000000..b78d187 --- /dev/null +++ b/docs/migration/full-modernization-architecture-blueprint/route_contracts.json @@ -0,0 +1,166 @@ +{ + "change": "full-modernization-architecture-blueprint", + "generated_at": "2026-02-12T00:00:00Z", + "routes": [ + { + "route": "/wip-overview", + "route_id": "wip-overview", + "scope": "in-scope", + "render_mode": "native", + "owner": "frontend-mes-reporting", + "visibility_policy": "released_or_admin", + "canonical_shell_path": "/portal-shell/wip-overview", + "rollback_strategy": "fallback_to_legacy_route" + }, + { + "route": "/wip-detail", + "route_id": "wip-detail", + "scope": "in-scope", + "render_mode": "native", + "owner": "frontend-mes-reporting", + "visibility_policy": "released_or_admin", + "canonical_shell_path": "/portal-shell/wip-detail", + "rollback_strategy": "fallback_to_legacy_route" + }, + { + "route": "/hold-overview", + "route_id": "hold-overview", + "scope": "in-scope", + "render_mode": "native", + "owner": "frontend-mes-reporting", + "visibility_policy": "released_or_admin", + "canonical_shell_path": "/portal-shell/hold-overview", + "rollback_strategy": "fallback_to_legacy_route" + }, + { + "route": "/hold-detail", + "route_id": "hold-detail", + "scope": "in-scope", + "render_mode": "native", + "owner": "frontend-mes-reporting", + "visibility_policy": "released_or_admin", + "canonical_shell_path": "/portal-shell/hold-detail", + "rollback_strategy": "fallback_to_legacy_route" + }, + { + "route": "/hold-history", + "route_id": "hold-history", + "scope": "in-scope", + "render_mode": "native", + "owner": "frontend-mes-reporting", + "visibility_policy": "released_or_admin", + "canonical_shell_path": "/portal-shell/hold-history", + "rollback_strategy": "fallback_to_legacy_route" + }, + { + "route": "/resource", + "route_id": "resource", + "scope": "in-scope", + "render_mode": "native", + "owner": "frontend-mes-reporting", + "visibility_policy": "released_or_admin", + "canonical_shell_path": "/portal-shell/resource", + "rollback_strategy": "fallback_to_legacy_route" + }, + { + "route": "/resource-history", + "route_id": "resource-history", + "scope": "in-scope", + "render_mode": "native", + "owner": "frontend-mes-reporting", + "visibility_policy": "released_or_admin", + "canonical_shell_path": "/portal-shell/resource-history", + "rollback_strategy": "fallback_to_legacy_route" + }, + { + "route": "/qc-gate", + "route_id": "qc-gate", + "scope": "in-scope", + "render_mode": "native", + "owner": "frontend-mes-reporting", + "visibility_policy": "released_or_admin", + "canonical_shell_path": "/portal-shell/qc-gate", + "rollback_strategy": "fallback_to_legacy_route" + }, + { + "route": "/job-query", + "route_id": "job-query", + "scope": "in-scope", + "render_mode": "native", + "owner": "frontend-mes-reporting", + "visibility_policy": "released_or_admin", + "canonical_shell_path": "/portal-shell/job-query", + "rollback_strategy": "fallback_to_legacy_route" + }, + { + "route": "/tmtt-defect", + "route_id": "tmtt-defect", + "scope": "in-scope", + "render_mode": "native", + "owner": "frontend-mes-reporting", + "visibility_policy": "released_or_admin", + "canonical_shell_path": "/portal-shell/tmtt-defect", + "rollback_strategy": "fallback_to_legacy_route" + }, + { + "route": "/admin/pages", + "route_id": "admin-pages", + "scope": "in-scope", + "render_mode": "external", + "owner": "frontend-platform-admin", + "visibility_policy": "admin_only", + "canonical_shell_path": "/portal-shell/admin/pages", + "rollback_strategy": "external_route_reversion" + }, + { + "route": "/admin/performance", + "route_id": "admin-performance", + "scope": "in-scope", + "render_mode": "external", + "owner": "frontend-platform-admin", + "visibility_policy": "admin_only", + "canonical_shell_path": "/portal-shell/admin/performance", + "rollback_strategy": "external_route_reversion" + }, + { + "route": "/tables", + "route_id": "tables", + "scope": "deferred", + "render_mode": "native", + "owner": "frontend-mes-reporting", + "visibility_policy": "released_or_admin", + "canonical_shell_path": "/portal-shell/tables", + "rollback_strategy": "fallback_to_legacy_route" + }, + { + "route": "/excel-query", + "route_id": "excel-query", + "scope": "deferred", + "render_mode": "native", + "owner": "frontend-mes-reporting", + "visibility_policy": "released_or_admin", + "canonical_shell_path": "/portal-shell/excel-query", + "rollback_strategy": "fallback_to_legacy_route" + }, + { + "route": "/query-tool", + "route_id": "query-tool", + "scope": "deferred", + "render_mode": "native", + "owner": "frontend-mes-reporting", + "visibility_policy": "released_or_admin", + "canonical_shell_path": "/portal-shell/query-tool", + "rollback_strategy": "fallback_to_legacy_route" + }, + { + "route": "/mid-section-defect", + "route_id": "mid-section-defect", + "scope": "deferred", + "render_mode": "native", + "owner": "frontend-mes-reporting", + "visibility_policy": "released_or_admin", + "canonical_shell_path": "/portal-shell/mid-section-defect", + "rollback_strategy": "fallback_to_legacy_route" + } + ] +} diff --git a/docs/migration/full-modernization-architecture-blueprint/route_scope_matrix.json b/docs/migration/full-modernization-architecture-blueprint/route_scope_matrix.json new file mode 100644 index 0000000..3b483de --- /dev/null +++ b/docs/migration/full-modernization-architecture-blueprint/route_scope_matrix.json @@ -0,0 +1,113 @@ +{ + "change": "full-modernization-architecture-blueprint", + "generated_at": "2026-02-12T00:00:00Z", + "phase": "phase-1-shell-and-content-modernization", + "policy": { + "scope_is_frozen": true, + "out_of_scope_tasks_must_be_rejected": true + }, + "in_scope": [ + { + "route": "/wip-overview", + "category": "report", + "canonical_shell_path": "/portal-shell/wip-overview", + "owner": "frontend-mes-reporting", + "visibility_policy": "released_or_admin" + }, + { + "route": "/wip-detail", + "category": "report", + "canonical_shell_path": "/portal-shell/wip-detail", + "owner": "frontend-mes-reporting", + "visibility_policy": "released_or_admin" + }, + { + "route": "/hold-overview", + "category": "report", + "canonical_shell_path": "/portal-shell/hold-overview", + "owner": "frontend-mes-reporting", + "visibility_policy": "released_or_admin" + }, + { + "route": "/hold-detail", + "category": "report", + "canonical_shell_path": "/portal-shell/hold-detail", + "owner": "frontend-mes-reporting", + "visibility_policy": "released_or_admin" + }, + { + "route": "/hold-history", + "category": "report", + "canonical_shell_path": "/portal-shell/hold-history", + "owner": "frontend-mes-reporting", + "visibility_policy": "released_or_admin" + }, + { + "route": "/resource", + "category": "report", + "canonical_shell_path": "/portal-shell/resource", + "owner": "frontend-mes-reporting", + "visibility_policy": "released_or_admin" + }, + { + "route": "/resource-history", + "category": "report", + "canonical_shell_path": "/portal-shell/resource-history", + "owner": "frontend-mes-reporting", + "visibility_policy": "released_or_admin" + }, + { + "route": "/qc-gate", + "category": "report", + "canonical_shell_path": "/portal-shell/qc-gate", + "owner": "frontend-mes-reporting", + "visibility_policy": "released_or_admin" + }, + { + "route": "/job-query", + "category": "report", + "canonical_shell_path": "/portal-shell/job-query", + "owner": "frontend-mes-reporting", + "visibility_policy": "released_or_admin" + }, + { + "route": "/tmtt-defect", + "category": "report", + "canonical_shell_path": "/portal-shell/tmtt-defect", + "owner": "frontend-mes-reporting", + "visibility_policy": "released_or_admin" + }, + { + "route": "/admin/pages", + "category": "admin", + "canonical_shell_path": "/portal-shell/admin/pages", + "owner": "frontend-platform-admin", + "visibility_policy": "admin_only" + }, + { + "route": "/admin/performance", + "category": "admin", + "canonical_shell_path": "/portal-shell/admin/performance", + "owner": "frontend-platform-admin", + "visibility_policy": "admin_only" + } + ], + "deferred": [ + { + "route": "/tables", + "reason": "deferred-to-follow-up-change" + }, + { + "route": "/excel-query", + "reason": "deferred-to-follow-up-change" + }, + { + "route": "/query-tool", + "reason": "deferred-to-follow-up-change" + }, + { + "route": "/mid-section-defect", + "reason": "deferred-to-follow-up-change" + } + ] +} diff --git a/docs/migration/full-modernization-architecture-blueprint/style_inventory.json b/docs/migration/full-modernization-architecture-blueprint/style_inventory.json new file mode 100644 index 0000000..0817b78 --- /dev/null +++ b/docs/migration/full-modernization-architecture-blueprint/style_inventory.json @@ -0,0 +1,30 @@ +{ + "change": "full-modernization-architecture-blueprint", + "generated_at": "2026-02-12T00:00:00Z", + "in_scope_routes": { + "/wip-overview": {"global_selectors": [], "status": "clean"}, + "/wip-detail": {"global_selectors": [], "status": "clean"}, + "/hold-overview": {"global_selectors": [], "status": "clean"}, + "/hold-detail": {"global_selectors": [], "status": "clean"}, + "/hold-history": {"global_selectors": [], "status": "clean"}, + "/resource": {"global_selectors": [], "status": "clean"}, + "/resource-history": {"global_selectors": [], "status": "clean"}, + "/qc-gate": {"global_selectors": [], "status": "clean-after-refactor"}, + "/job-query": {"global_selectors": [], "status": "clean"}, + "/tmtt-defect": {"global_selectors": [], "status": "clean"}, + "/admin/pages": { + "global_selectors": ["body"], + "status": "exception-registered", + "exception_id": "style-admin-pages-inline-css" + }, + "/admin/performance": { + "global_selectors": ["body"], + "status": "exception-registered", + "exception_id": "style-admin-performance-inline-css" + } + }, + "shared_layers": { + "frontend/src/styles/tailwind.css": [":root", "body"], + "frontend/src/portal-shell/style.css": [":root", "body"] + } +} diff --git a/docs/migration/portal-no-iframe/baseline_drawer_visibility.json b/docs/migration/portal-no-iframe/baseline_drawer_visibility.json index b3ffbce..4a83cbc 100644 --- a/docs/migration/portal-no-iframe/baseline_drawer_visibility.json +++ b/docs/migration/portal-no-iframe/baseline_drawer_visibility.json @@ -1,4 +1,5 @@ { + "generated_at": "2026-02-12T02:26:36.887797+00:00", "source": "data/page_status.json", "admin": [ { @@ -16,7 +17,7 @@ { "route": "/hold-overview", "name": "Hold 即時概況", - "status": "dev", + "status": "released", "order": 2 }, { @@ -42,7 +43,7 @@ { "route": "/hold-history", "name": "Hold 歷史績效", - "status": "dev", + "status": "released", "order": 3 }, { @@ -106,7 +107,7 @@ { "route": "/tmtt-defect", "name": "TMTT印字腳型不良分析", - "status": "released", + "status": "dev", "order": 5 }, { @@ -131,6 +132,12 @@ "status": "released", "order": 1 }, + { + "route": "/hold-overview", + "name": "Hold 即時概況", + "status": "released", + "order": 2 + }, { "route": "/resource", "name": "設備即時概況", @@ -151,6 +158,12 @@ "order": 2, "admin_only": false, "pages": [ + { + "route": "/hold-history", + "name": "Hold 歷史績效", + "status": "released", + "order": 3 + }, { "route": "/resource-history", "name": "設備歷史績效", diff --git a/docs/migration/portal-shell-route-view-integration/baseline_drawer_visibility.json b/docs/migration/portal-shell-route-view-integration/baseline_drawer_visibility.json index bd1f8ab..4a83cbc 100644 --- a/docs/migration/portal-shell-route-view-integration/baseline_drawer_visibility.json +++ b/docs/migration/portal-shell-route-view-integration/baseline_drawer_visibility.json @@ -1,5 +1,5 @@ { - "generated_at": "2026-02-11T07:44:03+00:00", + "generated_at": "2026-02-12T02:26:36.887797+00:00", "source": "data/page_status.json", "admin": [ { @@ -17,7 +17,7 @@ { "route": "/hold-overview", "name": "Hold 即時概況", - "status": "dev", + "status": "released", "order": 2 }, { @@ -43,7 +43,7 @@ { "route": "/hold-history", "name": "Hold 歷史績效", - "status": "dev", + "status": "released", "order": 3 }, { @@ -107,7 +107,7 @@ { "route": "/tmtt-defect", "name": "TMTT印字腳型不良分析", - "status": "released", + "status": "dev", "order": 5 }, { @@ -132,6 +132,12 @@ "status": "released", "order": 1 }, + { + "route": "/hold-overview", + "name": "Hold 即時概況", + "status": "released", + "order": 2 + }, { "route": "/resource", "name": "設備即時概況", @@ -152,6 +158,12 @@ "order": 2, "admin_only": false, "pages": [ + { + "route": "/hold-history", + "name": "Hold 歷史績效", + "status": "released", + "order": 3 + }, { "route": "/resource-history", "name": "設備歷史績效", diff --git a/frontend/src/hold-overview/components/FilterBar.vue b/frontend/src/hold-overview/components/FilterBar.vue index 5d32306..960bcbd 100644 --- a/frontend/src/hold-overview/components/FilterBar.vue +++ b/frontend/src/hold-overview/components/FilterBar.vue @@ -22,17 +22,13 @@ const props = defineProps({ const emit = defineEmits(['change']); -const holdTypeModel = computed({ - get() { - return props.holdType || 'quality'; - }, - set(nextValue) { - emit('change', { - holdType: nextValue || 'quality', - reason: props.reason || '', - }); - }, -}); +const HOLD_TYPE_OPTIONS = Object.freeze([ + { value: 'quality', label: '品質異常' }, + { value: 'non-quality', label: '非品質異常' }, + { value: 'all', label: '全部' }, +]); + +const holdTypeModel = computed(() => props.holdType || 'quality'); const reasonModel = computed({ get() { @@ -59,29 +55,44 @@ const reasonOptions = computed(() => { }); return items; }); + +function selectHoldType(nextValue) { + if (props.disabled) { + return; + } + const normalized = nextValue || 'quality'; + if (normalized === holdTypeModel.value) { + return; + } + emit('change', { + holdType: normalized, + reason: props.reason || '', + }); +}