跳到主要内容

StructuredCognitionResult 1.1 契约源

§0 范围与定位

本文件是 ADR-008 supplement 锁定的 StructuredCognitionResult 1.1 工程契约的单点 Pydantic schema 派生源。事实源是 ADR-008 supplement 机制层输出契约扩展;本文件做工程化派生(字段表 + enum 清单 + 字段间约束 + Pydantic v2 草案),方便 EvalHarness M0 schema 实施任务一次 load。字段语义、触发条件、机制间反向耦合、回路收敛上限以 ADR-008 supplement 为准;本文件不复述机制定义,仅以「来源 §N.M」回引。

正向语义读法(ADR-013 Build-Y over Prevent-X):本契约不是「一堆字段表 + 一堆禁令」。每个子模型 / 字段先回答「这字段产出什么用户价值(产出意图)」,约束挂在意图之下——约束是为了保住那份价值,不是凭空列禁令。§2 每个子模型段开头标注 「产出意图」;阅读时先读意图,再读字段表与 §4 约束。

§1 顶层契约(StructuredCognitionResult)

字段类型默认必选来源
structured_result_versionLiteral["1.1"]"1.1"必选§2 开篇
10 要素字段(1.0 主体 inline)main_answer / supporting_evidence / multi_perspectives / counter_evidence / prerequisites / invalidation_conditions / uncertainty_and_gaps / sources / follow_up_questions / historical_judgment_links见 §5 StructuredCognitionResultV10Body必选ADR-008 主体 + product-definition §7
phase_evidencePhaseEvidence | NoneNoneM3 启用必选§2.1
causal_graphTransmissionGraph | NoneNoneM5 启用必选§2.2
regulation_statusRegulationStatus | NoneNoneMCA 轴 3 = F2/F3 必选§2.3
applicability_flagsApplicabilityFlags | NoneNoneM6 启用必选§2.4
posteriorBimodalPosterior | NoneNoneM7.uq 启用必选§2.5
s1NarrativeNumberConsistency必选(横切)§2.6

Task schema 元数据 mca_bucket: MCABucket 必选;不进入 StructuredCognitionResult 本体(§2.7)。

10 要素的产出意图(1.0 主体,product-definition §7):每个要素先回答它给用户什么价值——

  • main_answer = 让用户第一屏就看到「结论 / 倾向」(非指令式,是认知材料)。
  • supporting_evidence = 让用户看到「凭什么这么判断」的依据,可自行核验。
  • multi_perspectives = 让用户看到「同一件事还有哪些看法」,不被单一视角锚定。
  • counter_evidence = 让用户主动看到「反方证据」,对冲确认偏误(空也要明示理由)。
  • prerequisites = 让用户看清「这判断在什么前提下才成立」。
  • invalidation_conditions = 让用户拿到「什么情况下该推翻这判断」的可证伪触发器(强约束非空:没有失效条件的判断不可发布)。
  • uncertainty_and_gaps = 让用户看到「哪里还不确定 / 信息有缺口」,而非伪装全知。
  • sources = 让用户看到来源与时间戳,判断时效与可信度。
  • follow_up_questions = 给用户「可以继续追问什么」的入口,把单次问答变成可深入的探究。
  • historical_judgment_links = 让用户回看「过去相关判断」,形成可追溯的判断链。

§2 子模型字段表

§2.1 PhaseEvidence + ClockPhase + ClockPhaseMatrix(来源 §2.1)

产出意图:让用户看到「现在处在市场周期的哪一段、各时钟是否相互矛盾」,而不是只给一个孤立的涨跌判断。下面的字段与约束都服务于「周期位置可被复盘、矛盾被显式标注」这份价值。

PhaseEvidenceclocks: list[ClockPhase](M3 不激活为 [])/ phase_matrix: ClockPhaseMatrix | None(综合层产;M3 不激活为 None)。

ClockPhaseclock_id: str(取值 M3.t1M3.t9)/ phase_label: str(机制自定枚举 late-debt / growth / speculative / hedge / ponzi 等)/ confidence: float ∈ [0,1] / evidence_ref: str

ClockPhaseMatrixaxes: list[str](N ≤ 9)/ cells: list[list[CellLabel]](CellLabel 见 §3)/ contradictions: list[ContradictionEntry]

