159 Commits

Author SHA1 Message Date
Elvis Wang
972c314656 feat: Web/API 指数入口与共享 canonical 去重基础 (#2312)
* feat: Web/API 指数入口与共享 canonical 去重基础

为 Issue #2303 Phase 2 PR1 落地 Web/API 指数入口适配:

- API 使用 parse_analysis_target 构造结构化 AnalysisTarget 并贯通到 pipeline
- API 与 TaskQueue 去重按 asset_type 分支(指数用 canonical_id,个股用 legacy code)
- BatchTaskAcceptedResponse 追加可选 rejected 字段,未登记 CSI 单股 400、批量仅该目标失败
- TaskInfo 固化 dedupe_key,避免指数与同码个股折叠及 _analyzing_stocks 残留
- Web 移除 assetType=index 全局过滤,Chat 名称识别保护指数 canonical
- 补齐 Pipeline 指数 DecisionSignal market_override=cn 真实分支测试

* fix: 收敛指数 canonical 身份与批量响应契约

PR #2312 review 修复:报告 meta 补充 asset_type 隐藏指数自选;/analyze 在解析前限制非空原始 token;is_single 统一驱动 metadata/409/单任务 202;HomePage 三元计数继续后续 chunk。

* fix: avoid double space in index news search query

* fix: preserve canonical index identity

* fix: validate legacy task asset type

* fix: preserve canonical index identity in chat

* fix: preserve index identity across chat backends
2026-09-01 19:25:15 +08:00
zhulinsen
ee2c113a1b feat: rebuild partial-data stock profile contract (#2308)
* feat: add partial-data stock profile contract

* fix: query stock profile aliases

* fix: converge US stock profile aliases

* fix: preserve stock profile intelligence coverage

* fix: preserve JP and KR profile identities

* fix: disambiguate profile persisted identities

* fix: complete offshore profile identities

* fix: isolate offshore profile identities

* fix: preserve Taiwan profile aliases

* fix: preserve explicit profile market identity

* fix: preserve market in history candidates

* fix: preserve stock profile research evidence

* fix: complete stock profile history evidence

* fix: reject conflicting stock profile identities

* fix: normalize persisted profile symbol filters

* fix: exclude ambiguous global stock aliases

* fix: deduplicate profile alias queries

* fix: exclude ambiguous profile history aliases

* fix: break stock profile import cycle

* fix: preserve market-unique legacy aliases
2026-08-30 20:38:33 +08:00
zhulinsen
0b5f9a6e31 feat: add research artifact contract (#2291)
* feat: add research artifact contract

* fix: preserve research artifact identity and falsey values

* fix: correct research artifact evidence quality
2026-08-29 17:20:25 +08:00
zhulinsen
0709b17ed1 feat: add data capability contract (#2289)
* feat: add data capability contract

* fix(review-feedback-2289): preserve unknown status until availability is checked and Make

* fix(review-feedback-2289): Aggregate daily quality across supported markets and add kline

* fix(review-feedback-2289): Honor daily-source circuit breakers in quality selection and Make

* fix(review-feedback-2289): Scope market-overview quality by market and Do not select a news

* fix: align data capability with runtime routes

* fix: align data capability runtime coverage

* fix: align source and index capability routes

* fix: preserve runtime capability uncertainty

* fix: include US index capability routes

* fix: align realtime and monitor capabilities

* fix: remove unsupported Tushare index capability

* fix: align capabilities with runtime routes

* fix: model realtime and breaker routes

* fix: align US realtime request priority

* fix: align realtime circuit coverage

* fix: filter unavailable daily priorities

* fix: align US realtime capability claims

* fix: align executable US data routes
2026-08-29 17:19:18 +08:00
wvyan
5bb3139209 fix: isolate runtime scheduler with portable watchdog (#2219)
* fix: isolate runtime scheduler with portable watchdog

* fix: harden runtime scheduler watchdog shutdown

* fix: prevent scheduled analysis after shutdown

* fix: fence scheduler shutdown and harden watchdog

---------

Co-authored-by: wvyan <13724623+wvyan@users.noreply.github.com>
2026-08-24 22:43:46 +08:00
青玉案
d0e66a1dc3 feat: 新闻检索为空时在报告中如实标注 (#2229)
* feat: 新闻检索为空时在报告中如实标注

消息面章节此前是「有内容才渲染」,检索一条没拿到时整段直接消失,
读报告的人无从判断是确实没新闻,还是检索静默失败了(搜索源限流、
未配置可用渠道等)。这把「抓取失败」呈现成了「确实没有新闻」。

- src/analyzer.py: AnalysisResult 新增 news_result_count,默认 None
- src/core/pipeline.py: 把 Step 4 已算好的计数交给结果对象
  (此前只进了 diagnostic context snapshot,报告层拿不到)
- src/notification.py: news_lines 为空且计数为 0 时,渲染明确提示,
  并说明结论未纳入新闻维度证据
- tests: 新增 5 条用例,含两条负例——计数为 None 时不得报警
  (那是未配置搜索渠道,不是失败)、拿到新闻时行为与改动前一致

不触碰任何检索路径,纯展示层增量。

* fix: 把新闻缺失提示放进真实渲染路径,并独立于模型输出判定

按 review 三条意见修正:

P1-1 提示只存在于 generate_daily_report,而正常流程从不调用它——
_send_single_stock_notification 与聚合报告走的是 dashboard / brief /
single_stock。原实现对所有标准 REPORT_TYPE 都不生效。
改为抽出共享判定 _empty_news_disclosure,四个渲染器统一接入。

P2 检索零命中但模型按 schema 写出了 market_sentiment / hot_topics 时,
原 elif 分支被跳过,报告会展示模型生成的情绪判断却隐瞒无新闻证据。
改为独立判定 news_result_count == 0,与模型是否产出文字无关。

P1-2 补 docs/CHANGELOG.md [Unreleased] 条目,并在
docs/data-source-stability.md 的「用户可见提示建议」一节记录该行为,
含 None / 0 / >0 三态语义表。

测试从 5 条增至 10 条,新增覆盖 dashboard、brief、single_stock 三个真实
渲染器,以及「模型有输出但检索为空」这一最糟组合。39 passed

* fix: 把新闻零命中披露覆盖到模板链路与企业微信入口

按 review 指出的 blocker 修正。此前只接了字符串拼接分支,遗漏两类活路径:

1. REPORT_RENDERER_ENABLED=true 时,generate_dashboard_report /
   generate_brief_report / generate_wechat_dashboard 会先 return render(...),
   模板链路一路不渲染披露;
2. generate_wechat_dashboard 的非模板 fallback 从未接入,而 pipeline 在
   企业微信非 brief 场景会直接调用它。

后果是同一份分析结果在部分渠道披露、在另一些渠道沉默。

改法不再逐点打补丁,而是抽出单一事实来源:

- 新增 src/services/empty_news.py 持有判定与中英文案
- src/notification.py 的 _empty_news_disclosure 改为委托该模块
- src/services/report_renderer.py 为每条结果预计算 empty_news_disclosure,
  三个平台模板共用
- templates/report_markdown.j2 / report_brief.j2 / report_wechat.j2 各加渲染分支
- generate_wechat_dashboard 的 fallback 正文接入披露

新增 6 条回归测试:模板链路三个平台各一条、企业微信入口一条,
外加两条负例(未执行检索时模板与企业微信均不得提示)。

本文件测试 10 → 16 全过;全量 5824 passed,9 个既有失败与本 PR 无关
(干净 main 上同样失败,属测试顺序依赖)。

* fix: 修正计数源头的两处缺口(自查发现)

按 review 的 merge-base..HEAD 方法自查全链路,发现此前几轮都只盯着渲染出口,
从未核对计数源头,而源头本身在两条路径上是错的:

1. src/core/pipeline.py: news_result_count 只在 intel_results 非空时赋值,
   搜索服务整体失败(正是所有搜索源限流全挂的场景)时停留在 None,
   语义为「未执行检索」,于是本 PR 想解决的头号场景反而不提示。
   改为检索一发起即置 0。

2. _analyze_with_agent: Agent 模式自行调用 search_stock_news 完成检索,
   却从不回写计数,该路径下零命中永远静默。改为按检索结果回写 0 或实际条数。

渲染层再周全,源头数据不对则全部落空。

新增 2 条测试锁住这两处语义(18 passed,此前 16)。
全量 5826 passed,9 个既有失败与本 PR 无关。

* fix: disclose missing news search configuration

* chore: remove unrelated agent guidance

* test: run all empty news tests directly

* fix: preserve empty news disclosure across reports

* fix: 让 Agent 模式的新闻披露跟随实际消费的证据

原问题:agent_arch=multi 等受支持的 Agent 配置下,报告可能声称「未纳入新闻
面证据」而分析其实用了新闻,或反过来该提示而不提示。

根因:news_result_count 取自 executor.run() 结束后为持久化情报补打的一次
search_stock_news()。真实情报由 IntelAgent 通过 search_comprehensive_intel
取得,两者不等价,因此披露与真实证据链可能相反。

修复点:新增 src/agent/news_evidence.py,以运行期证据作用域收集 Agent 搜索
工具的真实返回条数;搜索渠道不可用为 None(未执行检索),可用则从 0 起步、
拿到多少算多少。pipeline 在 executor.run() 前后开启并读取该作用域,事后的
持久化补查不再回写计数。

回归风险:工具在 ThreadPoolExecutor 中执行,runner.py 以
contextvars.copy_context() 提交,故作用域中必须是可变累加器对象,换成不可变
值会让父线程读不到;已加回归测试锁住该机制。原 test_agent_path_records_count
断言的正是被修复的错误行为,已替换为反向断言。

Refs #2225

* fix: 让新闻披露以实际证据为准而非搜索命中数

原问题:本地已落库的资讯池或社交情绪进入 news_context 参与分析后,报告仍可能
声称「未配置搜索渠道,本次分析未纳入新闻面证据」或「零命中」。

根因:news_context 由三路来源拼成——实时检索、社交情绪(美股)、本地资讯池,
但只有实时检索会更新 news_result_count。披露断言的是「结论有没有用到新闻面
证据」,而计数只是「搜索命中了几条」,两者是不同命题,后两路参与时必然失真。

修复点:AnalysisResult 新增 news_evidence_present,由 news_context 是否非空
得出,pipeline 两条路径共用 src/services/empty_news.news_evidence_present()
这一个判定函数。披露改为先看有无证据;确无证据时才用计数解释原因
(None=未配置渠道,0=检索零命中)。历史重建同步恢复该字段。

回归风险:旧记录没有该字段,按计数回退推断,与该记录当时的报告表现一致,不会
追溯改变旧报告;已有用例锁住。review 只点名了本地资讯池,社交情绪属同一缺陷类,
本次一并修复并加测试。另加源码断言:任一 pipeline 路径改回只传计数即失败。

Refs #2225

* fix: 按来源登记新闻证据,不让零命中占位文本冒充证据

原问题:普通分析链路在「搜索已执行但一条证据都没拿到」时,报告不再显示零命中
披露——正是本 PR 要修的核心场景,反而比改动前更差。

根因:src/search_service.py 的 format_intel_report() 即使所有维度失败或为空,
也会输出「【XX 情报搜索结果】」标题和每个维度的「未找到相关信息」占位文本,
整段永远非空。上一版把拼好的 news_context 整段交给 news_evidence_present()
判定,于是 news_result_count == 0 时 evidence 被翻成 true,披露被吞掉,错误
状态还会经 to_dict() 持久化,继续影响历史、详情 API 与 Web。

修复点:判定改为按来源逐个登记——实时检索的真实命中数、社交情绪内容、本地
资讯池内容,任一为真才算有证据;两条 pipeline 路径都不再传拼好的整段。
news_evidence_present() 的契约随之改为接收各来源,并在文档串里写明为什么不能
传整段。

回归风险:新增反例用真实的 format_intel_report() 产出占位文本(不用 mock),
断言其不得被判成证据、且报告必须出现零命中披露。另有源码断言:谁把整段
news_context 交回判定函数即失败。上一版两条测试实际在保护该缺陷(一条名为
「任何非空 context 都算证据」,一条要求必须传入 news_context),已一并纠正。

Refs #2225

---------

Co-authored-by: Mach-Chan <zz-b240@zz-b240deMacBook-Air.local>
2026-08-22 21:27:04 +08:00
Gach-Coder
f6b719d1fe 股票实体解析增强 (#2245)
Co-authored-by: zhulinsen <42829555+ZhuLinsen@users.noreply.github.com>
2026-08-22 21:23:55 +08:00
zhulinsen
46d5bf3472 fix: 恢复桌面端报告分享图 (#2169)
* fix: enable desktop report share images

* fix: include default share image branding

* fix(review-feedback-2169): Keep custom branding paired with its QR code

* fix: show default share image nickname

* fix(review-feedback-2169): Document the atomic branding fallback

* fix(review-feedback-2169): Remove the hard-coded social account default

* fix(review-feedback-2169): Remove the bundled account QR fallback

* fix(review-feedback-2169): update docs/share-images

* fix(review-feedback-2169): [Verification blocker] 当前 Head 的阻断型 CI

* fix(review-feedback-2169): 补一条回归:用包含超长 fenced-code 行和超长原始 URL 的完整/通用报告分别走 build share image html
2026-08-09 13:53:00 +08:00
lyl2104626211
ed848da6f0 feat: persist Agent Chat Skill selection by session (#2160)
* feat: persist Agent Chat skill selection by session

* test: satisfy ChatPage mock immutability lint

* fix: preserve implicit Skill state for legacy sessions

* fix: make top-level Skill selection authoritative

* fix: preserve session skills for invalid requests

---------

Co-authored-by: zhulinsen <42829555+ZhuLinsen@users.noreply.github.com>
2026-08-05 23:12:42 +08:00
zhulinsen
4dda5d7148 feat: add explicit Responses API channel routing (#2157) 2026-08-05 19:15:08 +08:00
zhulinsen
e430fcfe48 fix: 收敛选股排序、缓存与热点并发契约 (#2145)
* fix: stabilize screening ranking and hotspot workflows

* fix(review-feedback-2145): Stop timed-out constituent workers before returning and Keep the

* fix: close screening review contract gaps

* fix: bound screening hotspot search workers

* fix(review-feedback-2145): [Verification blocker] 当前 Head 的阻断型 CI 已最终失败:backend-gate。请在本地运行对应

* fix: close screening contract review gaps

* fix: unify hotspot timeout contracts

* fix: bound hotspot search end to end

* fix: bound hotspot detail fallbacks
2026-08-02 18:32:30 +08:00
zhulinsen
91988da149 feat: 添加报告分享图片与 Web 一键分享 (#2146)
* feat: add report image sharing

* fix(review-feedback-2146): 评审结论 - 代码检查 :当前整个 PR 仍有 2 个未关闭的高置信度代码 blocker。最新复核摘要:基于 merge-base

* fix(review-feedback-2146): preserve the Markdown fallback for unavailable snapshots and preserve

* fix(review-feedback-2146): 补一组通知回归测试,至少覆盖

* fix(review-feedback-2146): 在源码树执行 npm ci 和 npx playwright install chromium,这与预编译 desktop 发行包环境不一致

* fix(review-feedback-2146): 评审结论 - 代码检查 :当前整个 PR 仍有 1 个未关闭的高置信度代码 blocker。最新复核摘要:基于 merge-base

* fix(review-feedback-2146): 补上明确的 CLI/Chromium 安装提示,避免当前日志和 503 文案继续把用户引向

* fix(review-feedback-2146): 补到与 docs/share-images.md 一致,直接提示 cd apps/dsa-web && npm ci 和 npx
2026-08-02 16:45:37 +08:00
Nicholas-Xiong
5edee53550 fix(#1970): 关闭认证强制要求当前管理员密码二次确认 (#2050)
* fix(#1970): 关闭认证强制要求当前管理员密码二次确认

后端 api/v1/endpoints/auth.py 的 auth_update_settings 在 disable 路径上即使携带有效 session cookie 也强制要求 current_admin_password,否则返回 400;密码错误统一返回 401,命中 rate limit 与 enable 路径一致返回 429。enable 与 initial setup 路径行为保持不变。

前端 AuthSettingsCard 在关闭认证场景下若 currentPassword 缺失,submit 按钮保持可点击(disabled 仅由 isDirty 决定),handleSubmit 校验后给出内联错误,避免用户面对一个长期 disabled 的按钮但不知所缺。新增 i18n key settings.authDisableRequiredCurrentPassword 中英文本,同步修订 authHelperTurnOff / authPasswordHintOff 文案以反映新契约,并避免 hint 文案与 inline error 文案完全重复导致测试 findByText 多匹配。

测试覆盖:

- tests/test_auth_api.py 新增 disable 路径在有/无 session、有/无 current_password、密码对错、rate limit 命中 6 种分支用例,全部通过。

- apps/dsa-web/__tests__/AuthSettingsCard.test.tsx 把原 'missing current password when session valid' 反向为 'blocks disabling when current password missing',并补 'disables auth with current password provided'。本机 vitest run AuthSettingsCard.test.tsx 6/6 通过。

issue #1970

* test(#1970): 关闭认证回归补真实 ASGI 端到端用例并清理无效 mock

针对 PR #2050 review 反馈,补齐两条回归用例并修正既有用例的误导性 mock:

1. 删除 AuthApiTestCase 三个 valid-session 用例中对 verify_session 的 patch。
   Disable 分支不会调用 verify_session(仅在 enable 分支的 TOCTOU 复检里用到),
   旧 mock 既不生效也容易让读者误以为 disable 路径会做 session 校验。

2. 新增 AuthDisableViaRealASGITestCase 通过真实 ASGI / AuthMiddleware / auth
   路由组合链路(create_app + httpx.ASGITransport,与 test_api_health.py 同路径)
   验证 Issue #1970 修复:
   - 真实 POST /api/v1/auth/login 拿到签名 cookie 后,仅带 session 不带
     currentPassword 调 /api/v1/auth/settings 关闭认证 -> 400 current_required;
   - 同上下文携带正确 currentPassword 关闭认证 -> 200,.env 翻转至
     ADMIN_AUTH_ENABLED=false,响应头携带 Set-Cookie 轮换 session secret。

3. 同步 /api/v1/auth/settings OpenAPI description:明确「关闭认证时
   currentPassword 必填、有效 session 不足够」这一新契约,与 endpoint
   行为及 Issue #1970 上下文对齐。

测试:tests/test_auth_api.py 35/35 全过。

* test(auth): fix rate-limit trigger test — needs MAX+1 iterations to reach 429

Previously range(RATE_LIMIT_MAX_FAILURES) ran only 5 iterations, but
check_rate_limit returns False only when count >= MAX. This means the
5th request enters with count=4 (4 < 5), passes check_rate_limit,
runs verify_stored_password + record_login_failure, and returns 401.
Only a 6th request - entering with count=5 (5 >= 5) - is rejected
early by check_rate_limit and returns 429.

Fix the loop range to RATE_LIMIT_MAX_FAILURES + 1 and update the
assertion: the first MAX attempts return 401 (each recording a
failure), and the final attempt returns 429. Also normalise a
mixed Chinese/English docstring to English-only. 35 tests pass.

* test: tighten ASGI auth disable coverage

- Drop the middleware-is_auth_enabled patch now that the endpoint
  disables auth by rotating the session secret in a single in-memory
  transition. Subsequent middleware checks in the same client see the
  disabled state via the auth module, so the patch was masking a
  state-leak instead of testing the real path.
- Make the positive disable test assert cookie deletion semantics
  (empty value + Max-Age=0/Expires-past + jar cleared) instead of just
  a presence check on Set-Cookie. A leaked pre-disable cookie must not
  remain usable after disable, and the previous assertion would still
  pass if the endpoint rotated to a fresh session id.

* test(auth): strip surrounding quotes when asserting empty dsa_session value

Starlette's delete_cookie serializes the empty cookie value as
dsa_session=""; Max-Age=0; ... — i.e. with surrounding double quotes.
The previous assertion expected the raw value to equal '' and so
failed on CI (which uses Starlette's stock serializer); locally the
TestClient happened to round-trip the same way but the strip happened
to make the assertion spuriously true (or the assertion was correct
against an older Starlette). Strip surrounding double quotes before
comparison so the test matches the actual deletion-form emitted by
delete_cookie.

* docs(changelog): move #1970 entry to [Unreleased] + drop 5 stray 3.28.0 文档段 entries

OR-COR-3defa936 blocker fix: 上轮 commit (`5219a43b`) 把 6 条 bullet 错误地追加到了已发布的 `## [3.28.0] - 2026-07-26` -> `### 文档` 段落,而不是 `[Unreleased]`。其中:

- 1 条属于本 PR (#1970) — 应放进 [Unreleased]
- 5 条属于其他 PR / issue (#2026 / #1985 / #2051 / Windows mimetypes / TUSHARE_HTTP_URL 工作流映射),且这些条目在 `3.28.0` 的 `### 新功能` / `### 改进` / `### 修复` 段已经发布过,再放进 `### 文档` 段属于重复 + 跨段误归类。

修复:
- 删除 `3.28.0 -> ### 文档` 段下的 6 条新增 bullet,恢复该段原本只剩「修复文档中的失效相对链接。」的 upstream/main 原貌;
- 在 `[Unreleased]` 段追加本 PR 的 #1970 单条扁平条目(与仓库约定一致:本 PR 自身只追加自身条目,不替其他 PR 处理)。

合并后 `docs/CHANGELOG.md` 的 `3.28.0 -> ### 文档` 段恢复 1 条原貌;`[Unreleased]` 段只新增 1 条本 PR 的条目,不再污染已发布版本历史。

* chore: trigger CI re-run after changelog fix (e01e0cf7 didn't fire pull_request event)

---------

Co-authored-by: xxiaoxiong <xxiaoxiong@users.noreply.github.com>
2026-08-01 14:33:38 +08:00
zhulinsen
bcb7ae4e13 feat: 将参考 AlphaSift 的选股实现纳入主项目 (#2136)
* feat: integrate built-in stock screening engine

* test: verify screening routes via public contract

* refactor: make screening integration fully native

* fix(review-feedback-2136): [Verification blocker] 当前 Head 的阻断型 CI 已最终失败:backend-gate。请在本地运行对应

* feat: persist screening runs and reuse DSA analysis

* fix(review-feedback-2136): 对选股重排应用统一的模型参数兼容逻辑

* fix(review-feedback-2136): 将字段缺失计入数据源失败

* fix(review-feedback-2136): 评审结论 - 代码检查 :当前整个 PR 仍有 3 个未关闭的高置信度代码 blocker。最新复核摘要:当前整个 PR 仍有 3

* fix(review-feedback-2136): 延迟写入候选直到覆盖率通过校验 and 将 DSA 日线成功结果写入 last-good 缓存

* fix(review-feedback-2136): 将直连日线源纳入统一调用超时 and 将新增的选股缓存目录加入桌面更新备份

* fix(review-feedback-2136): 保留完整热点缓存而非请求切片 and 遵守 DSA 上下文声明的候选上限

* fix(review-feedback-2136): 补一条端到端回归:把真实 ScreenResult 经 ScreeningService.screen 落到 /history 和

* fix(review-feedback-2136): 补一个 refresh=true 且 live fetch 失败时返回 stale cache 的回归测试,避免当前只更新 stale
2026-08-01 14:13:23 +08:00
zhulinsen
2643d47a96 fix: 让 Agent Chat 默认遵循 REPORT_LANGUAGE (#2102)
* fix: apply report language to agent chat defaults

* fix(review-feedback-2102): Treat null report language as missing and update those
2026-07-26 16:02:42 +08:00
zhulinsen
189b2fc3a1 fix: 补齐 Web 钉钉群机器人配置 (#2106)
* fix: expose DingTalk webhook settings

* fix(review-feedback-2106): 同步更新钉钉 Web UI 配置文档
2026-07-26 15:32:34 +08:00
lyl2104626211
68fc575f15 feat: 支持 Web/API 按市场触发大盘复盘 (#2074)
* feat: add request-scoped market review regions

* fix: keep server default runtime-resolved

* fix: trace market review regions through task lifecycle

---------

Co-authored-by: zhulinsen <42829555+ZhuLinsen@users.noreply.github.com>
2026-07-25 22:14:15 +08:00
Alfred
aa68d45d7f feat: add decision profile outcome calibration (#2072) 2026-07-23 19:21:23 +08:00
yejmin
b275b4ebea fix: prevent mimetypes hang on Windows by skipping registry init (#2059)
Co-authored-by: E <e@local.com>
Co-authored-by: zhulinsen <42829555+ZhuLinsen@users.noreply.github.com>
2026-07-22 23:36:06 +08:00
Alfred
628c5b6ef7 feat: add Codex App Server agent prototype (#2004) 2026-07-19 16:31:54 +08:00
Alfred
487e49e565 feat: 支持保存决策风格重评估结果 (#2014)
* feat: persist decision profile reassessment signals

* fix: align reassess persistence outcomes and lifecycle
2026-07-16 19:22:14 +08:00
Kushida
44371c2961 fix: delete all history records by stock code (#1987)
* fix: delete all history records by stock code

* fix: reject blank history stock codes

---------

Co-authored-by: zhulinsen <42829555+ZhuLinsen@users.noreply.github.com>
2026-07-12 15:02:54 +08:00
zhulinsen
6da1360a0b feat: 重建市场结构上下文 (#1981)
* feat: rebuild market structure context

* fix(review-feedback-1981): apps/dsa-web/src/components/report/MarketStructureCard.tsx 新增用户可见界面,但

* fix(review-feedback-1981): apps/dsa-web/src/components/report/MarketStructureCard.tsx 新增用户可见界面,但

* fix(review-feedback-1981): Scope in-flight ranking keys to each fetcher manager

* fix(review-feedback-1981): 修正无证据情况下的个股层级判定,并按仓库规范补充可访问的 Web 页面截图、更新 PR 描述事实

* fix(review-feedback-1981): apps/dsa-web/src/components/report/MarketStructureCard.tsx 新增用户可见界面,但

* fix(review-feedback-1981): 按 AGENTS.md 为新增市场结构卡片补充可直接查看的截图,并同步 PR 描述中的 diff 与 CI 事实

* fix(review-feedback-1981): apps/dsa-web/src/components/report/MarketStructureCard.tsx 新增用户可见界面,但

* fix(review-feedback-1981): 按仓库规范补充可直接审查的市场结构卡片截图,并同步 PR 描述中的 diff 与 CI 事实

* fix(review-feedback-1981): apps/dsa-web/e2e/market-structure-card-visual.spec.ts:276 在

* fix(review-feedback-1981): apps/dsa-web/e2e/market-structure-card-visual.spec.ts 将本 PR

* fix(review-feedback-1981): 同步当前 Head 的 diff/CI 结论,并按仓库规范在 PR 描述或评论中附可访问的市场结构卡片截图

* fix(review-feedback-1981): apps/dsa-web/e2e/market-structure-card-visual.spec.ts:261 新增 async 空对象解构

* fix(review-feedback-1981): 按仓库规范在 PR 描述或评论中附市场结构卡片的可访问截图,并同步当前 diff 统计和 CI 结果

* fix(review-feedback-1981): 消除当前运行结果对历史持久化成功的依赖,补充对应回归测试,并补齐可访问的 UI 截图及更新失真的 PR 描述

* fix(review-feedback-1981): src/utils/data processing.py 提取榜单时丢弃了上游 boards / concept boards 的

* fix(review-feedback-1981): 修正 PR 描述并补齐可访问的视觉证据

* fix(review-feedback-1981): 关闭市场结构前置数据获取可能阻塞主分析的问题,并同步修正 PR 描述、范围清单和视觉证据

* fix(review-feedback-1981): 将 PR 描述、完整范围、当前 CI 证据、视觉证据及回滚表述同步到最新 Head

* fix(review-feedback-1981): PR 描述与最新 Head 不一致:完整 diff 包含 38 个文件及 src/services/analysis

* fix(review-feedback-1981): 按最新 Head 同步 PR 描述,并补充可访问的市场结构卡片截图证据

* fix(review-feedback-1981): 统一即时响应与历史响应的 details.raw result 契约并补最终 API 回归测试,同时更新 PR 描述和可访问的视觉证据

* fix(review-feedback-1981): 将 PR 描述、完整范围、CI 结果及可访问的 UI 截图同步到最新 Head,消除描述与实际改动的实质性不一致

* fix(review-feedback-1981): 同步 PR 描述与最新 Head,并补充可访问的 Web 页面截图

* fix(review-feedback-1981): 同步 PR 描述并按仓库规范附上可访问的 Web 页面截图

* fix(review-feedback-1981): 代码结论 :不可。已按 origin/main...76b5b596fdff 的完整 38 文件 diff 重新建立基线。上次 6 个

* fix(review-feedback-1981): 代码结论 :不可。最新修复已正确收窄无成分股、无龙头证据的原生榜单路径:该路径现在返回 edge/partial,不再直接输出
2026-07-12 11:30:59 +08:00
zhulinsen
01ebf70a10 feat: add reliable home watchlist workspace (#1984)
* feat: add reliable home watchlist workspace

* fix(review-feedback-1984): Don't trust stale stock-bar rows after refresh failures

* fix(review-feedback-1984): apps/dsa-web/src/stores/stockPoolStore.ts 的 refreshStockBar

* fix(review-feedback-1984): Clear loading when refresh supersedes initial stock-bar load

* fix(review-feedback-1984): Type stock-bar test fixtures as StockBarItem and 跟进结论 - 结论 :不接受;最新

* fix(review-feedback-1984): tying the Today fetch to the same refresh path while this tab is
2026-07-11 21:45:04 +08:00
Alfred
7c17a242f0 feat: field decision signal profiles (#1967) 2026-07-10 22:05:10 +08:00
zhulinsen
8ff8124990 fix: speed up portfolio snapshot loading (#1914) 2026-07-04 12:10:41 +08:00
zhulinsen
a3e1b9e3ba fix: normalize watchlist separators (#1912) 2026-07-04 11:57:43 +08:00
zhulinsen
282efa18e1 fix: preserve zero sentiment score alignment (#1900)
* fix: preserve zero sentiment score alignment

* fix(review-feedback-1900): 修正 docs/CHANGELOG.md 中与本 PR 无关的条目,避免把未包含在当前 diff 的功能/修复写入本 PR and
2026-07-04 09:23:18 +08:00
zhulinsen
83b8154d0a fix: 评分建议过度归为持有,需收敛 hold/watch/buy/sell… (#1885) (#1887)
* fix(issue-1885): [bug]-评分建议过度归为持有,需收敛-hold/watch/buy/sell

* fix(review-feedback-1887): 澄清/修正评分与 action 的契约一致性问题,并补齐高风险路径的验证说明

* fix(review-feedback-1887): 补一句排除说明,避免和 AGENTS 对外部依赖/运行时配置变更需说明兼容、迁移与回退路径的要求产生歧义

* fix(review-feedback-1887): CI 当前未通过:结构化事实显示 backend-gate:failure,PR 描述中的本地验证也写明 test:TIMEOUT
2026-07-03 20:24:13 +08:00
sh1water
116d09e727 feat(agent): standardize stream progress events (#1871)
* feat(agent): standardize stream progress events

* docs(agent): document stream progress events

* docs: sync changelog with upstream main

* fix(web): render failed agent stages as non-success

* fix(agent): align stream stage lifecycle

* test(agent): stabilize timeout stream event clock

* fix(agent): split budget skip stream event

* docs(agent): document budget skip stream event

---------

Co-authored-by: Hzf <huangzhenfan666@163.com>
2026-07-03 19:37:51 +08:00
Alfred
7b39b73b9d feat: add generation backend status diagnostics (#1883) 2026-07-03 19:34:43 +08:00
Alfred
2e4c03e52d feat: add decision signal reassess preview (#1877) 2026-07-02 18:56:08 +08:00
HyunRyeol Park
043c60378e feat: 报告输出语言新增韩语支持 (Korean report language, ko) (#1614) (#1844)
* feat(i18n): add Korean to report language label maps

Extend the report language layer with a third code `ko` so reports can
render deterministic labels in Korean. Adds `ko` to the supported list,
aliases (korean/kr/ko-kr), every translation map, the full report label
set, sentiment bands, the config registry enum and `.env.example`.
`zh`/`en` behavior is unchanged and unknown languages still fall back to
the default. Prompt and Web surfaces follow in later changes.

Refs #1614

* feat(i18n): emit Korean output directives in analysis prompts

Make the analysis and market-review prompts produce Korean output when
REPORT_LANGUAGE=ko. The decision agent now appends a Korean
output-language directive (JSON keys and decision_type enum unchanged),
and the market-review prompt reuses the English structural scaffolding
while instructing the model to write the shell, headings and conclusion
in Korean. Market-phase and context-pack prompt sections route ko to the
English structural base. The market-review payload keeps the truthful
language code via a dedicated output-language helper, leaving zh/en
behavior unchanged.

Refs #1614

* fix(i18n): localize phase and market-context guardrails for Korean

Route Korean reports through the English structural scaffolding for
market-phase and market-context prompt sections, and add Korean output,
detection markers, negations and recap patterns to the phase-decision and
daily-market-context guardrails so they operate on Korean model output.
Confidence and operation labels now flow through the shared localize
helpers. zh/en behavior is unchanged.

Refs #1614

* feat(i18n): localize Korean fallback output across analysis pipeline

Add Korean output to the deterministic strings emitted outside the LLM:
per-stock and executor output-language directives, no-API-key / backend
/ parse error fallbacks, hold-watch advice and reasons, market-review
titles and summaries, and history and notification report labels. Fund
flow, trend and confidence values now flow through the shared localize
helpers, and language-keyed advice tables no longer raise KeyError for a
third language. Structural prompt sections route ko to the English
scaffolding. zh/en output is unchanged.

Refs #1614

* feat(web): add Korean report language rendering

Extend the Web ReportLanguage type with ko and add Korean copy to the
report detail surfaces: report text, sentiment labels, market-phase
labels, analysis-context summary, market-review view, diagnostics and
news source. Run-flow chrome that is keyed by UI language falls back to
English for ko. The report-language selector is driven by the backend
config schema, so Korean appears automatically. zh/en rendering is
unchanged.

Refs #1614

* docs(i18n): document Korean report language support

Note that REPORT_LANGUAGE accepts ko in the bilingual guides and the
analyze / market-review request-language parameters, and add a
CHANGELOG entry for Korean report output.

Refs #1614

* fix(i18n): canonicalize Korean values and accept ko in API schemas

Add Korean aliases to the operation-advice, trend, confidence, chip and
bias canonical maps so Korean model output (매수/매도/보유/관망 etc.)
resolves to the correct decision_type and signal level instead of
falling back to hold or a score-band signal. Accept ko in the
analyze, market-review and decision-signal request schemas (and the
static API spec) so the typed client and backend agree and per-request
Korean analysis is not rejected with 422.

Refs #1614
2026-06-30 19:02:46 +08:00
zhulinsen
a448886f67 fix: restore stock bar summary badges (#1848) 2026-06-29 21:18:02 +08:00
zhulinsen
3fddbd8fbc fix: clarify JP KR service boundaries (#1823)
* feat: add JP KR market review support

* fix: clarify JP KR service boundaries

* fix(review-feedback-1823): add the fields to the response schema and cover the endpoint path, not

* fix(review-feedback-1823): Avoid routing JP/KR reviews through MarketLight schema

* fix(review-feedback-1823): add JP/KR to that resolver when accepting these values

* fix(review-feedback-1823): Keep JP/KR daily contexts from normalizing to CN and add JP/KR labels

* fix(review-feedback-1823): 解决冲突后再合入

* fix(review-feedback-1823): 解决冲突并确认最终 diff 后再评审合入

* fix(review-feedback-1823): 澄清或补齐验证证据

* fix(review-feedback-1823): 解决冲突,并在冲突解决后的 head 上重新确认关键验证结果

* fix(review-feedback-1823): Make the Chinese JP/KR prompt shell region-aware

* fix(review-feedback-1823): 解决冲突后再判断最终 head 是否可合入

* fix(review-feedback-1823): 基于目标分支解决冲突,并在冲突后的最终 diff 上重新确认相关后端/Web 检查

* fix(review-feedback-1823): 修复

* fix(review-feedback-1823): 解决冲突

* fix(review-feedback-1823): 解决冲突后再合入

* fix(review-feedback-1823): 解决冲突后再合入

* fix(review-feedback-1823): Make the all-markets checkbox exclusive

* fix(review-feedback-1823): 解决冲突,并在冲突解决后的最新 head 上重新确认关键测试和 Web 构建结果

* fix(review-feedback-1823): 解决冲突并确保解决后的 head 重新通过对应验证

* fix(review-feedback-1823): 解决冲突,并在冲突解决后重新确认受影响的后端、Web 与文档改动仍一致

* fix(review-feedback-1823): 解决冲突,再基于最新 base 复核完整 diff,并重新确认相关后端/Web 验证结果仍成立

* fix(review-feedback-1823): 解决冲突后重新确认最终 diff 与 CI 结果

* fix(review-feedback-1823): 收敛

* fix(review-feedback-1823): 基于目标分支解决冲突并重新确认关键验证结果

* fix(review-feedback-1823): 解决

* fix(review-feedback-1823): 收敛

* fix(review-feedback-1823): 解决冲突后重新确认 diff 与 CI

* fix(review-feedback-1823): 补充本次未改变哪些配置契约、对应测试覆盖和回退方式

* fix(review-feedback-1823): 收敛

* fix(review-feedback-1823): PR 描述与实际 diff scope 仍不完全对齐:完整改动包含

* fix(review-feedback-1823): 解决冲突并在冲突后的最终 diff 上重新确认 CI/关键测试结果

* fix(review-feedback-1823): 解决冲突并确认解决后的 diff 与现有 43 个文件 scope 仍一致

* fix(review-feedback-1823): 解决冲突后再合入

* fix(review-feedback-1823): 解决冲突,并在最终 head 上重新确认受影响的后端与 Web 验证结果

* fix(review-feedback-1823): 解决冲突并确认冲突解决后的最终 head 仍通过对应验证

* fix(review-feedback-1823): 处理旧 both 历史记录在 JP/KR 复盘上下文匹配中的语义兼容风险
2026-06-28 18:53:39 +08:00
Alfred
62adb5c4ee feat: add Hermes local HTTP generation (#1824) 2026-06-28 17:02:17 +08:00
zhulinsen
03fe7a00a9 feat: 补齐大盘报告与 Web 个股页的概念板块展示 (#1764) (#1778)
* feat(issue-1764): feat:-补齐大盘报告与-web-个股页的概念板块展示

* fix(review-feedback-1778): 确认历史报告 fallback 路径是否完整透传 conceptRankings,否则会出现新字段在部分历史详情/API 场景中静默丢失

* fix: render market review industry and concept rankings side-by-side

* fix: refine related board display and concept ranking cache
2026-06-27 23:07:18 +08:00
zhulinsen
ef9371003c feat: harden JP/KR suffix market support (#1817)
* feat: harden JP/KR suffix market support

* fix: define yfinance index quote metadata

* fix(review-feedback-1817): Handle JP 4-digit bare-code lookup in analysis paths

* fix(review-feedback-1817): Route 4-digit JP bases through API normalization

* fix(review-feedback-1817): 补齐外部 API/provider/运行时配置风险说明或证明该检测为误报
2026-06-27 22:10:08 +08:00
zhulinsen
ebf340a519 fix: serve frontend js with javascript mime (#1808) 2026-06-27 17:09:06 +08:00
Wenyu Chiou
cb72be7408 feat(market): bring tw to first-class on decision-signal / portfolio / intelligence (service + API + frontend) (#1801)
Follow-up to the #1773 data-layer MVP (Taiwan suffix-only detection + routing,
merged in 2086e3c). That MVP deferred the service/API/frontend layers, leaving a
live defect: tw was absent from the DecisionSignal/Portfolio service VALID_MARKETS,
so _normalize_market("tw") raised ValueError on the decision-signal write path.
The analysis pipeline auto-extracts a DecisionSignal after history save
(_extract_decision_signal_after_history_save), so every tw analysis silently
failed to persist a signal while jp/kr succeeded -- tw was the only
yfinance-supported market that could be analyzed but never produced a signal.

Converge the tw market contract for DecisionSignal + Portfolio + Intelligence in
one pass (mirroring jp/kr #1720), per the human review on #1801 asking not to
land it piecemeal:

Backend service + API:
- src/services/{portfolio,intelligence}_service.py: VALID_MARKETS /
  _ALLOWED_MARKETS + _normalize_market error strings accept tw
- src/services/decision_signal_service.py: _normalize_market error string
  (VALID_MARKETS is imported from portfolio_service, so the set change propagates)
- src/services/decision_signal_extractor.py: drop the now-stale "(e.g. tw)" guard
  comment (tw is supported; the guard still protects genuinely-unsupported markets)
- api/v1/schemas/{decision_signals,intelligence,portfolio}.py: Pydantic Literals + tw
- api/v1/endpoints/decision_signals.py + docs/architecture/api_spec.json: market
  filter description + DecisionSignalMarket enum gain tw; test_api_schema_pydantic
  exact-match vs create_app().openapi() passes (api_spec kept CRLF)

Frontend (DecisionSignal + Portfolio typed consumers only; tsc + vitest pass):
- apps/dsa-web/src/types/{decisionSignals,portfolio}.ts + pages/{DecisionSignalsPage,
  PortfolioPage}.tsx + utils/{decisionSignalLabels,stockCode}.ts + i18n/uiText.ts:
  add tw to the DecisionSignalMarket / portfolio market unions, the market filter
  options, the tw display label, and .TW/.TWO stock-code normalization
- the alert Market-Light surface (types/alerts.ts MarketRegion, featureText
  ALERT_MARKET_REGION_*) is intentionally LEFT OUT: the backend market_light_service
  is cn/hk/us only, so exposing tw there would be a front/back mismatch

Tests:
- flip the two #1773 graceful-skip regressions to first-class assertions and add
  test_extract_and_persist_writes_tw_signal (end-to-end persist guard)
- frontend: PortfolioPage + stockCode vitest gain tw cases

Docs (reconcile the tw contract so changelog/topic docs/code state one fact):
- docs/CHANGELOG.md: rewrite the #1772 [Unreleased] entries so they no longer say
  "service/API deferred" + "tw gracefully skipped" alongside "tw now supported"
- docs/market-support.md, docs/decision-signals.md, docs/intelligence-sources.md:
  sync the tw market enum / filter / examples; keep the boundary note

Still deferred (separate follow-ups): the Taiwan stock-index/seed + Web autocomplete,
and the alert (大盘红绿灯) Market-Light tw support (needs a market_light backend change).

Refs #1772
2026-06-26 21:21:38 +08:00
zhulinsen
b308e44827 fix: repair backtest empty result handling (#1779) 2026-06-24 21:52:07 +08:00
mumu
f2e778c058 feat: 支持客户端多时间定时推送 (#1731)
* feat: support runtime multi-time scheduling

* fix(review-feedback-1731): 修复 and add the missing workers value here, likely None to preserve the

* fix: refine scheduler settings UI

* fix: compact scheduler time inputs

* fix(review-feedback-1731): Refresh scheduler status after saving changes

* fix(review-feedback-1731): Refresh scheduler status after env imports

* fix(review-feedback-1731): Do not mark swallowed analysis failures as success

* fix: align serve scheduler ownership

* fix: preserve runtime scheduler startup semantics

* fix: ignore immediate run when cli owns schedule

* fix(review-feedback-1731): main.py + api/app.py:--serve-only 下虽然 runtime schedule requested 被置为

* fix(review-feedback-1731): apps/dsa-desktop/main.js / main.py / api/app.py / src/services/runtime

* fix: preserve runtime scheduler ownership semantics

* fix(review-feedback-1731): 修正 Desktop 启动会自动分析/调度,以及 Web 调度开关在 runtime 状态与持久配置不一致时无法触发 reconcile 的问题

* fix: remove duplicate scheduler save diff variable

* fix: allow empty schedule times config

* fix: reject busy scheduler run-now requests

* fix(review-feedback-1731): 确认并修正 runtime scheduler 重建时可能重复注册 AGENT EVENT MONITOR ENABLED 后台任务的问题

* fix: keep runtime event monitor idempotent

* fix: preserve runtime scheduler CLI flags

* fix(review-feedback-1731): preserve schedule CLI flags in runtime runs

* fix(review-feedback-1731): 修正 --serve --schedule / --serve + SCHEDULE ENABLED=true 下 API

* fix(review-feedback-1731): 修复当前 diff 引入的运行时并发风险和 Uvicorn 兼容风险
2026-06-21 22:24:19 +08:00
mumu
0ab94a8c3e fix: support KR stock autocomplete suggestions (#1723)
* fix: support KR stock autocomplete suggestions

* fix(review-feedback-1723): 补充自动补全 JP/KR 建议渲染截图、前后对比或无法截图说明

* fix(review-feedback-1723): 补充 Web 自动补全 JP/KR 建议渲染的截图或无法截图说明

* fix(review-feedback-1723): docs/review-evidence-kr-autocomplete-ui.md 是针对本 PR

* fix(review-feedback-1723): 修正 PR 描述与当前 head 的实际改动、验证范围不一致问题

* fix(review-feedback-1723): 修正 PR 描述与当前 diff 的实质性不一致,避免合入记录误导后续维护者

* fix(review-feedback-1723): 收敛 PR 描述与实际 diff 的契约不一致,避免用户误以为裸 005930 已会解析为 005930.KS

* fix(review-feedback-1723): 把描述、验证证据和兼容性说明收敛到当前 6 个改动文件真实范围,或补齐描述中声称的后端/历史链路实现与测试

* fix(review-feedback-1723): 收敛 PR 描述与实际 diff,避免把未实现的 bare-code/历史展示能力作为本 PR 已交付内容合入

* fix(review-feedback-1723): 补上相应真实代码与测试后再审

* fix(review-feedback-1723): 补齐所声称的后端实现与测试后再评审

* fix(review-feedback-1723): PR description 与当前完整 diff 不一致:描述声称新增 bare JP/KR code

* fix(review-feedback-1723): PR 描述与当前完整 diff 不一致

* fix(review-feedback-1723): 补充 Refs 1718,方便后续追踪

* fix(review-feedback-1723): 收敛描述与验证证据

* fix: resolve JP KR bare stock codes

* fix: backfill JP KR daily analysis context

* fix(review-feedback-1723): preserve persisted phase timing

* fix: align JP KR history lookup keys

* fix(review-feedback-1723): preserve raw code for snapshot lookups

* fix(review-feedback-1723): 收敛
2026-06-20 10:39:40 +08:00
Alfred
bc673b0ddb docs: close out decision signal p7 (#1727) 2026-06-20 10:37:35 +08:00
mumu
9ea2dab7ad fix: backfill report decision signals (#1719)
* fix: backfill report decision signals

* fix(review-feedback-1719): 确认并修复“不明确建议”可能被默认回填成 hold 信号的正确性风险 and persist the report date in

* fix(review-feedback-1719): 修复 legacy decision type 被当作明确 action 导致误回填的问题

* fix(review-feedback-1719): Prevent stale backfills from staying active

* fix(review-feedback-1719): anchor the same metadata-based TTL that default expires at uses to the

* fix(review-feedback-1719): 修复或明确处理懒回填时间锚点的时区/时间域不一致风险
2026-06-19 13:26:52 +08:00
mumu
e49301a79f feat: 支持日本/韩国 suffix-only 个股分析 (#1720)
* feat: support JP/KR suffix stock analysis

* fix(review-feedback-1720): 解决冲突后再合入
2026-06-19 11:59:59 +08:00
Alfred
a7876fe11c feat: link decision signals with alerts and portfolio risk (#1715)
Co-authored-by: mumu <42829555+ZhuLinsen@users.noreply.github.com>
2026-06-19 09:43:40 +08:00
mumu
626b63c144 feat: feed intelligence sources into analysis contexts (#1709)
* feat: add intelligence source ingestion baseline

* feat: feed local intelligence into analysis contexts

* fix(review-feedback-1708): Reject DNS names that resolve privately and Validate redirect targets

* fix(review-feedback-1709): 处理大盘复盘本地资讯可能被搜索结果截断掉的问题,并澄清结构化检测到的外部模型/API 或运行时配置风险是否为真实变更

* fix(review-feedback-1708): Pin DNS resolution before fetching and Stream feeds before enforcing

* fix(review-feedback-1709): filter by published at for analysis evidence, or keep missing publish

* fix(review-feedback-1708): Sanitize fetch errors before returning them and Normalize nullable

* fix(review-feedback-1709): Normalize symbol scope before lookup

* fix(review-feedback-1708): Avoid rolling back prior item inserts on duplicate races and Reject

* fix(review-feedback-1709): Use the effective news window for local evidence and add the plain

* fix(review-feedback-1708): 落地可配置 RSS/Atom 情报源、存储、查询、retention 和基础安全边界

* fix(review-feedback-1709): 补充“revert 本 PR 或移除本地资讯接入入口/清退本地资讯源配置数据”级别说明即可

* fix(review-feedback-1708): 落地 RSS/Atom 情报源的存储、拉取、查询、retention 和基础安全边界

* fix(review-feedback-1709): 补 Refs 1707

* fix(review-feedback-1709): 解决冲突后再合入

* fix(review-feedback-1709): src/services/intelligence service.py 回退了资讯源 URL 安全防护:移除了 hostname DNS

* fix: harden intelligence source ingestion

* fix(review-feedback-1709): Sanitize upstream fetch errors before returning them

* feat: add NewsNow intelligence sources

* fix(review-feedback-1709): 确认并修复

* fix(review-feedback-1709): 补一个未命中敏感规则的异常回归测试

* fix(review-feedback-1709): 处理

* docs: enhance NEWSNOW_BASE_URL compatibility guidance with official links

- Add official NewsNow GitHub deployment guide link to .env.example
- Include curl-based API contract verification example for production validation
- Update CHANGELOG.md with official repository reference and deployment recommendation
- Clarify risk of public example instance and necessity for self-hosted in production
- All HTTP 500 responses already use sanitize_diagnostic_text for privacy

Ref #1707
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>

* fix(review-feedback-1709): 补齐官方 NewsNow 实例链接文档或 API 契约确认,明确指出公开实例风险(需结合当前部署指南文档,更新 .env.example

---------

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
2026-06-19 09:42:42 +08:00
mumu
cd37608506 feat: add intelligence source ingestion baseline (#1708)
* feat: add intelligence source ingestion baseline

* fix(review-feedback-1708): Reject DNS names that resolve privately and Validate redirect targets

* fix(review-feedback-1708): Pin DNS resolution before fetching and Stream feeds before enforcing

* fix(review-feedback-1708): Sanitize fetch errors before returning them and Normalize nullable

* fix(review-feedback-1708): Avoid rolling back prior item inserts on duplicate races and Reject

* fix(review-feedback-1708): 落地可配置 RSS/Atom 情报源、存储、查询、retention 和基础安全边界

* fix(review-feedback-1708): 落地 RSS/Atom 情报源的存储、拉取、查询、retention 和基础安全边界
2026-06-18 21:43:33 +08:00
Alfred
1f9ce289d2 feat: 新增 DecisionSignal 反馈、后验验证与统计 P5 (#1710)
* feat: add decision signal outcomes and feedback

* fix: align outcome filters and retry rotation
2026-06-18 21:23:11 +08:00