* chore: enforce flat format for [Unreleased] section in CHANGELOG to reduce merge conflicts
* chore: address review comments - append hint and flexible type in CHANGELOG format
* feat(web): truncate long stock names in history list
Display truncated stock names with a trailing dot (max 15 English / 8
Chinese / 10 mixed chars). Show full name on hover. Extract truncation
logic to utils/stockName with full test coverage.
(cherry picked from commit 76cf05db841dc8ee39436e0ba9cd86be2690252c)
* fix(web): remove redundant title attribute in HistoryListItem
The title attribute is no longer needed since truncateStockName
already handles long stock names properly.
* refactor(web): consolidate stockName variable usage in HistoryListItem
Unified duplicate item.stockName || item.stockCode expressions to use
the pre-computed stockName variable. Also added CHANGELOG entry
* feat(web): extract phase-0 design tokens and stabilize shell baseline
Background:
- PR9 needed a stable styling foundation before page-level polish could be grouped coherently.
- The web shell still mixed early layout DNA with page-local treatments, which made later visual cleanup noisy.
What changed:
- Extracted the initial phase-0 style tokens into the shared stylesheet baseline.
- Tightened shell and sidebar-adjacent framing so shared layout surfaces have a cleaner default edge treatment.
- Aligned common header and toolbar primitives with the phase-0 styling baseline.
- Added the cn utility test coverage that belongs with the shared styling foundation.
Why this grouping:
- These changes form the lowest-level visual baseline for the rest of the PR9 cleanup work.
- Keeping them together makes later page-focused commits easier to review and to revert independently.
Validation:
- Not run in this history-cleanup step; final branch verification will cover lint and build checks.
Risk:
- Shared shell and global stylesheet adjustments can affect multiple pages at once if any token mapping is off.
* refactor(web): restore settings theme consistency and light-mode hierarchy
Background:
- The settings area had drifted away from the restored theme system, especially in light mode where hierarchy, borders, and field framing no longer matched the password and auth surfaces.
- PR9 needed a dedicated settings pass so later page cleanup would not keep reintroducing local fixes.
What changed:
- Re-aligned settings cards, category navigation, field rows, and loading states with the shared theme baseline.
- Restored theme-toggle behavior and tightened the visual contract around settings-specific inputs and editors.
- Normalized related shared controls used by settings forms so select and badge treatments match the refreshed theme hierarchy.
- Updated the main stylesheet to give settings light-mode surfaces clearer spacing, contrast, and resting borders.
Why this grouping:
- These changes are all part of one coherent settings-theme recovery pass.
- Keeping settings recovery separate from chat, home, and backtest polish makes the later review path much easier to reason about.
Validation:
- Not run in this history-cleanup step; final branch verification will cover lint and build checks.
Risk:
- Theme hierarchy adjustments in shared form controls may subtly affect any page that reuses the same select or badge defaults.
* feat(web): add shared status primitives and refine chat-home interaction surfaces
Background:
- PR9 needed reusable status and tooltip primitives before the remaining page-level cleanup could converge on one visual language.
- Chat and home still carried a mix of page-local interaction cues, making report surfaces and message flow harder to keep consistent.
What changed:
- Added shared Tooltip and StatusDot primitives and wired them into the common component exports.
- Hardened tooltip rendering around report surfaces so overlays no longer clip inside constrained containers.
- Refined chat message flow, action affordances, session controls, and progress cues to support the non-blocking interaction model.
- Tightened home and report-facing surfaces, including shared card and input treatments that support the updated report hierarchy.
- Updated the related chat and home tests that move with these interaction changes.
Why this grouping:
- These changes all depend on the same shared primitive layer and mainly affect chat, home, and report-facing interaction surfaces.
- Keeping them in one commit isolates the reusable UI foundation from the later state-unification and final regression passes.
Validation:
- Not run in this history-cleanup step; final branch verification will cover lint and build checks.
Risk:
- Shared tooltip behavior, report surface styling, and chat interaction flow are cross-cutting and can regress multiple views if any container assumptions changed.
* refactor(web): unify empty states, status feedback, portfolio-backtest surfaces, and coverage
Background:
- After the shared primitive pass, PR9 still had fragmented state presentation across home, portfolio, backtest, and adjacent navigation flows.
- Empty states, task/status feedback, and portfolio/backtest surfaces needed to converge before the final regression cleanup could be reviewed sanely.
What changed:
- Unified empty-state and status-feedback treatments across home, task, portfolio, and backtest flows.
- Brought portfolio and backtest surfaces closer to the shared input-surface and table styling conventions, including the remaining page-level polish for their primary layouts.
- Tightened supporting shared components and sidebar behavior that participate in the refreshed state presentation.
- Added and expanded smoke, sidebar, backtest, and portfolio-related test coverage that belongs with this behavior shift.
- Updated the global stylesheet to carry the state, alert, and table refinements that power these pages.
Why this grouping:
- These changes are one coherent pass over the state-feedback layer and the portfolio/backtest page family.
- Keeping them together isolates the broad PR9 convergence work from the final light-theme regression fixes that follow.
Validation:
- Not run in this history-cleanup step; final branch verification will cover lint and build checks.
Risk:
- This commit touches multiple status-bearing pages and shared stylesheet rules, so regressions would most likely show up in empty states, task badges, table surfaces, or auth smoke flow assumptions.
* fix(web): close final light-theme regressions in login and chat presentation
Background:
- After the broader PR9 convergence work, a final pass was still needed to remove light-theme readability regressions and presentation rough edges in login and chat-adjacent surfaces.
- These were the last visible issues before the branch could be treated as a coherent PR9 cleanup line.
What changed:
- Restored light-theme contrast and text hierarchy in the affected login, chat history, and supporting content surfaces.
- Refined chat heading presentation and the sentiment gauge glow so the final visual hierarchy is clearer without adding new interaction patterns.
- Added the lightweight UI-governance coverage that belongs with these final presentation constraints.
- Applied the small follow-up stylesheet and tooltip adjustments required to support the final polish.
Why this grouping:
- These changes are intentionally limited to the last regression-fix pass rather than another broad refactor.
- Keeping them in one final commit makes the cleanup history easier to review and gives a clear rollback point for the last-mile polish.
Validation:
- Not run in this history-cleanup step; final branch verification will cover lint and build checks.
Risk:
- The remaining risk is concentrated in light-theme readability and chat-adjacent presentation details, especially where shared text and gauge styling overlap.
* fix(web): restore remaining PR9 state-feedback parity after regrouping
Background:
- The history regrouping left a small set of state-feedback and page-surface files out of sync with the original PR9 branch.
- Those differences were accidental cleanup omissions rather than intended design changes, so they need an explicit parity restore commit.
What changed:
- Restored the remaining Home, Portfolio, Settings, and task/status presentation updates to match the original PR9 branch content.
- Brought the supporting stylesheet and home-page test expectation back to parity with the source branch.
- Reinstated the intended SettingsAlert and page-level state-feedback treatments that belonged in the PR9 convergence work.
Why this grouping:
- These changes are a narrow parity-recovery pass caused by the history rewrite itself.
- Keeping them together makes it obvious that the commit exists to eliminate cleanup drift rather than introduce new behavior.
Validation:
- Not run in this history-cleanup step; final branch verification will cover lint and build checks.
Risk:
- The remaining risk is limited to state-feedback presentation on Home, Portfolio, and Settings, because this commit only restores source-branch parity for those areas.
* fix(web): keep chat message actions reachable on touch devices
* update docs
* fix(web): restore login page light theme
* fix(web): restore login theme tokens
* fix(auth): use rightmost X-Forwarded-For entry to prevent rate-limit bypass (CWE-345)
When TRUST_X_FORWARDED_FOR=true, get_client_ip() previously took the
leftmost (index [0]) entry from the X-Forwarded-For header. An attacker
can inject arbitrary leftmost values to rotate rate-limit buckets and
bypass brute-force protection on the login endpoint.
Change to [-1] (rightmost entry) which is the IP appended by the trusted
reverse proxy and cannot be controlled by the attacker.
* fix: address review feedback — add CHANGELOG entry, update deployment docs for XFF trust scope
* fix: move CHANGELOG entry from [3.10.1] to [Unreleased] section
* fix: align .env.example TRUST_X_FORWARDED_FOR comment with single-proxy security semantics
---------
Co-authored-by: mumu <42829555+ZhuLinsen@users.noreply.github.com>
- add a pre-hydration theme bootstrap in apps/dsa-web/index.html so the app sets html.dark before React mounts when no saved preference exists, while still respecting saved light/dark values
- introduce a scoped login appearance for the shared Input component so login inputs, labels, icons, placeholders, caret color, password bullets, and visibility toggle styling no longer inherit global theme text tokens
- migrate the login page to dedicated --login-* visual tokens to keep its dark presentation stable even when the global theme cache is light
- extend frontend tests to cover the login input appearance and the index.html theme bootstrap contract
- update docs/CHANGELOG.md for the user-visible behavior change
Co-authored-by: mumu <42829555+ZhuLinsen@users.noreply.github.com>
* fix: accept HK autocomplete codes on home analysis input
The home page stock input accepted plain A-share codes but rejected Hong Kong stocks selected from autocomplete. The root cause was that autocomplete submits the suggestion canonicalCode (for example 00700.HK), while the backend stock code utility only recognized .SH/.SZ/.SS suffixes. As a result, 00700.HK was treated as mixed alphanumeric noise and rejected with the generic validation error before analysis dispatch.
Extend shared stock code recognition and normalization to accept .HK suffixes alongside existing A-share suffixes. This keeps the existing manual input behavior for 00700 and makes the backend consistent with the canonicalCode format already used by the web stock index and autocomplete flow.
Add regression coverage on both sides of the boundary: backend contract tests now verify that trigger_analysis accepts 00700.HK from autocomplete and HK00700 from manual input, and frontend tests now verify that highlighted HK suggestions submit the canonical .HK code and are not rejected by local store validation.
* update CHANGELOG.md
* fix: align HK code validation with existing market rules
Follow up the home page HK autocomplete fix by tightening the shared stock code validator so exchange suffixes and prefixes no longer reuse the same generic 5-6 digit rule.
This change keeps SH/SZ/SS suffixes restricted to 6-digit mainland codes, treats HK suffixes and HK prefixes as 1-5 digit Hong Kong codes with zero-padding during normalization, and rejects invalid cross-market combinations such as 600519.HK, HK600519, and 00700.SH.
Add regression coverage for valid short HK forms like 1810.HK and HK700, plus negative tests for invalid suffix and prefix lengths, so the shared backend utility stays consistent with the existing web validation and data-provider normalization rules.
* feat(web): consolidate dashboard, chat, and backtest UI improvements
- polish dashboard follow-up pages and shared UI states across home, chat, and backtest flows
- consolidate chat and backtest page layout, styling, and interaction improvements into a single web UI update
- improve follow-up context handling in chat and add broader regression coverage for dashboard and chat components
- refine text color and opacity usage across shared components for more consistent readability
- restore home page mobile scrolling after the broader UI refactor changed page overflow behavior
- update related tests and changelog entries to reflect the finalized web interaction and styling changes
* feat(ui): optimize light theme shadows, navigation, alerts, and chat bubble styles
- Soften light mode box-shadows globally, replacing hardcoded grays with dynamic CSS variables for a cleaner, non-muddy depth effect.
- Unify SidebarNav active item style: remove inset shadow, apply primary background, and use bold font for better visibility.
- Fix ApiErrorAlert and InlineAlert contrast in light mode: use deep red text for high legibility, and robust dark/light theme CSS variables.
- Fix ThemeToggle menu z-index (z-40) in Shell to prevent overlap by main content pages (e.g., Settings, Backtest).
- Refactor ChatPage avatars and message bubbles to use dedicated dual-theme CSS classes (.chat-avatar-*, .chat-bubble-*).
- Add distinct borders to User/AI chat avatars with lowered opacity in dark mode to prevent visual glare.
- Add subtle borders to AI message bubbles in light mode to enhance separation, preserving semi-transparent borders in dark mode.
* fix(web): restore picker flows and align chat/report interactions
- restore intelligent import file picker behavior and add regression coverage
- align report markdown E2E expectations with the current UI
- improve markdown plain-text extraction used by report export flows
- fix chat session history deletion accessibility by separating row selection and delete actions into independent native buttons
- add chat history regression tests for keyboard-accessible deletion behavior
- deduplicate shared action button variant styles without changing the public Button variant API
- keep user-facing web interactions consistent after recent UI updates
* fix(web): resolve dashboard build issue and speed resolver benchmarks
- remove duplicate notify fields from useHomeDashboardState to fix the dsa-web TypeScript build
- keep the theme toggle button disabled in the current UI state
- cache local name-to-code indexes and fast-return on ambiguous local stock names
- split resolver performance coverage into fast-path and typo-fallback benchmarks with warm-up steps and smaller iteration budgets
* update README.md
- Add notify field to AnalyzeRequest schema (default: true)
- Pass notify as execution param through task_queue to analysis_service
- Add notify checkbox next to analyze button in HomePage
- Add notify state and setter to stockPoolStore
The LLM system prompts were hardcoded to "A 股" (China A-shares),
causing analysis of US and HK stocks to produce incomplete or
incorrect content.
Add src/market_context.py with market detection from stock codes
and market-specific role descriptions + trading rule guidelines.
Update the three system prompts in executor.py and analyzer.py
to dynamically inject the correct market context.
Co-authored-by: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat(autocomplete): refactor index generator to support Tushare and multi-market
* docs: update changelog and README for multi-market autocomplete
- Add Unreleased entries for Tushare stock list fetcher, multi-market
index generation scripts, and updated index data
- Update README to reflect A-share/HK/US coverage instead of
A-share-only first phase
- Add examples for HK and US stock autocomplete (tencent, aapl)
- Reference TUSHARE_STOCK_LIST_GUIDE.md for index update workflow
* fix: deduplicate US autocomplete symbols
* Merge feature/report-markdown-toolbar into feature/report-markdown-toolbar-fix
Conflicts:
- apps/dsa-web/src/pages/__tests__/HomePage.test.tsx: kept upstream dynamic button text
- docs/CHANGELOG.md: merged both sets of changelog entries
* fix: use remove-markdown library to preserve underscores in variable names
Replace regex-based markdown parsing with remove-markdown library to fix
the bug where underscores in variable names (e.g. stock_code, api_key_v2)
were incorrectly stripped. The original regex implementation treated
single underscores as Markdown italic markers.
Refs #785
* update CHANGELOG.md
* feat: add Slack as a first-class notification channel
* fix: guard Slack image delivery with _should_use_image_for_channel()
* fix: require SLACK_CHANNEL_ID in workflow config check
* docs: add Slack channel entry to CHANGELOG and fix README_CHT nav link
* fix: use Slack new file upload API for image delivery
* fix: update Slack image test for new upload API, add slack to md2img example
* fix: send raw bytes to Slack upload URL and unify bot/webhook precedence
* docs: unify Slack Bot > Webhook precedence across all docs
* docs: add Slack config entries and setup guide to full-guide (zh/en)
Add SLACK_BOT_TOKEN, SLACK_CHANNEL_ID, SLACK_WEBHOOK_URL rows to both
config tables (GitHub Actions + local run) and a dedicated Slack setup
section with Bot-first precedence, mirroring the existing Discord
section structure. Applied to both full-guide.md and full-guide_EN.md.
* feat: register Slack config fields in config_registry for Web settings
Add SLACK_BOT_TOKEN, SLACK_CHANNEL_ID, SLACK_WEBHOOK_URL to
_FIELD_DEFINITIONS (display_order 36-38, between Discord and Pushover)
so /api/v1/system/config/schema and the Web settings page can expose
them. Add SLACK to _infer_category() notification prefix list.
New test file test_config_registry.py (6 cases) verifies field
registration, sensitivity flags, display ordering, and schema response
inclusion — prevents future channels from shipping without UI exposure.
* fix: use password control for SLACK_WEBHOOK_URL to prevent plaintext leak
SLACK_WEBHOOK_URL was marked is_sensitive=True but ui_control was text,
inconsistent with DISCORD_WEBHOOK_URL and other sensitive Webhook fields.
The Web settings page would display the URL in plaintext.
Also added a registry-wide regression test: any is_sensitive field must
use ui_control=password, preventing future channels from repeating this.
* feat(autocomplete): rebuild web autocomplete mvp
* feat(autocomplete): add error boundary and runtime fallback
Add error boundary and runtime error handling to improve autocomplete stability:
- Add StockAutocompleteBoundary class component to catch render errors
- Add FallbackInput component for graceful degradation
- Add runtimeFallback state and error handling in useAutocomplete hook
- Wrap search logic with try-catch to prevent crashes
- Add comprehensive tests for error scenarios
This ensures the autocomplete degrades to a plain input when:
- Index loading fails (existing behavior)
- Runtime search throws (new)
- Component tree throws during render (new)
* feat(autocomplete): add input validation and optimize name resolution
- Add early rejection for obviously invalid mixed alphanumeric input
- Skip expensive AkShare/fuzzy fallback for non-CJK free text
- Enhance frontend validation with isObviouslyInvalidStockQuery
- Increase minimum query length from 1 to 2 characters
- Add comprehensive test coverage for validation logic
- Update E2E test placeholder text to reflect new capabilities
These changes address code review feedback about:
- Preventing abuse from invalid input patterns
- Improving performance by avoiding unnecessary network calls
- Ensuring consistent validation between frontend and backend
* fix(autocomplete): harden input validation and runtime guards
* update doc
* style(autocomplete): adjust suggestion item hover effect
- Reduce hover background opacity from 35% to 25% for lighter visual effect
- Brighten hover color in dark theme from #257280 to #2dcae6
* fix(autocomplete): do not auto-highlight first suggestion to preserve raw input on Enter
* test(home): align report fixture with report language metadata
* fix: unify task queue stock dedupe key
* feat: add configurable report language
* Fix review follow-ups for history and fallback localization
* fix: prefer .env report language at startup
* fix: address report language review feedback
* fix: address latest report language review feedback
* fix: harden agent runtime and config handling
* fix: restore cors test import and update review status
* fix: close remaining agent timeout gaps
* fix: align agent timeout defaults and fallback budget
* feat(theme): establish theme-aware design system and normalize UI tokens
* refactor(web): implement stockPoolStore and modernize dashboard architecture
* feat(web): enhance analysis follow-up flow and user experience
* test(web): fix layout regressions and strengthen automated coverage
* update CHANGELOG.md
* feat(ChatPage): enhance follow-up context handling and update tests for hydration logic.
update CHANGELOG.md
* feat(AuthContext): update login logic to reset dashboard state based on auth status
test(AuthContext): add test for dashboard state reset behavior when auth is enabled
feat(stockPoolStore): implement request sequencing to ignore late history responses
* fix(web): harden dashboard task sync and follow-up flow