ContradictionEntryaxes: list[str] / type: str / severity: Literal["low","medium","high"]

§2.2 TransmissionGraph + 子结构(来源 §2.2)

产出意图:让用户看到「钱 / 风险从哪传导到哪、哪条路径有反向力量、相关性是否进入尾部联动」,而不是只给一个静态的相关系数。correlation_regime 服务于「让用户在尾部联动 / 制度切换时被提前提醒」这份价值。

TransmissionGraphnodes: list[Node] / edges: list[Edge] / reverse_forces: list[ReverseForce] / endogeneity: dict[str, Literal["endogenous","exogenous"]](按 edge_id 键)/ correlation_regime: CorrelationRegime(M5 启用必选;regime_label 至少 normal)/ unbalanced_loop_warnings: list[UnbalancedLoopWarning]

Nodeid: str / object_ref: str / node_type: Literal["entity","relation","attribute"]

Edgeid: str / from_node: str / to_node: str / edge_type: Literal["causal","reflexivity","shared-book","institutional-friction","cross-market-mapping"] / form: str | None(shared-book 四形态 acute-liquidity / structural-holder-rotation / policy-credit / a-share-retail-acute)/ path_confidence: float ∈ [0,1] / translation_loss: float ∈ [0,1]

ReverseForceedge_id: str / force_type: Literal["arbitrageur","policy-hedge","liquidity-supplier","fundamental-reverter","structural-flow"] / evidence_ref: str

CorrelationRegimeregime_label: Literal["normal","tail-coupled","regime-switched"] / pair_correlations: list[PairCorrelation] / regime_shift_trigger: str | None

PairCorrelationnode_id_a: str / node_id_b: str / correlation: float ∈ [-1,1] / regime_label_local: Literal["normal","tail-coupled","regime-switched"]

UnbalancedLoopWarningedge_id: str / reason: str

§2.3 RegulationStatus(来源 §2.3)

产出意图:让用户看到「制度摩擦(涨跌停 / T+N / 熔断 / 限售等)会不会让一个理论上成立的判断在实操中失效」,把监管不确定性显式呈现而非默认忽略。

RegulationStatusfriction_layer: list[FrictionItem] / failure_modes: list[FailureModeFlag] / regulatory_uncertainty: float ∈ [0,1]

FrictionItemfriction_type: Literal["t-plus-n","price-limit","trading-halt","intraday-regulatory-change","short-sell-restriction","circuit-breaker","foreign-investor-quota"] / severity: Literal["low","medium","high"] / affected_node_ids: list[str] / evidence_ref: str

FailureModeFlagmode: Literal["a-acute-liquidity","b-structural-holder-rotation","c-policy-credit","d-a-share-retail-acute"] / confidence: float ∈ [0,1] / triggered_by_friction: bool / evidence_ref: str

§2.4 ApplicabilityFlags + PillarApplicability(来源 §2.4)

产出意图:让用户看到「这套判断的适用边界——估值 / 因子 / 衍生品三支柱各自是否适用、为什么不适用」,避免把一个只在某支柱成立的结论误当全局结论。reason 服务于「不适用要给得出理由,用户能据此自己判断」这份价值。

ApplicabilityFlagsvaluation: PillarApplicability / factor: PillarApplicability / derivatives: PillarApplicability

PillarApplicabilitylevel: Literal["applicable","partial","not-applicable"] / reason: str | Nonelevel=applicable 时可为 None)/ evidence_ref: str | None

§2.5 BimodalPosterior + PosteriorMode(来源 §2.5)

产出意图:让用户看到「双峰 / 重尾的风险结构,而不是一个虚假精确的单点预测」——两个模态各自的概率与尾宽把「可能大涨也可能大跌」显式摊开。

kelly_cap 已退役(ADR-021,2026-06-04)BimodalPosterior 原含 kelly_cap(认知层凯利上界估计),owner 定调其无用且误导,已从代码(FinBayes 684d69d)与本契约移除;不确定性仍由双峰重尾分布(mode_a / mode_b / tail_width)承载。

