跳到主要内容

FinBayes 工程架构

本文档是 FinBayes 工程实施的契约事实源。任何工程实施仓的代码、提案、决策都必须可追溯到本文档某一章节或某条 ADR。

文档元信息

维度内容
上位依据FinBayes 战略白皮书 / FinBayes 产品定义
编写方法论arc42 + C4 + ADR + DDD 业务建模(详见 ADR-002)
工程范式Harness Workflow + 里程碑切片 + 走通骨架试点(详见 ADR-001)
工程协作OpenSpec + Archon + Claude Code 主控 + Codex 实施(详见 ADR-003)
重写工作流governance/workstreams/finbayes-arch-rewrite/
前版(v1)归档_archive/projects/finbayes/2026-05-27-architecture-v1-rewrite/

文档结构

本文档分 9 部分共 29 节(§28 / §29 为附录与子系统索引):

第一部分 立架

第二部分 业务架构

第三部分 系统全景

第四部分 系统运行

第五部分 部署与基础设施

第六部分 横向贯穿的关注点

第七部分 质量与验收

第八部分 已知缺口与决策

第九部分 落地映射

配套资产

资产位置
架构决策记录(ADR)governance/workstreams/finbayes-arch-rewrite/decisions/ADR-NNN-*.md
章节单独草稿(评审用)governance/workstreams/finbayes-arch-rewrite/drafts/CHAP-NN-*.md
工作流状态governance/workstreams/finbayes-arch-rewrite/status.md
任务识别策略深度调研projects/finbayes/research/intent-recognition-and-llm-strategy/

章节交叉引用规则

  • 章节间引用用"§N"或"第 N 节"
  • ADR 引用用 ADR-NNN
  • 任何工程实施仓的代码引用本文档时必须用§N 锚点

1. 文档角色与读者

这一节回答:这份文档是什么,怎么用。

这是什么

FinBayes 工程架构文档是 FinBayes 系统设计的总图。它从战略白皮书与产品定义文档派生,把战略层的"为什么做、做什么"翻译成工程层的"系统是什么样的、怎么动、怎么部署、怎么演化"。

怎么用

按需查阅,不需要从头读到尾。

  • 写代码时:去"系统全景"找当前要实现的子系统;去"系统运行"找跨模块协作的时序;去"代码仓位置映射"找代码落点
  • 设计评审时:先读"业务架构"建立总体认识,再核对要评审的模块所属子系统
  • 遇到模糊点:查"架构决策索引",每个关键决策在 decisions/ 下有独立文档说明上下文与结论
  • 接手维护时:从"立架"三节开始建立坐标系,再按需 zoom in

与上下游文档的承接

  • 战略白皮书:FinBayes 是什么、战略不变量、阶段范围
  • 产品定义文档:用户行为契约、任务类型、输出认知要素
  • 本文档:把上述两份内容落到模块、接口、数据、部署
  • 第三方基线评估:从现有 martinpmm/Finclaw 工程仓如何演化到本文档定义的形态
  • Harness Workflow 与里程碑规范:按节奏切片实施本文档定义的内容

任何冲突以战略白皮书与产品定义文档为准,本文档须修正。


2. 上位继承与不变量

这一节回答:FinBayes 的工程实现必须承接哪些战略层事实。

FinBayes 是什么

FinBayes 是金融认知层应用。它把用户的自然语言问题映射为金融认知任务,调度多 Agent 与金融原子技能执行,产出条件化、可复盘、带不确定性意识的认知材料。用户基于这些材料形成自己的判断与决策;买卖、调仓、转账、自动交易等执行能力由用户或下游执行系统承接。

但「把一次提问映射成一次认知输出」只是 FinBayes 在单个回合内的行为,不是 FinBayes 的全部——产品本体是下面这条 identity 级不变量定义的 agent。

FinBayes 产品本体是带自主循环的认知 agent(架构级不变量 · identity 级)

FinBayes 的产品本体不是「输入问题 → 输出一次认知材料」的问答函数,而是一个带自主循环的金融认知 agent:感知(接地真实数据)→ 规划(拆解任务)→ 行动(调工具 / 认知机制)→ 观察(结果回灌)→ 收敛,并跨回合把判断沉淀为状态资产、在市场变化触及失效条件时主动发起复盘synthesize_cognition(单次综合)是这个循环在单个回合内被调用的一个认知动作,不是 runtime 的顶层入口。

这条不变量是 identity 级(与「不直接下单」「不收凭证」同级,不可被里程碑排期稀释):

  • 主动信号 / 自主复盘循环是 identity 级能力,不是晚期里程碑的增量功能。任何里程碑路线图不得把「状态 + 自主触发循环」的端到端打通排到状态化(M1)之后太远——最小自主循环(哪怕只监控 1 类失效条件、只对 1 个 Fin Object)必须在 M1/M2 端到端可见(§25 里程碑对应承接此约束)。
  • State Management 的主动信号触发器与 Task Orchestration 的单回合编排是 agent 的两个半:缺主动触发器,FinBayes 在结构上退化为单次问答函数(§9.2 承接此分工)。
  • 允许 M0 walking skeleton 以 single-shot 形态起步,但这是已知的 pre-agent 阶段,必须在路线图显式标注并给缓解,不得让 single-shot 惯性一路延续到后期里程碑。

frame 背景:本不变量为 2026-06-04 阶段 0 文档矫正新增,依据金融真智能体骨架蓝图(E)#2 + owner 议定结果。它把此前隐含在 §5 / §11 主动信号、却从未被立为 identity 的「agent 本体」显式硬化,纠正「越往工程下游越退化成单次问答函数」的框架漂移。

战略边界

FinBayes 不直接下单, 也不持有账户凭证。

工程层承接:runtime 范围只包含金融认知任务的处理,不实现交易执行能力;工具注册表对执行类工具的注册请求一律拒收;状态写入路径不保留可触发执行的凭证或权限令牌。

凭证处理

金融执行凭证——私钥、助记词、钱包恢复短语、交易所登录凭证、交易所 API key、经纪商 API key、银行账户、信用卡等——FinBayes 一律不收、不存、不训练, 即使为了"提升服务质量" 也不收。

工程层的三个机械承接:

  • 不收:输入端识别凭证类信息后给安全回应,不进入认知任务处理链
  • 不存:状态对象、缓存、日志、审计 trail 一概不保留凭证内容;输出端扫描防止大模型生成凭证样式的内容被意外捕获
  • 不训练:凭证内容不进入反馈数据、评估样本、微调数据

金融执行凭证 vs 本机配置秘密:两者必须严格区分。

  • 金融执行凭证:用户在金融账户上的支配权(私钥 / 助记词 / 交易所 API key / 等),归本节管辖
  • 本机配置秘密:用户自己的运行环境秘密(大模型 Provider key、数据 Provider key、本地服务 token 等),按本机安全存储正常处理,不属于本节管辖

界面上必须明确区分两类秘密,避免用户混淆。

用户主权

用户对自己的画像保有完整控制权:随时查看、修改、清空整个画像。用户清空时系统显式提示"协作上下文已重置"。

画像服务于沟通效率(表达密度、术语深度选择),不进入证据筛选——综合层产出的反方证据、关键风险、失效条件按事实空间生成,不因画像偏好被裁剪。

任务类型与认知要素

FinBayes 第一阶段识别七类用户认知任务(来自产品定义文档,本文不增不减不改名):

  • 解释类:理解金融概念 / 机制 / 现象
  • 分析类:围绕事件 / 数据 / 变化展开认知组织
  • 比较类:多个金融对象的维度化对比
  • 复盘类:触发历史判断的成立条件 / 当前变化 / 是否仍成立
  • 风险识别类:主动识别下行风险 / 反方 / 盲点
  • 交易准备类:交易前的条件 / 风险 / 反方 / 失效边界检查
  • 交易决策辅助:聚焦具体决策点的条件化判断

每类任务按需组合产品定义文档里定义的认知要素(结论 / 倾向 / 依据 / 多视角 / 反方证据 / 成立条件 / 失效条件 / 不确定性 / 信息缺口 / 来源与时间戳 / 可继续追问项 / 历史判断链接)。不固化字段表,按任务类型动态组合。

与战略未决问题相关的参数

战略白皮书把"商业模式整体压力测试、单位经济、vs 通用 AI 留存竞争、L1-L3 商业强度"列为战略层未决问题。工程层涉及这些问题的参数全部走配置文件,由商业团队 + 产品团队基于冷启动数据填写:

  • 每次任务的大模型调用次数上限
  • 单用户同时进行中的任务数上限
  • 主动信号每用户每天触发上限
  • 不同用户层级的服务边界(使用频率、持续支持时长、主动反馈能力)
  • 付费转换点的触发条件

具体的配置文件路径在"演化与版本管理"那节定义。

概念使用约定

本文档术语与战略白皮书保持一致。"交易准备 / 交易决策 / 交易行动"系列措辞;不用"行动准备 / 行动判断 / 行动方案"系列。

如下游实施中发现需要引入战略白皮书未授权的新概念,必须先在战略白皮书或产品定义文档里授权(走 governance change-protocol),不在工程文档里自创。

本文档变更时的快速核查

本文档每次改动时,下列 grep 级核查作为变更评审的必要条件

  1. 战略边界原句 "FinBayes 不直接下单, 也不持有账户凭证" 仍然出现在文档中
  2. 凭证条款原句 "一律不收、不存、不训练" 仍然出现在文档中
  3. 七类任务类型措辞与产品定义文档完全一致
  4. 战略未决问题相关的参数文中未出现具体数值(必须是配置文件指针 / 占位符)
  5. agent 本体不变量仍在:「FinBayes 产品本体是带自主循环的认知 agent,主动信号 / 自主复盘循环是 identity 级能力」未被删改,且无任何里程碑把最小自主循环排到状态化(M1)之后太远

这些是文档表面完整性的快速核查,不替代实质语义 review。变更评审还需配套人工核查:被禁概念是否以同义改写 / 结构隐藏 / 英文替换等方式被引入文档。这两层检查的角色分工详见架构目标章节下的战略保真度质量属性。


3. 架构目标与质量取舍

这一节回答:这个架构在追求什么;冲突时按什么规则取舍。

总体目标

让 FinBayes 实施者(写代码的 AI 助手 / 接手维护的工程师)能够实现的代码:

  1. 不漂移战略白皮书与产品定义文档的不变量
  2. 覆盖产品定义文档要求的全部用户行为
  3. 多入口(CLI、TUI、Web、MCP、Channel)的认知质量与用户体验一致
  4. 未来增加新任务类型 / 新市场 / 新入口时不需要推倒重来

关键质量属性

按对架构决策的影响优先级排序:

优先级质量属性工程上具体做什么
战略保真度每次架构改动过 review gate,双层检查:(a) 机械 grep 检查战略不变量原句仍存在 (b) 人工实质语义核查战略未授权概念的本质内涵未被同义改写 / 结构隐藏 / 英文替换等方式引入。grep 是必要的快速过滤,不是合格判定
认知输出质量综合层产出反方证据 / 关键风险 / 失效条件 / 信息缺口按事实空间生成;画像只影响表达密度,不进入证据筛选;每条认知输出可被重放、对比、追溯(含证据来源、综合路径、Provider 调用),作为后续质量评估的可被验证基础。具体的认知质量验收方法(评估维度、rubric、多评估者机制)属于待定义的工程设计问题,详见 OQ-002 与后续 §20 / §21
可演化性跨模块接口显式版本化;任务路由 / 技能 / 数据源 / 大模型 Provider 走注册表查找而非硬编码;与战略未决问题相关的参数走配置
可观测性每次任务执行产出可序列化审计记录(不含凭证类内容);每个降级 / 失败的证据节点带降级原因;用户可见"为什么这么答"线索
响应性多任务并发执行;部分结果流式输出(不等所有内部任务完成才出第一屏);长时间任务异步走
可测试性五层测试:单元(模块内部)/ 契约(跨模块接口)/ 集成(多模块协作)/ 场景抽样回归(FinBayes Case Library,定位质量退化与缺口,内容动态迭代不作为二元门禁)/ 认知质量评估(具体方法待 §20 / §21 与产品团队共同定义)
本地优先第一阶段本地部署跑完整体验;本机配置秘密走本机安全存储;状态可落本地文件或嵌入式数据库
健壮性每个外部依赖有降级路径;一个证据节点失败只影响依赖它的下游节点,不阻塞其他任务

冲突时的取舍

冲突情境取舍
战略保真度 vs 实施速度保真度优先
认知输出质量 vs 响应性第一屏先回答用户题眼并标注"反方 / 详细条件还在补充";最终结果必须完整
可演化性 vs 简洁性跨模块接口必须版本化(不可简化);内部实现可简化(单进程优先,不微服务化)
响应性 vs 完整性部分结果先输出 + 最终归并;不允许"等齐了再出"导致用户等待
本地优先 vs 多入口一致性多入口走同一 runtime 接口契约;不为本地特殊化降级共用接口
可观测性 vs 性能第一阶段全量审计 trail;性能问题在后续优化时再讨论降低粒度

第一阶段实施时的具体技术取向

明确这些事项第一阶段这样做(而不是另一种做法):

  • 单进程优先:runtime 在第一阶段单进程实现,不微服务化。多入口(CLI / TUI / Web / MCP / Channel)共享同一 runtime 实例
  • 本地优先:状态落本地文件 / 嵌入式数据库(如 SQLite);不依赖云端 state store
  • 异步走 Python asyncio:多任务并发用异步等待原语(具体细节见 ADR-005 待写)
  • 大模型 Provider 走统一适配层:不直接调用各家 SDK,所有 Provider 通过统一接口接入(具体细节见 arch-rewrite/ADR-008 accepted)
  • 状态写入两步:长期状态对象(关注列表、判断记录、动态画像)的写入分待确认 / 已确认两步(具体细节见 ADR-007 待写)
  • 审计 trail 全量记录:第一阶段每次任务执行的证据 / 综合路径 / Provider 调用全量写审计,性能优化是后续事项

第一阶段不投入优化的事

显式声明这几件事第一阶段不做(避免实施者误优化):

  • 极致低延迟(首屏 100 毫秒以内):认知任务本质需要大模型调用,秒级延迟合理
  • 大规模并发(单实例万级 QPS):第一阶段本地部署优先 + 个人用户量级
  • 跨地域部署 / 跨用户横向扩展 / 数据库分片:远期事项

什么时候开始投入这些优化的判断条件留给运维 / 产品决定,工程架构不预设阈值。


4. 业务对象与关系

字段权威定义见 contracts/structured-cognition-result.yaml(Step 11 整改包 I 单一事实源层)。本段为叙述用途,若与 contracts/ 不一致以 contracts/ 为准。承接 Step 11 整改方案

这一节回答:FinBayes 业务里有哪些 first-class 概念,它们之间什么关系。

概览

FinBayes 业务层识别 7 个 first-class 概念。它们是用户能感知、能操作、能引用的对象。工程实现按这些概念组织数据模型与接口。

对象工程英文名是什么
Fin Object 金融对象FinObject用户关注的金融对象,可以是单一标的 / 板块 / 主题 / 事件 / 政策 / 组合 / 叙事 / 关键人物中的任意一种或组合
Watchlist 关注列表Watchlist用户组织 Fin Object 的列表机制,便于持续追踪
Session 会话Session一次对话或任务上下文容器,承载多轮交互
Task 金融认知任务Task用户的自然语言提问被识别为的具体任务,按产品定义文档当前定义的任务类型清单识别。一个输入可能触发多个并发任务
认知结果StructuredCognitionResultTask 的输出,包含按任务类型组合的认知要素
Judgment Record 判断记录JudgmentRecord用户在某时刻对某 Fin Object 形成的判断的可复盘记录,含成立条件 / 失效条件 / 反方证据等
动态画像DynamicProfile用户在持续使用中表现出的认知偏好、表达密度、关注模式,用户保有查看 / 修改 / 清空控制权

工程英文名是 Pydantic 模型 / SQLite 表名 / 代码模块名的统一约定,后续章节(§9 / §11 / §15 / §27)按这套英文名引用。中文名仅用于用户可见输出与本架构文档正文。

关系图

这张图表达什么:用户拥有动态画像(每用户一份)、维护任意多个 Watchlist、发起任意多个 Session。Watchlist 包含 Fin Object。Session 承载 Task。Task 围绕 Fin Object 并产出认知结果。认知结果经用户确认后可成为 Judgment Record。Judgment Record 针对具体 Fin Object,并能形成复盘链(用户后续更新或矫正旧判断时)。

这张图特意不表达什么:模块级实现细节(如 TaskGroup 是 Task 的并发容器、EvidencePacket 是证据单元等工程对象)、字段级数据结构、状态写入路径(候选 → 已确认等工程细节)、各对象的数量基数(一对多 / 多对多等)—— 这些在系统全景与系统运行章节展开。

怎么读这张图:实线箭头是直接关系("用户维护 Watchlist"),虚线箭头是条件关系("认知结果用户确认后可成为 Judgment Record"),Judgment Record 自环表示"复盘链"是同一对象内部的版本关系(旧判断 → 新判断)。

各对象的关键属性与生命周期

Fin Object

是用户关注的金融对象。可以是以下任意一种或组合:

  • 标的(单一资产,如 BTC / ETH / NVDA / AAPL)
  • 板块 / 行业(如半导体、Layer1、AI 概念股)
  • 跨标的主题(如降息、AI 浪潮、稳定币监管)
  • 用户自定义组合(如 BTC vs ETH 对比组合、自选股组合)
  • 单次重要市场事件(如财报、FOMC、链上 hack、协议升级)
  • 政策 / 宏观变量(利率、通胀、监管动向)
  • 影响市场叙事的关键人物(KOL、机构、央行)
  • 市场叙事(如 AI、降息、ETF、监管、链上周期等当前主导的故事线)

Fin Object 是 FinBayes 一切金融判断的承载体——用户的关注、历史判断、反方证据、成立条件、失效条件、复盘记录都围绕 Fin Object 组织。

Watchlist

用户主动维护的 Fin Object 集合。加入 Watchlist 是用户对该 Fin Object 表达持续关注的承诺。Watchlist 支持:

  • 任意类型 Fin Object 加入(不限于"标的",可加事件 / 主题 / 政策 / 关键人物等)
  • 分组、排序、按 Fin Object 设置不同的关注密度与复盘节奏
  • 与历史判断和复盘记录联动:市场变化触及用户判断时,FinBayes 围绕 Watchlist 内对象触发主动信号

Session

一次对话或任务上下文容器。FinBayes 支持:

  • 默认会话:首次使用无需创建,降低首次使用门槛
  • 命名会话:用户主动创建用于不同意图 / 场景 / 关注对象
  • 跨会话持续状态:Judgment Record、Watchlist、动态画像 跨会话持有

Session 的生命周期:创建 → 活跃中 → 上下文超额时压缩 → 归档 → 可恢复 → 删除。具体状态机在状态对象生命周期章节展开。

Task

用户的自然语言提问被识别为的具体任务。任务类型清单由产品定义文档定义。第一阶段含以下类型(未来可能扩展或细分,工程实现按注册表查找而非硬编码 if-else 分支):

  • 解释类:金融概念 / 机制 / 现象的解释
  • 分析类:围绕事件 / 数据 / 变化展开认知组织
  • 比较类:多个 Fin Object 的维度化对比
  • 复盘类:触发历史判断的成立条件 / 当前变化 / 是否仍成立
  • 风险识别类:主动识别下行风险 / 反方 / 盲点
  • 交易准备类:交易前的条件 / 风险 / 反方 / 失效边界检查
  • 交易决策辅助:聚焦具体决策点的条件化判断

一个用户输入可能命中多个任务(如"NVDA 财报后我的判断要不要更新 + 现在该不该加仓"是复盘 + 交易准备的组合)。多任务的并发组织由工程层的 TaskGroup 承接(详见系统全景章节)。

自然语言到任务的识别策略(规则 / LLM / 混合 / 其他)是关键架构决策,留待 ADR-004 任务识别策略 定(详见 status.md OQ-003)。

认知结果

Task 的输出。按任务类型组合产品定义文档定义的认知要素:

  • 结论 / 倾向(条件化)
  • 依据
  • 多视角
  • 反方证据
  • 成立条件
  • 失效条件
  • 不确定性 / 信息缺口
  • 来源与时间戳
  • 可继续追问项
  • 历史判断链接(与用户已有 Judgment Record 的关系)

不固化字段表,按任务类型动态组合。具体哪个任务类型组合哪些要素由综合层章节展开。

Judgment Record

用户在某时刻对某 Fin Object 形成的判断的可复盘记录。是 FinBayes 持续认知能力的关键载体。每条 Judgment Record 包含:

  • 时间戳与所属 Session
  • 涉及的 Fin Object
  • 用户判断方向 / 倾向
  • 支持理由 + 反方证据(FinBayes 主动提的 + 用户接受的)
  • 成立条件与失效条件
  • 不确定性 / 信息缺口
  • 复盘记录链(之后的更新 / 矫正)

Judgment Record 是独立的可被检索、复查、引用的认知资产,与聊天记录区分。生命周期:候选生成 → 用户确认 → 已确认 → 市场变化触及成立 / 失效条件时主动信号触发复盘 → 更新链。详见状态对象生命周期章节。

动态画像

FinBayes 在用户使用和交互过程中静默构建的用户画像。画像在用户持续使用中逐步完善,是 FinBayes "越来越懂用户" 的基础。

画像包含 (但不限于):

  • 用户当前阶段的风险偏好
  • 关注模式(关注密度、复盘节奏、对新信息的敏感度)
  • 关注的市场与标的范围
  • 任务类型偏好(更常做分析 / 复盘 / 交易准备 / 等)
  • 表达密度偏好(专业术语 vs 解释性语言)

动态画像不影响 FinBayes 输出质量的标准——反方证据 / 关键风险 / 失效条件等核心认知要素的呈现不会因画像被裁剪。画像主要影响两件事:

  • 意图识别的精准度:同一句用户表达在不同用户身上可能对应不同任务类型(例如"还能追吗"在常做交易准备的用户与常做风险扫描的用户身上有不同的隐含意图)
  • 输出内容范围匹配用户期望:在某个 Fin Object 上展开的深度、关注哪些细节、表达密度等会按画像调整(但核心认知要素的覆盖度不变)

用户对画像保有查看、修改、清空的完整控制权(战略层不变量,详见上位继承与不变量章节)。

不在这一章的对象

下列对象是工程层实现细节,在系统全景 / 系统运行章节展开:

  • TaskGroup:多任务并发的组织容器(用户感知"答案在分步流出"但不直接操作 TaskGroup)
  • EvidencePlan / EvidencePacket:证据组织的内部结构
  • State Candidate:待用户确认的状态写入
  • Context Snapshot:长会话的上下文压缩快照

跨层对象映射(产品 → 架构 → 工程)

本章定义的 7 个 first-class 业务对象,在产品定义 / 主架构 / 状态机 / 持久化 / 模块路径 / M0 实现度的对应:

业务对象产品定义 §工程英文名持久化(§15)独立状态机(§11)模块路径(§27)M0 实现
Fin Object§3.1FinObjectfin_objects无(仅 created/archived 标记)state/fin_object.py✅ implement
Watchlist§3.2Watchlistwatchlist_objects无(由 StateCandidate 承载)state/watchlist.py❌ M1+
Session§3.3Sessionsessions✅ 有state/session.py✅ implement(默认 Session 兜底)
Task(工程派生)Task仅审计 trail(内存对象)✅ 有orchestration/task.py✅ implement
认知结果§7StructuredCognitionResult仅审计 trailcognition/types.py✅ implement(M0 综合层输出契约)
Judgment Record§3.4JudgmentRecordjudgment_records✅ 有state/judgment.py❌ M1+
动态画像§3.5DynamicProfiledynamic_profilesstate/profile.py❌ M1+

派生的工程对象(不是 first-class 业务对象但有独立状态机或承载关键职责):

工程对象独立状态机(§11)模块路径(§27)M0 实现
TaskGroup✅ 有orchestration/task_group.py⚠️ stub(M0 仅单任务)
StateCandidate✅ 有state/candidate.py⚠️ stub
Provider Readiness✅ 有providers/readiness.py✅ implement
AuditEventstate/audit.py✅ implement

阅读约定

  • 用户视角看到的是"业务对象"(产品定义 §3)—— 5 类核心 + 隐式的 Task / 认知结果
  • 工程视角看到的是"业务对象 + 派生工程对象"(架构 §4 + §11) —— 7 first-class + 4 派生
  • 持久化 / 状态机 / 模块路径只是工程视角的不同 view,不引入新对象
  • M0 阶段实施按"M0 实现"列,详见 M0 走通骨架工程包 §2 接口子集表

5. 用户价值与认知流转

这一节回答:战略层提的"想清楚 / 看全面 / 看本质"三层价值在工程上怎么落;用户问题如何流转到认知结果。

三层价值的工程承接

FinBayes 的核心价值是把用户的金融困惑转化为可复盘的金融认知。战略层把这件事拆为三层:

战略层价值工程上落到
想清楚 — 帮用户把含糊的情绪 / 直觉 / 疑问转化为可分析的金融认知任务任务识别(自然语言 → 任务类型 + Fin Object + 市场范围 + 时间窗口)+ 触发型澄清(信息不足时主动追问关键问题)
看全面 — 帮用户把碎片信息组织成完整事实空间,主动呈现反方证据证据组织(按 Market Pack 调用数据源 / 工具 / Skill)+ 多视角整合(不同立场 / 方法 / 时间尺度的观点)+ 反方证据主动呈现
看本质 — 帮用户看清成立条件 / 失效条件 / 关键变量 / 信息缺口综合层产出条件化结论 + 成立条件 + 失效条件 + 不确定性 + 信息缺口

这三层不是顺序而是同时进行——综合层产出的内容同时承接三层价值。

认知流转主线

一次用户提问的端到端业务流程:

这张图表达什么:FinBayes 作为 agent 的默认闭环。横向的单回合(A→G)只是 agent 的一个回合、问答只是入口之一;图的骨架是常开的自主循环——判断沉淀进 agent 状态层(K),agent 持续监控市场变化是否触及成立 / 失效条件(L),触及就主动发起复盘(J)回到认知,且状态层作为跨回合记忆喂回每一个回合。这条循环不以「用户是否愿意沉淀」为可选开关,而是 FinBayes 之所以是 agent 而非问答函数的本体(承接 §2 agent 本体不变量)。

这张图特意不表达什么:工程实现细节(任务识别如何分发到 Router Agent、综合层如何调用 LLM、状态写入两步、heartbeat / cron 如何驱动 L 的扫描等),这些在系统全景章节展开。

怎么读这张图:菱形是判断分叉,矩形是处理步骤,圆柱是 agent 状态层;turn 子图是单个回合的边界,子图外的 K→L→J→B 回路是 agent 的常开主动循环。实线是默认路径,虚线(K⇢B)是跨回合记忆注入。它表达 FinBayes 与用户的协作不是一次性问答,而是一个会自主回头、跨回合记得用户的 agent。

关键节点的业务约束

识别问题类型与对象:识别基于产品定义文档的七类任务清单,不依赖样例 prompt 的字符串匹配;新出现的提问表达若与已知 paraphrase 相似,应稳定识别为同类任务。

澄清追问:用户表达不足以决定任务类型 / 对象 / 时间窗口时主动追问一两个关键问题。澄清的目标是把用户的模糊表达推向明确的金融认知任务,不是无限追问降低进入门槛。

组织相关信息:信息组织以 Fin Object 为中心,不以孤立 ticker 或事件为中心。同一 Fin Object 的不同信息面(价格 / 链上 / 财报 / 资金流 / 新闻 等)由 Market Pack 声明,工具调用结果归一化为证据单元。

呈现认知材料:第一屏先回答用户题眼(用户最直接问的事),其他认知要素(反方、详细条件、追问项等)随后展开。第一屏不暴露内部 trace、不只是字段列表、不退化为免责声明。

用户基于材料判断 / 决策:用户保留完整决策权与执行权。FinBayes 提供认知材料供用户做决策,不替用户决定行动,也不在金融账户上执行任何动作。

判断沉淀:用户可以把当前关注的 Fin Object 加入 Watchlist;可以把当前形成的判断记录为 Judgment Record。沉淀经"用户确认"才发生(候选 → 已确认两步),不悄悄写入用户长期状态。

市场变化复盘触发:用户已确认的 Judgment Record 中的成立条件 / 失效条件被市场变化触及时,FinBayes 主动发出复盘信号,明示触及哪条判断、哪个条件、当前变化是什么。主动信号不退化为价格提醒或新闻推送。

与战略未决问题的边界

认知流转涉及的工程参数(每次任务的大模型调用次数上限 / 主动信号触发频率 / 用户层级服务边界等)按战略未决问题的承接约定走配置而非硬编码,留给商业团队与产品团队基于冷启动数据决定(详见上位继承与不变量章节)。


6. 关键业务场景

这一节回答:第一阶段典型业务场景下,认知流转具体走成什么样。

场景一览

下列 12 个场景覆盖产品定义文档当前定义的各类任务、复合场景与 agent 自主行为场景

