Commit Graph

145 Commits

Author SHA1 Message Date
egg
5d58ac551d fix(reject-history): WORKORDER bind variable error + move policy filters to in-memory
Three fixes for the reject history query feature:

1. Fix DPY-4010 bind variable error when querying by WORKORDER — the
   workflow_lookup CTE had hardcoded :start_date/:end_date which aren't
   provided in container mode. Replaced with {{ WORKFLOW_FILTER }} template
   slot that defaults to date-based filter or container-based filter.

2. Move policy toggle filters (material scrap, PB_diode, excluded reasons)
   from SQL-level to in-memory pandas filtering. Cache now stores unfiltered
   data so toggling policy filters reuses cached results instantly instead
   of requiring a ~30s Oracle round-trip per combination.

3. Add per-WORKORDER expansion_info display in FilterPanel for multi-order
   container resolution diagnostics.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 13:21:31 +08:00
egg
07ced80fb0 feat(admin-perf): full Vue SPA migration + slow-query/memory monitoring gaps
Remove Jinja2 template fallback (1249 lines) — /admin/performance now serves
Vue SPA exclusively via send_from_directory.

Backend:
- Add _SLOW_QUERY_WAITING counter with get_slow_query_waiting_count()
- Record slow-path latency in read_sql_df_slow/iter via record_query_latency()
- Extend metrics_history schema with slow_query_active, slow_query_waiting,
  worker_rss_bytes columns + ALTER TABLE migration for existing DBs
- Add cleanup_archive_logs() with configurable ARCHIVE_LOG_DIR/KEEP_COUNT
- Integrate archive cleanup into MetricsHistoryCollector 50-min cycle

Frontend:
- Add slow_query_active and slow_query_waiting StatCards to connection pool
- Add slow_query_active trend line to pool trend chart
- Add Worker memory (RSS MB) trend chart with preprocessing
- Update modernization gate check path to frontend style.css

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 09:48:54 +08:00
egg
c6f982ae50 test: fix E2E/integration failures, add trace pipeline E2E, remove dead migration tests
- Fix 6 Playwright strict-mode violations in query tool E2E (v-show dual-tab selectors)
- Update 5 resource history E2E tests for POST /query API restructure
- Add 22 trace pipeline E2E tests: admission control, async job queue, NDJSON streaming
- Fix 3 health endpoint tests: add circuit breaker + route cache mocks
- Fix WIP integration tests: load .env before DB module import for --run-integration
- Remove 4 dead migration test files (20 permanently-skipped tests)

Final: 1101 unit + 10 integration + 121 E2E + 23 stress = 1255 passed, 0 failed

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-26 08:33:07 +08:00
egg
dbe0da057c feat(trace-pipeline): memory triage, async job queue, and NDJSON streaming
Three proposals addressing the 2026-02-25 trace pipeline OOM crash (114K CIDs):

1. trace-events-memory-triage: fetchmany iterator (read_sql_df_slow_iter),
   admission control (50K CID limit for non-MSD), cache skip for large queries,
   early memory release with gc.collect()

2. trace-async-job-queue: RQ-based async jobs for queries >20K CIDs,
   separate worker process with isolated memory, frontend polling via
   useTraceProgress composable, systemd service + deploy scripts

3. trace-streaming-response: chunked Redis storage (TRACE_STREAM_BATCH_SIZE=5000),
   NDJSON stream endpoint (GET /api/trace/job/<id>/stream), frontend
   ReadableStream consumer for progressive rendering, backward-compatible
   with legacy single-key storage

All three proposals archived. 1101 tests pass, frontend builds clean.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 21:01:27 +08:00
egg
cbb943dfe5 feat(trace-pool-isolation): migrate event_fetcher/lineage_engine to slow connections + fix 51 test failures
Trace pipeline pool isolation:
- Switch event_fetcher and lineage_engine to read_sql_df_slow (non-pooled)
- Reduce EVENT_FETCHER_MAX_WORKERS 4→2, TRACE_EVENTS_MAX_WORKERS 4→2
- Add 60s timeout per batch query, cache skip for CID>10K
- Early del raw_domain_results + gc.collect() for large queries
- Increase DB_SLOW_MAX_CONCURRENT: base 3→5, dev 2→3, prod 3→5