BimodalPosteriorfit_method: Literal["prompt-direct","multi-scenario-fit","bayesian-module"] / mode_a: PosteriorMode / mode_b: PosteriorMode / slow_thinking_triggered: bool / prior_family: Literal["bimodal-fat-tail-default","single-mode-normal","single-mode-fat-tail","custom"]。(kelly_cap 已退役,见 ADR-021。)

PosteriorModevalue: float / weight: float ∈ [0,1] / tail_width: float ≥ 0

§2.6 NarrativeNumberConsistency + 子结构(来源 §2.6)

产出意图:让用户看清「故事(叙事)和数字是否相互印证、印证强度多大、是谁在带动谁」——当叙事远超数字(远期外推 / 数据脱节 / 口径不可比)时给出方向性提醒;正向耦合时也明确告知「这次叙事和数字是对得上的」。backtrigger / convergence_flag 服务于「让这份一致性判断在内部可被复算、收敛可控」。

NarrativeNumberConsistencys1_mode: list[S1Mode](可多选)/ coupling_direction: Literal["narrative-leads-numbers","numbers-lead-narrative","decoupled","positive-coupled"] / coupling_strength: float ∈ [0,1] / evidence: S1Evidence / falsification_ref: str | None / backtrigger: list[BackTrigger] / confidence: float ∈ [0,1] / second_order_branch: AttentionMarketBranch | None(由 §4 联动条件决定)/ convergence_flag: ConvergenceFlag

S1Evidencenarratives: list[str] / numbers_ref: list[str](引用 id,不复制)。

BackTriggertarget: Literal["M5","M6","M7","M7b-meta"] / reason: str / priority: Literal["high","medium","low"]

AttentionMarketBranchattention_signals: list[AttentionSignal] / narrative_self_consistency: float ∈ [0,1]

AttentionSignalsignal_type: Literal["funding-rate","on-chain-first-sign","concentration","kol","micro-cycle-phase"] / value: float / evidence_ref: str

ConvergenceFlagloop_count: int ∈ [0,3] / converged: bool / convergence_method: Literal["hash-stable","confidence-soft","max-loops","multimodal-archive"]

§2.7 MCABucket(Task schema 元数据,来源 §2.7)

产出意图:给整条判断打上「当前市场上下文特征」标签(投资者结构 / 衍生品成熟度 / 制度摩擦等七轴),让同一套机制在不同市场环境下被正确加权、复盘时可按环境分层。属 Task 元数据,不入 result body;用户面如需呈现由 widget 翻译为「市场上下文」。

MCABucketaxis_1_investor_structure: Literal["L1","L2","L3"] / axis_2_derivatives_maturity: Literal["D1","D2","D3"] / axis_3_institutional_friction: Literal["F1","F2","F3"] / axis_4_non_market_actor: Literal["N1","N2","N3"] / axis_5_credit_environment: Literal["C1","C2","C3"] / axis_6_information_availability: Literal["I1","I2","I3"] / axis_7_currency_cross_border: Literal["K1","K2","K3"] / bucket_label: Literal["B1","B2","B3","B4","B5a","B5b","B6","B7"] / worst_axis: str(如 axis_4_N3)/ tag_version: str(如 mca-v1.0)。

七轴语义(投资者结构 / 衍生品成熟度 / 制度摩擦 / 非市场参与者注入 / 信用环境 / 信息可得性 / 货币与跨境约束)来源 ADR-007 supplement §2.2。

§3 enum 取值清单