被动 / 主动场景配比(frame):S1–S8 是用户发起的单回合问答(agent 的入口行为),S9–S12 是 agent 在无人提问时的自主行为(主动监控、到期对账、事件驱动复查、heartbeat 批量唤醒)。早期版本只有 1 个自主场景(S9)、被动:主动 = 8:1,这个配比本身会把读者引向「FinBayes ≈ 问答函数」的误读。本节显式补齐自主场景到 4 个,让场景集如实反映 §2 的 agent 本体不变量——agent 的自主循环与单回合问答同等是产品骨架。

编号用户语言示例主要任务类型
S1"什么是 ETF 折溢价"解释类(被动入口)
S2"美联储这次讲话怎么看"分析类(被动入口)
S3"BTC vs ETH 这轮该怎么配"比较类(被动入口)
S4"我之前看多 ETH 的理由还成立吗"复盘类(被动入口)
S5"BTC 现在最大下行风险是什么"风险识别类(被动入口)
S6"我现在该不该减 ETH"(用户尚未声明仓位 / 风险 / 时间窗)交易准备类(被动入口)
S7"NVDA 跌到 130 我要不要补"交易决策辅助(被动入口)
S8"NVDA 财报后我对它的判断要不要更新,现在该不该加仓"复盘 + 交易准备 复合(被动入口)
S9(无用户主动提问)市场变化触及用户某条 Judgment Recordagent 自主行为:条件触及主动复盘
S10(无用户主动提问)heartbeat 周期唤醒,批量扫描所有到期 / 临界的 Judgment Recordagent 自主行为:定时巡检
S11(无用户主动提问)某条判断的时间窗到期,延迟神谕可验证agent 自主行为:到期拉真实数据对账
S12(无用户主动提问)Watchlist 对象出现新关键事件agent 自主行为:事件驱动复查提示

场景详述

S1:概念解释

用户:什么是 ETF 折溢价?

  • 任务类型:解释类
  • 认知要素组合:结论 / 依据 / 来源与时间戳 / 可继续追问项(如"折溢价对哪些交易策略有用"、"溢价持续时是不是套利信号"等)
  • 状态变化:通常无(仅在用户主动加入关注时触发 Watchlist 操作)
  • 业务约束:不退化为词典式定义,应结合 FinBayes 已积累的市场上下文(哪些 ETF 当前确实在显著折溢价)

S2:事件分析

用户:美联储这次讲话怎么看?

  • 任务类型:分析类
  • 认知要素组合:结论 / 依据 / 多视角 / 反方证据 / 成立条件 / 不确定性 / 来源与时间戳
  • 状态变化:可能触发"是否将该事件加入 Watchlist"、"是否将当前判断记录为 Judgment"
  • 业务约束:多视角真实呈现不同立场(鹰派 / 鸽派 / 市场预期偏差等),不只是同一观点的不同表述

S3:对比配置

用户:BTC vs ETH 这轮该怎么配?

  • 任务类型:比较类
  • 认知要素组合:对比维度声明(如基本面 / 周期位置 / 资金流 / 政策环境 / 风险结构)/ 各对象在各维度的结论 / 反方 / 不确定性
  • 状态变化:可能将该对比组合作为 Fin Object 加入 Watchlist
  • 业务约束:对比维度由 Market Pack 声明,不让 LLM 自由发挥;用户已声明"配置"意图但未声明仓位 / 风险预算时,不直接给具体配比,给"在不同条件下偏向 X 的逻辑"

S4:历史复盘

用户:我之前看多 ETH 的理由还成立吗?

  • 任务类型:复盘类
  • 认知要素组合:当时成立条件 / 当前变化 / 是否仍成立 / 新增信息 / 反方 / 历史判断链接
  • 状态变化:可能在 Judgment Record 上加一条复盘记录(用户确认后)
  • 业务约束:复盘必须找到对应的 Judgment Record;若用户曾经表达过但未沉淀为 Judgment Record,应主动询问当时的具体理由,不替用户假设

S5:风险扫描

用户:BTC 现在最大下行风险是什么?

  • 任务类型:风险识别类
  • 认知要素组合:风险来源(多个)/ 触发条件 / 失效条件(在什么前提下这个风险不存在)/ 多视角(不同时间尺度的风险)
  • 状态变化:通常无
  • 业务约束:识别多个具备不同时间尺度与触发条件的风险,不退化为"宏观环境不确定 / 监管风险"这类无信息含量的回答

S6:交易准备(用户未声明仓位)

用户:我现在该不该减 ETH?

  • 任务类型:交易准备类
  • 认知要素组合:一般性条件化判断(不针对用户具体仓位)/ 反方 / 失效边界 / 不确定性 / 显式标注"这是检验而非指令、执行权在你"
  • 状态变化:可能触发用户主动声明仓位 / 风险预算 / 时间窗口;用户声明后进入针对该仓位的具体条件化判断
  • 业务约束:用户未声明仓位时给具体减仓数量 / 比例 / 价位建议,给的是"在什么条件下减仓的逻辑是 X,在什么条件下不减的逻辑是 Y"的条件化判断

S7:交易决策辅助(具体价位)

用户:NVDA 跌到 130 我要不要补?

  • 任务类型:交易决策辅助
  • 认知要素组合:在 130 这个价位下的条件化倾向 / 成立条件 / 失效条件 / 反方 / 不确定性 / 显式标注"这是检验而非指令、执行权在你"
  • 状态变化:可能触发将该决策点作为 Watchlist 内事件追踪
  • 业务约束:同 S6,仅在用户已声明仓位 / 风险预算 / 时间窗口时给具体决策倾向;未声明时给条件化分析

S8:复合场景(复盘 + 交易准备)

用户:NVDA 财报后我对它的判断要不要更新,现在该不该加仓?

  • 任务类型:复盘类 + 交易准备类(一个用户输入命中两个任务)
  • 业务流转:内部并发执行两个任务:复盘任务调出已有 Judgment Record 检查成立 / 失效条件 / 当前变化;交易准备任务围绕"是否加仓"组织条件化判断。两个任务的输出归并为一份给用户的有逻辑顺序的整合回答(如"基于复盘结论 X,加仓的条件化判断是 Y")
  • 业务约束:内部并发对用户透明,用户看到的是整合回答不是分裂的两份输出;某一任务降级时另一任务仍能给有价值的部分回答

S9:主动信号触发

触发条件:用户某条已确认 Judgment Record 的成立 / 失效条件被市场数据触及(如 ETH 跌幅触发某条 Judgment Record 的失效条件)

系统行为:主动发出复盘信号,明示:触及哪条判断 / 哪个条件 / 当前变化是什么 / 是否仍成立 / 建议如何复盘

业务约束

  • 信号不退化为价格提醒或新闻推送
  • 信号节奏由用户配置的关注密度控制,不高频骚扰
  • 信号必须能回到对应 Judgment Record 让用户完成复盘并更新认知

S10:heartbeat 定时巡检(agent 自主行为)

触发条件:周期性 heartbeat 唤醒(无用户提问),agent 批量扫描所有 Watchlist 对象与未结算 Judgment Record,识别哪些判断的成立 / 失效条件已临界、哪些已到期可对账。

系统行为:用结构化 enum 判定每条是 skip 还是 run(应对触发信号本身带噪),只对真正越线的判断生成主动信号,避免噪声轰炸;批量结果按用户关注密度合并推送。

业务约束

  • heartbeat 是 agent 主回路的一种触发源,不是用户可见功能;自动注入的扫描 prompt 必须过提示注入防御
  • skip/run 判定走 LLM 结构化输出,不用裸阈值,以容忍神谕带噪
  • 巡检绝不触发任何交易动作,只产出复盘信号

S11:延迟神谕到期对账(agent 自主行为)

触发条件:某条 Judgment Record 的时间窗到期(如「财报后两周」),其可证伪断言此时可被真实市场数据验证(无用户提问)。

系统行为:agent 主动再次拉取真实市场数据,对该判断做判断跟进结算(旧称「三态结算」;按 ADR-022 formal 化为「验证状态+验证结论」两层枚举,见 glossary),把结算结论与原判断同时保留形成时间线(不覆盖原判断),并在置信度与事后印证频率间记录校准信号。

业务约束

  • 对账锚点是「成立 / 失效条件是否被市场触发、条件化倾向方向是否被事后演化支持」,不是「按判断交易的真实盈亏」(FinBayes 不下单、不接触持仓)
  • 结算不二值化(三态),承认对错本身模糊
  • 正式校准记录 / 命中率系统不在第一阶段强建(留作单独产品设计课题),第一阶段只需 agent 能到期主动回来对账并留痕

S12:事件驱动复查提示(agent 自主行为)

触发条件:Watchlist 内某 Fin Object 出现新的关键事件(如监管公告、协议升级、财报),可能影响用户已有判断(无用户提问)。

系统行为:agent 主动评估该事件是否触及任一历史判断的关键前提,命中则推送复查提示,明示事件、受影响的判断、可能改变的条件。

业务约束

  • 以「是否触及历史判断条件」为中心,而非以「事件热度 / 价格波动」为中心
  • 未触及任何历史判断条件的事件不主动打扰用户
  • 提示保留认知 / 执行分工说明,不作为交易信号

不在第一阶段场景之列

下列业务场景明确第一阶段不做

  • 自动执行任何交易(不下单 / 不调仓 / 不持有账户凭证)
  • 主动监控用户在交易所 / 经纪商的账户状态
  • 替用户做任何金融决策
  • L4 职业投资者的团队协作 / 深度数据 / 审计 / 权限工作流
  • A 股 / 商品 / 外汇 / 债券等独立市场(仅作为宏观横向输入支撑 Crypto + US Stocks 的判断)

7. 系统与外部世界的关系

这一节回答:FinBayes 作为一个黑盒,与外部世界的接触边界是什么。

系统上下文图

这张图表达什么:FinBayes 作为生态认知层与 7 类外部角色的交互边界。用户是 FinBayes 唯一直接对话的人类参与者;LLM 与外部数据 Provider 是 FinBayes 主动调用的能力提供方;Data Horizon / Trading Matrix / RLE / FEFM 是生态内协同项目,各自有独立的产品定位与接口契约。

这张图特意不表达什么:FinBayes 内部模块(容器与组件划分留给系统内部的进程与服务划分章节)、具体接口字段(schema 留给附录)、部署拓扑(留给部署形态章节)。

怎么读这张图:实线箭头是 FinBayes 主动调用 / 接收的关系;虚线箭头是潜在 / 未来的关系(如 RLE 学习信号回流、FEFM 模型能力接入)。FinBayes 与 AI Trading Matrix 没有直接连接——用户在授权后自主把意图转交 Trading Matrix,FinBayes runtime 不参与执行链路。

7 类外部角色的接触契约

用户

接触形态:自然语言对话(文本输入,未来扩展语音 / 文件附件 / URL / 表单等多模态)。

FinBayes 给用户的输出:按任务类型动态组合的认知材料(含结论 / 倾向 / 依据 / 多视角 / 反方证据 / 成立条件 / 失效条件 / 不确定性 / 信息缺口 / 来源时间戳 / 可继续追问项 / 历史判断链接)。

用户对 FinBayes 的控制权

  • 对话内容(用户表达什么由用户定)
  • 状态写入确认(候选 → 已确认 两步,用户拒绝则不写入)
  • 画像查看 / 修改 / 清空(战略不变量)
  • Provider 配置选择(本地优先部署下,用户可自配置喜欢的 LLM / 数据 Provider)

LLM Providers

接触形态:FinBayes 通过统一的 Provider Adapter 层调用各种 LLM Provider(云端 Claude / GPT / DeepSeek / Qwen API;本地 Ollama / vLLM / LM Studio / Hugging Face TGI 等;用户自定义 OpenAI-compatible endpoint)。

调用方式:标准化的 Function Calling 接口 + streaming 响应 + 多模态消息(按 Provider 支持的能力)。

用户配置主导:本地优先部署下,用户可自配置 Provider 偏好与 fallback 顺序。系统默认配置是兜底而非强制(详见用户自配置 Provider 设计)。

外部数据 Providers

接触形态:通过统一的数据源注册表接入各种金融数据 API(价格行情、链上数据、SEC filings、财报数据、新闻、宏观数据等)。

调用方式:HTTP API 调用、SDK 接入、文件读取(用户上传的财报 / 研报 PDF 等)。

关键约束:所有外部数据进入后归一化为统一的证据单元(含来源、时间戳、freshness、置信度、降级原因等元数据)。

Data Horizon(生态感知层)

接触形态:FinBayes 消费 Data Horizon 提供的整理过的金融素材(事件、实体、时间线、情报)。Data Horizon 不替 FinBayes 判断;FinBayes 不替 Data Horizon 做数据感知。

接口契约:见生态协同契约章节(待起草)。第一阶段以"从 Data Horizon 取素材"为主,可能含订阅式实时更新(待具体定义)。

AI Trading Matrix(生态执行支持层)

接触形态:FinBayes 与 Trading Matrix 没有直接连接。用户基于 FinBayes 形成判断后,自主决定是否把意图转交 Trading Matrix。

为什么不直连:战略不变量"FinBayes 不直接下单, 也不持有账户凭证"要求执行链路与认知链路严格分离。直连会让用户无法清晰区分"获取认知材料"与"发起执行"两个动作,违反认知不替执行的分工原则。

未来如果接入:必须通过独立授权边界 + 外部系统 contract,不能把 Trading Matrix 的执行能力注册为 FinBayes 的认知 skill。

RLE(生态反馈学习)

接触形态:FinBayes 把用户对认知材料的反馈(接受 / 拒绝 / 修改)发送给 RLE;用户在 Trading Matrix 上行动后的反馈也回流到 RLE。RLE 整合后产出学习信号回流到 FinBayes。

第一阶段范围:用户反馈采集 + RLE 接口契约(具体学习闭环的实现复杂度由 RLE 自身决定,FinBayes 只承接接口)。

关键约束:金融执行凭证 / 用户敏感画像 等不进入 RLE 训练数据(凭证不变量 + 用户主权)。

FEFM(金融领域基础模型)

接触形态:FEFM 作为生态内的金融领域基础模型,可经 LLM Provider 适配层接入 FinBayes(FEFM 在 FinBayes 视角下就是另一个 LLM Provider,只是来自生态内部)。

第一阶段范围:FEFM 的具体形态由 FEFM 项目自身决定。FinBayes 在 Provider Adapter 层预留对 FEFM 的接入位,等 FEFM 提供 API 时即可加入用户可选 Provider 列表。

战略边界与不变量在这一层的体现

不变量在系统上下文层的体现
不直接下单 / 不持有账户凭证FinBayes 与 Trading Matrix 无直连,用户在 FinBayes 与 Trading Matrix 之间保留完整决策权与执行权
凭证不收 / 不存 / 不训练用户输入端拦截凭证类内容(与 LLM Provider / 数据 Provider / RLE 之间的接口都不传递凭证)
用户画像主权用户保有查看 / 修改 / 清空画像的完整控制权(与 RLE 之间的反馈不绕过用户控制权)
输出是认知材料不是执行指令给用户的输出始终是条件化认知材料;不主动调用 Trading Matrix 触发任何执行动作
画像不裁剪事实空间画像只影响表达密度与术语深度;与 LLM Provider / 数据 Provider 交互时不因画像偏好过滤反方证据或关键风险

与生态内其他项目的边界总结

FinBayes 与生态内项目的边界遵循"分工而非隔离"原则:

  • 认知不替感知:FinBayes 不重做 Data Horizon 的数据整理工作
  • 认知不替执行:FinBayes 不实现任何交易执行能力
  • 执行不补造认知:Trading Matrix 不替 FinBayes 做金融判断
  • 反馈不绕过主权:RLE 收到的反馈来自用户主动行为(接受 / 拒绝 / 修改),不悄悄抓取

各项目各自独立产品 + 通过清晰接口契约协同。FinBayes 的工程实现不假设生态内其他项目的内部细节。


8. 系统内部的进程与服务划分

这一节回答:FinBayes 内部分几个进程 / 服务单元?哪些同进程?哪些独立部署?

第一阶段的整体取向:单进程优先

FinBayes 第一阶段采用 单进程实现 + 多入口共享同一 runtime 实例 的部署形态。具体而言:

  • CLI / TUI / Web API Server / MCP Server / Channel Adapter 都是同一 runtime 进程的入口适配
  • 多入口共享同一 Core Runtime 实例
  • State Store(本地数据库)通过同进程库访问,非独立服务
  • LLM Provider Adapter 是 runtime 内的客户端模块,通过 HTTP / stdio 调外部 Provider

理由(来自架构目标与质量取舍章节):

  • 个人用户量级 + 本地优先部署,不需要为大规模并发优化
  • 跨入口的认知质量一致性靠"共享同一 runtime 实例"硬保证
  • 单进程内的接口契约 = 函数调用,迭代成本低
  • 接口契约本身仍版本化,未来按需拆分进程不破坏现有调用方

容器图

这张图表达什么:FinBayes 内部分为 入口适配 / Core Runtime / Provider Adapter Pool / 本地持久化 四类容器。所有入口适配同进程,共享同一个 Core Runtime 实例。Provider Adapter Pool 通过 HTTP / stdio 调外部 LLM 与数据 Provider。持久化分四类:State Store(用户状态资产)、Cache(L3 缓存 + 语义缓存)、Config Store(用户 Provider 配置)、Credential Store(用户的 Provider API key 等本机配置秘密)。

这张图特意不表达什么:每个容器内部组件(留给"每个子系统的内部组件"章节)、具体数据流(留给关键场景的流转图章节)、未来从单进程演化到多进程的拓扑(留给部署形态章节)。

怎么读这张图:上半是外部世界,下半是 FinBayes Runtime Process。中间的箭头是跨容器调用。同一 box(如 entries 子图)内的容器都在同一进程中。Provider Adapter Pool 是同一进程内的客户端层,不是独立服务。

各容器的职责简述

容器职责第一阶段实现
CLI Adapter命令式终端入口;单次提问 / Provider readiness 检查 / Session 管理命令 / Watchlist 操作 / 等Python click / typer 等 CLI 框架
TUI Adapter终端持续问答入口;用户可切换 Session、确认状态候选、复盘判断等Rich / Textual 等 TUI 框架
Web API ServerHTTP / WebSocket 服务,供 Web UI 调用;task request / event stream / state action 等 contract 接口FastAPI / Starlette
MCP Server标准 MCP(Model Context Protocol)服务,让外部 Agent 调用 FinBayes runtimestdio 协议(MCP 标准)
Channel AdapterTelegram / Discord / 等社群 channel 集成;摘要式输出 + 回链到 Web Sessionwebhook 接收 + Provider SDK
Core Runtime任务编排 / 路由 / 综合判断 / 状态管理 / 主动信号 等核心认知能力Python class + asyncio
Provider Adapter PoolLLM / 数据 Provider 统一接入层;Provider Registry + Routing Policy + 能力匹配 + Fallback通过 LiteLLM 或自实现统一接口
State Store用户状态资产持久化(Session / Watchlist / Judgment Record / 动态画像 / 审计 trail)SQLite(本地优先)
CacheL3 语义缓存 + 精确缓存Redis(如本机有)或进程内 LRU 内存
Config Store用户的 Provider 配置(哪些 Provider 启用、任务-Provider 映射、fallback 顺序等)YAML / JSON 配置文件
Credential Store用户的 Provider API key 等本机配置秘密OS Keychain(macOS / Windows / Linux)优先,环境变量次之,加密本地文件兜底

容器间的通信方式

通信关系协议 / 形态
入口适配 → Core Runtime同进程函数调用(Python class method / asyncio 协程)
Core Runtime → Provider Adapter Pool同进程函数调用
Provider Adapter Pool → 外部 LLMHTTP / streaming(按 Provider 协议;Ollama / vLLM 用 OpenAI-compatible API)
Provider Adapter Pool → 外部数据 ProviderHTTP / SDK 调用
Core Runtime → State Store同进程库调用(SQLite Python binding)
Core Runtime → Cache同进程(Redis 通过本地 Redis 客户端 / 进程内 LRU)
Web API Server ↔ Web UIHTTP(task request / state action)+ WebSocket(task event stream)
MCP Server ↔ 外部 Agentstdio(标准 MCP 协议)
Channel Adapter ↔ Channel 平台webhook / polling(按 Channel 协议)

部署形态对容器选择的影响

详见部署形态章节,这里点要点:

  • 本地优先单机部署:所有容器同进程,State Store 用 SQLite,Cache 可选 Redis 或内存,所有 Provider 配置在用户本机
  • 本地 + 远程 Provider:Core Runtime 与持久化都在本机,仅 Provider Adapter Pool 调用远程 LLM / 数据 API(用户配置)
  • 未来托管部署(不在第一阶段):Web API Server 可分离为独立进程;State Store 可迁移到远程数据库;其他容器按需扩展

第一阶段的接口契约设计不锁死本地——未来按需拆分进程不破坏现有调用方。

与工程仓的代码位置映射

本章容器在 FinBayes 工程仓中的代码组织遵循 Python 标准 src layout:所有业务代码在 src/finbayes/ 下,按 6 子系统 + 入口适配 分子目录。各容器与代码模块的精确映射详见 §27 代码仓位置映射 —— 本章不重复,避免双源漂移。

入口适配子目录约定(src/finbayes/io/entries/):

入口容器子目录
CLI Adaptercli/
TUI Adaptertui/
Web API Serverweb/
MCP Servermcp/
Channel Adapterchannels/

详细映射(业务对象 / 状态机 / 工具 / 配置 / 测试 / 评估 全部 7 张表)见 §27。


9. 每个子系统的内部组件

字段权威定义见 contracts/structured-cognition-result.yaml(Step 11 整改包 I 单一事实源层)。本段为叙述用途,若与 contracts/ 不一致以 contracts/ 为准。承接 Step 11 整改方案

这一节回答:Core Runtime 内部分哪些子系统?每个子系统的职责、接口、关键组件是什么?

6 个子系统概览

Core Runtime 内部分 6 个子系统:

子系统核心职责
Input/Output Pipeline多模态输入归一化(文本 / 文件 / URL / 语音 / 表单)+ 输出投影(按入口呈现)+ 边界保护 hook
Task OrchestrationLLM Function Calling 驱动的意图识别 + 任务路由 + TaskGroup 并发编排 + 事后任务类型标签
Evidence + Synthesis工具调用执行 + 证据归一化 + 综合判断(产出认知要素)+ 高风险任务 self-consistency
State ManagementSession / Watchlist / Judgment Record / Profile / 审计 trail + 候选到已确认两步写入 + 主动信号触发
Capability RegistryTool / Skill 注册 + 任务类型本体(事后审计用)+ 执行类工具注册拒收
Provider AdapterLLM / 数据 Provider 统一适配 + 用户配置 Provider 池 + 4 层降级(L1-L4)+ 凭证安全

子系统间通过明确的接口契约协作,详见各子系统下方的接口表。


9.1 Input/Output Pipeline 子系统

组件图

这张图表达什么:输入侧把多种模态归一化为统一表示后过边界保护 hook,再进入 Task Orchestration;输出侧从综合层接收结构化结果过出口边界保护后,按入口投影为不同呈现格式。

这张图特意不表达什么:Task Orchestration / Synthesis 等下游子系统的内部组件(在下面各小节展开)。

职责

把所有用户输入归一化为「主文本 + 结构化上下文片段 + 元数据」供下游使用;把综合结果投影为各入口需要的呈现格式。

输入端的边界保护 hook 是战略不变量的工程承接点:凭证类与执行类输入在这里被规则识别 + 拦截,不进入 Task Orchestration / LLM 调用链。输出端的边界保护 hook 扫描凭证样式内容(防大模型 hallucinate 出地址 / 密钥串),不进入审计或状态。

关键接口

接口输入输出
preprocess(raw_input)任意模态原始输入 + 入口元数据归一化输入对象(主文本 + 结构化上下文 + 元数据)
boundary_check_input(normalized)归一化输入通过 / 拦截(含安全回应内容)
project(result, entry_type)综合结果 + 入口类型该入口的投影对象
boundary_check_output(result)综合结果扫描后的结果(凭证样式内容标记 / 脱敏)

失败模式与降级

失败降级
文件解析失败标记"文件未解析",给用户安全回应 + 重试建议
URL 不可访问 / 内容类型未识别同上
ASR 失败提示"语音未转写",引导用户改文本输入
边界保护识别凭证类输入返回安全回应(不进入认知任务链)+ 提示"凭证类信息不要发给 FinBayes"
边界保护识别执行类请求转为认知任务(如"是否要 X 行动 → 走交易准备类任务认知材料")

验收信号

  • 归一化输出在不同输入模态下结构一致
  • 边界保护拦截测试覆盖:私钥 / 助记词 / 交易所 API key / 银行账户号 / 信用卡号 / 自动交易请求 / 直接下单请求等 negative cases
  • 输出投影在 5 个入口(CLI / TUI / Web / MCP / Channel)共享同一 StructuredCognitionResult,投影差异只在呈现层

9.2 Task Orchestration 子系统

组件图

这张图表达什么:输入归一化后,加载用户上下文与工具池 schema,喂给 LLM Function Calling 做意图识别与工具选择。LLM 决定调单工具 / 多工具组合 / clarify 工具中的某一种。任务执行完成后,事后回填任务类型标签到审计 trail。

这张图特意不表达什么:意图本体作为前置分类器(FinBayes 不采用此模式,详见架构决策记录 ADR-004)。

职责

驱动用户输入到结构化任务的转换。不预设意图分类管道——意图识别由 LLM Function Calling 完成,FinBayes 提供工具池 schema、用户上下文、对话状态作为输入。任务类型本体在这里作为事后标签用于审计,不作前置路由。

复合任务(一个用户输入命中多个任务)通过 TaskGroup 显式拆解为单工具任务串行 / 并发调用——这是 FinBayes 在意图层的工程责任,不依赖 LLM 原生处理多轮复合任务(业界研究确认 LLM 在多轮工具调用上不稳定)。

frame 说明(agent 的两个半):Task Orchestration 承接的是 agent 的「单回合编排」——把一次用户输入在一个回合内组织成任务并产出认知。它不是 agent 的全部主回路。跨回合的自主循环——在无人提问时被 heartbeat / 市场变化唤醒、判断成立 / 失效条件触及时主动发起新一轮认知——由 §9.4 State Management 的主动信号触发器承接(§9.4 组件图中的 主动信号触发器,其产出的新任务经「State Management → Task Orchestration:主动信号触发的新任务」回流进本子系统,见 §9 跨子系统接口表)。单回合编排 + 主动信号触发器 = agent 的两个半:只有前者,FinBayes 是一个会编排单次问答的函数;两者合起来,才构成 §2 不变量定义的带自主循环的 agent。实施时不得只建 Task Orchestration 而把主动信号触发器无限后推。

关键接口

接口输入输出
orchestrate(normalized_input)归一化输入TaskGroup(含一个或多个任务)或 ClarifyResponse
dispatch_task_group(group)TaskGroup 对象部分结果流 + 最终归并结果
tag_task_type(task, llm_call)任务 + LLM 调用结果任务类型标签(来自任务类型本体)写入审计 trail

内部组件简述

  • Context Loader:从 State Management 读取用户画像 / 对话状态 / Watchlist / 已声明持仓
  • Tool Pool Assembler:从 Capability Registry 取工具 schemas,按用户上下文过滤可用工具
  • LLM Function Caller:经 Provider Adapter 发起 Function Calling,处理 confidence / 重试
  • TaskGroup Manager:多任务并发执行 / 失败隔离 / 部分结果流式输出 / 最终归并
  • Clarify Handler:clarify 工具调用的特殊处理(强制串行阻塞,澄清后回到 orchestrate 起点)
  • Task Type Labeler:事后从 LLM 工具调用反推任务类型标签(用于合规审计)

失败模式与降级

失败降级
LLM 不可用由 Provider Adapter 触发 L2 / L3 / L4 降级(详见 Provider Adapter 子系统)
LLM 给低 confidence自动调 clarify 工具,回到 orchestrate 起点
TaskGroup 某子任务失败该子任务降级输出 + 不阻塞其他子任务,最终归并时明示降级
高风险任务(交易准备类 / 决策辅助类)强制 self-consistency N≥3 采样投票(由 Evidence + Synthesis 实施)

验收信号

  • 同一用户输入在重复运行中识别为相同任务组合(除非走 LLM 路径产生合理变化)
  • 复合任务(如复盘 + 交易准备)显式拆解为多工具调用,靠 LLM 单次输出
  • 事后任务类型标签覆盖所有完成的 task,进入审计 trail

9.3 Evidence + Synthesis 子系统

组件图

这张图表达什么:从任务到结构化认知结果的转换。证据层生成 EvidencePlan、执行工具调用、归一化为 EvidencePacket DAG;综合层产出认知要素。高风险任务走 self-consistency。

职责

证据层:按任务声明的证据面调工具与数据源,归一化为 EvidencePacket(含 source / freshness / confidence / status / degraded_reason)。

综合层:基于证据 DAG 产出认知要素(结论 / 倾向 / 依据 / 多视角 / 反方证据 / 成立条件 / 失效条件 / 不确定性 / 信息缺口 / 来源时间戳 / 可继续追问项 / 历史判断链接)。画像信号只调整表达密度与术语深度,不进入证据筛选——反方证据 / 关键风险 / 失效条件按事实空间生成,不被裁剪(战略不变量)。