Test fixes (51 pre-existing failures → 0):
- reject_history: WORKFLOW CSV header, strict bool validation, pareto mock path
- portal shell: remove non-existent /tmtt-defect route from tests
- conftest: add --run-stress option to skip stress/load tests by default
- migration tests: skipif baseline directory missing
- performance test: update Vite asset assertion
- wip hold: add firstname/waferdesc mock params
- template integration: add /reject-history canonical route

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 16:13:19 +08:00
egg
49bd4b31d3 fix(mid-section-defect): use read_sql_df_slow to avoid 55s pool timeout
Station detection query with large date ranges (5+ months) exceeds the
55s pool call_timeout. Switch to read_sql_df_slow (300s, dedicated
connection) matching other historical query services.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 13:16:41 +08:00
egg
71c8102de6 feat: dataset cache for hold/resource history + slow connection migration
Two changes combined:

1. historical-query-slow-connection: Migrate all historical query pages
   to read_sql_df_slow with semaphore concurrency control (max 3),
   raise DB slow timeout to 300s, gunicorn timeout to 360s, and
   unify frontend timeouts to 360s for all historical pages.

2. hold-resource-history-dataset-cache: Convert hold-history and
   resource-history from multi-query to single-query + dataset cache
   pattern (L1 ProcessLevelCache + L2 Redis parquet/base64, TTL=900s).
   Replace old GET endpoints with POST /query + GET /view two-phase
   API. Frontend auto-retries on 410 cache_expired.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 13:15:02 +08:00
egg
cd061e0cfd test(msd): add unit tests for _build_detail_table structured output and CSV flatten
Covers task 14.3: verify UPSTREAM_MACHINES/UPSTREAM_MATERIALS list format,
WAFER_ROOT field, multi-reason row expansion, machine deduplication,
and CSV export flatten logic.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 11:28:28 +08:00
egg
86984cfeb1 feat: dimension pareto cache-based computation, filter propagation, and MSD events cache isolation
Reject History:
- Compute dimension pareto (package/type/workflow/workcenter/equipment) from
  cached DataFrame instead of re-querying Oracle per dimension change
- Propagate supplementary filters and trend date selection to dimension pareto
- Add staleness tracking to prevent race conditions on rapid dimension switches
- Add WORKFLOWNAME to detail and export outputs
- Fix button hover visibility with CSS specificity

MSD (製程不良追溯分析):
- Separate raw events caching from aggregation computation so changing
  loss_reasons uses EventFetcher per-domain cache (fast) and recomputes
  aggregation with current filters instead of returning stale cached results
- Exclude loss_reasons from MSD seed cache key since seed resolution does
  not use it, avoiding unnecessary Oracle re-queries
- Add suspect context panel, analysis summary, upstream station/spec filters
- Add machine bar click drill-down and filtered attribution charts

Query Tool:
- Support batch container_ids in lot CSV export (history/materials/rejects/holds)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-25 09:02:39 +08:00
egg
983737ca1a fix(job-query): align CSV export headers with frontend column names
Some checks failed
full-modernization-gates / frontend-route-governance (push) Has been cancelled
full-modernization-gates / backend-modernization-gates (push) Has been cancelled
released-pages-hardening-gates / released-pages-hardening (push) Has been cancelled
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 19:22:26 +08:00
egg
fc33ff0a0c fix(query-tool): rename CONTAINERNAMES to LOT ID in lot_jobs CSV export
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 19:16:02 +08:00
egg
70f94de38a fix(query-tool): rename jobs CONTAINERNAMES header to LOT ID and include in export
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 19:13:19 +08:00
egg
e37902861f fix(query-tool): export button hover visibility, jobs tab hide columns and export with txn history
- Increase CSS specificity for .btn-export to prevent portal-shell override on hover
- Remove RESOURCEID and CONTAINERIDS from jobs tab display columns
- Add lot_jobs_with_txn.sql joining JOB with JOBTXNHISTORY for complete export
- Route lot_jobs export through get_lot_jobs_with_history() for full transaction data

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 19:10:19 +08:00
egg
7fffa812a3 fix(query-tool): export all selected CIDs instead of single, fix hold detail float precision
Export was sending only one container_id while the detail table loaded
data for all selected CIDs (including subtree), causing "查無資料" errors.
Now sends container_ids array and uses batch service functions.

Also rounds hold detail age KPI cards to 1 decimal place.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 18:41:24 +08:00
egg
bb6eec6a87 fix(mid-section-defect): include non-charge-off rejects, fix forward tracing, remove auto-refresh
- Add DEFECTQTY to reject SUM in station_detection, station_detection_by_ids,
  and downstream_rejects SQL so KPI/charts include both charge-off and
  non-charge-off reject quantities
- Wire forward direction through events-based trace pipeline so downstream
  pareto charts and detail table populate correctly