Literal取值
structured_result_version1.1
node_typeentity / relation / attribute
edge_typecausal / reflexivity / shared-book / institutional-friction / cross-market-mapping
edge.form 建议值acute-liquidity / structural-holder-rotation / policy-credit / a-share-retail-acute
force_typearbitrageur / policy-hedge / liquidity-supplier / fundamental-reverter / structural-flow
endogeneity 值域endogenous / exogenous
regime_labelnormal / tail-coupled / regime-switched
phase_matrix.cells 单元 (CellLabel)aligned / lead-1 / lead-2 / lag-1 / lag-2 / opposed / not-applicable
severitylow / medium / high
friction_typet-plus-n / price-limit / trading-halt / intraday-regulatory-change / short-sell-restriction / circuit-breaker / foreign-investor-quota
failure_modea-acute-liquidity / b-structural-holder-rotation / c-policy-credit / d-a-share-retail-acute
pillar.levelapplicable / partial / not-applicable
fit_methodprompt-direct / multi-scenario-fit / bayesian-module
prior_familybimodal-fat-tail-default / single-mode-normal / single-mode-fat-tail / custom
s1_mode(多选)a-far-extrapolation / b-source-missing / c-narrative-data-detachment / d-unit-accounting-incompatible / positive-coupling
coupling_directionnarrative-leads-numbers / numbers-lead-narrative / decoupled / positive-coupled
backtrigger.targetM5 / M6 / M7 / M7b-meta
backtrigger.priorityhigh / medium / low
attention.signal_typefunding-rate / on-chain-first-sign / concentration / kol / micro-cycle-phase
convergence_methodhash-stable / confidence-soft / max-loops / multimodal-archive
bucket_labelB1 / B2 / B3 / B4 / B5a / B5b / B6 / B7
七轴档位L1/L2/L3 · D1/D2/D3 · F1/F2/F3 · N1/N2/N3 · C1/C2/C3 · I1/I2/I3 · K1/K2/K3

§4 字段间依赖约束(来自 ADR-008 supplement 显式条款)

  1. mode_a.weight + mode_b.weight = 1.0(±1e-6 容差,§2.5)。
  2. applicability_flags.valuation.level == "not-applicable"s1.second_order_branch 必须非 None(§2.4 / §2.6)。
  3. applicability_flags.valuation.level == "applicable"s1.second_order_branch == None(§2.6)。
  4. applicability_flags.valuation.level == "partial" ⇒ 主流程 + 二阶并行,second_order_branchNone(子系统文档锁定)。
  5. applicability_flags.derivatives.level == "not-applicable"posterior.fit_method 不得选依赖衍生品 IV 的 bayesian-module 实现路径(§2.4 末段)。
  6. causal_graph.correlation_regime.regime_label == "regime-switched"posterior 强制必选(§2.5)。
  7. M5 启用 ⇒ causal_graph.correlation_regime.regime_label 至少 normal,不可缺省(§2.2)。
  8. MCA axis_3_institutional_friction ∈ {F2, F3}regulation_status 必选;F1 时可缺省为空对象(§2.3)。
  9. pillar.level == "applicable"reason 可为 Nonepartial / not-applicablereason 应非空(§2.4)。
  10. convergence_flag.loop_count ∈ [0, 3],N=3 上限(§2.6 / ADR-007 supplement §2.3 v1 锁定)。
  11. 概率类字段(path_confidence / translation_loss / confidence / coupling_strength / regulatory_uncertainty / weight / narrative_self_consistency / ClockPhase.confidence / FailureModeFlag.confidence)值域 [0, 1]tail_width ≥ 0correlation ∈ [-1, 1]。(kelly_cap 已退役,见 ADR-021。)
  12. s1.evidence.numbers_refs1.falsification_ref 仅存引用 id,不复制 10 要素内容(§2.6)。

§5 Pydantic v2 草案

字段在跨 milestone(M0 → M1 → M2)从 Optional → required 的收紧时点与 audit 触发条件见 里程碑字段宽紧度演化矩阵

# src/finbayes/cognition/types.py
from __future__ import annotations
from typing import Literal, Optional
from pydantic import BaseModel, ConfigDict, Field