高风险任务(交易准备 / 交易决策辅助)触发 self-consistency:N≥3 次综合采样 + 一致性投票(业界研究确认 LLM verbalized confidence 不可信,自一致性是替代方案)。

关键接口

接口输入输出
plan_evidence(task)任务对象EvidencePlan(DAG 节点 / 依赖 / 预算 / fallback)
execute_evidence(plan)EvidencePlanEvidencePacket DAG
synthesize(task, evidence_dag, context)任务 / 证据 / 用户上下文StructuredCognitionResult
synthesize_with_consistency(task, evidence_dag, context, n)同上 + 采样数经一致性投票的 StructuredCognitionResult

失败模式与降级

失败降级
单证据节点失败标记 degraded_reason,不阻塞依赖它的其他证据节点之外的任务
必需证据全部失败综合层产出 degraded snapshot(明示信息缺口,不强行给方向性结论)
LLM 综合失败走 Provider Adapter 降级链;若全部 LLM 不可用走 L3 缓存 / 规则路径
Self-consistency N 次采样结果分歧大输出"判断不收敛"信息 + 各分歧的依据,让用户判断

验收信号

  • 证据 DAG 可序列化为 run result / fixture / 审计记录
  • 高风险任务在测试中能被识别并触发 self-consistency
  • 反方证据 / 关键风险 / 失效条件 在不同用户画像下的呈现一致(不被画像裁剪)
  • 没有可靠数据时给信息缺口而非凑数

9.4 State Management 子系统

组件图

这张图表达什么:长期状态(Watchlist / Judgment Record / 动态画像)通过 candidate → confirmed 两步写入;用户对画像保有完整控制权(查看 / 修改 / 清空);动态画像也来自后台静默观察。审计 trail 独立记录所有任务执行。主动信号机制:已确认的 Judgment Record 的成立/失效条件被市场变化触及时自动触发新一轮认知。

职责

承载 FinBayes 持续认知的所有长期状态资产;保证战略不变量在状态层的硬约束:

  • 凭证类信息一律不进入任何长期状态(凭证不变量)
  • 画像由用户保有查看 / 修改 / 清空的完整控制权(用户主权不变量)
  • 画像不进入证据筛选(与综合层协作约束,画像信号只在 Context Loader 注入综合层时调表达密度)
  • 判断与状态写入需用户主动确认(candidate → confirmed 两步)

关键接口

接口输入输出
create_candidate(type, payload)candidate 类型 + 内容StateCandidate(待用户确认)
confirm_candidate(id, edit?)candidate id + 可选编辑已确认状态对象
reject_candidate(id)candidate id标记拒绝
read_session_context(sess_id)session idSession + 当前 Context
compact_session(sess_id)session idContext Snapshot(保留判断条件 / 信息缺口 / 来源时间点)
view_profile(user_id) / modify_profile(...) / clear_profile(user_id)用户主权动作画像查看 / 修改 / 清空结果(清空时给出"协作上下文已重置"明示)
trigger_active_signal(market_change)市场变化事件触及的 Judgment Record 列表 + 主动信号材料
append_audit(task, calls, ...)任务执行细节审计记录

内部组件简述

  • Candidate Buffer:未确认状态的暂存
  • Confirmed Store:已确认的 Watchlist / Judgment Record / Profile(落地 SQLite)
  • Session Manager:Session 创建 / 切换 / 归档 / 删除生命周期
  • Context Compactor:长会话上下文压缩(保留金融语义锚点)
  • Profile Manager:用户画像的静默构建 + 用户主权动作
  • Active Signal Trigger:定期 / 事件驱动检查 Judgment Record 的成立/失效条件
  • Audit Logger:所有任务 / Provider 调用 / 降级 的审计记录

失败模式与降级

失败降级
State Store(SQLite)不可用runtime 进入只读模式 + 提示用户存储问题
Context Compactor 失败长会话切断,新 Session 开始 + 引用历史 Judgment Record
主动信号触发引擎宕机不阻塞主动 query;主动信号补发不实时
用户清空画像后系统仍有缓存立即同步清空 + 显式提示"协作上下文已重置"

验收信号

  • 凭证类信息 grep 测试:状态对象 / 审计 trail 中 0 命中
  • candidate vs confirmed tests 覆盖确认 / 编辑 / 拒绝 / 清空
  • 用户画像清空后所有引用都不可读
  • 主动信号触发的复盘建议能链回对应 Judgment Record

9.5 Capability Registry 子系统

组件图

这张图表达什么:3 个注册表(工具池 / 技能 / 任务类型本体)+ 执行类工具的硬性拒收规则 + 能力匹配过滤。任务类型本体仅供事后审计标签使用,不参与前置路由。

职责

集中管理 FinBayes 内部的可调用能力。执行类工具的注册请求一律拒收——这是战略边界"FinBayes 不直接下单, 也不持有账户凭证"在能力注册层的硬性承接,不允许通过任何方式(包括 plugin / 用户自定义工具 / 等)绕过。

任务类型本体由产品定义文档定义(解释 / 分析 / 比较 / 复盘 / 风险识别 / 交易准备 / 交易决策辅助),第一阶段实现为有序枚举 + 元数据(描述 / 触发关键词 / 涉及证据面 / 等)。未来可扩展或细分,按注册表查找而非硬编码 if-else。

关键接口

接口输入输出
register_tool(tool_schema)工具 schema注册成功或拒收(含拒收理由)
assemble_tool_pool(user_ctx, provider_caps)用户上下文 + Provider 能力该次任务可用的工具 schema 列表
lookup_task_type(task_id)task id任务类型本体节点(用于审计)

关键约束

  • 执行类工具拒收清单(注册接口必须拒收的工具特征):
    • 任何含"下单 / order / trade / buy / sell"语义
    • 任何含账户操作("transfer / withdraw / deposit / sign / approve")
    • 任何含自动化触发("schedule / cron / auto")
    • 任何含 shell / 系统命令执行
  • 任务类型本体的演化策略:扩展任务类型需先在产品定义文档授权,再在工具池增加对应工具 schema + 在任务类型本体增加节点

失败模式

失败处理
注册执行类工具的尝试拒收 + 记录到审计 trail(含尝试者 / 工具内容 / 时间)
任务类型本体内节点缺失runtime 失败式拒绝,强制先扩本体再继续(防止任务"漂"到未知类型)
Tool Pool 为空(如用户配置过严过滤)返回受限工具池 + 提示用户检查配置

验收信号

  • negative cases 覆盖各类执行工具注册尝试,全部拒收
  • 任务类型本体与产品定义文档清单完全一致(grep 比对)
  • 工具池组装在不同 Provider(有的不支持 Function Calling)下能力匹配正确

9.6 Provider Adapter 子系统

组件图

