docs: close analysis context pack P6 (#1592)

This commit is contained in:
Alfred
2026-06-04 12:37:48 +08:00
committed by GitHub
parent 6784409183
commit 3281d96788
13 changed files with 237 additions and 18 deletions

View File

@@ -623,6 +623,10 @@ SQLITE_WRITE_RETRY_MAX=3
# SQLite 写入重试基础退避时间(秒,按指数退避递增)
SQLITE_WRITE_RETRY_BASE_DELAY=0.1
# 分析历史快照:设为 false 时不持久化整份 context_snapshot
# 包括 enhanced_context、market_phase_summary、AnalysisContextPack overview、diagnostics 和 raw snapshot 字段
SAVE_CONTEXT_SNAPSHOT=true
# ===================================
# 回测配置(可选)
# ===================================

View File

@@ -962,6 +962,18 @@ const settingsHelpZhCN: SettingsHelpMap = {
impact: ['影响分析总耗时。'],
notes: ['总耗时 ≈ 股票数 × 单股耗时 + (股票数-1) × ANALYSIS_DELAY。'],
},
'settings.system.SAVE_CONTEXT_SNAPSHOT': {
title: '保存分析上下文快照',
summary: '控制是否将分析历史的整份 context_snapshot 持久化到数据库。',
usage: '默认开启。关闭后,新历史记录不会保存 enhanced_context、market_phase_summary、AnalysisContextPack overview 或运行诊断快照等 context_snapshot 内容。',
valueNotes: [
'关闭后新历史记录的历史详情、completed 任务状态和 Web 报告页无法读取低敏输入数据块摘要。',
'该开关不关闭当次 AnalysisContextPack 构建,也不关闭 LLM Prompt 中的低敏 pack summary。',
'CLI 的 --no-context-snapshot 与设为 false 的持久化效果一致。',
],
impact: ['影响历史透明度、回测/诊断可用的上下文快照信息和 Web 报告页的数据来源摘要。'],
notes: ['若需要完全关闭 P3-P5 pack 接入,需要回滚相关代码;当前没有运行时 pack 总开关。'],
},
'settings.system.market_review': {
title: '大盘分析',
summary: '控制大盘分析功能的开关、覆盖市场和配色方案。',
@@ -1876,6 +1888,18 @@ const settingsHelpEnUS: SettingsHelpMap = {
impact: ['Affects total analysis time.'],
notes: ['Total time ≈ stock count × per-stock time + (count-1) × ANALYSIS_DELAY.'],
},
'settings.system.SAVE_CONTEXT_SNAPSHOT': {
title: 'Save Context Snapshot',
summary: 'Controls whether the full analysis history context_snapshot is persisted to the database.',
usage: 'Enabled by default. When disabled, new history records do not persist enhanced_context, market_phase_summary, AnalysisContextPack overview, diagnostic snapshots, or other context_snapshot content.',
valueNotes: [
'When disabled, history detail, completed task status, and Web report pages cannot read low-sensitivity input-block summaries from persisted records.',
'This switch does not disable AnalysisContextPack construction for the current run and does not remove the low-sensitivity pack summary from LLM prompts.',
'The CLI --no-context-snapshot flag has the same persistence effect as setting this to false.',
],
impact: ['Affects historical transparency, diagnostics that rely on context snapshots, and Web report data-source summaries.'],
notes: ['To disable the P3-P5 pack integration itself, roll back the related code; there is no runtime pack master switch.'],
},
'settings.system.market_review': {
title: 'Market Review',
summary: 'Controls the market review feature: on/off, coverage region, and color scheme.',

View File

@@ -132,6 +132,7 @@ const fieldTitleMap: Record<string, string> = {
MARKET_REVIEW_REGION: '大盘复盘市场',
MARKET_REVIEW_COLOR_SCHEME: '大盘复盘涨跌颜色',
ANALYSIS_DELAY: '分析启动延迟(秒)',
SAVE_CONTEXT_SNAPSHOT: '保存分析上下文快照',
SCHEDULE_TIME: '定时任务时间',
DEBUG: '调试模式',
HTTP_PROXY: 'HTTP 代理',
@@ -278,6 +279,7 @@ const fieldDescriptionMap: Record<string, string> = {
MARKET_REVIEW_REGION: '大盘复盘默认市场区域(如 cn/us/hk。',
MARKET_REVIEW_COLOR_SCHEME: '控制大盘复盘指数涨跌幅图标颜色green_up 为绿涨红跌red_up 为红涨绿跌。',
ANALYSIS_DELAY: '启动任务前的延迟秒数,可用于等待依赖服务就绪。',
SAVE_CONTEXT_SNAPSHOT: '控制是否持久化整份分析历史 context_snapshot关闭后不会保存低敏输入概览、市场阶段摘要和增强上下文但不影响当次分析的 pack 构建或 Prompt 摘要。',
SCHEDULE_TIME: '每日定时任务执行时间,格式为 HH:MM。',
DEBUG: '启用调试模式,输出更多诊断日志。',
HTTP_PROXY: '网络代理地址,可留空。',

View File

@@ -1,4 +1,5 @@
import { describe, expect, it } from 'vitest';
import { getSettingsHelpContent } from '../src/locales/settingsHelp';
import { getFieldDescriptionZh, getFieldOptionLabelZh, getFieldTitleZh } from '../src/utils/systemConfigI18n';
const requiredLocalizedKeys = [
@@ -65,6 +66,7 @@ const requiredLocalizedKeys = [
'MARKET_REVIEW_ENABLED',
'MARKET_REVIEW_REGION',
'ANALYSIS_DELAY',
'SAVE_CONTEXT_SNAPSHOT',
'DEBUG',
'AGENT_NL_ROUTING',
'AGENT_DEEP_RESEARCH_BUDGET',
@@ -139,3 +141,21 @@ describe('systemConfigI18n option label localization', () => {
});
});
});
describe('SAVE_CONTEXT_SNAPSHOT settings help contract', () => {
it('describes the persistence boundary without implying old records are changed', () => {
const help = getSettingsHelpContent('settings.system.SAVE_CONTEXT_SNAPSHOT', undefined, 'zh-CN');
const text = [
help?.summary,
help?.usage,
...(help?.valueNotes ?? []),
...(help?.impact ?? []),
...(help?.notes ?? []),
].join('\n');
expect(text).toContain('新历史记录');
expect(text).toContain('不关闭当次 AnalysisContextPack 构建');
expect(text).toContain('不关闭 LLM Prompt');
expect(text).not.toContain('旧记录');
});
});

View File

@@ -15,6 +15,8 @@ and this project adheres to [Semantic Versioning](https://semver.org/).
<!-- 每条独立一行追加到本段末尾,无需分类标题,合并时冲突最小 -->
- [改进] #1386 P6 复用市场阶段与 AnalysisContextPack 公开摘要联动告警、持仓手动分析、历史、回测和通知展示,不新增数据库迁移。
- [文档] 明确 AnalysisContextPack P6 文档、迁移与回滚边界,并同步既有 `SAVE_CONTEXT_SNAPSHOT``.env.example`、配置注册表、Web 设置帮助和完整指南。
## [3.20.0] - 2026-06-03
### 发布亮点

View File

@@ -42,7 +42,7 @@
| [Bot 命令与接入](bot-command.md) | Bot 命令、Webhook、平台接入和回调说明 |
| [Bot 平台配置](bot/) | 飞书、钉钉、Discord 等 Bot 配置截图和补充说明 |
| [实时告警中心](alerts.md) | EventMonitor 基线、Web 规则管理、通知结果、冷却状态和 Phase 边界 |
| [分析上下文包契约、运行态消费与可见性](analysis-context-pack.md) | AnalysisContextPack 首版范围、字段质量状态、P1/P2 内部契约、P3 Prompt 摘要消费、P4 历史/API/Web 低敏可见性、P5 数据质量评分与源码锚点 |
| [分析上下文包契约、运行态消费与可见性](analysis-context-pack.md) | AnalysisContextPack 首版范围、字段质量状态、P1/P2 内部契约、P3 Prompt 摘要消费、P4 历史/API/Web 低敏可见性、P5 数据质量评分、P6 迁移回滚与源码锚点 |
| [图片识别 Prompt](image-extract-prompt.md) | 图片识别股票信息的 Prompt 与使用边界 |
| [OpenClaw Skill 集成](openclaw-skill-integration.md) | OpenClaw / Skill 外部集成说明 |

View File

@@ -43,7 +43,7 @@ This is the entry point for project documentation. The README covers the project
| [Bot Commands (EN)](bot-command_EN.md) | Bot commands, webhooks, platform integration, and callback behavior |
| [Bot Platform Docs](bot/) <sub><sub>![P2 Badge](https://img.shields.io/badge/P2-yellow?style=flat)</sub></sub> (Chinese-only) | Feishu, DingTalk, Discord, and related Bot configuration screenshots and notes |
| [Real-Time Alert Center](alerts.md) <sub><sub>![P4 Badge](https://img.shields.io/badge/P4-yellow?style=flat)</sub></sub> (Chinese-only) | EventMonitor baseline, Web rule management, notification attempts, cooldown state, and phase boundaries |
| [Analysis Context Pack Contract, Runtime Consumption, And Visibility](analysis-context-pack.md) <sub><sub>![P5 Badge](https://img.shields.io/badge/P5-orange?style=flat)</sub></sub> (Chinese-only) | AnalysisContextPack first-scope boundaries, field quality states, P1/P2 internal contracts, P3 prompt-summary consumption, P4 history/API/Web low-sensitivity visibility, P5 data-quality scoring, and source anchors |
| [Analysis Context Pack Contract, Runtime Consumption, And Visibility](analysis-context-pack.md) <sub><sub>![P6 Badge](https://img.shields.io/badge/P6-orange?style=flat)</sub></sub> (Chinese-only) | AnalysisContextPack first-scope boundaries, field quality states, P1/P2 internal contracts, P3 prompt-summary consumption, P4 history/API/Web low-sensitivity visibility, P5 data-quality scoring, and P6 migration/rollback notes, plus source anchors |
| [Image Extraction Prompt](image-extract-prompt.md) <sub><sub>![P2 Badge](https://img.shields.io/badge/P2-yellow?style=flat)</sub></sub> (Chinese-only) | Prompt and boundaries for extracting stock information from images |
| [OpenClaw Skill Integration](openclaw-skill-integration.md) <sub><sub>![P2 Badge](https://img.shields.io/badge/P2-yellow?style=flat)</sub></sub> (Chinese-only) | OpenClaw / Skill external integration notes |

View File

@@ -1,6 +1,6 @@
# AnalysisContextPackP0 盘点、P1/P2 契约、P3 Runtime Consumption、P4 可见性、P5 数据质量与 P6 联动
# AnalysisContextPackP0 盘点、P1/P2 契约、P3 Runtime Consumption、P4 可见性、P5 数据质量、#1386 P6 联动与 #1389 P6 迁移回滚
本页是 Issue #1389 的专题文档,用于记录当前 DSA 分析上下文的真实来源、消费路径、字段状态边界,以及 `AnalysisContextPack` 内部契约、builder、运行态消费、低敏可见性数据质量评分边界。P0 负责现状盘点和契约边界P1 只新增内部 schema/envelope、block catalog、类型约定和脱敏序列化P2 只从 pipeline 已有 artifacts 组装 packP3 只把低敏摘要接入普通分析和 Agent 初始 PromptP4 只把低敏 overview 接入历史详情、同步分析响应、completed task status 和 Web 报告页P5 在同一 `PACK_VERSION = "1.0"` 内补齐数据质量评分、`fetch_failed` 状态、Prompt 数据限制和 overview 低敏展示;#1386 P6 复用同一公开 overview 做告警、持仓、历史、回测和通知联动,并在手动持仓分析时加入可选辅助 `portfolio` block。
本页是 Issue #1389 的专题文档,用于记录当前 DSA 分析上下文的真实来源、消费路径、字段状态边界,以及 `AnalysisContextPack` 内部契约、builder、运行态消费、低敏可见性数据质量评分、告警/持仓/历史/回测联动、迁移和回滚边界。P0 负责现状盘点和契约边界P1 只新增内部 schema/envelope、block catalog、类型约定和脱敏序列化P2 只从 pipeline 已有 artifacts 组装 packP3 只把低敏摘要接入普通分析和 Agent 初始 PromptP4 只把低敏 overview 接入历史详情、同步分析响应、completed task status 和 Web 报告页P5 在同一 `PACK_VERSION = "1.0"` 内补齐数据质量评分、`fetch_failed` 状态、Prompt 数据限制和 overview 低敏展示;#1386 P6 复用同一公开 overview 做告警、持仓、历史、回测和通知联动,并在手动持仓分析时加入可选辅助 `portfolio` block#1389 P6 只补齐文档、配置可见性、迁移和回滚说明,不新增 pack runtime、pack feature flag、DB migration 或 schema 版本
## 术语与边界
@@ -109,12 +109,12 @@ P4 把 P3 已构建的 `AnalysisContextPack` 投影为公共低敏 `analysis_con
overview 不输出 `blocks.*.items``items.value``news.content``trend_result``chip``fundamental_context` 原始 payload也不输出 `api_key``token``cookie``webhook_url``password``secret``authorization``sendkey``license_key` 等敏感键或值。
P4 持久化面只在 `analysis_history.context_snapshot` 顶层写入 `analysis_context_pack_overview`。运行态 prompt 字段仍会从 `enhanced_context` 和 history snapshot 中剥离:`market_phase_context``analysis_context_pack``analysis_context_pack_summary` 不进入公开历史详情或任务状态。`SAVE_CONTEXT_SNAPSHOT=false` 时不持久化 overview旧记录或缺少 overview 的记录继续返回空字段,不影响历史详情读取。
P4 持久化面只在 `analysis_history.context_snapshot` 顶层写入 `analysis_context_pack_overview`。运行态 prompt 字段仍会从 `enhanced_context` 和 history snapshot 中剥离:`market_phase_context``analysis_context_pack``analysis_context_pack_summary` 不进入公开历史详情或任务状态。`SAVE_CONTEXT_SNAPSHOT=false` 时不持久化整份 `analysis_history.context_snapshot`,因此也不会落库 overview、`market_phase_summary``enhanced_context` 或 raw snapshot 字段;旧记录或缺少 overview 的记录继续返回空字段,不影响历史详情读取。
公共 API 字段固定为 `report.details.analysis_context_pack_overview`Web 端经深度 camelCase 后读取 `analysisContextPackOverview`。接线面包括:
- `GET /api/v1/history/{record_id}` 历史详情。
- 同步 `POST /api/v1/analysis/analyze` 返回的 `AnalysisResultResponse.report.details`
- 同步 `POST /api/v1/analysis/analyze` 返回的 `AnalysisResultResponse.report.details`,但 overview 依赖已持久化的 `analysis_history.context_snapshot``SAVE_CONTEXT_SNAPSHOT=false` 时,新记录不保证返回 overview
- completed `GET /api/v1/analysis/status/{task_id}`,包括内存队列 enrichment 和 DB completed fallback。
API 返回给 Web 的 `details.context_snapshot` 会通过 `sanitize_context_snapshot_for_api()` 剥离顶层 `analysis_context_pack_overview`,避免 raw snapshot 面板重复展示或被当作完整上下文导出overview 只从 `extract_analysis_context_pack_overview()` 单独取出。Agent 路径与普通分析路径写入同一 overview 形状Agent 无新闻计数时 `metadata.news_result_count` 可为空。
@@ -156,6 +156,55 @@ overview 只扩展现有公开面:`analysis_context_pack_overview.data_quality
- 回测 phase filter 只基于公开 summary 做 bucket`premarket` 保持 premarket`intraday|lunch_break|closing_auction` 归入 intraday`postmarket` 保持 postmarket`non_trading|missing|invalid` 归入 unknown。带 phase 过滤时 repository 先按 SQL 条件批量读取结果和 snapshot服务层 bucket 后再分页和统计,避免 API 层分页后临时过滤。
- 通知摘要只消费 `market_phase_summary``analysis_context_pack_overview.data_quality`输出阶段、trigger source、partial-bar warning、质量等级和前两条 limitations不输出 raw pack、`analysis_context_pack_summary` Prompt 字符串、新闻正文或持仓敏感细节。
## P6 文档、迁移与回滚
P6 不改变 P1-P5 的运行时行为,只把已经落地的契约、可见性、配置、迁移和回滚边界写成稳定文档。它不新增 pack enable/disable feature flag不升级 `PACK_VERSION = "1.0"`,不新增 API 参数,不改变报告 JSON schema也不做数据库迁移。
四个数据面必须分开理解:
| 数据面 | 位置 | 可见性 | P6 边界 |
| --- | --- | --- | --- |
| 内部完整 pack | `AnalysisContextPack` / `AnalysisContextBuilder` 产物 | 仅内部运行态使用 | 不作为公共 API不写入历史不承诺外部稳定 wire contract。 |
| LLM 低敏摘要 | `analysis_context_pack_summary` | 普通分析、single Agent、multi-agent Prompt | 只包含 subject、pack version、block status/source/warnings/missing reason、新闻结果数和数据限制不包含 `items.value`、新闻正文、趋势/筹码/基本面 raw payload、secret、token 或 webhook。 |
| 公共低敏 overview | `report.details.analysis_context_pack_overview` | 历史详情、同步分析响应、completed task status、Web 报告页 | 只输出白名单字段和 `data_quality` 低敏评分;不输出完整 pack、Prompt summary 或 raw payload。 |
| 历史上下文快照 | `analysis_history.context_snapshot` | 持久化后供历史/API/Web/诊断读取 | `details.context_snapshot``sanitize_context_snapshot_for_api()` 剥离 `analysis_context_pack_overview``market_phase_summary`,避免 raw 面板重复公开稳定摘要。 |
摘要可见性矩阵:
| 消费面 | 暴露内容 | 不暴露内容 |
| --- | --- | --- |
| LLM Prompt | `analysis_context_pack_summary` 低敏状态摘要和数据限制 | 完整 pack、`items.value`、新闻正文、趋势/筹码/基本面 raw payload、secret/token/webhook |
| `GET /api/v1/history/{record_id}` | `report.details.analysis_context_pack_overview` | 完整 pack、Prompt summary、raw `analysis_context_pack_overview` duplicate |
| 同步 `POST /api/v1/analysis/analyze` | `report.details.analysis_context_pack_overview`,前提是本次历史已持久化 `analysis_history.context_snapshot` | 完整 pack、Prompt summary |
| completed `GET /api/v1/analysis/status/{task_id}` | `status.result.report.details.analysis_context_pack_overview` | 完整 pack、Prompt summary |
| Web 报告页 | 默认折叠的 `AnalysisContextSummary`,展示 block 状态、来源、缺失原因、质量分和限制 | 完整 pack、raw payload、Prompt summary |
| raw `details.context_snapshot` | 剥离后的历史快照 | 顶层 `analysis_context_pack_overview``market_phase_summary` |
| 通知、Bot、Desktop 专属展示 | P6 不新增专属展示 | 完整 pack、Prompt summary、raw payload |
字段质量状态全集保持为 `available``missing``not_supported``fallback``stale``estimated``partial``fetch_failed`。这些状态解释输入数据质量,不表示分析任务、告警、回测或通知投递本身成功或失败。
脱敏边界:
- 完整 `AnalysisContextPack` 不进入公共 API、Web、通知、Bot 或 Desktop 专属展示。
- `AnalysisContextPack.to_safe_dict()` 只作为内部安全序列化 helper公共 overview 仍必须通过 `render_analysis_context_pack_overview()` 投影。
- `analysis_context_pack_summary` 与 overview 都不得输出 `items.value`、新闻正文、`trend_result``chip``fundamental_context` 原始 payload、API key、token、cookie、完整 webhook URL、邮箱密码、secret、authorization、sendkey 或 license key。
- 已持久化 overview 再读取时必须经过 `extract_analysis_context_pack_overview()` / persisted sanitizerAPI 透明度面板必须继续通过 `sanitize_context_snapshot_for_api()` 剥离顶层稳定摘要。
迁移边界:
- P6 不做 DB migration旧历史记录缺少 `analysis_context_pack_overview``data_quality` 时返回空字段,报告仍正常读取。
- `SAVE_CONTEXT_SNAPSHOT=true` 是默认行为,会继续把 `analysis_history.context_snapshot` 作为历史透明度和诊断来源持久化。
- `SAVE_CONTEXT_SNAPSHOT=false` 或 CLI `--no-context-snapshot` 会停止持久化整份 `analysis_history.context_snapshot`;换言之,新历史不持久化整份 `analysis_history.context_snapshot`,包括 `enhanced_context``market_phase_summary``analysis_context_pack_overview``diagnostics``realtime_quote_raw` 和其他 raw snapshot 字段。
- 关闭持久化不影响当次 `AnalysisContextPack` 构建、`analysis_context_pack_summary` 注入 Prompt也不影响内存中的 `result.diagnostic_context_snapshot`
回滚方式:
| 手段 | 作用 | 不能做什么 |
| --- | --- | --- |
| 发布或代码回滚 P3-P5 相关改动 | 移除 pack prompt summary、overview 和数据质量接入 | - |
| `SAVE_CONTEXT_SNAPSHOT=false``--no-context-snapshot` | 停止保存新的历史 `context_snapshot`,从而不再从新历史公开 overview / phase summary / raw snapshot | 不能关闭当次 pack 构建或 LLM Prompt 中的低敏 summary |
| 运行时 pack 总开关 | 当前不存在 | 不能通过 env 一键关闭 P3-P5 pack 接入;需要代码回滚或后续单独设计 |
## 字段质量状态
未来 pack 的字段质量状态在 P0 先固定七词P5 在同一 1.0 umbrella 内追加 `fetch_failed`。它们描述字段或数据块的质量,不描述业务流程是否成功。

View File

@@ -123,6 +123,7 @@ daily_stock_analysis/
| `REPORT_INTEGRITY_RETRY` | 完整性校验重试次数(默认 `1``0` 表示仅占位不重试) | 可选 |
| `REPORT_HISTORY_COMPARE_N` | 历史信号对比条数,`0` 关闭(默认),`>0` 启用 | 可选 |
| `ANALYSIS_DELAY` | 个股分析和大盘分析之间的延迟避免API限流`10` | 可选 |
| `SAVE_CONTEXT_SNAPSHOT` | 是否保存分析历史 `context_snapshot`,默认 `true`;设为 `false` 或使用 `--no-context-snapshot` 时不持久化整份上下文快照 | 可选 |
| `MERGE_EMAIL_NOTIFICATION` | 个股与大盘复盘合并推送(默认 false减少邮件数量、降低垃圾邮件风险`SINGLE_STOCK_NOTIFY` 互斥(单股模式下合并不生效) | 可选 |
| `MARKDOWN_TO_IMAGE_CHANNELS` | 将 Markdown 转为图片发送的渠道用逗号分隔telegram,wechat,custom,email,slack单股推送需同时配置且安装转图工具 | 可选 |
| `NOTIFICATION_REPORT_CHANNELS` | report 路由渠道(单股推送、聚合日报、大盘复盘、合并推送等);留空表示所有已配置渠道 | 可选 |
@@ -414,6 +415,7 @@ daily_stock_analysis/
| `SCHEDULE_ENABLED` | 启用定时任务 | `false` |
| `SCHEDULE_TIME` | 定时执行时间 | `18:00` |
| `LOG_DIR` | 日志目录 | `./logs` |
| `SAVE_CONTEXT_SNAPSHOT` | 保存分析历史 `context_snapshot`;设为 `false` 时新历史不保存 enhanced_context、market_phase_summary、AnalysisContextPack overview 或诊断快照,但不关闭当次 Prompt 低敏摘要 | `true` |
---
@@ -763,7 +765,7 @@ P1a 本身不改变 Prompt 文案、API/Web/Bot 参数、报告结构、history/
P1b 将 P1a 的 runtime `market_phase_context` 投影为稳定、低敏、可公开的 `market_phase_summary`,并写入 `analysis_history.context_snapshot` 顶层。历史详情、同步分析响应和 completed `/api/v1/analysis/status/{task_id}` 都通过 `report.meta.market_phase_summary` 返回同一份市场阶段元信息completed 任务状态不新增 `TaskStatus` 顶层字段,只通过 `status.result.report.meta.market_phase_summary` 间接暴露。
`market_phase_summary` 只包含市场、阶段、市场本地时间、session date、effective daily-bar date、交易日/开市/partial-bar 标记、开收盘分钟数、触发来源、分析意图和 warning code。它不暴露完整 `market_phase_context`,也不加入 quote freshness、fallback、stale 或 data_quality scoring 字段。`report.details.analysis_context_pack_overview` 仍表示 #1389 输入数据块质量摘要API 返回的 `details.context_snapshot` 会剥离顶层 `market_phase_summary``analysis_context_pack_overview`,避免 raw snapshot 重复展示这些稳定公开字段。`SAVE_CONTEXT_SNAPSHOT=false` 旧历史记录缺少 summary 时字段为空,报告仍正常返回。
`market_phase_summary` 只包含市场、阶段、市场本地时间、session date、effective daily-bar date、交易日/开市/partial-bar 标记、开收盘分钟数、触发来源、分析意图和 warning code。它不暴露完整 `market_phase_context`,也不加入 quote freshness、fallback、stale 或 data_quality scoring 字段。`report.details.analysis_context_pack_overview` 仍表示 #1389 输入数据块质量摘要API 返回的 `details.context_snapshot` 会剥离顶层 `market_phase_summary``analysis_context_pack_overview`,避免 raw snapshot 重复展示这些稳定公开字段。`SAVE_CONTEXT_SNAPSHOT=false` 时不持久化整份 `analysis_history.context_snapshot`旧历史记录缺少 summary 时字段为空,报告仍正常返回。
P1b 不改 Prompt、不新增 `analysis_phase` 请求参数、不做 Web 阶段标签或页面展示,也不覆盖 pending/processing TaskPanel、SSE 进行中事件、Bot、通知、`market_review` 或 P3 盘中数据质量字段。
@@ -803,9 +805,9 @@ P3 当时不新增 API/Web/Bot 参数,不写入 history/task status/report met
#### AnalysisContextPack 低敏可见性Issue #1389 P4
P4 新增 `report.details.analysis_context_pack_overview`,历史详情、同步分析响应和 completed `/api/v1/analysis/status/{task_id}` 都会返回同一份低敏 overviewWeb 端报告页在“策略点位”和“资讯”之后展示默认折叠的数据块摘要折叠头部展示可用数、缺失数、非零的其他状态计数和触发来源展开后展示数据块状态、来源、warning、missing reason、状态计数和新闻结果数。API 返回的 `details.context_snapshot` 会剥离顶层 `analysis_context_pack_overview`,避免透明度面板重复展示 raw snapshot。
P4 新增 `report.details.analysis_context_pack_overview`,历史详情和 completed `/api/v1/analysis/status/{task_id}` 会从已持久化的 `context_snapshot` 返回同一份低敏 overview同步分析响应也会读取本次已落库的 `analysis_history.context_snapshot` 提取 overview因此 `SAVE_CONTEXT_SNAPSHOT=false` 时新记录不保证返回该字段。Web 端报告页在“策略点位”和“资讯”之后展示默认折叠的数据块摘要折叠头部展示可用数、缺失数、非零的其他状态计数和触发来源展开后展示数据块状态、来源、warning、missing reason、状态计数和新闻结果数。API 返回的 `details.context_snapshot` 会剥离顶层 `analysis_context_pack_overview`,避免透明度面板重复展示 raw snapshot。
该 overview 不包含完整 pack、`analysis_context_pack_summary` Prompt 字符串、`items.value`、新闻正文、`trend_result`、筹码或基本面原始 payload。`SAVE_CONTEXT_SNAPSHOT=false` 旧历史记录缺少 overview 时字段为空,报告仍正常返回。本阶段不覆盖 pending/processing TaskPanel、SSE 进行中事件、通知摘要、Bot/Desktop 专属展示、`market_review` overview 或数据质量评分。
该 overview 不包含完整 pack、`analysis_context_pack_summary` Prompt 字符串、`items.value`、新闻正文、`trend_result`、筹码或基本面原始 payload。`SAVE_CONTEXT_SNAPSHOT=false` 时不持久化整份 `analysis_history.context_snapshot`,因此不会从新历史记录读取 overview旧历史记录缺少 overview 时字段为空,报告仍正常返回。本阶段不覆盖 pending/processing TaskPanel、SSE 进行中事件、通知摘要、Bot/Desktop 专属展示、`market_review` overview 或数据质量评分。
#### AnalysisContextPack 数据质量评分与 Prompt 数据限制Issue #1389 P5
@@ -815,6 +817,14 @@ P5 在不修改 `PACK_VERSION = "1.0"`、不新增数据源和不改变报告 JS
历史详情、同步分析响应和 completed 任务状态继续只通过 `report.details.analysis_context_pack_overview` 暴露低敏字段P5 只在该 overview 下新增 `data_quality`,包含 score、level、block_scores 和 limitations不重复公开 `warnings`。Web 报告页仍默认折叠展示数据块摘要,折叠头部新增质量分/等级,展开后展示限制说明和 `fetch_failed` 状态;`details.context_snapshot` 继续剥离顶层 `analysis_context_pack_overview`
#### AnalysisContextPack 文档、迁移与回滚Issue #1389 P6
P6 只做文档与配置可见性收口,不新增 pack runtime、不新增 pack enable/disable feature flag、不修改 `PACK_VERSION = "1.0"`、不新增 API 参数、不改变报告 JSON schema也不做数据库迁移。完整契约、字段状态、低敏摘要可见性、脱敏边界、迁移和回滚说明见 [AnalysisContextPack 专题文档](analysis-context-pack.md)。
`SAVE_CONTEXT_SNAPSHOT` 是既有环境变量P6 只是把它同步到 `.env.example`、配置注册表和 Web 设置帮助。默认 `true`;设为 `false` 或 CLI 使用 `--no-context-snapshot` 时,新历史记录不再持久化整份 `analysis_history.context_snapshot`,包括 `enhanced_context``market_phase_summary``analysis_context_pack_overview`、诊断快照和 raw snapshot 字段。该设置不关闭当次 `AnalysisContextPack` 构建,不移除 Prompt 中的低敏 `analysis_context_pack_summary`,也不改变分析结果 JSON schema 或 API 请求参数。
当前没有运行时 pack 总开关;如果需要关闭 P3-P5 的 pack Prompt 摘要、overview 或数据质量接入,只能通过发布回滚或代码回滚完成。旧历史记录没有 `analysis_context_pack_overview` / `data_quality` 时继续返回空字段,报告读取保持兼容。
#### 盘中决策护栏与质量校验Issue #1386 P5
P5 在个股分析报告的 `dashboard.phase_decision` 中追加阶段化决策字段:`phase_context``action_window``immediate_action``watch_conditions``next_check_time``confidence_reason``data_limitations`。该字段只作为报告 JSON 的向后兼容扩展进入历史 `raw_result`;不新增 `analysis_phase` API 参数、不改变 Web 阶段入口、不新增配置项,也不影响每日收盘复盘默认行为。
@@ -1341,7 +1351,7 @@ FastAPI 提供 RESTful API 服务,支持配置管理和触发分析。
> 说明:`GET /api/v1/history/{record_id}/diagnostics` 支持历史记录主键 ID 或 `query_id`,返回 `normal/degraded/failed/unknown` 摘要、关键链路组件和可复制的脱敏 `copy_text`;旧报告缺少诊断快照时返回 `unknown`,不影响报告读取。
> 说明:`GET /api/v1/history` 的列表摘要可按 `stock_code` 分页查询同一股票历史,并返回趋势判断、分析摘要、模型名与分析时价格/涨跌幅等可选字段旧记录缺少快照字段时返回空值。Web 报告页的“历史趋势”抽屉复用该接口加载同股历史。
> 说明Issue #1520列表中的模型名展示字段仅来源于历史快照中的 `model_used`,仅用于历史回溯展示,不影响运行时模型模型路由(`litellm_model`、`llm_model_list`、Provider、Base URL 与配置迁移/清理语义。回退方式为回退本次提交,现网历史查询/抽屉/接口链路兼容性保持不变。
> 说明:历史详情、同步分析响应和 completed 任务状态会在 `report.details.analysis_context_pack_overview` 返回低敏输入数据块 overview`details.context_snapshot` 会剥离该顶层字段,不返回完整 `AnalysisContextPack` 或 Prompt summary。
> 说明:历史详情、同步分析响应和 completed 任务状态会在 `report.details.analysis_context_pack_overview` 返回低敏输入数据块 overview其中同步分析响应依赖本次已持久化的 `analysis_history.context_snapshot``SAVE_CONTEXT_SNAPSHOT=false` 时新记录不保证返回 overview。`details.context_snapshot` 会剥离该顶层字段,不返回完整 `AnalysisContextPack` 或 Prompt summary。
> 兼容性审计证据:
> - 官方来源LiteLLM OpenAI-compatible provider 文档 <https://docs.litellm.ai/docs/providers/openai_compatible>OpenAI Chat API 文档 <https://platform.openai.com/docs/api-reference/chat/create>DeepSeek API 文档 <https://api-docs.deepseek.com/>。

View File

@@ -123,6 +123,7 @@ Go to your forked repo → `Settings` → `Secrets and variables` → `Actions`
| `REPORT_INTEGRITY_RETRY` | Integrity retry count (default `1`, `0` = placeholder only) | Optional |
| `REPORT_HISTORY_COMPARE_N` | History signal comparison count, `0` off (default), `>0` enable | Optional |
| `ANALYSIS_DELAY` | Delay between stock analysis and market review (seconds) to avoid API rate limits, e.g., `10` | Optional |
| `SAVE_CONTEXT_SNAPSHOT` | Whether to persist analysis-history `context_snapshot`; defaults to `true`. Set to `false` or use `--no-context-snapshot` to stop persisting the full snapshot | Optional |
| `NOTIFICATION_REPORT_CHANNELS` | Report route channels for single-stock, aggregate daily, market review, merged push, and Feishu document success notifications. Empty means all configured channels | Optional |
| `NOTIFICATION_ALERT_CHANNELS` | Alert route channels for EventMonitor notifications. Empty means all configured channels | Optional |
| `NOTIFICATION_SYSTEM_ERROR_CHANNELS` | Reserved system_error route channels. No automatic system error producer is added in P3; empty means all configured channels | Optional |
@@ -346,6 +347,7 @@ For the notification baseline, diagnostics, and deployment notes, see [Notificat
| `SCHEDULE_RUN_IMMEDIATELY` | Run once immediately when scheduler mode starts; when unset it keeps following the legacy `RUN_IMMEDIATELY` runtime override | `true` |
| `RUN_IMMEDIATELY` | Run once immediately for non-scheduler startup; also acts as the legacy fallback when `SCHEDULE_RUN_IMMEDIATELY` is unset | `true` |
| `LOG_DIR` | Log directory | `./logs` |
| `SAVE_CONTEXT_SNAPSHOT` | Persist analysis-history `context_snapshot`. When false, new history records do not save enhanced_context, market_phase_summary, AnalysisContextPack overview, or diagnostic snapshots, but current-run prompt summaries remain enabled | `true` |
> Behavior notes:
> - When `TICKFLOW_API_KEY` is configured, CN market review first tries TickFlow for main indices. Market breadth also tries TickFlow only when the current TickFlow plan supports universe queries.
@@ -640,7 +642,7 @@ P1a itself does not change prompt wording, API/Web/Bot parameters, report schema
P1b projects the P1a runtime `market_phase_context` into a stable, low-sensitivity, public `market_phase_summary` and stores it at the top level of `analysis_history.context_snapshot`. History detail, sync analysis responses, and completed `/api/v1/analysis/status/{task_id}` responses return the same market-phase metadata at `report.meta.market_phase_summary`; completed task status does not add a top-level `TaskStatus` field and only exposes it through `status.result.report.meta.market_phase_summary`.
`market_phase_summary` only contains market, phase, market-local time, session date, effective daily-bar date, trading-day / market-open / partial-bar flags, open/close minute estimates, trigger source, analysis intent, and warning codes. It does not expose the full `market_phase_context`, and it does not add quote freshness, fallback, stale, or data-quality scoring fields. `report.details.analysis_context_pack_overview` remains the #1389 input data-block quality overview. API `details.context_snapshot` strips the top-level `market_phase_summary` and `analysis_context_pack_overview` so raw snapshots do not duplicate these stable public fields. When `SAVE_CONTEXT_SNAPSHOT=false` or older history records lack the summary, the field is empty and the report still loads.
`market_phase_summary` only contains market, phase, market-local time, session date, effective daily-bar date, trading-day / market-open / partial-bar flags, open/close minute estimates, trigger source, analysis intent, and warning codes. It does not expose the full `market_phase_context`, and it does not add quote freshness, fallback, stale, or data-quality scoring fields. `report.details.analysis_context_pack_overview` remains the #1389 input data-block quality overview. API `details.context_snapshot` strips the top-level `market_phase_summary` and `analysis_context_pack_overview` so raw snapshots do not duplicate these stable public fields. When `SAVE_CONTEXT_SNAPSHOT=false`, the full `analysis_history.context_snapshot` is not persisted; when older history records lack the summary, the field is empty and the report still loads.
P1b does not change prompts, does not add an `analysis_phase` request parameter, does not add Web phase labels or rendering, and does not cover pending/processing TaskPanel state, in-progress SSE events, Bot, notifications, `market_review`, or P3 intraday data-quality fields.
@@ -680,9 +682,9 @@ P3 itself did not add API/Web/Bot parameters, persist fields into history/task s
### AnalysisContextPack Low-Sensitivity Visibility (Issue #1389 P4)
P4 adds `report.details.analysis_context_pack_overview`. History detail, sync analysis responses, and completed `/api/v1/analysis/status/{task_id}` responses now return the same low-sensitivity overview; the Web report page renders a collapsed data-block summary after Strategy and News, with available/missing counts, non-zero other status counts, and trigger source in the header and data-block status, source, warnings, missing reasons, status counts, and news result count after expansion. API `details.context_snapshot` strips the top-level `analysis_context_pack_overview` so the raw snapshot panel does not duplicate the public overview.
P4 adds `report.details.analysis_context_pack_overview`. History detail and completed `/api/v1/analysis/status/{task_id}` responses read the same low-sensitivity overview from the persisted `context_snapshot`; sync analysis responses also extract the overview from the just-persisted `analysis_history.context_snapshot`, so new records do not guarantee this field when `SAVE_CONTEXT_SNAPSHOT=false`. The Web report page renders a collapsed data-block summary after Strategy and News, with available/missing counts, non-zero other status counts, and trigger source in the header and data-block status, source, warnings, missing reasons, status counts, and news result count after expansion. API `details.context_snapshot` strips the top-level `analysis_context_pack_overview` so the raw snapshot panel does not duplicate the public overview.
The overview does not include the full pack, the `analysis_context_pack_summary` prompt string, `items.value`, news body text, `trend_result`, chip, or fundamentals raw payloads. When `SAVE_CONTEXT_SNAPSHOT=false` or older history records lack the overview, the field is empty and the report still loads. This phase does not cover pending/processing TaskPanel, in-progress SSE events, notification summaries, Bot/Desktop-specific rendering, `market_review` overview, or data-quality scoring.
The overview does not include the full pack, the `analysis_context_pack_summary` prompt string, `items.value`, news body text, `trend_result`, chip, or fundamentals raw payloads. When `SAVE_CONTEXT_SNAPSHOT=false`, the full `analysis_history.context_snapshot` is not persisted, so new history records cannot provide the overview; older records without the overview keep returning an empty field and the report still loads. This phase does not cover pending/processing TaskPanel, in-progress SSE events, notification summaries, Bot/Desktop-specific rendering, `market_review` overview, or data-quality scoring.
### AnalysisContextPack Data Quality Scoring and Prompt Limitations (Issue #1389 P5)
@@ -692,6 +694,14 @@ P5 adds lightweight data-quality scoring and model-readable data limitations to
History detail, sync analysis responses, and completed task status responses still expose only `report.details.analysis_context_pack_overview`; P5 only adds a nested `data_quality` object with score, level, block_scores, and limitations, and does not duplicate `warnings`. The Web report page remains collapsed by default, adds quality score/level to the header, and shows limitations plus `fetch_failed` status after expansion; API `details.context_snapshot` continues to strip the top-level `analysis_context_pack_overview`.
### AnalysisContextPack Documentation, Migration, and Rollback (Issue #1389 P6)
P6 is a documentation and configuration-visibility closure only. It does not add pack runtime behavior, does not add a pack enable/disable feature flag, does not change `PACK_VERSION = "1.0"`, does not add API parameters, does not change the report JSON schema, and does not run a database migration. See the [AnalysisContextPack topic document](analysis-context-pack.md) for the full contract, field states, low-sensitivity visibility, redaction boundary, migration notes, and rollback path.
`SAVE_CONTEXT_SNAPSHOT` is an existing environment variable; P6 only exposes it through `.env.example`, the config registry, and Web settings help. It defaults to `true`. When set to `false`, or when the CLI uses `--no-context-snapshot`, new history records no longer persist the full `analysis_history.context_snapshot`, including `enhanced_context`, `market_phase_summary`, `analysis_context_pack_overview`, diagnostic snapshots, and raw snapshot fields. This setting does not disable current-run `AnalysisContextPack` construction, does not remove the low-sensitivity `analysis_context_pack_summary` from prompts, and does not change report JSON schemas or API request parameters.
There is no runtime pack master switch. Disabling the P3-P5 pack prompt summary, overview, or data-quality integration requires a release rollback or code rollback. Older history records without `analysis_context_pack_overview` / `data_quality` continue to return empty fields and remain readable.
### Intraday Decision Guardrails and Quality Checks (Issue #1386 P5)
P5 adds a phase-aware decision block under `dashboard.phase_decision` for individual stock analysis reports: `phase_context`, `action_window`, `immediate_action`, `watch_conditions`, `next_check_time`, `confidence_reason`, and `data_limitations`. This is a backward-compatible report JSON addition stored in historical `raw_result`; it does not add an `analysis_phase` API parameter, change Web phase entrypoints, add configuration, or change the default post-market daily review behavior.
@@ -1173,7 +1183,7 @@ FastAPI provides RESTful API service for configuration management and triggering
> Note: `GET /api/v1/history/{record_id}/diagnostics` accepts either the history primary key ID or `query_id`, and returns a `normal/degraded/failed/unknown` summary, key pipeline components, and sanitized `copy_text`. Older reports without `context_snapshot.diagnostics` return `unknown` without affecting normal report reads.
> Note: `GET /api/v1/history` list summaries can be paginated by `stock_code` for same-stock history and now include optional trend, summary, model, and analysis-time price/change fields. Older rows without persisted snapshots return empty values. The Web report page's "History Trend" drawer reuses this endpoint.
> Issue #1520 compatibility note: The `model`/`model_used` returned here is read-only historical snapshot metadata from each record, used only for trend drawer/history display. It does not alter runtime model/model-provider/base URL resolution, config migration, or cleanup semantics in the analysis path. Rollback is by reverting this commit; history query, API response shapes, and UI drawer consumption remain compatible.
> Note: history detail, sync analysis responses, and completed task status responses expose a low-sensitivity input data-block overview at `report.details.analysis_context_pack_overview`; `details.context_snapshot` strips that top-level field and does not return the full `AnalysisContextPack` or prompt summary.
> Note: history detail, sync analysis responses, and completed task status responses expose a low-sensitivity input data-block overview at `report.details.analysis_context_pack_overview`; sync analysis responses depend on the just-persisted `analysis_history.context_snapshot`, so new records do not guarantee the overview when `SAVE_CONTEXT_SNAPSHOT=false`. `details.context_snapshot` strips that top-level field and does not return the full `AnalysisContextPack` or prompt summary.
> Compatibility audit evidence:
> - Official references: LiteLLM OpenAI-compatible provider documentation <https://docs.litellm.ai/docs/providers/openai_compatible>, OpenAI Chat API <https://platform.openai.com/docs/api-reference/chat/create>, and DeepSeek API docs <https://api-docs.deepseek.com/>.

View File

@@ -2981,6 +2981,37 @@ _FIELD_DEFINITIONS: Dict[str, Dict[str, Any]] = {
],
"warning_codes": [],
},
"SAVE_CONTEXT_SNAPSHOT": {
"title": "Save Context Snapshot",
"description": "Persist the full analysis_history.context_snapshot for history/API/Web transparency. Disable only to stop storing snapshots; it does not disable AnalysisContextPack prompt summaries during the current run.",
"category": "system",
"data_type": "boolean",
"ui_control": "switch",
"is_sensitive": False,
"is_required": False,
"is_editable": True,
"default_value": "true",
"options": [],
"validation": {},
"display_order": 52,
"help_key": "settings.system.SAVE_CONTEXT_SNAPSHOT",
"examples": [
"SAVE_CONTEXT_SNAPSHOT=true",
"SAVE_CONTEXT_SNAPSHOT=false",
"python main.py --no-context-snapshot",
],
"docs": [
{
"label": "AnalysisContextPack P6 文档、迁移与回滚",
"href": "https://github.com/ZhuLinsen/daily_stock_analysis/blob/main/docs/analysis-context-pack.md#p6-文档迁移与回滚",
},
{
"label": "完整指南:其他配置",
"href": "https://github.com/ZhuLinsen/daily_stock_analysis/blob/main/docs/full-guide.md#其他配置",
},
],
"warning_codes": [],
},
"DEBUG": {
"title": "Debug Mode",
"description": "Enable debug mode with verbose logging.",

View File

@@ -31,6 +31,7 @@ def test_analysis_context_pack_doc_has_required_sections() -> None:
"## P3 Runtime Consumption",
"## P4 历史记录、任务状态与 Web 可见性",
"## P5 数据质量评分与 Prompt 数据限制",
"## P6 文档、迁移与回滚",
"## 字段质量状态",
"## 现有状态映射",
"## 七路径盘点",
@@ -297,6 +298,7 @@ def test_analysis_context_pack_doc_defines_p4_visibility_contract() -> None:
"`analysisContextPackOverview`",
"`GET /api/v1/history/{record_id}`",
"同步 `POST /api/v1/analysis/analyze`",
"overview 依赖已持久化的 `analysis_history.context_snapshot`",
"completed `GET /api/v1/analysis/status/{task_id}`",
"`sanitize_context_snapshot_for_api()`",
"`extract_analysis_context_pack_overview()`",
@@ -304,6 +306,9 @@ def test_analysis_context_pack_doc_defines_p4_visibility_contract() -> None:
"`trend_result`",
"`fundamental_context`",
"`SAVE_CONTEXT_SNAPSHOT=false`",
"不持久化整份 `analysis_history.context_snapshot`",
"`market_phase_summary`",
"`enhanced_context`",
"`AnalysisContextSummary`",
"位置在策略点位和资讯之后、运行诊断之前",
"默认折叠",
@@ -345,6 +350,37 @@ def test_analysis_context_pack_doc_defines_p5_data_quality_contract() -> None:
assert token in section
def test_analysis_context_pack_doc_defines_p6_migration_and_rollback_contract() -> None:
section = _section(_read_doc(), "P6 文档、迁移与回滚")
for token in (
"四个数据面",
"内部完整 pack",
"`analysis_context_pack_summary`",
"`analysis_context_pack_overview`",
"`analysis_history.context_snapshot`",
"摘要可见性矩阵",
"`SAVE_CONTEXT_SNAPSHOT=true`",
"`SAVE_CONTEXT_SNAPSHOT=false`",
"`--no-context-snapshot`",
"不持久化整份 `analysis_history.context_snapshot`",
"本次历史已持久化 `analysis_history.context_snapshot`",
"`enhanced_context`",
"`market_phase_summary`",
"`diagnostics`",
"`realtime_quote_raw`",
"不影响当次 `AnalysisContextPack` 构建",
"不影响内存中的 `result.diagnostic_context_snapshot`",
"当前不存在",
"运行时 pack 总开关",
"发布或代码回滚",
"secret",
"token",
"webhook",
):
assert token in section
def test_analysis_context_pack_doc_maps_existing_status_terms() -> None:
section = _section(_read_doc(), "现有状态映射")
@@ -392,19 +428,20 @@ def test_analysis_context_pack_doc_updates_indexes_and_changelog() -> None:
changelog = (PROJECT_ROOT / "docs" / "CHANGELOG.md").read_text(encoding="utf-8")
assert "[分析上下文包契约、运行态消费与可见性](analysis-context-pack.md)" in index
assert "P1/P2 内部契约、P3 Prompt 摘要消费、P4 历史/API/Web 低敏可见性、P5 数据质量评分" in index
assert "P1/P2 内部契约、P3 Prompt 摘要消费、P4 历史/API/Web 低敏可见性、P5 数据质量评分、P6 迁移回滚" in index
assert (
"[Analysis Context Pack Contract, Runtime Consumption, And Visibility](analysis-context-pack.md) "
"<sub><sub>![P5 Badge](https://img.shields.io/badge/P5-orange?style=flat)</sub></sub> "
"<sub><sub>![P6 Badge](https://img.shields.io/badge/P6-orange?style=flat)</sub></sub> "
"(Chinese-only)"
) in index_en
assert "P1/P2 internal contracts, P3 prompt-summary consumption, P4 history/API/Web low-sensitivity visibility, P5 data-quality scoring" in index_en
assert "P1/P2 internal contracts, P3 prompt-summary consumption, P4 history/API/Web low-sensitivity visibility, P5 data-quality scoring, and P6 migration/rollback notes" in index_en
assert "新增 AnalysisContextPack P0 上下文盘点" in changelog
assert "新增 AnalysisContextPack P1 内部契约与脱敏序列化测试" in changelog
assert "新增 AnalysisContextPack P2 builder" in changelog
assert "普通分析与 Agent 运行时 Prompt 接入 AnalysisContextPack 低敏摘要" in changelog
assert "AnalysisContextPack P4 低敏 overview 接入历史详情" in changelog
assert "AnalysisContextPack P5 增加数据质量评分" in changelog
assert "明确 AnalysisContextPack P6 文档、迁移与回滚边界" in changelog
assert "#1386 P5 为个股分析报告新增 `dashboard.phase_decision`" in changelog
assert "优化 Web 报告详情页信息层级" in changelog
@@ -422,6 +459,8 @@ def test_full_guides_clarify_pack_summary_does_not_replace_legacy_payload_channe
assert "折叠头部展示可用数、缺失数、非零的其他状态计数和触发来源" in guide
assert "Web 报告页在策略点位和资讯之后默认折叠展示数据块状态" in guide
assert "`details.context_snapshot` 会剥离顶层 `analysis_context_pack_overview`" in guide
assert "同步分析响应也会读取本次已落库的 `analysis_history.context_snapshot` 提取 overview" in guide
assert "`SAVE_CONTEXT_SNAPSHOT=false` 时新记录不保证返回该字段" in guide
assert "AnalysisContextPack 数据质量评分与 Prompt 数据限制Issue #1389 P5" in guide
assert "盘中决策护栏与质量校验Issue #1386 P5" in guide
assert "`dashboard.phase_decision`" in guide
@@ -429,16 +468,23 @@ def test_full_guides_clarify_pack_summary_does_not_replace_legacy_payload_channe
assert "折叠头部新增质量分/等级" in guide
assert "`report.meta.market_phase_summary`" in guide
assert "`details.context_snapshot` 会剥离顶层 `market_phase_summary`" in guide
assert "AnalysisContextPack 文档、迁移与回滚Issue #1389 P6" in guide
assert "`SAVE_CONTEXT_SNAPSHOT` 是既有环境变量" in guide
assert "不持久化整份 `analysis_history.context_snapshot`" in guide
assert "不关闭当次 `AnalysisContextPack` 构建" in guide
assert "当前没有运行时 pack 总开关" in guide
assert "in this new pack-summary section" in guide_en
assert "not full `news.content`" in guide_en
assert "Existing `news_context`, Agent pre-fetched JSON, and `enhanced_context` raw-payload channels keep their pre-P3 behavior" in guide_en
assert "`report.details.analysis_context_pack_overview`" in guide_en
assert "completed `/api/v1/analysis/status/{task_id}`" in guide_en
assert "the Web report page renders a collapsed data-block summary after Strategy and News" in guide_en
assert "The Web report page renders a collapsed data-block summary after Strategy and News" in guide_en
assert "available/missing counts, non-zero other status counts, and trigger source" in guide_en
assert "the Web report page shows the data-block summary collapsed after Strategy and News" in guide_en
assert "API `details.context_snapshot` strips the top-level `analysis_context_pack_overview`" in guide_en
assert "sync analysis responses also extract the overview from the just-persisted `analysis_history.context_snapshot`" in guide_en
assert "new records do not guarantee this field when `SAVE_CONTEXT_SNAPSHOT=false`" in guide_en
assert "AnalysisContextPack Data Quality Scoring and Prompt Limitations (Issue #1389 P5)" in guide_en
assert "Intraday Decision Guardrails and Quality Checks (Issue #1386 P5)" in guide_en
assert "`dashboard.phase_decision`" in guide_en
@@ -446,3 +492,8 @@ def test_full_guides_clarify_pack_summary_does_not_replace_legacy_payload_channe
assert "adds quality score/level to the header" in guide_en
assert "`report.meta.market_phase_summary`" in guide_en
assert "API `details.context_snapshot` strips the top-level `market_phase_summary`" in guide_en
assert "AnalysisContextPack Documentation, Migration, and Rollback (Issue #1389 P6)" in guide_en
assert "`SAVE_CONTEXT_SNAPSHOT` is an existing environment variable" in guide_en
assert "the full `analysis_history.context_snapshot` is not persisted" in guide_en
assert "does not disable current-run `AnalysisContextPack` construction" in guide_en
assert "There is no runtime pack master switch" in guide_en

View File

@@ -259,6 +259,7 @@ class TestSettingsHelpMetadata(unittest.TestCase):
"DEBUG",
"MAX_WORKERS",
"ANALYSIS_DELAY",
"SAVE_CONTEXT_SNAPSHOT",
"MARKET_REVIEW_ENABLED",
"MARKET_REVIEW_REGION",
"MARKET_REVIEW_COLOR_SCHEME",
@@ -300,6 +301,21 @@ class TestSettingsHelpMetadata(unittest.TestCase):
self.assertEqual(field["category"], "system")
self.assertNotEqual(field["display_order"], 9000)
def test_save_context_snapshot_is_explicitly_registered(self):
field = get_field_definition("SAVE_CONTEXT_SNAPSHOT")
self.assertEqual(field["category"], "system")
self.assertEqual(field["data_type"], "boolean")
self.assertEqual(field["ui_control"], "switch")
self.assertFalse(field["is_sensitive"])
self.assertTrue(field["is_editable"])
self.assertEqual(field["default_value"], "true")
self.assertEqual(field["display_order"], 52)
self.assertEqual(field["help_key"], "settings.system.SAVE_CONTEXT_SNAPSHOT")
self.assertTrue(field.get("examples"))
self.assertTrue(field.get("docs"))
self.assertIn("analysis-context-pack.md#p6-", field["docs"][0]["href"])
def test_restart_warning_codes_match_runtime_behavior(self):
restart_required_keys = (
"RUN_IMMEDIATELY",