S1Mode = Literal["a-far-extrapolation","b-source-missing","c-narrative-data-detachment","d-unit-accounting-incompatible","positive-coupling"]
RegimeLabel = Literal["normal","tail-coupled","regime-switched"]
PillarLevel = Literal["applicable","partial","not-applicable"]
Severity = Literal["low","medium","high"]
CellLabel = Literal["aligned","lead-1","lead-2","lag-1","lag-2","opposed","not-applicable"]
NodeType = Literal["entity","relation","attribute"]
EdgeType = Literal["causal","reflexivity","shared-book","institutional-friction","cross-market-mapping"]
ForceType = Literal["arbitrageur","policy-hedge","liquidity-supplier","fundamental-reverter","structural-flow"]
FrictionType = Literal["t-plus-n","price-limit","trading-halt","intraday-regulatory-change","short-sell-restriction","circuit-breaker","foreign-investor-quota"]
FailureMode = Literal["a-acute-liquidity","b-structural-holder-rotation","c-policy-credit","d-a-share-retail-acute"]
FitMethod = Literal["prompt-direct","multi-scenario-fit","bayesian-module"]
PriorFamily = Literal["bimodal-fat-tail-default","single-mode-normal","single-mode-fat-tail","custom"]
CouplingDirection = Literal["narrative-leads-numbers","numbers-lead-narrative","decoupled","positive-coupled"]
BackTriggerTarget = Literal["M5","M6","M7","M7b-meta"]
Priority = Literal["high","medium","low"]
AttentionSignalType = Literal["funding-rate","on-chain-first-sign","concentration","kol","micro-cycle-phase"]
ConvergenceMethod = Literal["hash-stable","confidence-soft","max-loops","multimodal-archive"]
BucketLabel = Literal["B1","B2","B3","B4","B5a","B5b","B6","B7"]

class _Base(BaseModel):
model_config = ConfigDict(extra="ignore")

class ContradictionEntry(_Base):
axes: list[str]; type: str; severity: Severity

class ClockPhase(_Base):
clock_id: str; phase_label: str
confidence: float = Field(ge=0.0, le=1.0)
evidence_ref: str

class ClockPhaseMatrix(_Base):
axes: list[str]; cells: list[list[CellLabel]]
contradictions: list[ContradictionEntry] = []

class PhaseEvidence(_Base):
clocks: list[ClockPhase] = []
phase_matrix: Optional[ClockPhaseMatrix] = None

class Node(_Base):
id: str; object_ref: str; node_type: NodeType

class Edge(_Base):
id: str; from_node: str; to_node: str; edge_type: EdgeType
form: Optional[str] = None
path_confidence: float = Field(ge=0.0, le=1.0)
translation_loss: float = Field(ge=0.0, le=1.0)

class ReverseForce(_Base):
edge_id: str; force_type: ForceType; evidence_ref: str

class PairCorrelation(_Base):
node_id_a: str; node_id_b: str
correlation: float = Field(ge=-1.0, le=1.0)
regime_label_local: RegimeLabel

class CorrelationRegime(_Base):
regime_label: RegimeLabel
pair_correlations: list[PairCorrelation] = []
regime_shift_trigger: Optional[str] = None

class UnbalancedLoopWarning(_Base):
edge_id: str; reason: str

class TransmissionGraph(_Base):
nodes: list[Node] = []
edges: list[Edge] = []
reverse_forces: list[ReverseForce] = []
endogeneity: dict[str, Literal["endogenous","exogenous"]] = {}
correlation_regime: CorrelationRegime
unbalanced_loop_warnings: list[UnbalancedLoopWarning] = []

class FrictionItem(_Base):
friction_type: FrictionType; severity: Severity
affected_node_ids: list[str]; evidence_ref: str

class FailureModeFlag(_Base):
mode: FailureMode
confidence: float = Field(ge=0.0, le=1.0)
triggered_by_friction: bool; evidence_ref: str

class RegulationStatus(_Base):
friction_layer: list[FrictionItem] = []
failure_modes: list[FailureModeFlag] = []
regulatory_uncertainty: float = Field(ge=0.0, le=1.0)

class PillarApplicability(_Base):
level: PillarLevel
reason: Optional[str] = None
evidence_ref: Optional[str] = None

class ApplicabilityFlags(_Base):
valuation: PillarApplicability
factor: PillarApplicability
derivatives: PillarApplicability

class PosteriorMode(_Base):
value: float
weight: float = Field(ge=0.0, le=1.0)
tail_width: float = Field(ge=0.0)

class BimodalPosterior(_Base):
fit_method: FitMethod
mode_a: PosteriorMode; mode_b: PosteriorMode
slow_thinking_triggered: bool
prior_family: PriorFamily

class S1Evidence(_Base):
narratives: list[str] = []
numbers_ref: list[str] = []

class BackTrigger(_Base):
target: BackTriggerTarget; reason: str; priority: Priority

class AttentionSignal(_Base):
signal_type: AttentionSignalType; value: float; evidence_ref: str