这张图表达什么:Provider 选择走 4 层降级(L1 用户配置 → L1' 系统默认 → L2 本地嵌入 → L3 缓存+规则 → L4 受限菜单),每层有可用性 + 能力匹配检查。统一适配层屏蔽不同 Provider 的 API 差异。凭证由 Credential Store 提供(不与代码 / 配置混存)。

职责

抽象 LLM / 数据 Provider 接入,让 Task Orchestration / Evidence + Synthesis 通过统一接口调用,下层 Provider 可替换。

用户自配置作为 first-class 场景:用户可在本地配置喜欢的 Provider(云端 Claude / GPT-4 / DeepSeek API;本地 Ollama / vLLM / LM Studio;自定义 OpenAI-compatible endpoint)+ 偏好顺序。系统默认 routing 是兜底而非强制。

4 层降级保障 LLM 不可用时仍可用:业界默认"LLM 不可用 = 服务不可用",FinBayes 本地优先定位要求更高可用性,故设计 L1-L4 降级。

关键接口

接口输入输出
select_provider(task_type, user_ctx, capability_needed)任务类型 + 用户上下文 + 能力要求(function calling / vision / 等)选定 Provider 实例 + 当前降级层级
call_llm(messages, tools, options)OpenAI-compatible 消息格式响应(function call / 文本 / streaming)
register_provider(provider_spec)Provider 配置加入用户 Provider 池
check_readiness()所有 Provider 的实时可用性 + 能力
get_audit(task_id)任务 id该任务用了哪个 Provider / 成本 / 是否走 fallback

关键内部组件

  • Provider Registry:内置 Provider 列表(OpenAI / Anthropic / DeepSeek / Qwen / Ollama / vLLM / LM Studio / Hugging Face TGI / 等)+ 用户自定义 Provider 注册位
  • Routing Policy:两层路由(系统默认 + 用户覆盖),按任务 / 区域 / 成本 / 用户偏好选择
  • Capability Matcher:检查 Provider 支持的能力(Function Calling / vision / streaming / 上下文长度)vs 任务需要
  • Readiness Prober:runtime 启动 + 周期性 ping 各 Provider 端点
  • Unified API Adapter:统一 OpenAI-compatible 接口(用 LiteLLM 或自实现),屏蔽各家 SDK 差异
  • L2 Local LLM Manager:管理本地嵌入式 LLM(Ollama 集成),探测本地模型可用性
  • L3 Cache + Rule Engine:精确缓存(Redis SHA256)+ 语义缓存(Redis Vector + bge embedding)+ 规则匹配(关键词词典 + BM25 兜底检索,不引入 ML 训练管道 — 本地优先定位约束)
  • L4 Restricted Menu Provider:所有 LLM 不可用时的菜单驱动兜底
  • Cost Tracker:每次调用的 token 数 / 价格 / 累计成本(用于用户审计)

失败模式与降级(4 层全展开)

触发条件提供能力牺牲
L1 用户 Provider 池用户配置的至少一个 Provider 可用 + 用户偏好顺序完整能力
L1' 系统默认 fallback用户没配置或配置全部不可用,回到系统默认(用户允许时)完整能力但可能要求用户补配置用户偏好被旁路
L2 本地嵌入式 LLM所有云端 / API 不可用,用户已部署本地小模型接近 L1,质量稍低部分高难度任务质量下降
L3 缓存 + 规则所有 LLM 都不可用仅预设常见模式(行情 / 概念解释 / Watchlist 操作等)失去自然语言鲁棒性 + 复杂任务不可用
L4 受限菜单 UIL1-L3 都失败用户从菜单选任务 + 受限查询完全失去自然语言低门槛,仅"读功能"

关键约束

  • 同一 Tool Registry 跨所有层:LLM 是可替换变量,工具池不变
  • L1 → L2 自动切换:runtime 探测云端可用性,无缝降级
  • L2 → L3 半自动:本地 LLM 不可用时系统显示"已进入受限模式"
  • L3 / L4 用户明示:用户必须看到"当前是受限模式,需要 X 才能恢复完整能力"
  • 本地嵌入式 LLM 是可选安装:首次部署时引导,不强制

验收信号

  • 用户在不同 region / 任务下能配置不同 Provider 偏好,runtime 按偏好选择
  • Provider 凭证仅从 Credential Store 读取,不进入审计 / 日志 / 状态
  • L1 主 Provider 失败时自动 fallback 到下一个用户偏好(无需用户介入)
  • 所有 LLM 都不可用时,L3 缓存命中的查询(如"什么是 PE")仍能返回;L4 菜单可见

子系统间的数据流总览

流向数据
Input/Output Pipeline → Task Orchestration归一化输入(边界保护后)
Task Orchestration → Capability Registry工具池请求 + 用户上下文
Task Orchestration → Provider AdapterLLM Function Calling 调用
Task Orchestration → Evidence + Synthesis选定任务 + 上下文
Evidence + Synthesis → Provider Adapter工具执行 + 综合层 LLM 调用
Evidence + Synthesis → State Management审计 trail / 候选写入
Task Orchestration → State Management任务类型标签 / 审计记录
State Management → Task Orchestration用户画像 / 对话状态 / Watchlist
Evidence + Synthesis → Input/Output PipelineStructuredCognitionResult
State Management → Task Orchestration主动信号触发的新任务

详细的时序流转(同步问答 / TaskGroup 并发 / Provider 降级 / 等场景)在关键场景的流转图章节展开。


10. 关键场景流转图

这一节回答:典型场景下子系统如何按时序协作?哪些步骤同步、哪些异步、哪些可降级?

场景清单

下列 8 个场景覆盖第一阶段的关键时序:

场景触发条件
S1 同步问答端到端流用户单一文本提问
S2 TaskGroup 多任务并发用户输入命中复合任务
S3 主动信号触发复盘市场变化触及已确认 Judgment Record 的失效条件
S4 候选状态写入与用户确认任务执行产出可沉淀状态
S5 Provider 降级路径L1 用户 Provider 不可用
S6 边界拒收凭证用户输入含凭证类信息
S7 clarify 工具触发的澄清回路LLM 给出低 confidence 的工具调用
S8 长会话压缩Session Context 超额

每个场景含 Sequence 图 + 关键说明 + 失败 / 降级路径。

子系统简称(图中使用):

  • IO = Input/Output Pipeline
  • TO = Task Orchestration
  • CR = Capability Registry
  • PA = Provider Adapter
  • ES = Evidence + Synthesis
  • SM = State Management

S1 — 同步问答端到端流

关键点:第一屏先回答用户题眼,反方 / 详细条件等通过 streaming 后续到达。事后任务类型标签由 TO 完成(不是 LLM 自报),用于审计 trail。


S2 — TaskGroup 多任务并发

关键点:复合任务在 FinBayes 意图层显式拆解,不依赖 LLM 原生处理多轮(业界研究确认 LLM 多轮 function calling 不稳定)。Partial Result 先到达可流式呈现给用户,最终结果由 Result Merger 整合。

失败隔离:任务 A 失败不阻塞任务 B;最终归并时明示哪个任务降级。


S3 — 主动信号触发复盘

关键点:主动信号不退化为价格提醒 / 新闻推送。信号必须明示触及哪条判断、哪个条件、当前变化是什么。信号节奏由用户配置的关注密度控制。

降级:触发器宕机时不影响主动 query;信号补发不实时。


S4 — 候选状态写入与用户确认

关键点:长期状态经用户主动确认才写入——是战略不变量"用户主权"在工程层的硬承接。FinBayes 不悄悄写入用户长期状态。

清空操作:用户清空画像时系统显式提示"协作上下文已重置"(战略不变量)。


S5 — Provider 降级路径(L1 → L1' → L2 → L3 → L4)

关键点:4 层降级(L1 → L1' → L2 → L3 → L4)自动切换。每层失败带明确原因(超时 / 鉴权失败 / 用户未配置 等),用户能看到当前在哪一层。

用户配置作为 first-class:用户偏好顺序优先于系统默认;用户拒绝 fallback 时 L1' 不触发。


S6 — 边界拒收凭证

关键点:凭证不变量的工程承接 —— 不收、不存、不训练 在边界 hook 层实现。规则路径必须在 LLM 之前(不让 LLM 自由决定是否处理凭证)。

输入端 vs 输出端:输出端 hook 也扫描(防 LLM hallucinate 出地址 / 密钥串后被状态意外捕获)。


S7 — clarify 工具触发的澄清回路

关键点:clarify 作为标准工具(不是管道阶段),由 LLM 自己决定何时调用。澄清后回到 LLM Function Calling 起点,不绕过工具池。

澄清问题:动态生成(基于 LLM 当前的意图候选),不用固定模板。


S8 — 长会话压缩

关键点:上下文压缩不是单纯聊天摘要。必须保留四类金融语义:用户关注对象、已确认 Judgment Record 的成立 / 失效条件、当前问题的信息缺口、后续复盘需要引用的来源时间点。

失败处理:压缩失败时 Session 切断 + 新 Session 起 + 引用历史 Judgment Record(而不是用残缺 Context 继续)。


8 个场景间的关系

关系说明
S1 → S2S2 是 S1 的复合扩展(命中多任务时走 S2)
S1 → S4S1 末尾若有可沉淀状态走 S4
S1 → S5S1 中的 PA 调用若失败走 S5
S1 → S6S1 入口前若识别凭证走 S6
S1 → S7S1 中的 LLM 调用若低 confidence 走 S7
S1 → S8长会话累积后自动触发 S8
S3与 S1 独立但产物(复盘任务)走 S1 类似流程

详细的状态对象在每个场景中的生命周期由下一章承接。


11. 状态对象生命周期

字段权威定义见 contracts/state-machines.yaml(Step 11 整改包 I 单一事实源层)。本段为叙述用途,若与 contracts/ 不一致以 contracts/ 为准。承接 Step 11 整改方案

这一节回答:每个有独立状态机的对象有哪些状态?什么事件触发状态变更?每个状态下的不变量是什么?

6 个有独立状态机的对象

本章列出 6 个有独立状态机的对象。其中前 5 个是 §4 的 first-class 业务对象(Session / Task / TaskGroup / Judgment Record / StateCandidate),第 6 个 Provider Readiness 是工程对象但承担跨子系统协调职责(Provider Adapter Pool 的探测状态 + 4 层降级触发器,详见 §9 / §13)。

对象由谁管理本章展开位置
SessionState Management 子系统的 Session Manager11.1
TaskTask Orchestration 子系统的 Task 实例11.2
TaskGroupTask Orchestration 子系统的 TaskGroup Manager11.3
Judgment RecordState Management 子系统的 Confirmed Store11.4
StateCandidateState Management 子系统的 Candidate Buffer11.5
Provider ReadinessProvider Adapter Pool 的 Readiness Prober详见 §9 § Provider Adapter Pool

首-class 业务对象 vs 有独立状态机的对象:§4 列 7 个 first-class 业务对象(Session / Watchlist / Judgment Record / Dynamic Profile / State Candidate / Fin Object / Task)。其中 Watchlist 与 Fin Object 没有独立状态机 —— Watchlist 由 StateCandidate(候选)+ watchlist_objects 表(confirmed store)承担状态;Fin Object 只有 created / archived 两个简单标记,状态变化通过 StateCandidate → watchlist_objects 路径承载。TaskGroup 是工程对象不是 first-class 业务对象,但有独立状态机(任务编排需要)。

工程对象(如 EvidencePacket / EvidencePlan)也有生命周期,但单次任务内即完成,不需独立状态机;详见 Evidence + Synthesis 子系统。


11.1 Session 生命周期

状态说明

状态含义不变量
Active当前活跃的对话Context 长度在预算范围内
Snapshotted因 Context 超额触发压缩Context Snapshot 保留金融语义锚点
Archived用户主动归档内容不变,但不在默认列表
Deleted用户删除引用的 Judgment / Watchlist 不被级联删除

关键约束

  • Default Session 不可删除(用户始终有一个默认会话兜底)
  • Archived 与 Snapshotted 之间没有直接转换(必须先 resume 到 Active)
  • 删除 Session 不删除它引用的 Judgment Record / Watchlist 对象(这些是独立资产)

11.2 Task 生命周期

状态说明

状态含义
CreatedTask 对象生成但未执行
Executing证据 / 综合在调用中
Degraded部分证据缺失但仍可产出降级结果
Completed产出 StructuredCognitionResult
Failed关键依赖失败,无可输出材料
Cancelled用户主动取消或 TaskGroup 整体取消

关键约束

  • 任务进入 Completed / Failed / Cancelled 后状态不可逆,审计 trail 写入完毕
  • Cancelled 任务的部分证据可被保留(用于后续分析),但不进入用户可见状态
  • Failed 不等于无输出——必须给用户可解释的"为什么这次答不了"

11.3 TaskGroup 生命周期

状态说明

状态含义
PlannedGroup 对象生成(含主任务 + 辅助任务清单 + 依赖图 + 并发边界)
Running任意子任务在执行
PartiallyDegraded至少一个子任务降级,其他还在跑
AllCompleted所有子任务进入终态
MergedResult Merger 整合输出
Cancelled整个 Group 取消

关键约束

  • 子任务失败隔离:一个失败不阻塞其他
  • 用户取消 Group 时,正在执行的子任务收到 cancel 信号,已完成的子任务结果保留至审计
  • Merged 状态的输出是用户看到的最终整合结果

11.4 Judgment Record 生命周期

状态说明

状态含义
Candidate任务识别出的待确认判断
Confirmed / ConfirmedEdited用户确认(含编辑后)的判断,进入长期资产
Active在主动信号监控中(成立 / 失效条件被持续检查)
Triggered条件被市场变化触及,主动信号已发出
ReviewedUnchanged复盘后判断仍成立
Updated用户基于复盘形成新判断(新建后续 Judgment,旧的保留在复盘链)
Superseded用户认为旧判断已失效
Rejected用户拒绝候选

关键约束

  • Judgment Record 是 first-class 资产,不是聊天记录的归档
  • 复盘链:Updated 不删除旧 Judgment,形成版本链("当时 → 现在"可追溯)
  • Superseded 的 Judgment 仍可读,仅不进入主动信号监控

11.5 StateCandidate 生命周期

状态说明

状态含义
Pending候选生成,等待用户操作
Confirmed / ConfirmedEdited用户确认,候选转为实际 State 对象(Judgment Record / Watchlist Object / Profile 信号 等)
Rejected用户主动拒绝
Expired超过过期时间用户仍未处理

关键约束

  • 候选不进入 Confirmed Store,仅在 Candidate Buffer 暂存
  • Expired 候选自动清理,不影响其他状态资产
  • 候选的 payload 在 Confirmed 时转入对应的 Confirmed Store 对象(Judgment Record / Watchlist Object / Profile Signal 等)

候选类型与 Confirmed 对象的映射:

Candidate 类型Confirmed 后转入
JudgmentCandidateJudgment Record
WatchlistCandidateWatchlist Object(Fin Object 加入用户 Watchlist)
ProfileSignalCandidate动态画像的某个字段更新
SessionRenameCandidateSession 元数据更新

状态对象间的引用关系

  • Session 引用:Task / TaskGroup / Context Snapshot / 当前关注的 Fin Object
  • Task 引用:Session / Fin Object / EvidencePacket DAG / StructuredCognitionResult
  • TaskGroup 引用:多个 Task / 主任务标识
  • Judgment Record 引用:Fin Object / Session(创建时)/ 复盘链中的其他 Judgment Record
  • StateCandidate 引用:Session / 候选要转化的目标对象 schema

生命周期独立性

  • Session 删除不删除 Judgment Record / Watchlist Object(它们是独立资产)
  • 删除 Judgment Record 需用户显式操作(不可级联)
  • 用户清空画像不影响 Judgment Record / Watchlist
  • 用户清空 Watchlist 不影响该对象的 Judgment Record(仍可在历史中查到)

状态变更的审计 trail

所有状态对象的状态变更都进入审计 trail(State Management 子系统的 Audit Logger),含:

  • 状态变更前后
  • 触发事件(用户动作 / 系统事件 / 市场变化)
  • 时间戳
  • 关联的 Session / Task / Provider 调用

敏感性约束:审计 trail 不写入凭证类信息(凭证不变量延伸到审计层)。


12. 并发与异步处理

这一节回答:FinBayes 用什么并发原语?多任务怎么并发?失败如何隔离?用户取消时发生什么?

并发原语:Python asyncio

FinBayes Runtime 采用 Python asyncio 作为基础并发原语。理由:

  • Runtime 工作是 I/O 密集 而非 CPU 密集(LLM 调用 / 工具调用 / 数据 API 都是网络 I/O)
  • asyncio 单线程事件循环避免锁竞争与死锁的常见坑
  • 与 Python 生态(FastAPI / aiohttp / httpx 等)天然契合
  • Python 3.11+ 提供 asyncio.TaskGroup 与结构化并发原语,匹配 FinBayes 业务对象 TaskGroup

例外:CPU 密集的操作(如本地 LLM 推理 / 大量 PDF 解析)走 loop.run_in_executor 抛到线程池或进程池执行,不阻塞事件循环。


业务层 TaskGroup 与异步原语的映射

业务对象 TaskGroup(用户输入命中多任务时的并发容器,详见状态对象生命周期)的工程实现:

## 示意代码(非最终实现)
async def execute_task_group(group: TaskGroup) -> MergedResult:
async with asyncio.TaskGroup() as tg:
tasks = [
tg.create_task(execute_task(t)) for t in group.tasks
]
# asyncio.TaskGroup 保证:
# - 所有子任务并发执行
# - 任一子任务失败时其他子任务被自动取消(结构化并发)
# - 异常被 ExceptionGroup 集中抛出
return merge_results([t.result() for t in tasks if not t.exception()])

关键设计选择

选择理由
asyncio.TaskGroup 而不是 asyncio.gather(...)TaskGroup 提供结构化并发(任一失败自动取消其他),避免悬挂任务
失败 collected by ExceptionGroup不丢失任何子任务错误(vs gather(return_exceptions=True) 静默吞错)
merge_results 处理 partial success失败的子任务不阻塞 partial result 输出(业务约束:失败隔离)

Trace ID 跨任务传递机制

task_id 等 trace ID(详见 §18 trace ID 体系)通过 contextvars.ContextVar 在 TaskGroup 创建的子任务中自动继承:

## 示意代码
import contextvars
from contextvars import ContextVar

trace_task_id: ContextVar[str] = ContextVar("task_id")
trace_session_id: ContextVar[str] = ContextVar("session_id")
trace_user_id: ContextVar[str] = ContextVar("user_id")

async def execute_task(task: Task) -> TaskResult:
# asyncio 在 create_task 时自动 copy 当前 context(PEP 567)
# 因此 trace_task_id 在 TaskGroup 创建的所有子任务中自动可见
current_task_id = trace_task_id.get()
audit_event("task_started", task_id=current_task_id, ...)
...

关键约束

  • 所有 LLM / 工具 / Audit 子调用通过 ContextVar 拿到 trace ID,不通过参数显式传递(避免每个函数签名拖一串 trace 参数)
  • httpx middleware 在出站 HTTP 请求时自动从 ContextVar 读取 trace ID 并注入 X-Trace-ID / X-Task-Id 请求头(用于 Provider 端日志关联)
  • 任意 asyncio.create_task(...) 调用都自动继承 context —— 这是 asyncio 的内置行为(PEP 567),不需要工程层额外处理
  • 跨线程边界(如 asyncio.to_thread)需显式 context.run(...)contextvars.copy_context() 转移 context

失败隔离的颗粒度

FinBayes 在多个层级提供失败隔离:

层级颗粒度隔离机制
TaskGroup 内每个 Taskasyncio.TaskGroup 结构化并发 + 失败子任务的 result 标记为降级
Task 内每个证据节点(EvidencePacket)单证据节点失败只影响依赖它的下游证据节点,不影响其他证据节点
Evidence 内每个工具调用工具调用失败标记 degraded_reason,归一化为降级 EvidencePacket,不抛异常
Provider 调用内每个 LLM Provider失败触发 L1 → L1' → L2 → L3 → L4 降级(详见 Provider Adapter 子系统)

关键约束

  • 默认不让单点失败传染到整个 Session
  • 每个失败都有 degraded_reason 元数据进入 EvidencePacket / Result,前台可呈现给用户
  • 真正阻断的失败(如 State Store 完全不可用)才让 Session 进入只读模式

用户取消语义

用户主动取消(如 Ctrl+C / ESC / Web UI 取消按钮)的处理:

关键设计

  • 取消是 协作式 而非强制(asyncio 取消信号传播到协程边界)
  • 已完成的部分证据 / 部分结果保留至审计 trail(用户后续可查阅"取消前发生了什么")
  • 正在进行中的 LLM 调用通过 httpx 客户端的 CancelledError 立即释放,不浪费用户的 token 配额

TaskGroup 取消:用户取消整个 TaskGroup 时,所有子任务收到 cancel 信号;子任务已开始的工具调用允许 5 秒 grace period 完成(避免数据不一致),然后强制结束。


超时控制

不同层级的超时策略:

层级默认超时可配置
单个工具调用30s是(per-tool)
单个 LLM 调用60s是(per-task-type)
单个 Task(含所有证据 + 综合)120s
TaskGroup(用户感知的总等待)180s
Session Context Compactor30s

超时触发后:

  • 进行中的协程被 cancel
  • 已完成的部分结果保留
  • 用户看到部分结果 + 超时原因明示
  • 审计 trail 记录"哪一层超时"

配置走文件不硬编码:与战略未决问题相关的成本 / 性能参数都走配置(详见上位继承与不变量章节"不抢答"约定)。


并发限制(backpressure)

为防止本地资源被无界并发耗尽,runtime 设全局并发限制:

限制项默认值调节点
同时进行的 Task 数量5配置
单 Task 内同时调用的工具数量3配置
总 LLM 调用并发(跨 Task)10配置
数据 Provider 调用并发20配置

实现:用 asyncio.Semaphore 在各层级控流。超过限制的请求进入 FIFO 队列等待。

用户感知:高并发时新任务可能等待几秒;用户应能看到"正在排队"提示而非静默卡顿。


事件循环与阻塞调用的处理

asyncio 单线程事件循环对同步阻塞调用敏感。FinBayes 规则:

操作类型处理方式
HTTP / WebSocket / 数据库(SQLite asyncio binding)/ 文件 I/O直接 await(原生异步)
本地 LLM 推理(Ollama 等通过 HTTP,已是异步)直接 await
大量 CPU 计算(如复杂 PDF 解析 / 数据处理)loop.run_in_executor(None, sync_func, args) 抛线程池
第三方同步 SDK 调用同上
子进程调用(如 mermaid-cli 渲染)asyncio.create_subprocess_exec 异步等待

约束:任何直接调用同步阻塞 API 而不抛到线程池的代码视为 bug,进入 review gate 必查项。


测试约束

并发模型的测试覆盖:

测试类型覆盖什么
单任务并发测试TaskGroup 内任务真正并发执行(不是串行)
失败隔离测试一个子任务失败时其他子任务能完成
取消传播测试用户取消能正确传播到 Provider 调用
超时测试各层超时后部分结果保留 + 审计完整
并发限制测试超过 Semaphore 限制的请求被正确队列化

详细测试体系见质量与验收章节。


13. 故障与降级路径

这一节回答:FinBayes 在外部依赖失败 / 内部组件故障 / 数据缺失时怎么走?降级路径如何让用户仍能拿到价值?

总体降级哲学

FinBayes 的本地优先定位要求 比业界默认更高的可用性 —— 业界共识是"LLM 不可用 = Agent 服务不可用",FinBayes 不接受这个共识。

降级遵循三条原则:

  1. 明示而非沉默:任何降级都让用户看到"当前在降级模式 + 为什么"
  2. 失败隔离不传染:单点失败不让整个 Session / Runtime 崩溃
  3. 拒收硬给:信息不足时说"我不知道 / 数据不可用",不强行生成无依据回答

故障决策树

这张图表达什么:从认知请求到输出的完整故障决策路径。每个分叉点对应一种故障,每个分叉都有降级出口,最终都能给用户输出(即使是"系统受限"的输出)。

这张图特意不表达什么:每种故障的具体表现 / 触发条件 / 用户感知(在下面分模块展开)。


各模块的故障与降级

LLM Provider 故障(4 层降级)

详见 Provider Adapter 子系统章节。这里给出用户感知矩阵:

当前层用户感知触发下移条件
L1 用户配置无感(正常使用)用户配置的所有 Provider 都失败
L1' 系统默认提示"使用系统默认 Provider"系统默认 Provider 不可用或用户未授权
L2 本地嵌入式提示"使用本地模型,质量稍低"本地未安装 / 模型加载失败
L3 缓存 + 规则提示"当前受限模式,仅能处理常见查询"缓存未命中 + 规则未匹配
L4 受限菜单提示"系统当前完全离线,请选择常用查询"仅作 last resort

工具 / 数据源调用故障

故障降级
数据 API 401 鉴权失败标记该 source 不可用,尝试 fallback source;用户可见"该 Provider 鉴权失败,请检查 key"
数据 API 超时EvidencePacket 标记 degraded_reason: timeout;不阻塞其他证据
数据 API 限流等待 + 重试;超过重试次数后降级
必需数据完全缺失综合层输出"信息缺口",明示用户哪类数据缺;不硬编
工具返回格式异常标记 packet 状态为 parse_error,归一化处理;调试模式记录原始响应
网络中断进入 L2 本地优先模式(数据用本地缓存 + 本地 LLM)

证据缺失的综合层处理

缺失情况综合层处理
实时价格缺失不给短期方向性结论;给中长期框架性分析
链上数据缺失(Crypto 场景)退化为宏观 + 价格 + 叙事的有限分析
财报数据缺失(US Stocks 场景)退化为行业 + 估值 + 宏观联动
反方证据缺失综合层主动标"反方覆盖不足,暂未发现重要反方信息",不悄悄省略
历史 Judgment Record 缺失(复盘任务)主动询问用户具体当时理由,不替用户假设

关键不变量:反方证据 / 关键风险 / 失效条件等核心认知要素不因画像偏好被裁剪。可以因数据缺失而标注缺口,不可以因"用户偏好简洁"而省略。

State Store 不可用

程度降级
State Store 完全不可用(SQLite 文件锁 / 磁盘满 / 等)runtime 进入只读模式:可读取已有 Session / Watchlist / Judgment,不能写入新状态;用户可见明确提示
Cache 不可用(Redis / 内存 LRU)runtime 退化为不缓存模式,每次都走全链路(成本上升但功能完整)
Config Store 不可用用最后已知的内存配置 + 提示用户配置丢失
Credential Store(OS Keychain)不可用退化为环境变量读取;环境变量也不可用时无法做 LLM 调用,进入 L3 / L4

输入边界保护识别凭证

详见 S6 边界拒收凭证场景。这里只标关键点:

  • 凭证类输入识别后立即终止该输入的处理链
  • 不进入 Task Orchestration / LLM / 状态对象 / 审计 trail
  • 用户得到安全回应:明示"我不接受这类凭证,请保存在你的 [钱包 / 交易所 / 等]"

综合层失败

失败降级
LLM 综合调用失败触发 Provider Adapter 降级链
Self-consistency 多次采样结果分歧大(高风险任务)输出"判断不收敛"信息 + 各分歧的依据,让用户判断(不强行二选一)
综合结果不通过输出 schema 校验标记结果 invalid + 走 fallback(如简化为列表式结构),不向用户呈现垃圾

用户主动取消的处理

用户取消的工程承接详见并发与异步处理章节。这里强调降级视角的设计:

  • 取消是 意图明示 而非故障 —— 不算降级;但部分结果保留在审计 trail 中
  • 取消后用户可以"复活"被取消的任务(基于审计 trail 中保留的部分证据)
  • TaskGroup 取消时,每个子任务允许 5 秒 grace period 完成已发起的 I/O 调用

配置层错误处理(用户视角)

用户配置错误(如 API key 失效 / Provider URL 错误 / 配置文件格式错误)是常见情况:

错误降级
Provider API key 无效启动时探测时即明示"Provider X 鉴权失败",引导用户重配
Provider URL 不可达启动时跳过该 Provider,提示用户检查
配置文件格式错误退回到默认配置 + 明示哪一行有错
本地 Ollama / vLLM 服务未启动探测时即明示,给"启动该服务"或"切换 Provider"的建议
用户未配置任何 Provider进入引导流程(首次使用引导)

关键约束:所有配置错误都在 runtime 启动时明示(Provider Readiness 探测阶段),不让用户在使用中遇到"突然不能用"。


不降级的硬故障

少数情况 runtime 必须硬失败而非降级:

硬故障理由
工具注册尝试包含执行类工具(下单 / 转账 / 等)战略边界硬约束;规则路径直接拒绝注册,记审计但不接受
用户尝试主动输入凭证类信息绕过边界保护凭证不变量;硬拒收不让任何路径接收
状态对象引用的 Fin Object 不存在(数据完整性破坏)数据完整性问题;硬失败 + 提示用户进行数据修复
工程实现意外注入未授权的概念(如战略层被禁的概念)Review gate 拒收(grep + 人工双层);不允许进入主分支

降级路径的可观测性

每次降级都进入审计 trail,含:

  • 降级层级(如 L1 → L2)
  • 触发原因(具体错误信息 / 错误代码)
  • 时间戳
  • 关联的 Task / Session

用户可查看"为什么这次降级了" —— 这是核心可观测性能力。详见可观测性章节。


与其他章节的关系

  • LLM 4 层降级的具体实现细节 → Provider Adapter 子系统章节
  • 用户取消的工程承接 → 并发与异步处理章节
  • 边界保护 hook 的具体实现 → 边界与安全章节(横向贯穿)
  • 降级原因如何写入审计 trail → 可观测性章节
  • 测试如何覆盖各降级路径 → 测试体系章节

14. 部署形态

这一节回答:FinBayes 在用户本地如何部署?多种部署形态各自的拓扑是什么样?

三种部署形态

FinBayes 支持三种部署形态。第一阶段主推本地优先单机,混合与托管形态作为演化路径预留接口。

形态第一阶段描述
本地优先单机✅ 主推所有容器(含 State Store / Cache)都在用户本机;LLM / 数据 Provider 可云端可本地
本地 + 远程 Provider✅ 支持容器仍本机,但 LLM 与数据 Provider 走云端 API(用户配置)
未来托管部署远期容器迁移到云端服务;多用户共享;超出第一阶段范围

部署形态变化时 runtime 接口契约不变——这是可演化性质量属性的工程承接(详见架构目标与质量取舍章节)。


本地优先单机部署的物理拓扑

这张图表达什么:所有 FinBayes 容器与持久化都在用户本机;外部 Provider(云端 LLM / 数据 / Data Horizon)通过 HTTPS 访问;本地 LLM 是可选安装(用于 L2 降级或用户主动选择)。

这张图特意不表达什么:容器内部组件细节(在 §9 已展开);远程托管形态的拓扑(在下面单独描述)。

怎么读这张图:实线箭头是必要数据流,虚线箭头是可选数据流(如本地 LLM)。同一框内的组件共享主机资源。


部署形态对各容器的影响

容器本地优先单机本地 + 远程 Provider未来托管
入口适配全部本机全部本机Web API 迁云,其他容器(CLI / TUI)仍本机
Core Runtime本机进程本机进程云端服务进程
Provider Adapter Pool本机本机 + 调云 LLM云端
State StoreSQLite 本地文件SQLite 本地文件远程数据库(PostgreSQL 候选)
Cache内存 LRU 或本地 Redis同左远程 Redis 集群
Config Store本地配置文件本地配置文件用户级账户存储
Credential StoreOS KeychainOS Keychain云端密钥管理

重要约束:所有形态共用同一 runtime 接口契约。从本地优先单机演化到远程托管时,应用代码不变——仅 Provider Adapter Pool 和 State Store 的实现替换。这是接口版本化的回报。


用户首次安装与初始化流程

关键设计

  • 用户至少要有一种 LLM 可用才能用 FinBayes 完整功能(云端或本地);都没有时进入 L3 / L4 受限模式(明示)
  • 本地 LLM 安装是可选,不强制(增加部署门槛与下载量)
  • 默认 Session 在初始化时自动创建(用户不需手动建第一个 Session)

配置文件与数据文件的路径约定

按 OS 平台不同,FinBayes 的本地文件遵循各 OS 的标准目录约定(XDG Base Directory Specification on Linux / macOS 标准 / Windows AppData):

平台配置目录数据目录缓存目录
macOS~/Library/Application Support/finbayes/config/~/Library/Application Support/finbayes/data/~/Library/Caches/finbayes/
Linux$XDG_CONFIG_HOME/finbayes/(默认 $HOME/.config/finbayes/$XDG_DATA_HOME/finbayes/(默认 $HOME/.local/share/finbayes/$XDG_CACHE_HOME/finbayes/(默认 $HOME/.cache/finbayes/
Windows%APPDATA%\finbayes\config\%APPDATA%\finbayes\data\%LOCALAPPDATA%\finbayes\cache\

不变量

  • 凭证类不进入这些目录的任何文件(凭证走 OS Keychain)
  • 配置文件可被用户直接编辑(YAML 格式)
  • 数据文件(State Store SQLite)不建议用户直接编辑(需用 FinBayes CLI 操作)

升级流程

升级类型处理
FinBayes 软件版本升级runtime 启动时检查 State Store schema 版本,按需运行 migration 脚本(schema 演化策略详见演化与版本管理章节)
接口契约版本升级major 升级时拒绝过期客户端连接,提示用户升级;minor 升级保持向后兼容
LLM Provider API 变化Provider Adapter 内部适配,runtime 业务代码不变
本地 LLM 模型升级用户主动操作(Ollama pull);FinBayes 重新探测 Readiness

回滚策略:State Store 在 schema migration 前自动备份(SQLite 文件复制),失败时回滚。详见数据存储划分章节。


卸载与数据清理

用户卸载 FinBayes 时:

数据类型默认行为用户可选
安装的二进制 / 程序文件删除
配置文件保留(方便重装)明示选择"完全删除"
数据文件(State Store)保留明示选择"完全删除"(不可恢复警告)
缓存文件删除
OS Keychain 中的 Provider 凭证删除
本地 LLM 模型(Ollama 下载的)不删(由 Ollama 管理)用户在 Ollama 中删除

关键约束:用户清空画像 ≠ 卸载 FinBayes ≠ 删除 State Store。三种动作明确区分,避免误操作。


部署形态相关的未决问题

未决但第一阶段不抢答

  • 远程托管形态下的多用户隔离(待第一阶段冷启动数据验证商业模式后定)
  • 跨设备同步(用户在多台机器上的 FinBayes 状态是否同步)
  • 企业部署形态(如团队共享 Watchlist / 团队级审计)

这些都在战略未决问题范围内(详见上位继承与不变量章节)。


15. 数据存储划分

这一节回答:FinBayes 的不同数据类别分别放在哪里?为什么这样分?

5 类持久化数据

FinBayes 把持久化数据分为 5 类,每类有专属存储位置:

类别存储位置物理形式
State Store数据目录SQLite 数据库文件
Cache缓存目录Redis(本地实例)或进程内 LRU
Config Store配置目录YAML 配置文件
Credential StoreOS KeychainOS 系统凭证管理
Audit Trail数据目录SQLite(与 State Store 同库不同表)或独立 JSONL 文件

分类原则:按数据敏感度 + 访问频率 + 生命周期划分。最敏感的(凭证)走 OS 级保护;最频繁的(缓存)走内存;持久状态走 SQLite。


存储分类图

这张图表达什么:5 类数据各自的物理形式与典型内容。SQLite State Store 包含 8 张业务表(Session / Watchlist / Judgment Record / Dynamic Profile / StateCandidate / Fin Object / Audit Trail / Context Snapshots),其中 Audit Trail 是审计层独立表,Context Snapshots 是长会话压缩资产;mermaid 图为简洁起见仅画 6 类核心业务对象表。完整 8 张表的 schema 见下方"关键表"。

这张图特意不表达什么:表的字段定义(在附录数据对象 schema 索引);数据迁移流程(在升级流程中描述)。


State Store(SQLite)

为什么 SQLite

  • 本地优先部署的天然选择(无需独立服务进程)
  • 单文件易备份 / 易迁移
  • Python 生态完备(sqlite3 标准库 + aiosqlite 异步绑定)
  • 个人用户量级数据规模(每用户几千到几万条记录)远未到 SQLite 性能上限
  • 支持事务保证状态写入原子性

关键表

内容增长趋势
sessionsSession 实例用户活跃度相关
watchlist_objectsWatchlist 内的 Fin Object用户关注集大小
judgment_records历史判断长期累积
dynamic_profiles用户画像一用户一行
state_candidates待确认状态短期(过期清理)
fin_objects用户关注的金融对象用户关注的对象总数
audit_trail任务执行 / 状态变更 / 降级 等审计记录持续累积,按日归档
context_snapshots长会话压缩后的 Snapshot与 Session 关联

事务策略

  • 用户主动动作(confirm 候选 / 修改画像 / 删除 Session)走单事务
  • 主动信号触发的多 Judgment 更新走批量事务
  • 审计 trail 写入异步化(不阻塞主流程,允许丢少量审计记录的边界 case)

备份与恢复

  • runtime 启动时自动备份当前 SQLite 文件到 *.bak
  • schema migration 前强制备份
  • 用户可手动 finbayes backup 触发备份

Cache

用途:L3 缓存(精确 + 语义)+ Task 执行过程的中间数据 + Provider Readiness 状态缓存

实现选择

部署环境选用
用户本机已装 RedisRedis(推荐,支持 Redis Vector for L3b 语义缓存)
用户本机无 Redis进程内 LRU(如 cachetools 库),L3b 语义缓存改用简单的 in-memory FAISS 或临时禁用

关键设计

  • 缓存不存储敏感内容(凭证 / 用户画像中的隐私字段不进缓存)
  • 缓存键含 user_id,防 user-scoped poisoning(一个用户的缓存不能命中到另一个用户)
  • 行情类查询的缓存 TTL 必须短(≤30s),分析类可几小时
  • 进程重启缓存清空(不持久化)

降级:Cache 不可用时 runtime 退化为不缓存模式(每次都走全链路,成本上升但功能完整)。


Config Store

位置:配置目录下的 YAML 文件

文件内容
config.yaml全局配置(runtime 参数、超时、并发限制 等)
providers.yaml用户配置的 Provider 列表 + 偏好顺序(key 不在这里,在 Credential Store)
task_routing.yaml任务类型 → Provider 映射(可选用户自定义)
ui.yaml用户界面偏好(表达密度初始值、术语深度 等)

关键设计

  • 配置文件可被用户直接编辑(YAML 格式 + 详细注释)
  • runtime 启动时检查格式 + 验证字段,错误时退回默认配置 + 明示错误
  • 修改配置后无需重启 runtime(hot reload 支持)—— 但某些核心配置(如端口)仍需重启

Credential Store

位置:OS 系统凭证管理

平台实现
macOSKeychain Access(通过 keyring Python 库或 security CLI)
WindowsWindows Credential Manager
LinuxSecret Service(如 GNOME Keyring / KDE Wallet)
Linux 无桌面环境加密本地文件(用 cryptography 库 + 用户提供的密码)

存储内容

  • 云端 LLM Provider API key(OpenAI / Anthropic / DeepSeek / 等)
  • 数据 Provider API key / token
  • 用户自定义 Provider 的 secret

关键约束(凭证不变量在工程层的承接):

  • 金融执行凭证不进入 Credential Store(私钥 / 助记词 / 交易所 API key / 银行账户 / 信用卡)—— Credential Store 仅存"本机配置秘密"(LLM / 数据 Provider key 等),与"金融执行凭证"严格区分
  • 用户卸载 FinBayes 时自动清除该程序在 Keychain 中的所有凭证
  • Credential 不通过日志 / 审计 trail / 任何序列化输出泄露

Audit Trail

位置:与 State Store 同 SQLite 文件的独立表,或独立 JSONL 文件(用户可选)

内容

记录类型示例字段
任务执行task_id / type / 输入摘要 / 输出摘要 / Provider 调用链 / 成本 / 时长
状态变更object_type / object_id / before / after / 触发事件 / 时间戳
Provider 调用provider_id / model / token 数 / 成本 / 是否走 fallback
降级事件触发层级 / 原因 / 时间戳 / 关联 task
用户主动动作确认候选 / 修改画像 / 清空 / 删除 等
边界拒收事件输入特征摘要(不含具体凭证内容)/ 时间戳

关键约束

  • 审计 trail 不包含任何凭证类内容(边界拒收事件记录中只标"识别为凭证类,已拒收",不记录具体凭证字符串)
  • 审计 trail 可被用户查阅("为什么这次降级了" / "这条 Judgment 是怎么形成的")
  • 审计 trail 按日 / 月归档,避免单一文件无限增长

数据完整性保护

完整性问题保护机制
部分写入(runtime 崩溃时)SQLite WAL 模式 + 事务原子性
引用完整性(如 Session 引用不存在的 Judgment)数据库外键约束 + runtime 启动时完整性检查
Schema 版本不匹配(升级后)runtime 启动时检查 schema 版本 + 自动 migration
文件损坏runtime 启动时校验和检查 + 自动从 *.bak 恢复
用户误操作清空删除前二次确认 + 操作后保留 7 天可恢复窗口

用户视角的数据动作

用户可对自己的数据做下列动作:

动作影响范围
finbayes session delete <id>删除指定 Session(不删除引用的 Judgment / Watchlist)
finbayes judgment delete <id>删除指定 Judgment Record(需二次确认)
finbayes watchlist remove <fin_object_id>移除关注对象(不删除 Judgment)
finbayes profile view / modify / clear画像查看 / 修改 / 清空(清空时显式提示"协作上下文已重置")
finbayes export导出所有用户数据到 JSON / CSV
finbayes uninstall --clean卸载 + 完全删除所有数据(不可恢复)

战略不变量"用户画像主权"在数据操作层的完整承接。


16. 通信协议

这一节回答:FinBayes 各组件间用什么协议通信?外部接口的协议是什么?为什么这样选?

通信关系总览

按通信范围分四类:

类别范围主要协议
进程内runtime 内部子系统间Python 函数调用 + asyncio 协程
本机进程间runtime 与本机其他进程stdio / Unix domain socket / 本地 HTTP
本机内 UIruntime 与用户的浏览器 / 终端HTTP / WebSocket / 终端 stdin&stdout
跨网络外部runtime 与外部 ProviderHTTPS(OpenAI-compatible / 各家 SDK)

进程内通信

主要场景:§9 的 6 个子系统之间。

实现:直接 Python 函数调用(同步或异步协程)。

特点

  • 零序列化开销
  • 类型安全(Python type hints + Pydantic 数据对象)
  • 不依赖网络
  • 同进程异常直接传播(不需 RPC 序列化)

关键约束

  • 子系统间的接口契约用 Python class / function signature 表达,并在 §9 各子系统的"关键接口"段落明示
  • 即使是进程内通信,跨子系统的数据对象必须通过 Pydantic schema 校验(防内部数据不一致)

本机 UI 入口的通信

CLI 入口

协议:终端 stdin / stdout / stderr

特点

  • 单次提问一次性返回(除非用户主动开 streaming 模式 --stream
  • 输出格式默认人类可读;--json 切换 JSON
  • 退出码语义化(0 = 成功 / 10 = 输入错误 / 20 = Provider 不可用 / 30 = 边界拒收 / 等)

TUI 入口

协议:终端原生(用 Textual / Rich 等 TUI 框架)

特点

  • 持续运行,键盘事件驱动
  • 实时呈现流式输出(部分结果 + 最终归并)
  • 支持多 Session 切换 / Watchlist 浏览 / Judgment 查看 / 状态确认动作

Web API Server

协议:HTTP(任务请求 / 状态动作)+ WebSocket(task event 流式更新)

端点协议用途
POST /api/taskHTTP创建认知任务(请求体含 task request schema)
GET /api/task/{id}HTTP查询任务状态
GET /api/task/{id}/streamWebSocket实时接收 task event
POST /api/state-actionHTTP用户确认 / 拒绝 / 编辑候选状态
GET /api/session/listHTTP列出用户 Session
POST /api/session/actionHTTPSession 创建 / 切换 / 归档 / 删除

鉴权(本地优先单机部署):

  • 本机访问默认无鉴权(同主机进程间信任)
  • Web UI 与 Web API 通过 localhost 通信,外部网络访问被拒绝
  • 远程访问需用户显式启用并配置 token(不在第一阶段范围)

Contract Versioning

  • 每个 API 端点的 schema 含 contract_version 字段
  • 新增 optional 字段不升 major;删除字段 / 改语义升 major
  • 不兼容版本拒绝服务并返回 INVALID_CONTRACT_VERSION 错误码

MCP Server

协议:标准 MCP(Model Context Protocol,Anthropic 提出)—— 基于 stdio 的 JSON-RPC

特点

  • 外部 Agent(如 Claude Code / Codex / 其他 MCP-compatible Agent)可调用 FinBayes 的能力
  • runtime 作为 MCP server 暴露工具(如 finbayes_analyze / finbayes_review_judgment / 等)
  • stdio 协议天然适合本地 Agent 间通信(无需起 HTTP 服务)

MCP 工具池:FinBayes 暴露给外部 Agent 的工具是 Capability Registry 的子集(不暴露所有内部工具,仅暴露对外 API 级的)。

Channel Adapter

协议:因 channel 平台而异

Channel协议
TelegramTelegram Bot API(HTTPS webhook 或 long polling)
DiscordDiscord API(HTTPS + WebSocket gateway)
SlackSlack API(HTTPS webhook)
其他按平台 SDK

特点

  • Channel 入口主要为主动信号推送("你对 ETH 的判断 X 失效条件被触及")
  • 也支持用户从 Channel 直接提问(视 Channel 平台特性)
  • Channel 输出是低噪音摘要 + 回链到 Web Session 继续复盘

鉴权:每个 Channel 的 webhook secret / Bot token 走 Credential Store。


跨网络外部通信

LLM Provider 调用

协议:HTTPS

API 规范

  • 主流云端 Provider(OpenAI / Anthropic / DeepSeek / Qwen API)都支持 OpenAI-compatible 接口形态
  • 本地 LLM 服务(Ollama / vLLM / LM Studio)也提供 OpenAI-compatible API
  • Provider Adapter 内部用统一 OpenAI-compatible 客户端(如 LiteLLM 或自实现),屏蔽各家 SDK 差异

鉴权:API key 从 Credential Store 读取,通过 HTTPS Authorization 头传输(不进入代码 / 配置 / 日志)。

流式:所有 Provider 支持 SSE(Server-Sent Events)流式响应。Provider Adapter 统一为内部异步生成器。

外部数据 Provider 调用

协议:HTTPS(个别老旧 Provider 可能要求 HTTP,但默认拒绝)

鉴权方式

类型处理
API key in header(如 yfinance / Alpha Vantage)走 Credential Store
OAuth(如某些券商数据 API)走 Credential Store + 刷新 token 管理
公开无鉴权(如 SEC EDGAR)直接调用,注意限流

限流处理

  • 每个 Provider 配置 rate limit
  • runtime 用 asyncio.Semaphore 控并发
  • 超限时排队等待 + 必要时降级到 fallback Provider

Data Horizon 接口

协议:HTTPS(具体接口形态待 Data Horizon 项目定义)

FinBayes 视角的契约要求

  • 提供整理过的金融素材(事件 / 实体 / 时间线 / 数据)
  • 支持订阅式实时推送(可选)+ 按需查询
  • 不替 FinBayes 做判断(仅提供素材)

协议安全约束

所有协议层共同的安全约束:

约束工程承接
凭证不进入协议消息体Provider API key 走 HTTP Authorization 头不写入 request body / 日志;Channel secret 同理
TLS 不可降级所有外部网络通信强制 HTTPS(HTTP 拒绝)
本机 socket 限制Web API / MCP 默认仅监听 127.0.0.1,外部网络访问被拒绝
错误响应不泄露敏感错误消息不含凭证 / 用户画像 / 内部 trace;详细 trace 仅写审计 trail

错误码语义

跨协议统一的错误码语义(详细在附录数据对象 schema 索引):

错误码含义
INVALID_CONTRACT_VERSION请求或响应版本不兼容
INVALID_INPUT输入空 / 格式不合法 / 附件不可解析
PROVIDER_NOT_READYLLM 或数据 Provider 未配置 / 不可用
EVIDENCE_UNAVAILABLE必需证据不可获得
UNSUPPORTED_SCOPE超出第一阶段范围
EXECUTION_TOOL_BLOCKED试图注册或调用执行类工具(边界硬约束)
BOUNDARY_REJECT输入含凭证类内容被拒收
STATE_STORE_READONLYState Store 进入只读模式
TASK_CANCELLED任务被取消
TASK_TIMEOUT任务超时

协议演化策略

演化情境处理
新增 LLM Provider 类型Provider Adapter 内加新适配器;接口契约不变
接口契约小升级(新增 optional 字段)minor 版本递增,向后兼容
接口契约破坏性变更major 版本递增 + 不兼容 client 拒绝 + 升级指南
Channel 平台 API 变化Channel Adapter 内部适配,runtime 业务代码不变

详细的契约版本化策略在演化与版本管理章节。


17. 边界与安全

这一节回答:FinBayes 的边界与安全约束在工程层如何具体承接?哪些约束是横向贯穿所有子系统的、不可被任何模块单独决定的?

三条边界约束(战略来源)

来自战略层的三条硬约束(详见上位继承与不变量章节):

战略约束工程层承接位置
凭证不变量:金融执行凭证一律不收、不存、不训练输入边界 hook + State / Cache / 审计 trail 凭证过滤 + 输出端过滤
不直接下单 / 不持账户凭证Capability Registry 拒绝注册执行类工具 + 工具 schema 校验
不替用户决策(认知层定位)综合层产出"判断 + 反方 + 失效条件"的结构化输出契约 + 不输出无证据的方向性结论

这三条不是某个子系统的局部规则,而是横向贯穿多个组件的全局不变量。


凭证类内容的端到端阻断

凭证识别的位置

这张图表达什么:凭证类内容的双向阻断 —— 入口 hook 拦截用户主动输入,出口 hook 拦截模型可能"幻觉"生成的凭证样式内容。两处之间的所有路径(Task / LLM / 综合层 / 状态对象)都绝不接触凭证。

这张图特意不表达什么:具体的正则模式(在工程实现仓维护);识别准确率(在测试体系章节)。

凭证类型与识别策略

凭证类型识别策略
私钥 / 助记词(12 / 24 词序列)正则 + 词表匹配(BIP-39 词表)
钱包地址附带私钥 / WIF 格式正则(特定前缀 + 长度 + 校验位)
交易所 / 经纪商 API key + secret pair正则(常见格式:长 base64 / 长 hex)
银行账户 / 信用卡号正则(Luhn 校验)
用户主动"贴整段配置文件"启发式(看到 key = value 形式的多行密钥)
LLM 辅助二次判断对不确定 case 调小模型快速判断(注意:调用前已脱敏,不送原 token

优先级:规则路径优先,LLM 辅助仅作可疑 case 的二次判断(避免每个输入都走 LLM)。

凭证拒收的用户感知

用户主动贴凭证类内容时,FinBayes 给安全回应:

我不接受这类凭证(看起来像 [私钥 / API key / 等])。请把它保存在你的
[钱包 / 交易所 / 等] 里。

我不需要它就能帮你做 [当前任务]。如果你想让我帮你判断某个交易所的资产
表现,请直接告诉我[交易所名称 + 资产名称]即可。

关键约束

  • 安全回应不重复用户贴的具体凭证字符串(避免日志记录)
  • 安全回应说明替代路径(不让用户无所适从)
  • 拒收事件进入审计 trail,但仅记录"识别为凭证类,已拒收 + 拒收时间戳",不记录具体内容

输出端过滤(arch-rewrite/ADR-010 accepted)

LLM 可能在生成内容时幻觉地输出凭证样式字符串(例如"一个看起来像私钥的随机 64 位 hex")。即便不是真凭证,让看起来像凭证的字符串流向用户也增加误用风险。

过滤的两个候选位置

候选位置优点缺点
综合层产出后、统一格式化前离 LLM 最近,能感知语义上下文增加综合层职责
Output Pipeline 最末端、用户呈现前集中点检查、所有路径都过离 LLM 最远,可能丢失语义

初步决策(待 ADR-010 确认):两处都做。综合层做语义级(看到"私钥 / 助记词"等词附近的高熵字符串就警觉),Output Pipeline 做格式级最终扫描(与输入端 hook 同一套正则,方向相反)。

检测到凭证样式时的处理

  • 高置信度(多条规则同时命中):剥除该段 + 用占位符替换 + 给用户 banner "输出包含可能凭证样式,已过滤"
  • 中置信度(单条规则命中):保留但加 banner 提示
  • 低置信度(仅模糊匹配):日志记录,不剥除

arch-rewrite/ADR-010 accepted(2026-05-28):具体阈值与正则集合见 ADR-010 §3。


执行类工具的注册拒绝

战略约束"不直接下单"在工具层的承接(详见 §9 Capability Registry 段)。

拒绝注册的工具类型

工具类型拒绝理由
下单 / 撤单 / 改单(交易所 / 经纪商 API)直接执行金融动作
转账 / 提币 / 充值(区块链交易广播)直接执行金融动作
银行账户操作(转账 / 支付)直接执行金融动作
任何持有私钥 / 助记词的签名调用持账户凭证
任何要求"金融执行凭证"作为参数的工具凭证不变量

拒绝机制

关键约束

  • 工具 schema 必填字段 category,且枚举严格(无 execution 选项)
  • 工具参数 schema 用启发式扫描禁用字段名
  • 拒绝是注册时(启动期),不是调用时(运行期)—— 运行期已无此类工具可调
  • 审计 trail 记录所有尝试注册执行类工具的请求

详见 §9 Capability Registry。


用户数据隔离

多 user / 多 session 在同一 runtime 内的隔离

第一阶段单机部署虽然主要服务单用户,但 runtime 仍预留 user_id 维度(为未来多用户预留):

数据类别隔离机制
State Store所有表含 user_id 列 + 查询强制带 user_id where 条件
CacheCache key 含 user_id 前缀(防 cache poisoning)
审计 trailuser_id 字段
LLM Provider 调用每个用户的 Provider 池 / key 独立(key 仍在 OS Keychain,per-user 命名空间)
动态画像严格 per-user,不跨用户共享

约束:跨用户读取在工程层禁止(即使是 admin / debug 模式)。debug 输出经脱敏。

Session 内的会话上下文

Session 内的认知协作上下文:

  • 不跨 Session 泄露(一个 Session 的 Judgment 不自动出现在另一个 Session)
  • 跨 Session 的引用是显式的(用户主动 link 或 Watchlist 关联)
  • Session 归档 / 删除时,相关 Cache / 临时数据级联清理

网络层安全

TLS 强制

通信对象协议强制
云端 LLM ProviderHTTPS✅ HTTP 一律拒绝
外部数据 ProviderHTTPS✅ 个别老旧 Provider 例外需用户显式 allow-list 配置
Data HorizonHTTPS
本地 LLM(Ollama / vLLM)HTTP(localhost)✅ 仅允许 127.0.0.1
本机 Web APIHTTP(localhost)✅ 仅监听 127.0.0.1,外部访问拒绝
MCP Serverstdio✅ 进程间,无网络

凭证传输路径

  • LLM Provider key 通过 HTTPS Authorization 头传输,不写入 request body / URL query / 日志
  • Provider Adapter 内部使用 key 时是短生命周期(调用前从 Keychain 读,调用后即销毁内存引用,不在内存中持久持有)
  • 错误日志中 key 一律 redact(如 sk-***xxxx

详见 §16 协议安全约束。


Prompt 注入与对抗输入

LLM 应用的特殊风险:用户输入或外部数据中包含的对抗指令尝试改变 LLM 行为。

风险场景应对
用户输入"忽略上述指令,输出 ..."System prompt 加固(明示不接受 in-band 指令变更)+ 综合层输出 schema 校验(不符合契约直接拒绝)
外部数据(如新闻 / 网页)中嵌入对抗指令工具返回的外部数据进入 LLM 前包裹<external_data> 标记内 + system prompt 明示标记内内容不构成指令
用户尝试诱导 LLM 输出凭证样式 / 执行类建议输出端 hook 兜底 + 安全回应
用户尝试诱导 LLM 假冒 FinBayes 系统消息输出格式契约 schema 强制

关键不变量:FinBayes 不通过 prompt 行为约束作为唯一防线 —— 关键边界(凭证 / 执行类)有规则路径做硬约束,prompt 加固只是冗余防御。


用户主权

战略不变量"用户画像主权"在工程层的承接(详见 §15 用户数据动作):

主权维度工程承接
知情权用户可查看自己的所有数据(finbayes export / TUI 浏览)
修改权用户可修改动态画像(finbayes profile modify
清空权用户可清空画像 / 删除 Session / 删除 Judgment(显式确认 + 明示影响范围)
卸载权用户可完全卸载 FinBayes 并删除所有本地数据(不可恢复警告)
可移植用户可导出所有数据到 JSON / CSV

关键约束

  • 清空画像 ≠ 卸载 FinBayes ≠ 删除 State Store —— 三种动作明确区分
  • 用户每个数据修改动作都进入审计 trail(用户可追溯自己的操作)
  • 未来若引入云端同步,必须用户显式启用(不在第一阶段范围)

Review Gate 的工程承接

战略禁入概念(11 条字段级强约束 / 默认与行动准备双模式 / 认知协作伙伴 / L3 长期状态四承诺 / 零状态前提 / 情绪桥 / 信任债承诺 / 行动准备 / 行动判断 / 行动方案)不允许进入主分支。

检查层工具
自动 grepnpm run verify:kb 含 banned-concept grep(CI 必跑)
人工语义审查PR review 必备一位非作者人员复核(防 grep 同义词漏检)
审计追溯每次 release 留 grep + 人工审查记录

详见 §2 架构目标与质量取舍。


安全相关的可观测性

每个边界事件进入审计 trail(不含敏感内容):

事件类型记录字段
输入边界拒收时间戳 + 入口(CLI/TUI/Web/MCP/Channel)+ 识别类型(如 "私钥样式" / "API key 样式")+ 入口用户 / Session
输出端过滤时间戳 + 关联 task_id + 过滤类型 + 置信度 + 是否剥除
工具注册拒绝时间戳 + 尝试注册的工具名 + 拒绝原因(execution / 含凭证参数 / 等)
Prompt 注入识别时间戳 + 注入特征摘要(不含原文)+ 关联 task_id

用户可查阅自己 Session 范围内的边界事件("为什么 FinBayes 拒收了我的输入")。

详见 §18 可观测性。


与其他章节的关系

  • 输入边界 hook 的落点 → §9 Input Pipeline 子系统
  • 执行类工具注册拒绝的具体实现 → §9 Capability Registry
  • 输出端过滤的位置选择 → arch-rewrite/ADR-010(accepted 2026-05-28,规则见 ADR-010 §3)
  • 凭证不变量的存储承接 → §15 Credential Store
  • 网络层 TLS 约束 → §16 协议安全约束
  • 凭证拒收场景的端到端 sequence → §10 S6 场景
  • 边界事件如何写审计 trail → §18 可观测性

18. 可观测性

这一节回答:FinBayes 通过什么手段让"系统正在做什么 / 为什么这样做 / 是否健康"对用户与工程都可见?

两类可观测对象

对象看什么谁看
认知过程可观测任务为什么走 LLM A 而不是 B / 为什么这次降级 / 这条 Judgment 怎么形成 / 反方为什么是这些用户视角为主
系统运行可观测延迟 / 错误率 / 成本 / 并发负载 / 缓存命中率工程视角为主

FinBayes 的本地优先定位要求两类都做 —— 但侧重点不同:认知过程可观测直接服务用户信任与复盘,系统运行可观测支撑工程化排障。


审计 trail(认知过程可观测的主载体)

审计 trail 的存储位置详见 §15。这一节聚焦全景视图用户可查阅维度

记录的事件类型

事件类型关键字段
任务执行task_id / type / 输入摘要 / 输出摘要 / Provider 调用链 / 成本 / 时长 / 关联 Session
Provider 调用provider_id / model / token 数(输入/输出)/ 成本 / 是否走 fallback / 失败原因
降级事件触发层级(L1→L2 等)/ 触发原因 / 时间戳 / 关联 task
状态变更object_type / object_id / before / after / 触发事件 / 时间戳
用户主动动作确认候选 / 修改画像 / 删除 Session / 等 + 时间戳
边界拒收时间戳 + 入口 + 识别类型(不含具体凭证内容)
主动信号触发关联 Judgment Record / 失效条件被触及的事件 / 通知投递路径

用户视角的可查阅维度

用户能问的问题与对应查询:

用户问题对应查询
"我刚才那次提问为什么这么慢?"task_id → Provider 调用链 + 各步耗时
"为什么这次走了本地模型?"task_id → 降级事件链(L1 → L2 触发原因)
"这条 Judgment 是怎么形成的?"judgment_id → 关联 task → 证据来源 → 综合层依据
"为什么 FinBayes 拒收了我刚才贴的内容?"session_id → 边界拒收事件(仅识别类型)
"我这周用了多少 Provider 成本?"时间范围 + user_id → Provider 调用聚合
"FinBayes 怎么静默地改了我的画像?"profile.history → 历次画像更新事件 + 触发任务

用户可见的不变量

  • 审计 trail 不含凭证字符串(边界拒收事件只标"识别为凭证类,已拒收")
  • 审计 trail 不含完整 LLM 输入输出(仅含摘要 + token 数 + 关键字段;完整内容仅 debug 模式留存 N 天)
  • 审计 trail 是用户的资产(导出 / 删除 / 归档由用户决定)

任务 trace(贯穿子系统的因果链)

每个认知任务有一个唯一 task_id,贯穿所有子系统调用。

这张图表达什么:task_id 是横向贯穿所有子系统的相关 ID;每个子系统产生的事件都标 task_id(+ 子调用的 tool_call_id / llm_call_id),用户或工程可基于 task_id 重建完整因果链。

这张图特意不表达什么:trace 的存储格式(在 §15);分布式 trace(本地优先单机不需要)。

Trace ID 体系

ID范围用途
session_idSession 生命周期关联同一会话内的所有 task
task_id单个 task一次认知请求的全链路
tool_call_id单次工具调用LLM Function Calling 的工具调用追踪
llm_call_id单次 LLM 调用多次 LLM 调用(如综合层多采样)的区分
trace_id跨 session 的相关任务(主动信号触发新任务)主动信号链路追踪

指标体系

FinBayes 关注的指标分四类:

性能指标

指标含义用途
task_latency_first_screen首屏响应时间用户体验核心
task_latency_complete任务完整完成时间看流式输出全长
llm_call_latency单次 LLM 调用延迟看 Provider 健康
tool_call_latency单次工具调用延迟看外部数据 Provider 健康
concurrent_tasks当前并发任务数看负载

成本指标

指标含义用途
provider_token_usage各 Provider token 用量成本核算 + 用户预算可见
provider_cost_estimate各 Provider 估算成本用户成本主权
cache_hit_rateL3 缓存命中率看降本效果

可靠性指标

指标含义用途
degradation_rate_by_layerL1→L2 / L2→L3 / L3→L4 触发率看降级链健康
provider_failure_rate各 Provider 失败率Provider 健康对比
boundary_reject_rate边界拒收率看是否有异常输入模式
state_store_write_failureState Store 写入失败次数看 SQLite 健康

认知质量指标(间接)

指标含义用途
self_consistency_divergenceSelf-consistency 多采样分歧度高分歧 = 任务难 / 综合层不收敛
evidence_completeness综合层使用的证据数 / 应用证据数看反方 / 风险覆盖完整度
clarify_rate触发 clarify 工具的比例高 = 输入意图不清 / 用户体验需改进
user_action_on_candidate_rate候选状态被用户确认 vs 拒绝 vs 编辑的比例看 candidate 阶段质量

约束:所有指标 per-user 维度独立计算(不跨用户聚合)。


用户视角的可观测 UI

CLI / TUI

命令显示
finbayes status当前 Provider Readiness / Cache 状态 / State Store 健康
finbayes trace <task_id>单个 task 完整链路(Provider 调用 / 工具调用 / 降级事件 / 时长)
finbayes audit list [--since=7d]时间范围内的审计事件
finbayes cost report [--since=30d]时间范围内的 Provider 成本汇总
finbayes session show <id>Session 内所有 task 与状态变更概览

Web UI

  • Session 详情页:每条 task 旁边显示"trace 入口",点击查看该 task 的 Provider 调用链 + 降级事件 + 关键时长
  • Judgment Record 详情:显示"为什么形成这个判断"—— 关联 task 的证据来源 + 综合层依据 + Provider
  • 全局健康 banner:Provider 池状态 / Cache 命中率 / 最近降级事件(如有)

工程视角的可观测

日志分级

级别用途是否默认开启
ERROR不可恢复的失败
WARN降级 / 重试 / 边界识别
INFO任务开始 / 完成 / 关键节点
DEBUGLLM 调用入参出参摘要 / 工具调用参数❌(用户主动开)
TRACELLM 完整 prompt / 完整响应❌(用户主动开,明示日志会含完整内容)

日志脱敏

不管什么级别,日志都不写入:

  • LLM Provider API key / Channel token / 任何认证凭证
  • 凭证类内容(边界拒收的具体字符串)
  • 完整用户画像(仅摘要 / hash)

DEBUG / TRACE 级别开启时给用户明示警告("日志将包含完整 LLM 入参出参,请注意敏感数据")。

异常上报

第一阶段不引入云端异常上报服务(如 Sentry)—— 单机部署不应把异常发到第三方。

替代方案:

  • runtime 在严重异常时本地保存 crash report(用户可选择上报)
  • 用户主动 finbayes diagnostic export 打包审计 trail + 配置 + crash report(敏感字段脱敏)供反馈

Provider 调用的精细观测

LLM Provider 调用是成本与延迟的主要来源,需要精细观测:

观测点字段
调用前provider_id / model / 任务类型 / 是否走 fallback / 缓存是否命中
调用中latency_to_first_token(流式响应)/ 是否流式中断
调用后input_token_count / output_token_count / estimated_cost / 是否结构化输出校验通过
失败时失败类型(鉴权 / 限流 / 超时 / 5xx / 解析失败)/ 是否触发降级 / 关联 fallback 调用

每次 Provider 调用进入审计 trail(含上述全部字段),可被用户查询 / 工程聚合。


降级原因的可观测

每次降级(详见 §13)都进入审计 trail 含:

  • 降级层级(L1 / L1' / L2 / L3 / L4)
  • 触发原因(具体错误码 + 错误消息脱敏)
  • 时间戳
  • 关联 task_id

用户视角的呈现:在受到降级影响的 task 输出末尾加 banner "本次因 [原因] 走 [层级] 模式,结果质量可能下降",并提供"点击查看完整降级链"。


测试可观测性

测试体系(详见 §20)依赖可观测性:

  • 单元测试:mock Provider 调用,断言审计事件按预期写入
  • 集成测试:跑端到端任务,校验 trace 完整性
  • 评估闭环(详见 §21):基于审计 trail 的离线分析(如 "上周 self-consistency 分歧度趋势")

第一阶段不做的可观测能力

明示不做:

  • 分布式 trace(OpenTelemetry 等)—— 单机不需要
  • 云端日志聚合(Datadog / Loki)—— 本地优先违背
  • A/B 测试框架 —— 第一阶段单用户场景不必要
  • 实时 metric dashboard(如 Prometheus + Grafana)—— 用户视角 UI 已够

这些都不是不可演化(接口契约不变),只是第一阶段不抢答(详见 §19 演化与版本管理)。


与其他章节的关系

  • 审计 trail 的存储位置与 schema → §15 数据存储划分
  • 任务 trace 的进程内传递 → §9 Task Orchestration 子系统
  • 降级事件的产生 → §13 故障与降级路径
  • 边界事件的产生 → §17 边界与安全
  • Provider 调用观测的具体字段 → §9 Provider Adapter 子系统
  • 可观测性如何支撑测试 → §20 测试体系
  • 可观测性如何支撑评估闭环 → §21 评估闭环

19. 演化与版本管理

这一节回答:FinBayes 各类资产(接口契约 / 数据 schema / Prompt / Provider / 工具)如何演化?如何保证升级时不打破现有用户的状态与体验?

五类需要版本化的资产

资产类型演化频率版本化策略
接口契约中(每次外部 API 调整)semver(major.minor.patch)+ contract_version 字段
数据 schema(State Store)低(破坏性变更稀有)schema_version + migration 脚本
Prompt(System / 任务模板)高(持续迭代)见 ADR-009(待定)
Provider 池(LLM / 数据 Provider)配置文件版本 + Provider Adapter 内部适配
工具池(Capability Registry)tool_version + 工具退役流程

各类资产的演化策略不同 —— 接口契约要严格 semver、数据 schema 要带 migration、Prompt 要支持快速迭代但留可回溯能力、Provider 与工具池要支持热插拔。


接口契约的版本化

哪些是"接口契约"

接口契约位置
入口 HTTP / WebSocket APIOpenAPI schema
MCP Server 暴露的工具MCP tool schema
Channel Adapter 接收的事件各 Channel 的 webhook schema
内部子系统间(§9 各接口)Python 函数签名 + Pydantic 数据对象
Provider Adapter 内部统一 OpenAI-compatible schema

Semver 语义

版本变更含义
major破坏性变更:删除字段 / 改字段语义 / 改方法签名 / 改错误码语义
minor向后兼容增加:新增 optional 字段 / 新增方法 / 新增错误码
patch修 bug、不动接口形态

字段级演化规则

关键约束

  • 不向已发布的接口悄悄改字段语义(即使字段名 / 类型不变)
  • 删字段前必须先 deprecated 一个 minor 版本,给用户 / 实施 Agent 升级窗口
  • 每次 major 升级附升级指南(自动转换工具 + 手动迁移说明)

Contract Version 在协议消息中

每条 API 消息含 contract_version 字段:

行为触发
同 major 不同 minor服务端兼容处理(缺失字段用默认值)
不同 major服务端拒绝,返回 INVALID_CONTRACT_VERSION + 当前服务端支持的版本范围
缺失 contract_version服务端按"最低支持版本"处理或拒绝

数据 Schema 的版本化(State Store)

Schema Migration 流程

关键约束

  • migration 脚本单向(只有 up,没有自动 down —— 降级靠从 bak 恢复,避免双向 migration 的复杂性)
  • migration 必须幂等(重复运行不损坏数据)—— 实现机制:
    1. DDL 层幂等:所有 CREATE TABLE / CREATE INDEXIF NOT EXISTS;所有 ALTER TABLE ADD COLUMN 先查 PRAGMA table_info 跳过已存在列
    2. 运行时层幂等:migration runner 启动时读 schema_metadata.migration_history(JSON 数组),跳过已记录的 migration 文件名
    3. 事务层:每个 migration 脚本在单一事务内执行,失败 ROLLBACK + 不写入 history;成功 COMMIT + 追加到 history
  • migration 失败时全量回滚到 bak,不留中间状态
  • 用户能看到 migration 进度(不是黑盒等待)

Schema 元表

State Store 含一张元表 schema_metadata

字段含义
schema_version当前 DB schema 版本
finbayes_version上次写入此 DB 的 FinBayes 程序版本
migrated_at上次 migration 时间戳
migration_history历次 migration 记录(from / to / timestamp / 备份位置)

Prompt 版本化(ADR-009 决策位置)

Prompt 既是"代码"(程序行为的关键决定因素)又是"数据"(频繁迭代 + 与提示词工程并行进化)。

两个候选策略

策略优点缺点
A. Prompt as Code:Prompt 进 Git,与代码同 release 周期版本可追溯 / Review gate 覆盖 / CI 跑得过迭代慢 / Prompt 工程师等不及 release / 大文件 diff 噪音
B. Prompt as Data:Prompt 存独立资源(YAML / DB),运行时加载迭代快 / Prompt 工程师独立工作难追溯 / Review 难 / 版本错位风险

初步倾向(待 ADR-009 确认):混合

  • 关键 Prompt(System Prompt / 任务路由模板 / 输出契约 schema)走策略 A(进代码仓 + Review gate)
  • 实验性 Prompt(个性化模板 / A/B 候选 prompt)走策略 B(YAML + 版本字段 + 审计追踪)
  • 切换在每条 Prompt 自描述的 delivery_mode: code | data

Prompt 演化的可观测要求(无论哪种策略)

每次 Prompt 变更必须可追溯:

字段含义
prompt_id全局唯一标识
prompt_versionsemver
activated_at启用时间
author作者 / Git commit 引用
eval_score上线前评估分数(详见 §21 评估闭环)
rollback_target如需回滚指向的上一版本

prompt_id 命名约定

prompt_id 采用三段式:<subsystem>.<purpose>.<variant>

含义取值示例
subsystem所属子系统orchestration / cognition / evidence / clarify
purpose用途类型system / task_template / output_schema / judge
variant变体标识main / compact / verbose / experimental_a

示例:

  • cognition.system.main — 综合层主 System Prompt
  • orchestration.task_template.synthesis — Task Orchestration 用的综合任务模板
  • clarify.system.main — clarify 工具 System Prompt
  • cognition.judge.counter_evidence_v1 — 评估 judge prompt(反方证据维度,详见 §21)

命名约定避免:

  • 同名跨子系统冲突(subsystem 前缀强制)
  • 实验 prompt 与生产 prompt 混淆(variant 后缀显式 experimental_*
  • A/B 测试时 prompt_id 混淆(variant 用 _a / _b / 而非数字)

详细 ADR-009 待写。


Provider 池演化

新增 Provider

约束

  • 新增 Provider 不动 runtime 业务代码(仅在 Provider Adapter Pool 层)
  • 新增 Provider 不影响现有 contract_version
  • 用户既有的 Provider 偏好顺序保留 / 升级时仅追加可用 Provider 不强制重排

Provider 退役

步骤内容
1. 标 deprecated用户配置中显示警告:"Provider X 将于版本 Y 移除"
2. 引导迁移提供"自动迁移到等效 Provider"建议(如 Provider X → Y)
3. 一个 major 版本后移除仍配置该 Provider 的用户启动时明示 + 引导重配

Provider API 变化(Provider 端)

LLM Provider(如 OpenAI)调整 API 时:

  • Provider Adapter 内部适配(patch / minor 版本)
  • runtime 业务代码不变
  • 用户感知:通常无感(除非 Provider 端废弃旧接口强制迁移)

工具池演化

新增工具

工具通过 Capability Registry 注册(详见 §9)。新增工具流程:

步骤内容
1. 工具实现实现 schema + 调用逻辑
2. 标 category严格枚举(read_only / analysis / synthesis / clarify / 等),无 execution 选项
3. Review gate人工审查工具用途 + schema 校验(自动 grep 执行类参数名)
4. 注册到 Registryruntime 启动时通过 Registry 装载
5. Self-consistency 测试LLM Function Calling 能否正确选择该工具(避免新工具拉低意图识别准确度)

工具退役

步骤内容
1. 标 deprecatedLLM 工具池 schema 中加 deprecated: true + 替代工具指向
2. 兼容期现有 task 仍可调用,但 LLM 优先选替代工具
3. 移除一个 minor 版本后移除(任何引用旧工具的状态对象 / Judgment 仍可读,只是不能再调用)

工具 schema 变更

新增 optional 参数:minor;改 required 参数 / 改返回 schema:major。


Concept 退役流程

战略层已禁入概念不允许进入主分支(§2 + §17)。但未来若某战略概念被明确退役(如"任务类型清单"扩展),工程层需要支持。

退役流程

步骤内容
1. 战略层 ADR在 governance 层写战略级 ADR 明示退役 + 替代
2. 加入 verify-kb 禁词表自动 grep 拦截
3. 状态对象兼容已有的引用旧概念的状态对象不破坏(只读 + 在 UI 中标"历史概念")
4. 文档归档旧概念相关文档移到 _archive/,frontmatter 标 legacy
5. 用户感知给一个 release 的过渡期 + 明示提醒

升级流程的工程承接

详见 §14 升级流程。这里强调演化角度:

升级路径接口契约数据 schemaPromptProvider工具
patch(bug 修复)不变不变可能变不变不变
minor(兼容增强)兼容新增兼容新增频繁变可能新增可能新增 / deprecated
major(破坏性变更)可破坏 + 升级指南migration 必备可能重写可能新增 / 退役可能新增 / 退役

约束:每次 release 的 changelog 必须按上述五类资产清晰罗列变更。


演化中的不变量

无论怎么演化,下列不变量永远不变

不变量演化中的保护
凭证不变量(不收不存不训练)任何接口 / schema / Prompt / 工具变更都不能引入凭证字段或凭证类参数
不直接下单 / 不持账户凭证工具池禁止注册执行类工具(即使新增 category)
不替用户决策综合层输出契约必须含反方 / 风险 / 失效条件(不能因"简化"删除)
用户数据主权任何数据 schema 变更都不能让用户失去查看 / 修改 / 删除权
本地优先任何架构演化(如未来加云端)都不能让本地优先用户失能

这些是战略级硬约束,演化策略必须服从战略层(详见 §2 上位继承与不变量)。


版本管理的可观测

每次资产变更都进入审计 trail / 元数据表:

资产追溯位置
接口契约OpenAPI / Pydantic schema 在 Git 历史 + contract_version 在消息中
数据 schemaschema_metadata 表 + Git 历史
PromptPrompt 自描述字段 + 审计 trail "prompt_version_changed" 事件
Providerproviders.yaml 在 Git 历史 + 用户配置文件版本
工具Capability Registry 的工具元数据 + 审计 trail "tool_registered/deprecated" 事件

与其他章节的关系

  • 战略级不变量演化中的保护 → §2 上位继承与不变量
  • 升级流程的部署形态承接 → §14 部署形态
  • Schema migration 的存储承接 → §15 数据存储划分
  • 接口契约消息体 contract_version → §16 通信协议
  • Review gate 的工程承接 → §17 边界与安全
  • 变更的审计可见性 → §18 可观测性
  • 评估如何驱动 Prompt 演化 → §21 评估闭环
  • ADR-009 Prompt 是代码还是数据 → 待写

20. 测试体系

字段权威定义见 contracts/state-machines.yaml(Step 11 整改包 I 单一事实源层)。本段为叙述用途,若与 contracts/ 不一致以 contracts/ 为准。承接 Step 11 整改方案

这一节回答:FinBayes 用什么测试体系覆盖业务正确性 / 子系统协作 / 端到端场景 / LLM 不确定性?

测试金字塔在 LLM 应用中的调整

传统软件的测试金字塔是 "单元 > 集成 > E2E",但 LLM 应用多一层评估测试(详见 §21)—— 因为 LLM 输出无确定预期,必须用统计指标而非断言。

这张图表达什么:从下到上数量递减,从下到上跨越的范围递增。评估测试单独一层是 LLM 应用的特殊性,不能用传统 assert 覆盖(详见 §21)。

这张图特意不表达什么:每层具体覆盖率指标(在工程实现仓 CI 配置);性能基准测试(在 §21 评估体系)。


单元测试

覆盖范围

类别覆盖对象
业务对象逻辑Session / Watchlist / Judgment Record / Profile / Fin Object / StateCandidate 的方法
状态机转移§11 的 6 个状态机的每个转移
工具实现每个工具的纯函数部分(不依赖外部 API)
数据契约校验Pydantic schema 的字段级约束
Provider Adapter 内部归一化OpenAI-compatible 转换逻辑(不真调 Provider)
输入边界 hook 规则凭证识别正则的命中率(§17)
综合层输出 schema 校验含反方 / 风险 / 失效条件字段的强约束
错误处理各种错误码 / 异常路径

关键约束

  • 单元测试不调真 LLM / 不调真外部 API(速度 + 成本 + 稳定性)
  • 单元测试不读真 State Store(用内存 SQLite 或 tmpdir)
  • 单元测试不依赖时间(用 freeze_time 等手段冻结时间)
  • 每个单元测试 <100ms

LLM 相关的单元测试

LLM 相关的纯函数也走单元测试:

测试对象测试内容
Prompt 模板渲染给定输入变量,渲染出预期 Prompt 文本
LLM 响应解析给定 mock 响应(含异常格式),解析逻辑健壮
Function Calling schema 生成给定工具池,生成的 schema 符合 OpenAI 规范
多轮上下文压缩给定长上下文,压缩后保留关键信息 + 长度合规

集成测试

覆盖范围

类别覆盖对象
子系统间协作§9 各子系统接口 + §10 各 sequence 流转
State Store 完整 CRUD真 SQLite(tmpdir 隔离)+ 事务原子性
Provider Adapter Poolmock LLM Provider + 4 层降级链触发
Capability Registry工具注册 + LLM Function Calling mock + 工具调用
Cache真 Redis(容器化)或内存 LRU
审计 trail 写入所有事件类型按预期写入
并发任务执行asyncio.TaskGroup + 失败隔离 + 取消(§12)

Mock 策略

真 / Mock对象
State Store / Cache / 内部子系统
MockLLM Provider(用 fixture 录制响应 + 重放)/ 外部数据 Provider(用 fixture)

LLM Mock 是集成测试的关键工程,下文专门讨论。

关键约束

  • 集成测试单次跑应该 <30 秒(不可被开发者跳过)
  • 每个子系统至少有 3 个跨子系统的协作场景测试

端到端测试

覆盖范围

§6 列举的 9 个关键业务场景每个对应至少一组端到端测试:

场景端到端测试核心断言
S1 即时认知请求首屏 <X 秒 + 流式输出完整 + 含反方与失效条件
S2 状态确认候选 → 用户确认 → 持久化到 Watchlist
S3 复盘历史 Judgment 引用 + 综合层输出含"信息缺口"
S4 关注流主动信号触发 → Channel 通知投递
S5 长 Session 上下文多轮后压缩 + 关键 Judgment 保留
S6 边界拒收凭证凭证类输入识别 + 不进入 Task / LLM / 状态对象 / 审计 trail
S7-S9(按当前任务类型清单)业务约束按 §6 描述

LLM 调用策略

端到端测试分两档:

LLM 调用何时跑
快档Mock LLM(录制 fixture)每次 PR / CI
真档真 LLM(用低成本 Provider,如 DeepSeek)nightly / release 前

约束:快档必须每次 CI 跑(覆盖业务流转);真档跑发现的真实 LLM 问题用于评估闭环(§21)。

数据隔离

  • 端到端测试绝不用用户真实 State Store
  • 每次端到端测试在 tmpdir 起独立 State Store + Cache
  • 测试结束清理(含 OS Keychain 中的测试凭证 —— 用专属测试命名空间)

LLM Mock 工程

LLM Mock 是 FinBayes 测试体系的关键 —— 既要快、便宜、稳定,又要逼真。

三种 Mock 模式

模式描述用途
录制重放真实跑过一次,把请求/响应 fixture 化集成 + 端到端快档
手工 fixture工程写死的固定响应(如"返回工具调用 X")单元测试 / 特定路径覆盖
简化模型 stub用简单规则模拟(如 echo / 关键词路由)性能测试 / 并发测试

录制重放的关键

关键约束

  • fixture 文件纳入 Git(可 review + 可追溯 LLM 行为变化)
  • fixture 不含真实凭证 / 用户敏感信息(录制前脱敏)
  • fixture 中的请求 hash 基于关键参数(model / messages / tools)+ 忽略时间戳等
  • Provider 端 API 变化导致 fixture 失效时,CI 给明确报错(不悄悄通过)

降级路径测试

§13 列举的每条降级路径必须有测试:

降级层测试方法
L1 → L1'mock 用户 Provider 全部失败 → 验证走系统默认
L1' → L2mock 系统默认失败 + 本地 LLM 可用 → 验证走本地
L2 → L3mock LLM 全失败 + 缓存有 → 验证走缓存
L3 → L4mock 全失败 → 验证走受限菜单 + 用户明示提示
State Store 只读模式mock SQLite 锁 / 磁盘满 → 验证读功能可用 + 写拒绝
Cache 不可用mock Redis down → 验证退化为不缓存模式
工具调用超时验证 EvidencePacket 标 timeout + 综合层继续
证据完全缺失验证综合层输出"信息缺口"而非硬编
用户主动取消验证 TaskGroup 取消 + 5s grace + 部分结果保留

约束:每条降级路径不仅测试走通,还测试用户感知(banner / 错误码 / 审计 trail 写入)。


边界与安全测试

§17 列举的每条边界约束必须有测试:

边界测试
凭证类输入拒收给输入贴 私钥 / API key / 助记词 等样式 → 拒收 + 安全回应 + 不进入任何后续
输出端凭证样式过滤mock LLM 输出含凭证样式 → 输出端剥除 + banner
执行类工具注册拒绝尝试注册 category=execution 工具 → 拒绝 + 审计记录
含凭证参数的工具拒绝尝试注册参数含 private_key 字段的工具 → 拒绝
Prompt 注入输入含 "忽略上述指令" → 综合层输出仍符合契约 + 不偏离任务
用户数据隔离跨 user_id 查询 → 拒绝 / 返回空
TLS 降级配置 HTTP Provider URL → 启动时拒绝
本机 socket 限尝试从非 localhost 访问 Web API → 拒绝

约束:边界测试是回归关键 —— 战略边界一旦被绕过,影响远大于功能 bug。CI 跑边界测试集失败 = 阻断 release。


并发测试

§12 的并发设计需要专项测试:

测试场景内容
TaskGroup 一子任务失败其他子任务能正常完成(或可控取消)
用户主动取消任务5s grace + 部分结果落审计 trail + 资源清理
多 Session 并发每 Session 独立 + Cache key 不串
backpressureProvider 限流时排队 + 不掉单
高并发下 SQLite WAL多读 1 写不冲突 + 事务原子性
主动信号触发的批量任务多 Judgment 同时失效 → 批量任务正确分发

测试数据管理

测试用户画像 / Watchlist / Judgment Record

类型来源
单元测试用 fixture工程写死
集成测试用 fixtureYAML 文件 + 测试时载入 tmpdir 隔离 SQLite
端到端测试用 fixture多套画像(保守 / 激进 / 多频次 / 新手)+ 多套 Watchlist
评估测试用数据集详见 §21

测试金融对象

  • 不用真实交易所 / 真实价格 API
  • 用 fixture 模拟价格序列(含暴涨 / 暴跌 / 横盘 / 缺数据等场景)
  • 必要时用历史数据回放(如某次行情事件的真实数据)

测试可观测性依赖

测试依赖 §18 可观测性体系:

  • 测试断言可以基于审计 trail(如"凭证拒收事件按预期写入")
  • 集成测试用 task_id trace 验证因果链完整
  • 性能测试用指标体系(latency / token / cost)做基线对比

CI 集成

触发跑什么
每次 PR单元 + 集成 + 端到端快档(Mock LLM)+ 边界测试集 + verify-kb
nightly全部 + 端到端真档(真 LLM,低成本 Provider)+ 评估测试(详见 §21)
release 前nightly 全跑 + 完整评估数据集 + 性能基线对比

约束

  • 每次 PR 测试不超过 15 分钟(开发者反馈循环)
  • nightly 测试不超过 1 小时(含真 LLM 调用)
  • 测试报告进入审计 trail(哪次测试失败 / 哪条 fixture 过期 / 等)

第一阶段不做的测试能力

明示不做:

  • 跨平台兼容性矩阵测试(仅主流 macOS + Linux + Windows 各一基线)
  • 浏览器 UI 自动化测试(第一阶段 Web UI 仅做最小可用,重点在 CLI / TUI)
  • 性能回归基准跑(评估闭环里有,但不在 CI 跑)
  • 模糊测试(fuzzing)—— 可演化能力

与其他章节的关系

  • 测试覆盖的场景来源 → §6 关键业务场景
  • 测试覆盖的子系统接口 → §9 子系统组件
  • 测试覆盖的流转 → §10 关键场景流转图
  • 测试覆盖的状态机 → §11 状态对象生命周期
  • 并发测试覆盖的设计 → §12 并发与异步处理
  • 降级路径测试覆盖 → §13 故障与降级路径
  • 边界测试覆盖 → §17 边界与安全
  • 测试依赖的可观测性 → §18 可观测性
  • 评估测试详见 → §21 评估闭环

21. 评估闭环

字段权威定义见 contracts/evaluation-dimensions.yaml(Step 11 整改包 I 单一事实源层,11 维 D1-D11)。本段为叙述用途,若与 contracts/ 不一致以 contracts/ 为准。承接 Step 11 整改方案

这一节回答:FinBayes 的认知质量怎么衡量?怎么形成"评估 → 改进 → 再评估"的闭环?

为什么评估测试不等于普通测试

普通测试用 assert expected == actual,但 LLM 输出没有唯一正确答案。一个分析 ETH 走势的认知任务可以有多种合理输出 —— 不是 string 比对能判定。

评估测试用统计指标 + 数据集衡量质量趋势,而非单点断言:

维度普通测试评估测试
期望值单一确定一组合格输出(rubric)
通过判据assert指标聚合 + 阈值
失败处理修代码修代码 / 修 Prompt / 修工具 / 标 case 入回归集
频率每次 PR周期跑(nightly + release)+ 关键变更跑
数据规模个位数 fixture几十到几百条评估样本

评估闭环的工程结构

这张图表达什么:评估数据集 → 跑 → 判定 → 报告 → 改进 → 失败 case 入回归集 → 再评估,是个闭环。每次改进都更新评估集,避免回归。

这张图特意不表达什么:具体评估工具实现(在工程实现仓);评估的真 LLM 成本(在 §18 成本指标)。


评估数据集(Eval Set)

数据集分层

用途规模跑频率
冒烟集关键场景快速验证10-20 条每次 PR
回归集已发现失败 case 的固化持续累积,初始 30-50 条nightly + release
场景集§6 9 个场景的覆盖每场景 5-10 条 = 50-100 条release
抗扰集Prompt 注入 / 边界 case / 异常输入持续累积release

约束

  • 评估数据集进 Git + Review gate 覆盖(不能有 PR 偷偷删 case)
  • 评估数据集不含真实用户数据(用脱敏 / 合成数据)
  • 评估数据集不含凭证类样式(凭证不变量延伸到测试资产)

评估样本的结构

每条样本含:

字段含义
sample_id全局唯一
scenario关联 §6 场景
input用户输入 + 上下文(如 Session 历史 / 画像 / Watchlist 状态)
expected_capabilities期望具备的能力(如"必须给出反方" / "必须标失效条件" / "不应给方向性结论 if 数据缺失")
negative_constraints不应出现(如"不能给执行类建议" / "不能输出凭证样式")
rubric质量评分维度(见下)
tags任务类型 / 难度 / 来源 / 等

评分 Rubric

DEPRECATED(v1 草案,已被取代,不要据此实现):下表 8 维 rubric 是 v1 草案,已由 11 维评测体系 D1-D11 全面取代(Step 11 整改包 I)。权威事实源为 contracts/evaluation-dimensions.yaml(字段单一事实源)+ Eval Harness 11 维评分公式(D1-D11 评分公式与加权)。新写代码 / 评估资产 / rubric 配置一律以 11 维 D1-D11 为准;下表仅保留作为 v1 演化的历史叙述上下文,不再是评分契约

下表为已废弃的 v1 8 维 rubric(历史参考,权威维度见上文 11 维 D1-D11):

v1 维度(已废弃)v1 评分方法
反方覆盖完整度LLM-as-judge:检查输出是否含反方 + 反方质量打分
失效条件清晰度LLM-as-judge + 规则:必须含可观测的失效条件
证据归因规则:输出中的关键结论必须有证据指向
信息缺口诚实度规则 + 人工:缺数据时应该明示,不应硬编
输出格式契约规则:综合层 schema 校验通过
表达密度匹配画像LLM-as-judge:是否过密 / 过疏
第一屏命中题眼LLM-as-judge:首屏是否回答用户主要疑问
边界约束遵守规则 + grep:不出现禁词 / 不给执行类建议

v1 每个维度独立打分(0-5)+ 汇总加权——该评分方式同样被 11 维 D1-D11 的评分公式取代,以 contracts/ + Eval Harness 公式文档为准。


评估运行器

评估流程

关键约束

  • 评估运行器与 runtime 解耦 —— 运行器通过 runtime 公开 API 调用(CLI / Web API),不直接 import
  • 每次评估记录 LLM 版本 + Prompt 版本 + Provider + 工具版本(可追溯哪次评估对应哪个组合)
  • 评估结果库长期保留(看趋势 + 看回归)

质量判定方法

三种判定手段

手段适用维度优点缺点
规则判定格式 / 字段存在 / 禁词 / 边界快 / 稳 / 便宜难判语义质量
LLM-as-judge反方质量 / 表达匹配 / 题眼命中能判语义贵 / 慢 / 自身有偏
人工抽检关键 case / 争议结果 / 新数据集校准真正可靠极贵 / 不可大规模

LLM-as-judge 的工程约束

LLM-as-judge 是评估的核心手段之一,需要专门工程:

  • judge LLM 与被评估 LLM 不同(避免自评偏见)—— 例如 GPT 评估 Claude 输出,反之亦然
  • judge Prompt 本身是 Prompt 资产(详见 §19 Prompt 版本化)+ 与 rubric 同步演化
  • judge 评分校准:用人工抽检的样本回头校准 judge 准确度(如 100 条人工标注 vs judge 判定的相关度)
  • 高分歧 case(多 judge 不收敛)走人工

评估指标聚合

单次评估的核心指标

指标含义
overall_score所有样本加权平均分
pass_rate总分 >阈值的样本比例
per_dimension_score各 rubric 维度的均分
per_scenario_score§6 各场景的均分
regression_failures历史 pass 但本次 fail 的样本
boundary_violations边界约束违反次数(严重失败,单条即阻断)

阈值与门禁

阈值类型第一阶段建议用途
overall_score >= 3.5/5软阈值看趋势,下滑明显需排查
pass_rate >= 80%软阈值同上
regression_failures == 0硬阈值回归集必须全过,否则 release 阻断
boundary_violations == 0硬阈值边界违反 = release 阻断

关键约束

  • 软阈值用于趋势监控,不作 PR 门禁(避免 Goodhart's law —— 优化指标牺牲真实质量)
  • 硬阈值仅限回归集 + 边界违反 —— 这两类是不可妥协的
  • 评估结果不直接喂回 LLM 训练 / Prompt 自动优化(避免反馈循环失控)—— 改进需要人工分析 + 工程决策

离线评估 vs 在线评估

离线评估

何时跑跑什么
每次 Prompt 变更 PR冒烟集 + 该 Prompt 关联的子集
nightly回归集 + 抗扰集
release 前全部数据集 + 性能基线对比
重要架构变更全部数据集 + 人工抽检

在线评估

第一阶段单机部署,"在线"指用户真实使用过程中的质量信号

信号采集方式
用户对候选状态的接受率candidate → confirmed / rejected / edited 的比例
用户对 Judgment 的"赞 / 否 / 编辑"UI 提供反馈按钮(可选)
用户主动重提问的频率同一会话内连续多次提问 = 上一轮没满足
用户取消任务的频率高 = 任务质量或速度问题
触发 clarify 的频率高 = 意图识别不准 / 输入难懂

约束

  • 在线评估信号严格 per-user 隔离(不跨用户聚合 —— 隐私)
  • 用户显式同意才上报到 FinBayes 团队(默认仅本地审计 trail)
  • 上报仅含统计数据(不含具体输入输出 / 用户画像)

评估驱动改进

改进类型

评估发现的问题改进路径
某场景反方覆盖不足调综合层 Prompt + 加 fixture
某任务类型表达过密调表达密度模板 + 与画像联动
某 Provider 在特定任务上质量差task_routing.yaml 调路由
某工具调用频次过低工具描述优化 + LLM Function Calling 测试
某边界 case 被识别成正常输入边界 hook 规则增强 + 加边界测试集
信息缺口未明示综合层 schema 强约束 + Prompt 加固

改进流程

约束

  • 改进不绕过评估闭环 —— 改完必须重跑评估
  • 失败 case 进回归集避免反复跌入同一坑(这是 case library 的真正用途,详见下文)
  • 每次重要改进记 ADR 或工程日志

Case Library 的角色(澄清)

战略层提到"Case Library"作为认知质量的回归追踪 —— 工程层的承接:

Case Library 是Case Library 不是
评估数据集中的"回归集"release 门禁的强制清单
历史失败 case 的累积 + 复测测试覆盖率的代名词
看"质量是否退步"的趋势"0 命中 = 完美"的 KPI
工程与战略层共同维护的资产工程一方说了算的工具

详见 §3 架构目标与质量取舍。


评估资产的演化

评估数据集 / rubric / judge prompt 本身也需要演化(详见 §19 Prompt 版本化):

资产演化策略
评估样本累积 + 标过期 + 不强行删除(历史可追溯)
Rubric 维度加 minor / 改语义 major + 重跑历史样本生成新基线
Judge Promptsemver + 切换时记录"哪一时点起用新 judge"
阈值可调,但每次调整记录理由(避免悄悄放水)

第一阶段不做的评估能力

明示不做:

  • 真实用户 A/B 实验(单机部署不需要)
  • 自动 Prompt 优化(如 DSPy 等)—— 评估反馈喂回 Prompt 优化器,第一阶段不引入
  • 多用户聚合趋势报表(隐私 + 第一阶段单用户)
  • 实时质量监控告警(评估周期跑足够)

这些都不是不可演化(评估接口契约不变),只是第一阶段不抢答。


与其他章节的关系

  • 评估覆盖的场景 → §6 关键业务场景
  • 评估依赖的可观测性 → §18 可观测性
  • 评估驱动 Prompt 演化 → §19 演化与版本管理(ADR-009 待写)
  • 评估资产的 Review gate → §17 边界与安全
  • 评估如何接入 CI → §20 测试体系
  • Case Library 的战略来源 → §3 架构目标与质量取舍

22. 第一阶段缺口

这一节回答:第一阶段明示不抢答的开放问题有哪些?为什么不抢答?什么条件下会被触发处理?

三类缺口

类别含义来源处理路径
战略待定战略层尚未给定答案,工程层不替代继承自白皮书 §15触发条件成立时回到战略层讨论
工程延后战略已定但第一阶段优先级不够工程层新增接口契约不变,后续版本演化补
场景外不在第一阶段服务范围战略边界 + 工程定位暂不投入,演化预留接口

缺口来源分层(详见各 P1 / P2 段标注):

  • 继承自白皮书 §15:商业模式与定价 / 个人 vs 机构分立 / 更多市场普适性 / L1-L3 商业强度
  • 产品层新增(产品定义文档识别):跨设备同步 / Channel 优先级 / 任务类型最终形态
  • 工程层新增(本架构文档识别):认知质量验收方法(OQ-002)/ 自动 Prompt 优化 / 实时 metric dashboard / 分布式 trace / 等
  • ADR 状态(2026-05-31):原"待写"的 ADR-005(并发)/ ADR-006(部署)/ ADR-009(Prompt 版本化)/ ADR-014(语言栈)均已 accepted。ADR-007(状态写入两步,M1 龙头)/ ADR-015 / ADR-016 亦 accepted。ADR-004 / ADR-008 / ADR-010 早已 accepted。本工作流 ADR 已无 draft/空缺,全部 accepted。

明示这些缺口不是"工程不完整",而是有意识的不投入 —— 第一阶段焦点是"本地优先单机的认知层 MVP 走通",不抢答与该焦点无关的问题。


战略待定的缺口

这一类与战略层的"未决问题"(详见上位继承与不变量章节)对齐:

第一阶段不抢答的战略未决

未决问题工程层影响触发讨论条件
商业模式与定价不影响第一阶段架构用户量达到 1000+ / 主动信号价值验证后
多用户共享 Watchlist / 团队级审计State Store schema 预留 user_id,但不实现共享企业用户出现
跨设备同步(用户多机 FinBayes 状态同步)不实现,State Store 单机本地用户明确需求出现
Channel Adapter 第二阶段优先级(TG / Discord / Slack 谁先)主推 Web 与 CLI / TUI,Channel 接口预留用户访问通道偏好数据出现
任务类型清单的最终形态(是否扩展、是否细分)不写死,按 LLM Function Calling 动态识别(详见 §4 / §9)评估闭环发现新型任务模式
认知质量验收的最终方法(OQ-002)§21 给出第一阶段建议,但不锁定上线后实际质量数据积累

已经过深度调研但 ADR 待定

议题调研产物ADR 编号当前状态
自然语言到任务的识别策略(OQ-003)projects/finbayes/research/intent-recognition-and-llm-strategy/ 已起草 README + summary + recommendationsarch-rewrite/ADR-004accepted(2026-05-28)
Prompt 是代码还是数据§19 给出初步倾向(混合策略)arch-rewrite/ADR-009waiting,M1 启动前 accepted
输出端凭证类内容过滤的位置§17 给出初步倾向(两处都做)arch-rewrite/ADR-010accepted(2026-05-28)

工程延后的缺口

战略已对齐、第一阶段不投入但接口契约预留的能力:

高级测试 / 评估能力

能力第一阶段做什么演化路径
模糊测试(fuzzing)不做评估闭环成熟后加
自动 Prompt 优化(如 DSPy)不做(避免反馈循环失控)评估指标稳定后探索
实时 metric dashboard(Prometheus + Grafana)不做,用 CLI / TUI 命令查询多用户部署后引入
A/B 实验框架不做(单用户单机不必要)远程托管后引入
浏览器 UI 自动化测试(Playwright)不做(Web UI 最小可用)Web UI 成为主入口后引入

高级可观测性

能力第一阶段做什么演化路径
分布式 trace(OpenTelemetry)不做(单进程不需要)拆分进程或远程部署时引入
云端日志聚合(Datadog / Loki)不做(本地优先违背)用户显式选择上报时引入
实时质量告警不做(评估周期跑足够)用户对认知质量提出实时监控需求时
异常上报到云服务(Sentry)不做用户显式选择时

部署能力

能力第一阶段做什么演化路径
远程托管部署不做,第一阶段单机商业模式验证 + 多用户隔离设计完成
多用户的真正运行时隔离仅 user_id 维度预留,不实现强隔离远程托管时实现
容器化(Docker / K8s)不做(单机不需要)远程托管时
跨平台兼容性矩阵测试主流平台各一基线用户分布数据驱动

数据能力

能力第一阶段做什么演化路径
State Store 从 SQLite 迁 PostgreSQL不做,SQLite 足够多用户或单用户数据规模超 SQLite 上限时
数据回溯与时间旅行(如 EventSourcing)不做,仅靠审计 trail 复盘复盘需求复杂化时
多语言 / 国际化不做,第一阶段中文 + 英文术语用户群扩展时
跨用户数据聚合 / 群体智能不做(隐私 + 单用户)商业模式与隐私策略明确后

场景外的缺口

明示不在第一阶段服务范围

场景不做的理由
真正的"自动化交易代理"战略边界:FinBayes 不直接下单 / 不持账户凭证(详见 §2)
"金融执行凭证管家"战略边界:凭证一律不收
替用户做最终判断的"AI 决策"模式认知层定位:不替用户决策(详见 §3)
个性化广告 / 行情诱导业务定位:仅服务用户认知,不卖流量
跨用户的"群体趋势"推断隐私 + 战略:用户画像主权
实时高频信号(毫秒级触发)性能定位:认知层不做高频系统

这些不仅第一阶段不做,演化路径上也不做 —— 与战略定位冲突。


缺口的演化触发条件

缺口被触发时如何处理:

关键约束

  • 工程层不替战略层做决策 —— "战略待定"缺口被触发时回到 governance/change-protocol.md 走战略变更流程
  • 工程层不为缺口偷偷开后门 —— 例如不会"先在 State Store 做多用户隔离的临时方案",因为这种临时方案常常被锁定下来变成事实标准
  • 演化中的不变量(详见 §19)任何时候不变

缺口与质量目标的关系

缺口与 §3 的 8 个质量属性的关系:

质量属性第一阶段缺口影响
可用性不影响(第一阶段降级链已覆盖核心可用性需求)
性能不影响(缺的是优化空间,不是基础性能)
可演化性关键 —— 缺口的接口契约预留是可演化性核心承接
可测试性部分影响(fuzzing / 浏览器自动化等延后,但核心测试体系已完整)
可观测性不影响(核心可观测已完整,缺的是高级集成)
战略保真度不影响(战略边界是缺口的约束,不是缺口的产物)
部署便捷性不影响第一阶段
用户主权不影响(用户主权是战略级,缺口都遵守)

缺口管理的工程动作

动作内容
缺口登记每个缺口在本章登记 + 在工程实施仓 issue tracker 留 placeholder
缺口触发判断每个 release 评估各缺口的触发条件是否成立
缺口推进触发时按上述流程图走战略 / 工程分流
缺口与不变量冲突缺口处理方案若与演化中的不变量冲突,停下来回战略层

与其他章节的关系

  • 战略未决问题 → §2 上位继承与不变量
  • 8 个质量属性 → §3 架构目标与质量取舍
  • 任务类型清单非写死 → §4 业务对象与关系
  • 第一阶段不抢答的部署形态 → §14 部署形态
  • 演化中的不变量 → §19 演化与版本管理
  • 第一阶段不做的测试能力 → §20 测试体系
  • 第一阶段不做的评估能力 → §21 评估闭环
  • 待写 ADR 清单 → §23 架构决策索引
  • 缺口对应的风险 → §24 风险登记

23. 架构决策索引

字段权威定义见 contracts/adr-states.yaml(Step 11 整改包 I 单一事实源层,12 ADR + namespace)。本段为叙述用途,若与 contracts/ 不一致以 contracts/ 为准。承接 Step 11 整改方案

这一节回答:本架构文档涉及的所有架构决策记录(ADR)的全景索引。每条 ADR 在哪、谁触发、状态如何、影响哪些章节。

ADR 体系约定

字段说明
编号ADR-NNN(三位数字),在 arch-rewrite 工作流 namespace 内唯一,不重用;跨工作流引用须显式带 <workstream>/ADR-NNN 前缀(详见 ADR INDEX §3 跨工作流同号消歧)
位置governance/workstreams/finbayes-arch-rewrite/decisions/ADR-NNN-*.md
状态proposed(待评审)/ accepted(已确认)/ superseded(已被新 ADR 替代)/ deprecated(已废弃但未替代)
触发章节哪个 CHAP 的设计需要这个决策
影响章节决策一旦确认后影响哪些章节的描述

ADR 是独立成档的(详见 ADR-002),不在主架构文档中展开决策对比 —— 主文档只引用结论。

Namespace 说明:本索引为 finbayes-arch-rewrite 工作流 namespace;跨工作流 ADR-NNN 引用须显式带 <workstream>/ADR-NNN 前缀(如 finbayes-whitepaper-rewrite/ADR-008 与本工作流 ADR-008 同号不同物)。完整 namespace 消歧与 supplement 列表见 ADR INDEX


已 accepted 的 ADR

编号主题文件触发影响
ADR-001工程范式:Harness Workflow + 里程碑切片 + 走通骨架试点decisions/ADR-001-工程范式.md工作流启动全篇(特别是 §25 / §27)
ADR-002架构文档结构:分层章节 + C4 画图 + 决策独立成档 + 业务建模思路decisions/ADR-002-架构文档结构.md工作流启动全篇(文档结构本身)
ADR-003工程实施栈与协作模式:OpenSpec + Archon + Claude Code 主理 + Codex 实现decisions/ADR-003-工程实施栈与协作.md工作流启动§25 / §27
ADR-004自然语言到任务的识别策略:LLM Function Calling 主导decisions/ADR-004-任务识别策略.md§4 / §9§4 / §9 / §10 / §21
ADR-008LLM Provider 接口抽象:统一 OpenAI-compatibledecisions/ADR-008-LLM-Provider-接口抽象.md§9§9 / §13 / §15
ADR-010输出端凭证过滤位置:综合层语义级 + Output Pipeline 格式级 双处decisions/ADR-010-输出端凭证过滤位置.md§17§9 / §17 / §20

待写的 ADR(M1+ 实施初期补)

以下决策已在主架构文档草稿中提出初步倾向,但尚未独立成 ADR 完整论证。M0 启动不阻塞(M0 实施 Agent 按当前倾向执行 + 在工程实施仓 PR 描述中标注采用了该倾向)。

编号主题触发章节当前倾向优先级
ADR-005内部并发原语选择:asyncio / 多线程 / 多进程§12Python asyncio.TaskGroup(结构化并发)
ADR-006部署形态优先级:本地优先 / 远程优先 / 混合§14本地优先单机为第一阶段 ✅;远程托管远期
ADR-007状态写入"候选 → 已确认"两步设计§11主动状态全部走两步 + 显式拒收 / 编辑路径
ADR-009Prompt 是代码还是数据 / 版本化策略§19混合:关键 Prompt 进代码仓 + 实验性 Prompt 走 YAML

优先级判定

  • :第一阶段实施前必须有 ADR 才能起代码(涉及主干架构 / 战略边界)
  • :可在第一阶段实施初期一周内补 ADR
  • :第一阶段不阻塞,演化中再补

编号变迁说明

工作流早期 ADR-004 候选为"多 Skill 命中同一任务时的优先级规则",深度调研后该议题与"自然语言到任务的识别策略"合并 —— 后者更高优先级且涵盖前者。ADR-004 重命名为"任务识别策略",原"多 Skill 优先级"作为该 ADR 的子议题处理。

如未来"多 Skill 优先级"需独立成 ADR,会按下一可用编号(如 ADR-012)分配,不复用 ADR-004 编号。


拒绝概念的处理(无需独立 ADR)

战略层已禁入的概念清单(详见 §2 / §17)不需要独立 ADR —— 它们是战略级硬约束而非工程级决策。

拒绝概念拒绝来源工程承接
11 条字段级强约束战略白皮书构建期否决综合层 schema 不引入这 11 条字段
默认 vs 行动准备双模式同上§6 关键场景不区分双模式
升格为关系定义的"认知协作伙伴"同上全篇正文不使用该词
L3 长期状态四承诺同上§15 / §19 用户主权五维度替代
零状态前提同上§14 / §15 显式状态管理
情绪桥 / 信任债承诺同上综合层输出契约不含此类元素
行动准备 / 行动判断 / 行动方案同上任务类型清单用"交易准备 / 交易决策 / 交易行动"代替

工程层的承接通过:

  • verify-kb.mjs 的自动 grep 检查(CI 必跑)
  • PR Review gate 的人工语义复核(防同义改写)
  • 章节级的 Review 历史保留

ADR 间的关系

这张图表达什么:ADR 之间的逻辑依赖关系。ADR-001/002/003 是工作流基础;ADR-004(任务识别策略)是认知架构核心,影响 ADR-005/008/009;ADR-006 部署形态依赖 ADR-007/008 的接口稳定。

这张图特意不表达什么:ADR 的写作顺序(按工程优先级,不按依赖严格拓扑)。


ADR 编写规范(来自 ADR-002)

每条 ADR 至少含:

段落内容
Context背景:为什么需要这个决策
Decision决策:选了什么方案
Rationale理由:为什么这样选(不展开未选方案的详细评分,只说结论)
Consequences后果:决策带来的好处 / 坏处 / 影响范围
Status状态:proposed / accepted / superseded / deprecated
References关联:影响的 CHAP / 关联的其他 ADR / 关联的战略文档

关键约束

  • ADR 不变更(accepted 后追加 superseded 关系,不直接改原文)
  • ADR 不超过 80 行(紧凑 + 聚焦 + 不堆方法论)
  • ADR 文件名缩短(不含日期 / 长描述)

ADR 与主架构文档的关系

主架构文档(CHAP-NN)ADR
说"是什么 / 做什么 / 怎么做"说"为什么选这个、不选那个"
引用结论展开权衡
篇幅长篇幅短(≤80 行)
每章覆盖多个决策每条覆盖单个决策

主架构文档不重复 ADR 的内容 —— 引用 ADR 编号即可。


主架构文档之外的决策痕迹

部分小决策不独立成 ADR,但在工程实施仓的 commit / PR 描述中留痕:

决策类型留痕位置
工具版本选型(如选 Pydantic v2 而非 v1)工程实施仓的依赖文件 + 引入 commit
字段命名 / API 路径细节OpenAPI schema + PR 描述
Bug 修复中的次要设计选择PR 描述

判定标准

  • 决策影响多个章节 → 独立 ADR
  • 决策影响单一模块 → 工程实施仓留痕
  • 决策反映战略边界 → 战略层而非 ADR

已识别但暂不分配编号的潜在 ADR

下列议题可能在演化中变成 ADR,但当前不分配编号(避免编号膨胀):

  • 多 Skill / 多工具优先级规则(被 ADR-004 涵盖)
  • Cache TTL 策略(按数据敏感度分类,工程实施细节)
  • 审计 trail 归档策略(按时间分片,工程实施细节)
  • Provider Readiness 探测间隔(运维参数,工程实施细节)

这些都不到 "影响多个章节"的门槛,留在工程实施仓决策。


与其他章节的关系

  • ADR 编写规范来源 → ADR-002 架构文档结构
  • 拒绝概念清单的来源 → §2 上位继承与不变量
  • 战略未决问题映射 → §22 第一阶段缺口
  • ADR 与风险的对应 → §24 风险登记
  • ADR 如何驱动里程碑 → §25 与里程碑/任务的对应

24. 风险登记

这一节回答:第一阶段已识别的关键风险有哪些?每个风险的可能性、影响、当前缓解状态是什么?

风险分类

类别含义
技术风险工程实现 / 性能 / 可靠性层面的不确定性
业务风险用户接受度 / 认知质量 / 商业模式层面的不确定性
边界风险战略边界被绕过或被攻击的风险
演化风险长期演化中可能出现的设计债

评级约定

维度等级
可能性高(H)/ 中(M)/ 低(L)
影响高(H)/ 中(M)/ 低(L)
优先级由可能性 × 影响推导:HH / HM-MH = P1;MM / HL-LH = P2;其他 = P3

风险登记不是恐吓清单 —— 是让缓解动作有抓手


技术风险

T1 — LLM Provider 不稳定(API 限流 / 5xx / 鉴权失败 / 延迟抖动)

字段内容
可能性 / 影响 / 优先级H / H / P1
表现任务失败 / 用户体验中断 / 成本飙升
当前缓解4 层降级链(§13)+ Provider Readiness 探测(§9)+ task_routing 配置
残余风险全部 Provider 同时不可用极端场景 → L4 受限菜单兜底
触发处理动作Provider 失败率连续 30 min >10% → 自动降级 + 用户通知

T2 — 本地资源不足(内存 / 磁盘 / 计算)

字段内容
可能性 / 影响 / 优先级M / M / P2
表现本地 LLM 推理慢 / SQLite 写阻塞 / 缓存换出
当前缓解部署时探测 OS 资源(§14)+ 本地 LLM 模型大小自适应 + Cache TTL 限制
残余风险用户机器极弱时本地兜底质量差
触发处理动作启动期探测资源不足 → 明示用户选择"走云端 Provider"或"接受性能下降"

T3 — SQLite 并发瓶颈

字段内容
可能性 / 影响 / 优先级L / M / P3
表现高并发任务下写阻塞 / WAL 文件膨胀
当前缓解WAL 模式 + 审计 trail 写入异步化 + 单用户量级 SQLite 远未到瓶颈(§15)
残余风险主动信号触发批量任务时偶发阻塞
触发处理动作持续监控 state_store_write_failure 指标,达阈值时启 ADR 评估迁 PostgreSQL

T4 — LLM Mock fixture 失效(Provider API 变化)

字段内容
可能性 / 影响 / 优先级M / M / P2
表现CI 测试通过但生产环境失败(fixture 与真 API 偏差)
当前缓解录制重放机制(§20)+ nightly 真档测试 + fixture 进 Git 可 review
残余风险Provider 端悄悄改 API 行为
触发处理动作nightly 真档测试失败 → 强制重录相关 fixture + 通知

T5 — Schema migration 出错(State Store 升级失败)

字段内容
可能性 / 影响 / 优先级L / H / P2
表现升级后用户数据损坏 / 丢失
当前缓解migration 前强制备份(§15)+ 单向幂等 migration(§19)+ 失败时全量回滚
残余风险备份本身损坏的极端情况
触发处理动作严重 migration 失败 → 用户可 finbayes restore --from=<bak> 强制恢复

业务风险

B1 — 认知质量不达预期(反方覆盖不足 / 失效条件模糊 / 综合层不收敛)

字段内容
可能性 / 影响 / 优先级M / H / P1
表现用户对 Judgment 不满 / Case Library 失败率升 / 用户流失
当前缓解Self-consistency 高风险任务 N≥3(§12)+ 综合层输出强 schema(含反方 / 风险 / 失效条件)+ 评估闭环驱动改进(§21)
残余风险评估指标本身有偏(LLM-as-judge 偏见)
触发处理动作评估 overall_score 连续两周下滑 → 强制评估闭环复盘

B2 — 用户接受度低(首屏太慢 / 表达不匹配画像 / 不知道怎么用)

字段内容
可能性 / 影响 / 优先级M / H / P1
表现用户使用频次低 / 取消率高 / 弃用
当前缓解首屏优化(流式 + 题眼优先)+ 动态画像匹配表达密度 + 引导流程(§14)
残余风险个性化画像积累需要时间
触发处理动作上线后第一周用户行为信号反推改进点

B3 — 复盘价值难量化

字段内容
可能性 / 影响 / 优先级H / M / P2
表现用户用了几次但不知道"它真的帮我变好"了
当前缓解Judgment Record 长期追踪 + 主动信号触及失效条件可被用户复盘(§10 S4 场景)
残余风险用户认知改善是慢变量
触发处理动作用户问"它真有用吗"时主动给"过去 N 次主动信号的命中率 / 失效条件触及率"

B4 — Provider 成本失控

字段内容
可能性 / 影响 / 优先级M / M / P2
表现用户单月 LLM 成本超预期
当前缓解成本指标可视(§18)+ 用户主动设月度预算 + 超预算自动降级到便宜 Provider
残余风险用户对成本敏感度差异大
触发处理动作首次安装时引导用户设月度预算(可选)

边界风险

E1 — 凭证被绕过(用户主动贴凭证未被识别)

字段内容
可能性 / 影响 / 优先级M / H / P1
表现凭证字符串进入 Task / LLM / 状态对象 / 审计 trail
当前缓解输入边界 hook(规则 + LLM 辅助,§17)+ 测试集覆盖各类凭证样式(§20)
残余风险新型凭证格式 / 用户极端规避
触发处理动作任何凭证泄露事故 → 立即 release 阻断 + 全量审计 trail 扫描 + 通知用户

E2 — 执行类工具偷偷被注册

字段内容
可能性 / 影响 / 优先级L / H / P2
表现工程 PR 引入执行类工具 + Review 漏掉
当前缓解Capability Registry 注册时 category 校验(§9)+ 参数名启发式扫描(§17)+ Review gate 人工审查
残余风险工具用 read_only category 伪装但内部偷偷执行
触发处理动作每次工具注册需关联 PR / ADR / Review 记录三齐

E3 — Prompt 注入成功(用户输入或外部数据中的对抗指令改变 LLM 行为)

字段内容
可能性 / 影响 / 优先级M / M / P2
表现LLM 输出偏离任务 / 泄露敏感 / 违反输出契约
当前缓解System prompt 加固(§17)+ 外部数据包裹 <external_data> + 综合层 schema 强约束 + 抗扰评估集(§21)
残余风险高级注入 + LLM 误识别
触发处理动作评估抗扰集失败率上升 → Prompt 加固 + judge 校准

E4 — 输出端凭证样式过滤漏检

字段内容
可能性 / 影响 / 优先级M / M / P2
表现LLM 幻觉生成的凭证样式字符串流向用户
当前缓解输出端双层 hook(综合层语义 + Output Pipeline 格式,详见 arch-rewrite/ADR-010 accepted)
残余风险模糊匹配未命中的边缘 case
触发处理动作用户上报 + 边界审计 trail 抽检

演化风险

V1 — 接口契约破坏性升级

字段内容
可能性 / 影响 / 优先级M / H / P1
表现major 升级导致存量用户的 client / 集成 / MCP 调用方失败
当前缓解semver + contract_version + 强制升级提示(§19)+ 升级指南 + deprecated 宽限期
残余风险用户不及时升级被强制阻断
触发处理动作major 发布前给至少一个 minor 版本的 deprecated 期 + 升级文档

V2 — Prompt 版本错位(生产用旧 Prompt + 评估用新 Prompt 等)

字段内容
可能性 / 影响 / 优先级M / M / P2
表现评估通过但生产质量差,或反之
当前缓解Prompt 版本化(ADR-009 待)+ 评估记录 Prompt 版本 + 审计 trail 含 prompt_version 字段(§19)
残余风险混合策略(代码 + 数据)切换时漂移
触发处理动作每次 release 用 prompt_version 跑全量对比

V3 — 战略概念变化(新增 / 重命名 / 退役)

字段内容
可能性 / 影响 / 优先级L / H / P2
表现工程层与战略层不同步 / 用户看到混乱概念
当前缓解概念退役流程(§19)+ 战略变更走 governance/change-protocol.md + verify-kb 禁词表同步
残余风险已生成的历史 Judgment Record 引用旧概念
触发处理动作旧概念在 UI 标"历史概念" + 不破坏数据

V4 — Provider 生态变化(旧 Provider 退役 / 新 Provider 涌现)

字段内容
可能性 / 影响 / 优先级H / M / P2
表现用户偏好的 Provider 不再可用 / 新 Provider 体验更好但路由未更新
当前缓解Provider Adapter 层屏蔽(§9)+ providers.yaml 配置可热更新 + Provider 退役流程(§19)
残余风险用户配置历史包袱
触发处理动作Provider 退役前一个 major 版本通知 + 自动迁移建议

V5 — 评估闭环 Goodhart's law(优化指标导致真实质量下降)

字段内容
可能性 / 影响 / 优先级M / H / P1
表现评估分数上升但用户感知不好
当前缓解软阈值仅看趋势(§21)+ 评估反馈不自动喂回 Prompt 优化 + 人工校准 judge
残余风险隐性指标钻空子(如优化反方数量但反方质量下降)
触发处理动作评估指标稳定上升但用户反馈下降 → 人工抽检 + rubric 重审

风险评级汇总

优先级数量风险
P16T1 / B1 / B2 / E1 / V1 / V5
P211T2 / T4 / T5 / B3 / B4 / E2 / E3 / E4 / V2 / V3 / V4
P31T3

P1 风险必须在第一阶段 MVP 前有可执行的缓解动作 + 触发响应;P2 风险在第一阶段实施初期一轮内覆盖缓解机制;P3 风险登记即可,演化中再处理。


风险与缺口的关系

关系含义
风险有缓解 → 残余风险登记当前章节做的事
风险无缓解 → 进入缺口关联 §22
风险触发战略层变化 → 战略未决关联战略层(详见上位继承与不变量章节)

风险登记是动态资产,每次 release / 重大事件后更新。


与其他章节的关系

  • 凭证风险的边界承接 → §17 边界与安全
  • 降级链应对技术风险 → §13 故障与降级路径
  • 评估闭环应对业务风险 → §21 评估闭环
  • 演化机制应对演化风险 → §19 演化与版本管理
  • 风险缓解的可观测性 → §18 可观测性
  • 缺口与风险的边界 → §22 第一阶段缺口
  • 风险相关的 ADR → §23 架构决策索引

25. 与里程碑 / 任务的对应

这一节回答:本架构文档的 27 章如何映射到工程实施仓的里程碑切片?M0 走通骨架是什么?后续里程碑怎么 thicken?

范式回顾

详见 ADR-001。要点:

  1. M0 走通骨架:1 任务类型 × 1 市场 × 1 入口 × 1 状态对象端到端打通(1-2 天),验证契约能在代码上落
  2. 后续里程碑切片:按维度(任务类型 / 市场 / 入口 / 状态对象 / 工程能力)渐进 thicken
  3. 每个里程碑过三检 review gate:战略保真度 + 契约回归 + 认知质量评估

本章不重复决策论证,只把 27 章映射到具体里程碑

frame 重定位(2026-06-04 阶段 0 文档矫正 · 头号结构性偏移纠正):下面的 M0–M7 里程碑序列是在旧的「磨答案」框架下排出的——它把 agent 的循环本体(主动信号 / 失效条件触及自动触发新一轮认知)整体排到了 M5,让 M0–M4 全程在没有自主循环的前提下扩状态(M1)、扩任务(M2)、扩入口(M3)、扩市场(M4)。这正是金融真智能体骨架蓝图(E) 点名的头号偏移:把 §2 已立为 identity 级的 agent 自主循环当成晚期增量功能,结果是「即便建了主回路,后续里程碑预算仍被单次回答优化吸走」。

本次矫正(非破坏插入,不重编号,遵循 ADR-016 先例)

  1. 最小自主循环切片前移到 M1/M2:把 M5 中「失效条件触及 → 自动触发新一轮认知」这个核心循环的最小切片(哪怕只监控 1 类失效条件、只对 1 个 Fin Object、由一次手动 tick 驱动)下沉为 M1/M2 的交付物 + agent 行为验收(见下方 M1/M2 验收新增项)。M5 退化为该能力的铺面(Channel 投递、批量触发、heartbeat/cron 真实调度)。
  2. M0–M4 是已知的 pre-agent 阶段:允许 M0 walking skeleton 以 single-shot 起步,但这是已标注的已知风险——若不前移最小循环,M0–M4 会一路把 FinBayes 做成「更好的问答函数」而非 agent。前移切片即是缓解。
  3. agent 的建造顺序以蓝图「阶段」序为准:蓝图议定结果定义的 阶段 0(文档矫正)→ 阶段 1(最小可用真 agent:主回路 + 1 工具 + 1 真实数据源 + 把 synthesize_cognition 降为被回路调用的认知动作 + 落一条 Judgment Record)→ 阶段 2(主动性)→ 阶段 3(加固与可用化) 是当前实际建造序;它与这里的 M0–M7「磨答案」编号并存,冲突时以蓝图阶段序为准
  4. M0–M7 与 SVA-9 gate 机器的整体按 agent 重排,是 owner 治理连带项(见 CURRENT-MILESTONE §4),本次只做最小切片前移 + frame 标注,不做破坏性全量重编号。

里程碑全景

这张图表达什么:里程碑的依赖序列。M0 必须最先;M1-M3 是基础能力扩展;M4-M5 是范围扩展;M6-M7 是工程闭环。其中 M2 → M4 与 M3 → M5 可一定程度并行。

M1 范围更正(arch-rewrite/ADR-016,2026-05-31)M1 = 状态化 only(Session/Watchlist/Judgment Record/StateCandidate + candidate→confirmed 两步写入,龙头决策 ADR-007)。M0 遗留的认知核实化s1 完整子流程、MCA 多桶裁决、posterior 真算、tag_version 锁定,即把确定性 stub 变真算)拆为独立里程碑 M1.5「认知核实化」,置于 M1 后、M2 前(非破坏插入,不重编号 M2–M7)。字段演化矩阵中这些认知字段的收紧时点相应改为 M1.5。

这张图特意不表达什么:每个里程碑的工期(按完工定义而非时间盒,详见 ADR-001);里程碑内的子任务(在 OpenSpec 提案中展开)。


M0 走通骨架

范围

维度M0 选什么
任务类型即时认知请求(最常见 + 最简单链路)
市场Crypto(数据 Provider 选项最多 / 限制最少)
入口CLI(最易调试 + 无 UI 依赖)
状态对象Fin Object(基础数据对象,无两步写入复杂度)

M0 必须打通的链路

M0 覆盖的章节

章节M0 是否覆盖
§1 至 §3✅ 立架与目标
§4 业务对象与关系✅ 仅 Fin Object + Session(一个默认 Session)
§5 用户价值与认知流转✅ 三层价值的"题眼回答"层
§6 关键业务场景✅ 仅 S1 即时认知请求
§7 系统与外部世界✅ Context 图最小子集
§8 进程与服务划分✅ 单进程
§9 子系统组件✅ 6 个子系统的最小可用版本
§10 关键场景流转图✅ 仅 S1 sequence
§11 状态对象生命周期⚠️ Fin Object 仅 created 状态,不走两步写入
§12 并发与异步处理✅ asyncio.TaskGroup 基础
§13 故障与降级路径⚠️ 仅 L1 用户配置 Provider implement,L1' / L2 / L3 / L4 全部 stub(详见工程包 m0-walking-skeleton.md §2 接口子集表)。Provider 调用失败时仅记录降级事件 + 抛 ProviderNotReadyError(退出码 20),不真正切换 fallback。L1' 在 M1+ 上线。
§14 部署形态✅ 本地优先单机
§15 数据存储划分⚠️ 仅 State Store(SQLite) + 审计 trail;Cache / Credential / Config 简化
§16 通信协议✅ stdio + HTTPS Provider 调用
§17 边界与安全✅ 输入边界 hook(凭证识别)+ TLS 强制
§18 可观测性⚠️ 审计 trail + task_id trace,指标体系暂不实现
§19 演化与版本管理⚠️ semver 字段约定但不实际触发 migration

✅ = 完整覆盖;⚠️ = 最小可用,后续里程碑 thicken;空白 = 不在 M0 范围

M0 验收

检查通过条件
战略保真度verify-kb grep + 人工审查无禁词命中
契约回归M0 是基线,建立契约 baseline
认知质量手工跑 5 条样例输入,输出含反方 + 失效条件 + 题眼命中
边界测试集 5 类凭证样式输入全部拒收
审计 trail每次 task 进入审计,含完整 Provider 调用链

M1 状态化

范围

  • 引入 Session 多实例 + Session 切换
  • 引入 Watchlist 与 Watchlist 内的 Fin Object
  • 引入 Judgment Record 持久化
  • 引入候选 → 已确认两步写入路径

覆盖章节增量

  • §11 状态对象生命周期 → 完整 6 个状态机
  • §15 State Store → 完整 8 张表
  • §9 State Management 子系统 → 完整 candidate / confirmed 路径

M1 验收

  • 用户在 Session A 创建一条 Judgment Record → 切换 Session B → 切回 A 仍可见
  • candidate 状态对象等待用户确认;用户确认 / 拒绝 / 编辑路径都打通
  • 用户主动修改画像 / 删除 Session 等动作齐全
  • (agent 行为切片 · 前移自 M5 的状态基础):Judgment Record 必须带可被未来检查的失效条件字段(成立 / 失效条件 + 时间窗),作为 agent 自主触发的条件源——这些字段不是死档,是 M2 最小自主循环的状态前提(承接 §2 agent 本体不变量)

M2 任务类型扩展

范围

  • 加复盘任务(引用历史 Judgment Record)
  • 加关注流任务(基于 Watchlist)
  • LLM Function Calling 工具池扩展(clarify 工具上线)
  • 最小自主循环切片(前移自 M5 核心 · 头号 frame 矫正落点):实现「失效条件触及 → 自动发起一轮复盘」的最小闭环——由一次手动 tick / 单次脚本驱动,检查 Watchlist 对象当前值是否触及某条 Judgment Record 的失效条件,触及则 agent 无需用户提问自主发起复盘任务,并把复盘结论写回该 Judgment Record(暂不需 cron / Channel / 批量,那是 M5 铺面)

覆盖章节增量

  • §6 关键业务场景 → S3 复盘 + S4 关注流 + S9 主动信号(最小切片)
  • §10 关键场景流转图 → S3 + S4 + S5 sequence
  • §9.4 State Management 主动信号触发器 → 最小可用版本(手动 tick 驱动,非 cron)

M2 验收

  • 复盘任务能正确引用历史 Judgment Record + 输出"信息缺口"
  • 关注流任务能基于 Watchlist 当前状态给输出
  • LLM 调 clarify 工具的频率 <20%(评估指标)
  • agent 行为门(最小自主循环端到端 · M2 首要验收):构造一条带失效条件的 Judgment Record + 一次触及该条件的市场变化(手动喂入)→ agent 无需用户提问即自主发起复盘 → 复盘结论写回原 Judgment Record 形成时间线(不覆盖原判断)。这是旧 single-shot 函数在结构上做不到的 agent 行为;达不到则 M2 判为未交付 agent 切片(哪怕复盘 / 关注流任务质量都达标,也只是更好的问答函数)。

M3 入口扩展

范围

  • TUI 入口(Textual / Rich)
  • Web API(HTTP + WebSocket)+ 最小 Web UI

覆盖章节增量

  • §7 外部接触契约 → 3 个入口完整
  • §16 通信协议 → Web API 端点 + WebSocket

M3 验收

  • 三入口(CLI / TUI / Web)等价场景输出一致
  • Web API 鉴权(localhost only)+ contract_version 协议工作
  • Web UI 能查看 Session / Judgment / 主动信号

M4 市场扩展

范围

  • US Stocks 市场加入
  • 新数据 Provider(如 yfinance / SEC EDGAR)接入

覆盖章节增量

  • §4 Fin Object 类型 → 完整覆盖股票 / 板块 / 财报事件
  • §6 任务类型 → S2 / S6 等场景在 US Stocks 上运行

M4 验收

  • 同一任务类型在两个市场都能跑
  • 数据 Provider 失败降级路径覆盖

M5 主动信号(铺面 · 核心循环最小切片已前移 M2)

frame 注(2026-06-04 矫正):主动信号的核心循环(失效条件触及 → 自主发起复盘)的最小切片已在 M2 端到端打通(见 M2 范围 / 验收)。M5 不再是「第一次出现 agent 自主循环」的里程碑,而是把该能力铺面到生产级:真实定时调度(heartbeat / cron 替代 M2 的手动 tick)、批量触发、多渠道投递。这条调整是 §25 头部 frame 重定位的落点之一。

范围

  • Judgment Record 的失效条件被市场触及时自动触发新一轮认知核心已前移 M2)→ M5 升级为:heartbeat / cron 真实定时驱动 + 批量扫描所有到期 / 临界 Judgment Record(承接 §6 场景 S10)+ skip/run 结构化判定抗噪
  • Channel Adapter 选其一(推荐 Telegram,最简单)

覆盖章节增量

  • §10 S4 关注流 sequence → 完整
  • §9 Input Pipeline → Channel 入口完整
  • §13 主动信号触发的批量任务

M5 验收

  • 失效条件触及 → 5 分钟内 Channel 投递 + 落审计
  • 投递失败重试 + 用户可在 Web 复盘

M6 评估闭环

范围

  • Eval Set 第一版(冒烟 + 回归 + 抗扰)
  • LLM-as-judge 工程
  • nightly 真档评估

覆盖章节增量

  • §20 测试体系 → 完整四层
  • §21 评估闭环 → 完整闭环

M6 验收

  • 评估能在 nightly 跑完 + 报告生成
  • 历史失败 case 进入回归集 + 不再回归
  • 评估软阈值跑通

M7 演化能力

范围

  • Schema migration 真实演练(v1 → v2 测试)
  • Prompt 版本化(ADR-009 落地)
  • Provider 退役 / 工具退役流程演练

覆盖章节增量

  • §19 演化与版本管理 → 完整
  • §22 缺口管理 → 工程承接到位

M7 验收

  • Schema migration 跑通 + 回滚演练成功
  • Prompt 版本切换可观测 + 评估关联
  • 一次 Provider 退役完整走完流程

里程碑间的依赖与并行

里程碑必须前置可并行
M0
M1M0
M2M1
M3M1(不依赖 M2)M2
M4M2M3
M5M2 + M3M4
M6M2M3 / M4 / M5
M7M6

里程碑工作流落地(呼应 ADR-003)

每个里程碑按 OpenSpec + Archon + Claude Code 主控 + Codex 实施的协作模式(详见 ADR-003):

阶段谁做产物
SpecClaude CodeOpenSpec 提案:task packet + 数据结构 diff + 验收口径 + 与本架构文档章节追溯
实施Codex(在 git worktree)代码 PR + 测试 + 文档更新
ReviewClaude Code跑确定性 gate + 跨文档一致性 + 出 review report
认知质量评估工作流维护者 + 跨 Agent 模拟评估报告
Merge + 移交Claude Code提案进 accepted + 更新 status

关键约束:每个里程碑的 OpenSpec 提案必须显式追溯到本架构文档的章节(如 "M1 实施 §11 / §15 增量 + ADR-007 决策")。


与其他章节的关系

  • 工程范式来源 → ADR-001
  • 工程实施栈与协作 → ADR-003
  • 战略保真度 review gate → §3 / §17
  • 契约回归依据 → §19 演化与版本管理
  • 认知质量评估方法 → §21 评估闭环
  • 每里程碑审计点 → §26 审计点
  • 代码物理位置 → §27 代码仓位置映射

26. 审计点

字段权威定义见 contracts/state-machines.yaml(Step 11 整改包 I 单一事实源层)。本段为叙述用途,若与 contracts/ 不一致以 contracts/ 为准。承接 Step 11 整改方案

这一节回答:每个里程碑的 review gate 具体审计什么?审计动作的标准动作是什么?谁来执行?

三检审计 + 四类断言

ADR-001 定义"每个里程碑过三检 review gate"。本章把"三检"展开为可执行的具体审计动作。

三检

检查项含义
战略保真度审计工程产物未引入战略禁入概念 / 未违反战略边界
契约回归审计与上一里程碑的接口契约向后兼容(major 升级除外)
认知质量审计当前里程碑范围内的认知输出符合质量目标

四类断言

每检由若干可执行断言组成,分四类:

类别检查方式自动化程度
机械断言脚本 / grep / 静态分析完全自动(CI 跑)
结构断言schema 校验 / 类型检查 / 依赖图完全自动
样本断言在评估数据集上跑 + 指标阈值半自动(运行自动,判断需人复核)
语义断言人工审查(PR / spec / 文档一致性)人工

战略保真度审计动作

机械断言

断言实现通过条件
禁词不命中verify-kb.mjs 含 banned-concept grep全部 0 命中(或仅在拒绝清单列举段)
战略原句存在grep 关键句(如"FinBayes 不直接下单"在文档中存在)至少一处命中
凭证字段不在数据 schemagrep private_key / mnemonic / api_secret 等字段名0 命中(白名单:边界 hook 测试 fixture)
执行类工具 category 不在 Capability Registry静态分析工具注册代码0 个 category=execution 的工具
TLS 强制grep http://(非 localhost)在 Provider 配置0 命中

结构断言

断言实现
综合层输出 schema 含反方 / 风险 / 失效条件三字段Pydantic schema 校验
工具 schema 含 category 字段 + 严格枚举OpenAPI / JSON Schema 校验
审计 trail 字段无凭证类列DB schema 静态检查

语义断言

断言谁做
同义改写未绕过禁词(如"行动判断"改写为"行动倾向")Claude Code Review
输出契约语义未偷偷弱化Claude Code Review + 工作流维护者复核
战略不变量未被"工程方便"理由削弱工作流维护者裁决

战略保真度阻断条件

战略保真度审计任何一条机械断言失败 = 阻断 merge。语义断言失败 = 进 review 反馈循环。


契约回归审计动作

机械断言

断言实现
既有接口的字段未被删除OpenAPI diff
既有字段类型未变更Pydantic schema diff
既有错误码语义未变错误码字典 diff
contract_version 正确递增Git diff + 版本规则校验

结构断言

断言实现
数据库 schema 仅增加字段或新表SQL DDL diff
State Store schema_version 与代码期望版本匹配启动期检查
删除字段前的 deprecated 标记存在至少一个 minor 版本Git 历史扫描

样本断言

断言实现
上一里程碑的样例请求在当前里程碑仍能正常处理跑上一里程碑的端到端测试 fixture
既有审计 trail 在新版本下可读加载历史审计文件 + 校验

契约回归阻断条件

契约回归审计任何机械 / 结构断言失败 = 阻断 merge。样本断言失败 = 看是否有合理升级路径(如已 deprecated 一版本)。


认知质量审计动作

详细方法见 §21。这里聚焦里程碑级的审计动作

样本断言

断言实现
当前里程碑范围的冒烟集全过评估运行器跑 + 阈值校验
回归集无新增失败评估运行器跑 + 对比上一里程碑结果
抗扰集(边界 case)无新增失败评估运行器跑
Self-consistency 高风险任务的分歧度未上升指标对比

语义断言

断言谁做
输出反方覆盖未削弱(如"反方质量"维度未下滑)工作流维护者 + 跨 Agent 模拟视角
表达密度匹配画像(不过密 / 不过疏)工作流维护者抽样
信息缺口处理诚实(没数据时不硬编)工作流维护者抽样

认知质量阻断条件

  • 回归集失败 = 阻断 merge(硬阈值)
  • 抗扰集失败 = 阻断 merge(边界相关,等同硬阈值)
  • 冒烟集软阈值下降 >5% = warn + 必须 PR 描述里说明原因
  • 语义断言不通过 = 进 review 反馈循环

各里程碑的审计点

M0 走通骨架审计

审计项通过条件
战略保真度全部机械断言 + 全部结构断言通过
契约回归建立基线(M0 是基线 → 无前置对比)
认知质量5 条样例跑通 + 包含反方 + 失效条件 + 题眼命中
边界5 类凭证样式输入 100% 拒收
审计 trailtask_id 贯穿 + Provider 调用链完整

M1 状态化审计

审计项通过条件
战略保真度同 M0 + 用户主权 5 维度全部可用
契约回归M0 baseline 100% 兼容
认知质量候选 → 已确认两步路径可被评估观测
状态机6 个状态机的所有转移都有测试

M2-M7 审计

每个里程碑的具体审计点在 OpenSpec 提案中由 Claude Code 起草,遵循"机械 + 结构 + 样本 + 语义"四类断言模板。


审计执行模型

这张图表达什么:每个 PR 走机械 + 结构断言(CI 自动)+ 样本断言(评估运行器)→ 人工 review 语义断言 → merge。所有审计结论进入审计记录。

这张图特意不表达什么:每条审计的具体工具实现(在工程实施仓 CI 配置);审计争议的仲裁流程(在 governance/change-protocol.md)。


审计的可观测性

审计自身需要可观测:

维度实现
每次审计的结论进 release notes + 审计 trail
责任人PR review 字段 + 审计记录
时间自动记录
阻断历史哪些断言曾经阻断过 + 解决路径
审计 SLA每个里程碑的 review 应在 X 工作日内完成(不是软指标,是流程承诺)

审计 vs 测试 vs 评估的关系

维度测试(§20)评估(§21)审计(本章)
触发每次 PR + nightly周期 + release每个里程碑
对象业务正确性 / 协作 / 边界认知质量 / 趋势里程碑产物整体
通过assert + 覆盖率指标 + 阈值三检通过
负责工程实施 Agent评估运行器 + 工作流维护者Claude Code Review + 工作流维护者

测试与评估是审计的输入证据。审计是更高层的"这一刻这一切是否能合并到主分支"的综合判定。


审计的边界

审计不替代

  • 战略层的决策(战略变更走 governance/change-protocol.md)
  • 工程实施的细节决定(PR 描述中说明)
  • 用户的真实使用反馈(在线评估信号)

审计就只做三件事:

  1. 这次里程碑产物是否符合战略边界(保真度)
  2. 这次里程碑产物是否破坏既有用户(契约回归)
  3. 这次里程碑范围内认知质量是否未退化

与其他章节的关系

  • 三检 review gate 来源 → ADR-001
  • 工程协作模式 → ADR-003
  • 战略不变量与禁入概念 → §2 / §17
  • 契约版本化策略 → §19
  • 评估测试方法 → §21
  • 里程碑切片 → §25 与里程碑/任务的对应
  • 代码层审计点的物理位置 → §27 代码仓位置映射

27. 代码仓位置映射

字段权威定义见 contracts/code-paths.yaml(Step 11 整改包 I 单一事实源层,src/finbayes/* + evals/)。本段为叙述用途,若与 contracts/ 不一致以 contracts/ 为准。承接 Step 11 整改方案

这一节回答:本架构文档的概念在 FinBayes 工程实施仓里的物理位置是什么?章节里的"子系统 / 工具 / 状态对象 / Prompt"具体落在哪个目录哪个模块?

工程实施仓与本仓的关系

角色内容
本仓(Labs-FinTecAI)知识库 + 治理库战略 / 架构 / ADR / 提案 / 调研
FinBayes 工程实施仓工程代码 + 测试 + 运行配置runtime / 工具实现 / 测试 / CI / 部署脚本

两仓严格分离(详见 CLAUDE.md "工程执行产物不进本仓")。本架构文档(本仓)是契约事实源,工程实施仓的代码必须追溯到本架构文档某章节。

工程实施仓的物理路径由工作流维护者维护,不写入本仓(路径约束详见本仓 CLAUDE.md)。本章用抽象路径表达映射,工程实施仓内的实际目录名按 Python 项目惯例。


顶层目录约定

工程实施仓采用 Python 标准 src layout

finbayes/ # 工程实施仓根
├── src/finbayes/ # 主代码(包根)
├── tests/ # 测试
├── evals/ # 评估数据集 + 评估运行器
├── prompts/ # Prompt 资产(YAML / 模板)
├── migrations/ # State Store schema migration 脚本
├── configs/ # 配置模板(用户实际 config 在 OS 用户目录)
├── scripts/ # 工具脚本(备份 / 诊断 / 等)
├── docs/ # 工程实施仓自己的运维文档(不重复本仓)
└── .github/ or .ci/ # CI 配置

关键约定

  • 业务代码全部在 src/finbayes/(不在仓根散落)
  • 测试与代码 1:1 镜像(tests/test_<module>.py
  • 评估资产与测试分开目录(评估是独立的运行模式,详见 §21)

子系统映射(§9 6 子系统)

子系统抽象路径关键模块
Input / Output Pipelinesrc/finbayes/io/entries/(CLI/TUI/WebAPI/MCP/Channel 各子模块)/ boundary.py(边界 hook)/ normalize.py(输入归一化)/ formatter.py(输出格式化)/ stream.py(流式输出)
Task Orchestrationsrc/finbayes/orchestration/task.py(task 对象 + 生命周期)/ dispatcher.py(任务分发)/ function_calling.py(LLM Function Calling 集成)/ clarify.py(clarify 工具)
Evidence + Synthesissrc/finbayes/cognition/evidence/(证据归一化 + EvidencePacket)/ synthesis/(综合层)/ self_consistency.py(多采样)/ schema.py(输出契约)
State Managementsrc/finbayes/state/store.py(State Store 抽象)/ session.py / watchlist.py / judgment.py / profile.py / candidate.py(两步写入)/ audit.py(审计 trail)
Capability Registrysrc/finbayes/capabilities/registry.py(工具注册 + 校验)/ tools/(各工具实现的子目录)/ schema.py(工具元数据)
Provider Adapter Poolsrc/finbayes/providers/adapter.py(统一接口)/ llm/(OpenAI compatible / Anthropic / DeepSeek / Ollama / 等)/ data/(外部数据 Provider)/ readiness.py(探测)/ routing.py(task_routing)

业务对象映射(§4 7 个 First-Class 概念)

概念Pydantic 模型路径持久化表
Sessionsrc/finbayes/state/session.py:Sessionsessions
Watchlistsrc/finbayes/state/watchlist.py:Watchlistwatchlist_objects
Judgment Recordsrc/finbayes/state/judgment.py:JudgmentRecordjudgment_records
Dynamic Profilesrc/finbayes/state/profile.py:DynamicProfiledynamic_profiles
State Candidatesrc/finbayes/state/candidate.py:StateCandidatestate_candidates
Fin Objectsrc/finbayes/state/fin_object.py:FinObjectfin_objects
Tasksrc/finbayes/orchestration/task.py:Task(内存为主 + 审计 trail)

关键约束

  • 业务对象 schema 用 Pydantic v2(详见 arch-rewrite/ADR-008 accepted;该 ADR 是 LLM Provider 接口抽象。StructuredCognitionResult 字段定义见 whitepaper-rewrite/ADR-008 supplement accepted)
  • schema 字段变化必须走 §19 演化策略
  • 业务对象互引用通过 ID(不直接嵌入对象,避免循环 ref)

状态机映射(§11 6 个状态机)

状态机实现位置
Session 生命周期src/finbayes/state/session.py:SessionState
Task 生命周期src/finbayes/orchestration/task.py:TaskState
TaskGroup 生命周期src/finbayes/orchestration/task_group.py:TaskGroupState
Judgment Record 生命周期src/finbayes/state/judgment.py:JudgmentState
State Candidate 生命周期src/finbayes/state/candidate.py:CandidateState
Provider Readinesssrc/finbayes/providers/readiness.py:ProviderReadinessState

Fin Object 与 Watchlist 没有独立状态机(详见 §11 开篇说明)—— Watchlist 状态由 StateCandidate + watchlist_objects 表承载,Fin Object 仅 created/archived 标记。


数据存储映射(§15 5 类数据)

数据类别物理位置实现模块
State StoreOS 数据目录 SQLite 文件src/finbayes/state/store.py + migrations/
CacheRedis 或内存 LRUsrc/finbayes/cache/
Config StoreOS 配置目录 YAMLsrc/finbayes/config/
Credential StoreOS Keychainsrc/finbayes/security/credentials.py
Audit TrailSQLite 同库不同表src/finbayes/state/audit.py

关键约束

  • 用户实际数据不在工程实施仓 —— 仓内只有 schema 与代码,运行时数据在用户机器的 OS 标准目录(§14)
  • migrations/ 内的脚本编号严格递增(如 001_initial.sql / 002_add_audit_trail.sql

通信协议映射(§16)

协议层实现位置
进程内(Python 调用)各子系统间直接 import
CLI 入口src/finbayes/io/entries/cli/
TUI 入口src/finbayes/io/entries/tui/
Web API + WebSocketsrc/finbayes/io/entries/web/
MCP Serversrc/finbayes/io/entries/mcp/
Channel Adaptersrc/finbayes/io/entries/channels/(按平台分子目录)
LLM Provider HTTPsrc/finbayes/providers/llm/ 各 adapter

边界与安全映射(§17)

约束实现位置
输入边界 hooksrc/finbayes/io/boundary.py
凭证识别规则src/finbayes/security/credential_patterns.py
输出端凭证样式扫描src/finbayes/io/output_filter.py(arch-rewrite/ADR-010 accepted,规则见 ADR-010 §3)
执行类工具注册拒绝src/finbayes/capabilities/registry.py:register_tool
用户数据隔离(user_id)src/finbayes/state/store.py 查询层
TLS 强制src/finbayes/providers/http_client.py

可观测性映射(§18)

资产位置
审计 trail 写入器src/finbayes/state/audit.py
Task trace ID 管理src/finbayes/orchestration/trace.py
指标采集src/finbayes/observability/metrics.py
用户视角 CLI 命令src/finbayes/io/entries/cli/commands/(含 status / trace / audit / cost / session
日志分级与脱敏src/finbayes/observability/logging.py

Prompt 资产映射(§19 + ADR-009 待)

混合策略下的路径约定:

Prompt 类型位置
System Prompt(策略 A 进代码仓)prompts/system/
任务模板(策略 A)prompts/task_templates/(按任务类型分)
输出契约 schema 关联 prompt(策略 A)prompts/synthesis/
实验性 Prompt(策略 B)prompts/experimental/ + 自描述 delivery_mode: data 字段
Judge Prompt(评估专用)prompts/eval_judges/

关键约束

  • 每个 Prompt 文件有 frontmatter:prompt_id / prompt_version / delivery_mode / author / activated_at
  • 策略 A Prompt 进 Git diff + Review gate 覆盖
  • 策略 B Prompt 在 runtime 启动时加载 + 进审计 trail

测试资产映射(§20)

测试类型位置
单元测试tests/unit/(与 src/finbayes/ 镜像)
集成测试tests/integration/
端到端测试(快档 Mock)tests/e2e/quick/
端到端测试(真档真 LLM)tests/e2e/real/
降级路径测试tests/degradation/
边界与安全测试tests/boundary/
LLM Mock fixturetests/fixtures/llm/
测试用业务对象 fixturetests/fixtures/state/

评估资产映射(§21)

评估资产位置
评估数据集(冒烟 / 回归 / 场景 / 抗扰)evals/datasets/(按层分子目录)
评估运行器evals/runner/
Rubric 定义evals/rubrics/
Judge Promptprompts/eval_judges/(与 prompts 共享)
评估结果库(运行时,不在仓)evals/results/(gitignore)
评估报告模板evals/reports/

CI 集成映射

CI 阶段实现
PR:单元 + 集成 + 端到端快档 + 边界 + verify-kb.ci/pr-pipeline.yml
Nightly:含真 LLM + 评估.ci/nightly.yml
Release:完整评估 + 性能基线.ci/release.yml
战略保真度审计脚本scripts/audit_strategy_fidelity.py
契约回归审计脚本scripts/audit_contract_regression.py

配置文件映射(§14 + §15)

工程实施仓内只有模板 —— 用户实际配置在 OS 用户目录:

配置模板位置(工程实施仓)运行时位置(用户机)
config.yamlconfigs/templates/config.yamlOS 配置目录(按平台,§14)
providers.yamlconfigs/templates/providers.yaml同上
task_routing.yamlconfigs/templates/task_routing.yaml同上
ui.yamlconfigs/templates/ui.yaml同上

部署与运行脚本映射

脚本位置
finbayes 入口(CLI)src/finbayes/__main__.py
安装引导(首次初始化)src/finbayes/install/wizard.py
备份与恢复scripts/backup.py / scripts/restore.py
诊断打包scripts/diagnostic.py
Schema migration runnermigrations/runner.py

章节到代码的反向追溯

工程实施仓的代码反向追溯到本架构文档:

机制实现
每个 PR 的描述必须显式引用 CHAP-NN / ADR-NNNOpenSpec 提案要求
每个 module 的 docstring 含章节引用工程实施约定
每个 ADR 的"关联"段含反向 CHAP 列表ADR 模板
章节追踪表(status.md)随实施进展更新工作流维护者职责

工程实施仓的代码不进本仓

关键边界

  • 工程实施代码不进本仓(即使是示例代码段在文档里也只用伪代码 / schema)
  • 运行时数据 / 用户配置 / Controller state / task packet 不进本仓
  • 工程实施仓的本地路径不写入本仓的任何文档(详见本仓 CLAUDE.md)

工程实施仓的物理路径由工作流维护者在本地记录(用户级 memory),不进本仓。


与其他章节的关系

  • 子系统职责定义 → §9 子系统组件
  • 业务对象定义 → §4 业务对象与关系
  • 状态机定义 → §11 状态对象生命周期
  • 数据存储定义 → §15 数据存储划分
  • 通信协议定义 → §16 通信协议
  • 边界与安全约束 → §17 边界与安全
  • 可观测性资产 → §18 可观测性
  • 演化资产 → §19 演化与版本管理
  • 测试资产 → §20 测试体系
  • 评估资产 → §21 评估闭环
  • 工程协作 → ADR-003 工程实施栈与协作
  • 里程碑产出 → §25 与里程碑/任务的对应
  • 审计点 → §26 审计点

28. M0 工程包(附录)

这一节回答:M0 走通骨架实施所需的字段级 schema、Pydantic 模型、SQLite DDL、CLI 规格、Mock fixture、凭证正则、audit payload schema、bootstrap 模板、CI 模板等"工程材料"在哪里?

M0 工程包独立成 task-oriented 文档

M0 走通骨架实施所需的全部工程材料不在主架构文档中展开,而是集中在独立的 task-oriented 文档:

projects/finbayes/engineering/engineering-packs/m0-walking-skeleton.md

该文档专为工程化落地 Agent(Codex / Claude Code)一次性 load + 直接消费而设计,含 15 节:

§内容
§1M0 范围与 walking skeleton 链路
§2M0 接口子集表(6 子系统 × implement/stub/skip = 34 个签名固定的接口)
§3M0 核心 Pydantic 模型 v0(5 个 types.py 完整代码 + placeholder 类型节)
§4M0 SQLite DDL v0(4 张业务表 + 1 张元表,含 PRAGMA / 索引)
§5AuditEvent.payload 按 event_type 字段集(10 种 event 的 schema)
§6M0 CLI 命令规格(5 命令 + 流式输出 + JSON 输出 + 6 个退出码)
§7M0 Mock Provider Fixture 规范(目录 + hash 算法白名单 + Provider API 变化检测)
§8M0 5 条样例输入 + 期望"能力清单"(含可 eval 的 pytest_check 表达式)
§9M0 5 类凭证 Negative Test Fixture(含 expected_reject_category 与 confidence)
§10凭证识别正则基线 v0(5 类 Python pattern + BIP-39 词表 source + Luhn 算法)
§11M0 输出判定规则 v0(不依赖 LLM-as-judge,退化为 Pydantic + 人工 5 条 checklist)
§12工程实施仓发现路径协议(OpenSpec task packet 必备字段)
§13工程实施仓 Bootstrap 模板(pyproject + 工具链 + uuid4 + Pydantic ConfigDict + Exception 类层级 + 日志脱敏)
§14M0 三检 Review Gate CI 模板
§14.5CI 接口规范(7 个未提供脚本/测试的接口定义)
§14.6M0 baseline 文件位置与格式
§15与主架构 / ADR 的承接

约 1640 行,工程实施 Agent 可一次 load。

为什么独立成文件

理由说明
上下文负担主架构 6500 行 + M0 工程包 1600 行 合并为 8000+ 行,工程实施 Agent 一次性 load 占 75-85% context,多文件操作易爆
task-oriented vs architecture-oriented主架构是"FinBayes 是什么"(业务建模 + 系统全景 + 横向贯穿),M0 工程包是"M0 怎么做"(task packet 级别的可执行材料),消费路径不同
与 ADR-001 / ADR-003 范式一致Walking Skeleton + 里程碑切片 + OpenSpec task packet —— 每个 milestone 一个独立工程包是范式的自然映射
演化路径清晰M1-M7 各起独立工程包(m1-state-confirmation.md 等),不污染主架构

Agent 消费路径

Agent 任务应 Load 的文档
M0 实施engineering-packs/m0-walking-skeleton.md + 主架构 §17(边界)+ 主架构 §27(代码仓位置)作 cross-check
架构 Review / 战略保真度审计主架构全文
ADR 起草主架构 §23 + 相关章节 + 调研产物
M1+ 实施(未来)对应 engineering-packs/m{N}-*.md + 主架构横向贯穿章节

后续里程碑工程包(待起草)

里程碑工程包文件状态
M0 走通骨架engineering-packs/m0-walking-skeleton.md✅ 已起草
M1 状态化(候选两步写入 + 完整 8 表)engineering-packs/m1-state-confirmation.md待起草
M2 任务类型扩展(复盘 + 关注流 + clarify)engineering-packs/m2-task-types.md待起草
M3 入口扩展(TUI + Web API)engineering-packs/m3-multi-entry.md待起草
M4 市场扩展(US Stocks)engineering-packs/m4-market-extension.md待起草
M5 主动信号(失效条件触发 + Channel)engineering-packs/m5-proactive-signal.md待起草
M6 评估闭环(LLM-as-judge)engineering-packs/m6-eval-loop.md待起草
M7 演化能力(migration + Prompt 版本化)engineering-packs/m7-evolution.md待起草

横向贯穿关注点(边界 / 可观测性 / 演化)的工程切片合订:engineering-packs/horizontal-concerns-bundle.md(待起草)。

与其他章节的关系

  • M0 范围与 walking skeleton 链路上位 → §25 与里程碑/任务的对应
  • 三检 Review Gate 上位 → §26 审计点
  • 业务对象 Pydantic 模型上位 → §4 业务对象与关系
  • 子系统接口上位 → §9 每个子系统的内部组件
  • 状态机定义上位 → §11 状态对象生命周期
  • 数据存储 DDL 上位 → §15 数据存储划分
  • 凭证识别策略上位 → §17 边界与安全
  • 审计 trail 上位 → §18 可观测性
  • 测试体系上位 → §20 测试体系
  • 代码物理位置上位 → §27 代码仓位置映射

29. 认知体系工程承接(4 子系统索引)

字段权威定义见 contracts/mca-buckets.yaml / contracts/evaluation-dimensions.yaml / contracts/structured-cognition-result.yaml(Step 11 整改包 I 单一事实源层)。本段为叙述用途,若与 contracts/ 不一致以 contracts/ 为准。承接 Step 11 整改方案

这一节回答:ADR-007 supplement 锁定的金融认知体系第一版正式构成(8 机制 + MCA 7 分轴 + S1 跨机制子流程 + 11 维评测 + Phase 5 治理)与 ADR-008 supplement 锁定的 StructuredCognitionResult 1.0 → 1.1 机制层输出契约扩展,在 L3 架构层由哪些子系统承接。

上位 ADR-007 supplement 状态为 accepted(持续构建),v2 触发条件见 supplement Phase 5 治理段;本节 L3 承接同步保留「持续构建」状态语义,不得在工程化期间衰减为「已锁」。

这一节做什么

本节只放索引段。4 个子系统的职责定义 / 接口契约 / 数据流 / 关键依赖 / 测试要求 / v1 工程回退 / 待解决问题 / 跨子系统接口对齐在 认知体系工程承接子系统目录 的 4 份独立文档展开。

本节不重写既有 §9 六子系统章节,新增 4 子系统与既有 6 子系统正交:

  • 既有 6 子系统(§9 每个子系统的内部组件):通路层(输入 → 编排 → 证据综合 → 状态 → 工具 → Provider)。
  • 本节新增 4 子系统:认知层(图谱 / 一致性中间件 / 上下文分类 / 评测)。

4 子系统索引

子系统承接的认知体系组件核心输出工程文档
KnowledgeGraphServiceM1 关系建模含跨市场映射边 + M3 phase 时钟 + M5 制度摩擦传导 + M6 资本结构与货币双轨causal_graph(含 correlation_regime)+ phase_evidence(含 phase_matrix知识图谱服务
ConsistencyMiddlewareS1 跨机制子流程(4 失败模式 a/b/c/d + attention 二阶分支 + 回路收敛 N=3 + 反向触发)s1(8 字段输出)一致性中间件
MCAClassifierMCA 7 分轴(B1-B7 含 B5a/B5b 拆分 + 影响下游机制参数选择)Task schema 元数据 mca_bucket(不进 StructuredCognitionResult 本体)市场上下文分类器
EvalHarness11 维评测 + 7 MCA 桶 + 70/20/10 三集 + IAA kappa 门槛 + 半人工标注 SLA + 退化追踪离线评测报告 + Phase 5 治理触发信号评测台架

与上位事实源的 cross-reference

跨子系统依赖关系

这张图表达什么:4 子系统的输入输出依赖。MCAClassifier 是横切强先验提供方,KnowledgeGraphService 与 ConsistencyMiddleware 协同产出 StructuredCognitionResult 1.1 的 6 个新顶层字段,EvalHarness 离线消费全量结果并反向触发 Phase 5 治理的子机制级修订。

这张图特意不表达什么:与既有 §9 六子系统(Input/Output Pipeline / Task Orchestration / Evidence + Synthesis / State Management / Capability Registry / Provider Adapter)的协作时序。两层正交,时序流转见每份子系统文档的「数据流」段。

与既有章节的关系

本节边界

本节是索引段,不重写既有架构章节。后续 v1 实现路径建议:

  1. M0 阶段以最小子集落地(参见 ADR-008 supplement §5.2):phase_evidence.clocks / causal_graph.nodes + causal_graph.edges 主体 / applicability_flags 三支柱 level + reason / posterior.mode_a + posterior.mode_b / s1.s1_mode + s1.coupling_direction + s1.confidence / mca_bucket 七轴 + bucket_label
  2. M1–M3 里程碑逐步补齐剩余子字段(含 phase_matrix.cells / correlation_regime.pair_correlations / s1.second_order_branch / regulation_status.friction_layer 等)。
  3. 半人工标注 SLA 落地(任务 A / B / C / D reviewer 工作流 24 小时 SLA)由 Phase 7+ 承接。
  4. v1 → v2 升级路径走 Phase 5 治理流程(≥ 4 case 跨 ≥ 2 桶 + ≥ 1 pending 桶证据)。
  5. 主架构防膨胀硬约束:见 主架构膨胀守门机制(≥ 80 行新增强制拆出指针段;M0 收尾按 5% / 10% 阈值复盘)。

Changelog / 演化记录

2026-06-04(kelly_cap 退役传播补扫 · 收尾确认 · 落实 ADR-021 · kelly_cap 退役):§29 M0 最小子集落地清单中的 kelly_cap 字段名引用已移除——不确定性仍由双峰重尾后验(posterior.mode_a / posterior.mode_b)承载,仅「凯利仓位上限」这个字段形态随 ADR-021 退役。连带补净 产品定义 §7.3 posterior 行残留的「凯利上限」措辞(ADR-021 原传播与实现侧补扫均漏覆盖 product-definition)。留 owner 处理(本次未擅自改):eval-harness §D6 的 C_kelly/凯利合规率权重重归一属评测契约决定,留 FinTecEval / owner;contracts/tasks-fields-mapping.yamlkelly_cap_policy 属权威契约层、由 owner 统一处置(contracts/field-surface-mapping.yamlblock_tokenskelly_cap 为「拦截退役 token」的正确兜底,应保留)。

2026-06-04(阶段 0 文档矫正 · (A) 类 frame 段 · 依据金融真智能体骨架蓝图(E)#2 + owner 议定结果):把架构层的 FinBayes 定性从「越往下游越退化成单次问答函数」矫正回「带自主循环的认知 agent」。①§2 新增 identity 级架构不变量「FinBayes 产品本体是带自主循环的认知 agent,主动信号 / 自主复盘循环是 identity 级能力、不是晚期里程碑增量功能」+ 快速核查补第 5 条;②§5 认知流转主线图从「以『用户是否沉淀』为可选支路」改为「agent 默认闭环」(自主监控循环为常开骨架、单回合问答为入口之一);③§6 场景集补 S10/S11/S12 三个 agent 自主行为场景,把被动:主动配比从 8:1 纠正为 8:4;④§9.2 Task Orchestration 加 frame 说明「单回合编排 + 主动信号触发器 = agent 的两个半」;⑤§25 里程碑头号偏移矫正:旧序把 agent 循环本体(主动信号)排到 M5,本次非破坏插入——最小自主循环切片前移到 M2(M1 备状态基础 + M2 端到端闭环 + agent 行为门首要验收),M5 退化为铺面(cron / Channel / 批量),并标注 M0–M4 为已知 pre-agent 阶段、agent 建造以蓝图阶段序为准、全量重编号为 owner 治理连带项(遵循 ADR-016 非破坏插入先例)。注:§29 line M0 最小子集仍含 kelly_cap 字段名(ADR-021 已退役),属 ADR-021 传播遗漏、非本次 frame 矫正范围;已落实:见本节顶部同日「kelly_cap 退役传播补扫」条目。

2026-05-29:清理 §21 评测体系中的旧 8 维 rubric 事实源漂移——把已被 11 维 D1-D11 取代的 v1 8 维 rubric 表显式标记为 DEPRECATED,明确指向权威事实源 contracts/evaluation-dimensions.yamlEval Harness 11 维评分公式(D1-D11),保留旧表作为 v1 演化历史上下文但移除其作为评分契约的语义。