- Remove inappropriate 5-min auto-refresh from query tool page; replace
  useAutoRefresh with local createAbortSignal for request cancellation

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 18:20:09 +08:00
egg
f14591c7dc feat(mid-section-defect): full-line bidirectional defect trace center with dual query mode
Transform /mid-section-defect from TMTT-only backward analysis into a full-line
bidirectional defect traceability center supporting all detection stations.

Key changes:
- Parameterized station detection: any workcenter group as detection station
- Bidirectional tracing: backward (upstream attribution) + forward (downstream reject rates)
- Dual query mode: date range OR LOT/工單/WAFER container-based seed resolution
- Multi-select filters for upstream station, equipment model (RESOURCEFAMILYNAME), and loss reasons
- Progressive 3-stage trace pipeline (seed-resolve → lineage → events) with streaming UI
- Equipment model lookup via resource cache instead of SPECNAME
- Session caching, auto-refresh, searchable MultiSelect with fuzzy matching
- Remove legacy tmtt-defect module (fully superseded)
- Archive openspec change artifacts

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-24 16:16:33 +08:00
egg
bb58a0e119 feat(query-tool): optimize equipment tracking UI and unify column labels
- Equipment selector shows only RESOURCENAME (remove redundant RESOURCEID)
- Equipment lots table: remove CONTAINERID, add WAFER LOT/TYPE/BOP/WORKORDER
- Rename CONTAINERNAME to LOT ID across all tables and CSV exports
- Rename PJ_TYPE/PJ_BOP/PJ_WORKORDER to TYPE/BOP/WORKORDER in history and equipment lots
- Add export formatters for equipment_lots, lot_history, and lot_rejects

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 20:21:15 +08:00
egg
8694780abb fix(resource): use auto-fit grid for summary cards to follow sidebar toggle
Summary grid used fixed 10-column layout with viewport-based media queries
that didn't account for sidebar width changes, causing overflow when sidebar
opened and blank space at certain breakpoints.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 19:04:55 +08:00
egg
fd78c02b2d fix(job-query,query-tool): align txn history column order with field_contracts
Replace dynamic Object.keys(row) column derivation with explicit display
column lists matching field_contracts.json txn_table definition, ensuring
consistent column order across job-query and query-tool transaction tables.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 18:16:28 +08:00
egg
80a39c6145 fix asset readiness manifest for admin pages 2026-02-23 17:54:34 +08:00
egg
e5d7700b36 harden released pages and archive openspec change 2026-02-23 17:48:32 +08:00
egg
6e2ff9813e chore(query-tool): promote to released status and move to main drawer
Some checks failed
full-modernization-gates / frontend-route-governance (push) Has been cancelled
full-modernization-gates / backend-modernization-gates (push) Has been cancelled
Move query-tool from dev-tools drawer to main drawer and update status
from dev to released now that the UI alignment work is complete.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 15:23:10 +08:00
egg
3fa5e23f3b fix(query-tool): add MultiSelect and btn-sm styles to self-contained CSS
The MultiSelect component styles (.multi-select-*) and .btn-sm were
previously provided by resource-shared/styles.css which is no longer
loaded by the portal-shell native module registry for this route.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 14:28:40 +08:00
egg
db756eb333 refactor(query-tool): align UI to semantic CSS classes matching system-wide conventions
Convert all 18 query-tool Vue components from Tailwind utility classes to
semantic CSS classes (.header, .card, .btn-primary, .query-tool-tab, etc.)
consistent with reject-history, hold-overview, and other pages. Create
self-contained style.css with design tokens, base classes, and page-specific
styles. Fix portal-shell native module loader to load query-tool/style.css
instead of resource-shared/styles.css. Add CSS link tags to Django template
for standalone page rendering.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 13:56:14 +08:00
egg
5d570ca7a2 feat(admin-performance): Vue 3 SPA dashboard with metrics history trending
Rebuild /admin/performance from Jinja2 to Vue 3 SPA with ECharts, adding
cache telemetry infrastructure, connection pool monitoring, and SQLite-backed
historical metrics collection with trend chart visualization.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 09:18:10 +08:00
egg
1c46f5eb69 chore(openspec): archive query-tool change and commit remaining updates 2026-02-23 07:10:51 +08:00
egg
58e4c87fb6 feat(reject-history): two-phase query architecture with cached views
Replace per-interaction Oracle queries with a two-phase model:
- POST /query: single Oracle hit, cache full LOT-level DataFrame (L1+L2)
- GET /view: read cache, apply supplementary/interactive filters via pandas