class AttentionMarketBranch(_Base):
attention_signals: list[AttentionSignal] = []
narrative_self_consistency: float = Field(ge=0.0, le=1.0)

class ConvergenceFlag(_Base):
loop_count: int = Field(ge=0, le=3)
converged: bool
convergence_method: ConvergenceMethod

class NarrativeNumberConsistency(_Base):
s1_mode: list[S1Mode] = []
coupling_direction: CouplingDirection
coupling_strength: float = Field(ge=0.0, le=1.0)
evidence: S1Evidence
falsification_ref: Optional[str] = None
backtrigger: list[BackTrigger] = []
confidence: float = Field(ge=0.0, le=1.0)
second_order_branch: Optional[AttentionMarketBranch] = None
convergence_flag: ConvergenceFlag

class MCABucket(_Base):
axis_1_investor_structure: Literal["L1","L2","L3"]
axis_2_derivatives_maturity: Literal["D1","D2","D3"]
axis_3_institutional_friction: Literal["F1","F2","F3"]
axis_4_non_market_actor: Literal["N1","N2","N3"]
axis_5_credit_environment: Literal["C1","C2","C3"]
axis_6_information_availability: Literal["I1","I2","I3"]
axis_7_currency_cross_border: Literal["K1","K2","K3"]
bucket_label: BucketLabel
worst_axis: str
tag_version: str

class StructuredCognitionResultV10Body(_Base):
"""1.0 主体(10 认知要素 inline 完整模型)。

字段提取自 product-definition.md §7 十要素表与 m0-walking-skeleton §3 的
`StructuredCognitionResult` 1.0 schema 草案。M0 已实现前 7 个内容字段;
剩余 3 个(multi_perspectives / prerequisites / follow_up_questions /
historical_judgment_links)由 1.0 主体在 1.1 完整模型合并时一次补齐。

内部 `model_config` 单独使用 `extra="forbid"`,语义是「锁 identity / 版本 / 安全
相关字段完整性」(防止 1.0 直出漏 structured_result_version 等核心键),不是
「禁止认知要素层按任务动态增减」——动态组合由 tasks-fields-mapping 决定,不靠
全局 forbid 固化(ADR-013 去全局固化);合并到 `StructuredCognitionResultFullV11`
后由后者的 `extra="ignore"` 覆盖(见下方 ConfigDict 合并语义锁)。
"""
model_config = ConfigDict(extra="forbid")

# 10 认知要素(product-definition §7)
main_answer: str = Field(..., min_length=30) # 1. 结论 / 倾向(第一屏题眼回应,≥30 字硬约束)
supporting_evidence: list[str] = Field(default_factory=list) # 2. 依据
multi_perspectives: list[str] = Field(default_factory=list) # 3. 多视角
counter_evidence: list[str] = Field(default_factory=list) # 4. 反方证据(M0 允许空但必须明示理由)
prerequisites: list[str] = Field(default_factory=list) # 5. 成立条件
invalidation_conditions: list[str] = Field(..., min_length=1) # 6. 失效条件(M0 必填非空)
uncertainty_and_gaps: list[str] = Field(default_factory=list) # 7. 不确定性 / 信息缺口
sources: list[dict] = Field(default_factory=list) # 8. 来源与时间戳
follow_up_questions: list[str] = Field(default_factory=list) # 9. 可继续追问项
historical_judgment_links: list[str] = Field(default_factory=list) # 10. 历史判断链接

# 1.0 主体内部 audit 字段(不暴露到 1.1 顶层 audit)
non_instruction_notice: str = "本回答是认知材料,不是执行指令。"
schema_validation_passed: bool = True


class StructuredCognitionResult11MinimalAdditions(_Base):
"""1.1 新增 6 顶层字段(与 m0-walking-skeleton §3.5 `StructuredCognitionResult11Minimal`
对应;本类提供 1.1 完整版字段类型,M0 子集见 m0-pack)。"""
structured_result_version: Literal["1.1"] = "1.1"
phase_evidence: Optional[PhaseEvidence] = None
causal_graph: Optional[TransmissionGraph] = None
regulation_status: Optional[RegulationStatus] = None
applicability_flags: Optional[ApplicabilityFlags] = None
posterior: Optional[BimodalPosterior] = None
s1: NarrativeNumberConsistency


class StructuredCognitionResultFullV11(
StructuredCognitionResultV10Body,
StructuredCognitionResult11MinimalAdditions,
):
"""1.1 完整模型:1.0 十要素 + 1.1 新增 6 顶层字段,共 16 顶层字段
(Task 元数据 `mca_bucket: MCABucket` 不入本模型本体,由 Task 携带,见 §2.7)。

ConfigDict 合并语义见下方「ConfigDict 合并语义锁」段。
"""
# extra="ignore" 是设计意图(不是疏忽):承接 ADR-008 supplement §3.1 兼容策略,
# 旧 1.0 consumer 读到 1.1 输出时必须能忽略新字段不报错;1.0 主体内部用 forbid
# 防误用、合并后由本层 ignore 覆盖,详见 §6 与 m0-pack §3.5 注释。
model_config = ConfigDict(extra="ignore")

ConfigDict 合并语义锁(C-E + C-J):

  1. 多继承顺序StructuredCognitionResultFullV11(StructuredCognitionResultV10Body, StructuredCognitionResult11MinimalAdditions)。Pydantic v2 多继承 model_config 取最末次显式声明者(本类自身的 extra="ignore" 覆盖父类)。即 1.0 主体的 extra="forbid" 在合并到 1.1 完整模型后被 extra="ignore" 覆盖,理由:1.0 → 1.1 兼容契约(ADR-008 supplement §3.1:旧 consumer 必须能忽略 1.1 新字段不报错)。

  2. extra="ignore" 是设计意图,不是疏忽:1.1 输出契约用 extra="ignore" 承接 ADR-008 supplement §3.1 兼容策略(旧 1.0 consumer 必须能忽略 1.1 新字段不报错);1.0 主体单独使用时(如 M0 阶段 StructuredCognitionResult 直出)保持 extra="forbid",但其语义范围是**「锁 identity / 版本 / 安全相关字段完整性」**(防止 1.0 直出漏 structured_result_version 等核心键),不是「禁止认知要素层按任务动态增减字段」——「单次输出携带哪些认知要素」由 task_type × 机制激活 动态决定(事实源 field_composition_policy / contracts/tasks-fields-mapping.yaml),不靠全局 forbid 钉死(ADR-013 Build-Y over Prevent-X,去全局固化)。Codex 实施时不得把 StructuredCognitionResultFullV11.model_config 改为 extra="forbid",否则破坏兼容契约引入 schema drift。

  3. 顶层 audit 字段策略:1.1 顶层只暴露 structured_result_version: Literal["1.1"];1.0 主体内部的 schema_validation_passed 在合并模型中保留但不计入「audit-versioning 暴露面」(即 audit 层仅以 structured_result_version 作为版本筛选键)。

  4. JSON 序列化口径:合并模型序列化时统一用 model_dump(by_alias=False, exclude_none=False),确保 10 要素 + 6 新字段在单一 JSON object 中输出(10 要素中 list 字段允许 [],6 新字段在未启用机制时输出 null)。

  5. 合并函数接口规约(供综合层在 1.0 + 1.1 两阶段产出时一次合并使用):

    接口签名 merge_cognition_result_v1_1(base: dict, extension: dict) -> dictbase = StructuredCognitionResultV10Body.model_dump()(10 要素 + 内部 audit),extension = StructuredCognitionResult11MinimalAdditions.model_dump()(6 顶层字段 + structured_result_version);输出 StructuredCognitionResultFullV11.model_validate(merged).model_dump(),顶层 structured_result_version 强制 "1.1"extension 覆盖 base 残留),键冲突以 extension 为准(两类字段命名理论不重叠),历史遗留未知字段由 extra="ignore" 静默丢弃不 raise。

跨字段约束(§4 第 1 / 2 / 3 / 5 / 6 / 8 条)不在草案以 model_validator 强制实现,留 EvalHarness M0 实施任务在 cognition/types.py 落盘时按 Pydantic v2 @model_validator(mode="after") 加约束。

§6 与 1.0 兼容性