Add container query mode (LOT/工單/WAFER LOT with wildcard support),
supplementary filters (Package/WC GROUP/Reason) from cached data,
PB_* series exclusion (was PB_Diode only), and query loading spinner.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-23 07:08:27 +08:00
egg
57a0b780b1 feat(query-tool): align lineage merge semantics and add tree exports 2026-02-23 07:07:36 +08:00
egg
3dc7886c90 fix(query-tool): show hold lot id via containername and align export 2026-02-22 18:32:07 +08:00
egg
bfec6b2293 feat(query-tool): align lot reject detail with reject-history layout 2026-02-22 18:17:44 +08:00
egg
97872cca97 fix(query-tool): finalize raw-material tab/export and resolve ORA-00918 2026-02-22 17:59:27 +08:00
egg
9890586191 feat(query-tool): align lineage model and tighten timeline mapping 2026-02-22 17:36:47 +08:00
egg
6016c31e4d fix(reject-history): improve Pareto top-80% filter and add detail table loading spinner
Pareto filter now includes the item that crosses the 80% threshold and
guarantees at least 5 items, so the chart stays useful when one reason
dominates (e.g. defect-only mode). Detail table shows a spinner overlay
while the list is refreshing.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 15:19:52 +08:00
egg
33ef58f833 fix(reject-history): resolve SPEC→WORKCENTER via lookup and fix Pareto reactivity
SQL CTEs now join on SPECNAME instead of WORKCENTERNAME to resolve
correct WORKCENTER/GROUP from DW_MES_SPEC_WORKCENTER_V, fixing cases
where the raw WORKCENTERNAME was mismatched (e.g. W/B-END with 成型_料).
WORKCENTER_GROUP filter converts groups→specs via cached mapping before
querying. Pareto chart now recalculates on legend toggle by spreading
the ECharts selected object to trigger Vue reactivity.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 14:31:02 +08:00
egg
5f6e2a5ce0 feat(reject-history): add detail columns, CSV export polish, and metric filter sync
Add EQUIPMENTNAME and REJECTCOMMENT columns to the detail table, list SQL,
and per-LOT base query. Rewrite CSV export to use per-LOT rows with Chinese
headers, BOM UTF-8 encoding, and fetch-based blob download with loading
spinner. Sync trend chart legend filter (reject/defect) to detail table and
export via metric_filter parameter through the full stack. Fix chart sizing
with containLabel and autoresize throttle.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 13:50:54 +08:00
egg
5e5cc487ac feat: archive filter strategy change and optimize reject-history filters 2026-02-22 12:50:05 +08:00
egg
7bf9e33cd5 feat: polish reject history UI and enhance WIP filter interactions 2026-02-22 11:54:51 +08:00
egg
9687deb9ad feat(query-tool): split serial reverse trace tab and use reverse lineage 2026-02-22 09:52:06 +08:00
egg
75fbdf2f88 fix(query-tool): lazy-load detail, multi-root trees, timeline UX overhaul
- Tree: render separate ECharts series per wafer-lot root instead of
  overlapping single-data trees
- Lazy loading: resolve builds tree only; detail/timeline load on node
  click to reduce initial resource consumption
- Timeline: group tracks by WORKCENTER_GROUP × LOT ID × Equipment with
  multi-line Y-axis labels (LOT ID + 機台編號)
- Timeline: backend enriches history rows with WORKCENTER_GROUP via
  filter_cache; timeRange derives only from history bars for dynamic
  updates on filter/selection change
- TimelineChart: teleport tooltip to body (fixed positioning) to prevent
  clipping; adaptive chart width scaling; edge-aware boundary detection
- Build script: add reject-history HTML copy; feature flag registered

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-22 09:13:56 +08:00
egg
05d907ac72 feat(reject-history): ship report page and archive openspec change 2026-02-13 20:35:52 +08:00
egg
7cbb155619 sync oracle metadata and register new ERP scrap tables 2026-02-13 17:52:59 +08:00
egg
248cbc25e0 fix(query-tool): batch detail loading, UX polish, and docs cleanup
- Fix multi-WO display: auto-select all tree roots after resolve so detail
  panel loads data for every work order, not just the first seed CID
- Disable scroll-wheel zoom on lineage tree (roam: 'move') to prevent
  accidental layout jumps while preserving drag-pan
- Add batch API endpoints (get_lot_history_batch, get_lot_associations_batch)
  to avoid N parallel requests hitting rate limits
- Remove redundant Split sub-tab from LOT detail (tree already shows splits)
- Rename 退貨 → 報廢 to match actual reject/scrap data semantics
- Hide internal ID columns (CONTAINERID, EQUIPMENTID, RESOURCEID) from
  history table display
- Add timeline scroll container and time range header for long timelines
- Remove obsolete migration and architecture docs no longer needed

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 17:42:11 +08:00
egg
5b358d71c1 feat(query-tool): rewrite frontend with ECharts tree, multi-select, and modular composables
Replace the monolithic useQueryToolData composable and nested Vue component tree
with a modular architecture: useLotResolve, useLotLineage, useLotDetail, and
useEquipmentQuery. Introduce ECharts TreeChart (LR orthogonal layout) for lot
lineage visualization with multi-select support, subtree expansion, zoom/pan,
and serial number normalization. Add unified LineageEngine backend with split
descendant traversal and leaf serial number queries. Archive the query-tool-rewrite
openspec change and sync delta specs to main.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-13 15:25:00 +08:00
egg
653900dc15 chore(deps): lock pandas to 2.3.3 and add upper bounds 2026-02-13 14:41:34 +08:00
egg
5a47bc87d8 fix(sql): remove colon prefix from SQL comments to prevent bind param errors, archive trace-progressive-ui
SQLAlchemy text() parses :param patterns in SQL comments as bind
parameters. When EventFetcher replaces the WHERE clause via string
substitution, orphaned :container_id in comments causes
"A value is required for bind parameter 'container_id'" errors.

Changes:
- Remove colon prefix from parameter names in SQL comments for
  lot_history, lot_rejects, lot_holds, lot_materials
- Archive trace-progressive-ui change (22/22 tasks complete)
- Sync delta specs to main: add trace-staged-api, progressive-trace-ux,
  merge api-safety-hygiene (+2 requirements)

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 16:53:54 +08:00
egg
519f8ae2f4 feat(lineage): unified LineageEngine, EventFetcher, and progressive trace API
Introduce a unified Seed→Lineage→Event pipeline replacing per-page Python
BFS with Oracle CONNECT BY NOCYCLE queries, add staged /api/trace/*
endpoints with rate limiting and L2 Redis caching, and wire progressive
frontend loading via useTraceProgress composable.

Key changes:
- Add LineageEngine (split ancestors / merge sources / full genealogy)
  with QueryBuilder bind-param safety and batched IN clauses
- Add EventFetcher with 6-domain support and L2 Redis cache
- Add trace_routes Blueprint (seed-resolve, lineage, events) with
  profile dispatch, rate limiting, and Redis TTL=300s caching
- Refactor query_tool_service to use LineageEngine and QueryBuilder,
  removing raw string interpolation (SQL injection fix)
- Add rate limits and resolve cache to query_tool_routes
- Integrate useTraceProgress into mid-section-defect with skeleton
  placeholders and fade-in transitions
- Add lineageCache and on-demand lot lineage to query-tool
- Add TraceProgressBar shared component
- Remove legacy query-tool.js static script (3k lines)
- Fix MatrixTable package column truncation (.slice(0,15) removed)
- Archive unified-lineage-engine change, add trace-progressive-ui specs

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 16:30:24 +08:00
egg
c38b5f646a feat(modernization): promote deferred routes to in-scope and unify page header styles
Promote /tables, /excel-query, /query-tool, /mid-section-defect from
deferred to full shell-governed in-scope routes with canonical redirects,
content contracts, governance artifacts, and updated CI gates.

Unify all page header gradients to #667eea → #764ba2 and h1 font-size
to 24px for visual consistency across all dashboard pages. Remove
Native Route-View dev annotations from job-query, excel-query, and
query-tool headers.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 13:20:06 +08:00
egg
0ed69ce326 fix(lot-detail): use actual data update time and add LF/wafer description fields
Hold Detail "Last Update" now reads dataUpdateDate from the API response
instead of using browser-local page load time. Lot Detail panels in both
WIP Detail and Resource Status tooltip now show LEADFRAMEDESC and WAFERDESC
from DWH.DW_MES_LOT_V, with multi-row values joined by ", ".

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 11:46:37 +08:00
egg
7cb0985b12 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 <noreply@anthropic.com>
2026-02-12 11:26:02 +08:00
egg
2c8d80afe6 feat(resource-status): enrich LOT tooltip with product/material info and draggable header
Add WIP detail API integration to FloatingTooltip for LOT popups, displaying
product info (Product, Product Line, Package, Workorder) and material info
(Wafer Lot ID, Wafer P/N, Leadframe, Compound) with client-side caching.
Make the tooltip header draggable for both LOT and JOB popups.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-02-12 08:40:21 +08:00