承接 ADR-008 supplement §3.1:

  • 旧 consumer(声明 structured_result_version = "1.0")必须能忽略新字段不报错;合并模型 StructuredCognitionResultFullV11 顶层 model_config = ConfigDict(extra="ignore") 已就位(覆盖 1.0 主体的 extra="forbid",合并语义见 §5 「ConfigDict 合并语义锁」),序列化层在反序列化 1.1 输出到 1.0 consumer 时 6 新字段以「未知字段宽容」模式跳过。
  • 新 consumer 收到 structured_result_version = "1.0"(或缺省)时,6 新字段以 None 缺省;评测维度 D4 / D6 / D7 缺字段时降级为「文本层评测」并标注 degraded-text-only,不阻断管线。
  • 每条 Judgment Record 顶层写入 structured_result_version + mca_bucket;撤回 / 降级支持按版本筛选。
  • 1.x 系列承诺向后兼容;2.0 走变更协议 L4 + 14 天异议期。

§7 半人工标注承接

承接 ADR-008 supplement §5.1 与 Phase 7 半人工标注 SLA 附录

允许人工标注覆盖(v1):

  • causal_graph.edges[?].form ∈ {"policy-credit", "a-share-retail-acute"}(任务 A / B)。
  • regulation_status.failure_modes[?].mode ∈ {"c-policy-credit", "d-a-share-retail-acute"}(与 form 联动)。
  • mca_bucket.axis_4_non_market_actor = "N3"(任务 D,Audit Trail 标注「半人工」)。
  • posterior.slow_thinking_triggered(任务 C,M7.meta-v1 推翻路径)。
  • applicability_flags.{valuation|factor|derivatives}.levelapplicablepartial 边缘判定(not-applicable 门槛较硬,推翻须附 reason + evidence_ref)。

必须模型自动产出phase_evidence.clocks.* / phase_evidence.phase_matrix.cells / causal_graph.nodes / causal_graph.edges 主体结构 / causal_graph.correlation_regime.regime_label / posterior.mode_a / posterior.mode_b / s1.coupling_strength / s1.confidence / s1.convergence_flag.*

§8 待对齐项

  • phase_evidence.clocks[?].phase_label 未严格枚举化(机制自定枚举),下游按字符串处理;M3 v1 校准后再决议是否升级为 Literal
  • causal_graph.edges[?].form 在 ADR-008 supplement §2.2 列举 shared-book 四形态但未声明封闭枚举;草案保留 Optional[str]
  • causal_graph.endogeneity 键约束(必须覆盖所有 edges[?].id,还是允许子集)未显式说明,草案按「子集允许」实现。
  • regulation_status.friction_layer 在 MCA 轴 3 = F1 时「整体 None 与字段为空对象」二选一未锁定。
  • s1.evidence.numbers_ref / s1.falsification_ref 引用失效时的处理路径(重评 / 降级 / 阻断)由 Phase 7+ 决议。
  • mca_bucket.worst_axis 多桶命中边界(N3 + F3 同时命中)的裁决规则在 MCAClassifier 子系统 §7 已 flag,本契约不锁定。
  • kelly_cap 与战略不变量「FinBayes 不直接下单」的下游消费协议未在本契约层声明kelly_cap 已退役(ADR-021),本条作废。
  • 子系统 placeholder 类型见 4 子系统文档「子模型类型 placeholder」段(知识图谱服务 / 一致性中间件 / 市场上下文分类器 / 评测台架),M0 阶段为接口签名 import 链闭合给的最小定义;M1+ 收紧路径见各子系统 §9 实现里程碑映射 + 后续 milestone-field-evolution-matrix.md

§9 关联资产

§10 变更记录

  • 2026-05-29 Build-Y 换轨(ADR-013):补正向语义——§0 加「正向语义读法」;§1 加 10 要素「产出意图」;§2.1–§2.7 每子模型加「产出意图」(约束挂在意图之下,不凭空列禁令)。§5 ConfigDict 合并语义锁第 2 条 + StructuredCognitionResultV10Body 文档串明确 extra="forbid" 仅锁 identity / 版本完整性、不固化认知要素动态组合(与 contracts/structured-cognition-result.yaml 同步)。字段名 / 类型未变(无漂移)。