16 KiB
Interaction Boundary 与四挡合同设计
目的
这份设计要解决的不是“模型再聪明一点”,而是把 PMFlow 当前问答/建议/草稿/执行之间的边界收干净:
statusrecommendationdraftexecute
当前问题不是系统不会回答,而是系统没有一个正式的“本轮允许做到哪一挡、明确禁止升到哪一挡”的运行时合同,导致 recommendation ask 会误滑到 signal_source.onboard -> draft_pending_confirm。
本设计的目标是:
- 四挡独立,不能偷偷升级。
- 每一挡都支持澄清、纠错、再次思考。
- recommendation 必须能独立停住,不再被写链路抢走。
- 用户可见回复必须自然业务化,不像架构师,也不能泄漏 packet / contract 术语。
- 今天与昨天暴露出来的失败场景,必须转成自动化反例。
这次不做什么
- 不重写
requirement_plan/ action card 主链。 - 不重构
SignalSourceOrchestrationService业务编排本体。 - 不把前台所有文风都做一轮大翻修。
- 不引入新的中文关键词仓或正则仓去拍板
query vs draft vs execute。
当前已暴露的问题
1. recommendation ask 被错升成 onboard / draft
真实用户输入:
我看这个项目现在还没有成型的信号源。你先别出草稿,只按当前项目情况,帮我推荐几个最值得接的外部信号源,并说清楚各自的价值。
真实结果:
intent = signal_source.onboardstate = draft_pending_confirm- 先发
⏳ 已完成入库,当前进入待确认队列。
这说明:
- recommendation 与 draft 没有分层
- 负向边界
先别出草稿没生效 - executor 链被过早放行
2. recommendation ask 被答成现状核查
用户明明在问“推荐几个外部信号”,系统却回:
- 当前没有信号源
- 当前项目没有记录
- 当前盘面怎样
这说明:
status与recommendation没分开
3. recommendation ask 被答成保守拒答
用户问:
如果只考虑外部信号源,你会优先推荐哪 3 类?
系统回:
- 当前不能直接推荐
- 当前证据不足
这说明:
- recommendation 被误当成 freshness / fact verification
4. 稀疏项目只会打太极
例如 自动开票系统 只有一句描述时,系统长期只会回:
- 还缺业务步骤
- 还缺信号源
- 先别硬判
这类话术不算真正分析,只是保守拒答。
5. 客户可见回复泄漏内部术语
已经出现过:
分析包里明确写了missing_mappingfocus_objectsanalysis_packet
这说明:
- packet / presenter 边界没有守住
6. 新项目 / 新业务切换被旧线程污染
例如上一轮在聊 测试产能警告,下一轮问 AI客服这个项目...,却继续沿旧 subject / old scope 改写。
这说明:
- scope 连续性虽然已经补了治理,但还没有成为正式验收基线
设计原则
1. 先定边界,再决定动作
系统不能只理解“用户想干什么”,还必须理解“用户明确不要我干什么”。
2. 不追求一次答对,追求可纠错
系统要做到:
- 不越权
- 可停住
- 可被纠正
- 纠正后能原地重算
3. 结构化边界优先于运行时猜测
决策权不应该在:
if "先别出草稿" in textif "不要执行" in text
而应该在:
- 统一语义规划层结构化产出的边界合同
- gatekeeper 对结构合同的执行
4. recommendation 是独立主链,不是 query 的弱版也不是 draft 的前奏
只要用户要的是建议,就应该允许系统:
- 给候选
- 给排序
- 给理由
但不能:
- 冒充已验证事实
- 顺手起草
- 顺手执行
5. 每一挡都必须有澄清、纠错、再次思考
这三件事不是失败兜底,而是系统能力的一部分。
新增运行时结构
A. InteractionBoundaryPacket
职责:表达“这一轮允许做到哪一挡、禁止做到哪一挡”。
建议结构:
class InteractionBoundaryPacket(BaseModel):
boundary_version: str = "v1"
requested_level: Literal[
"status",
"recommendation",
"draft",
"execute",
"unclear",
] = "unclear"
forbidden_levels: list[
Literal["status", "recommendation", "draft", "execute"]
] = Field(default_factory=list)
allow_status: bool = True
allow_recommendation: bool = True
allow_draft: bool = False
allow_execute: bool = False
allow_write: bool = False
needs_clarification: bool = False
clarification_reason: str = ""
clarification_questions: list[str] = Field(default_factory=list)
correction_allowed: bool = True
correction_targets: list[
Literal["project", "object", "level", "priority", "assumption"]
] = Field(default_factory=list)
self_review_required: bool = True
confidence: float = 0.0
evidence: list[dict[str, Any]] = Field(default_factory=list)
这不是给用户看的,而是给 gatekeeper 用的。
B. AnswerControlDecision
职责:把 SemanticDecision + InteractionBoundaryPacket 合成真正能执行的层级结果。
建议结构:
class AnswerControlDecision(BaseModel):
effective_level: Literal[
"status",
"recommendation",
"draft",
"execute",
"clarify",
]
blocked_levels: list[str] = Field(default_factory=list)
blocked_workflows: list[str] = Field(default_factory=list)
allowed_workflows: list[str] = Field(default_factory=list)
downgraded_from: str | None = None
requires_confirmation: bool = False
requires_self_review: bool = True
requires_correction_slot: bool = True
reason: str = ""
四挡定义
1. status
定义:
- 只回答当前现状
- 不给建议
- 不起草
- 不执行
允许:
- 当前已知内容
- 当前未知内容
- 当前只看到哪些记录
禁止:
- 偷偷给候选建议
- 偷偷起草或执行
2. recommendation
定义:
- 可以给候选、排序、理由
- 不能起草
- 不能执行
- 必须明确“这是建议,不是已验证事实”
3. draft
定义:
- 可以起草一版
- 必须带假设、缺口、待确认点
- 不能执行
4. execute
定义:
- 必须显式确认
- 可以落库 / 接入 / 执行
- 必须回显要动哪个对象、影响范围和执行结果
决策顺序
后续实现必须按这个顺序:
- 现有
WorkflowSemanticPlanner继续产出SemanticDecision - 同轮补产出
InteractionBoundaryPacket - 把
workflow_plans映射到四挡 - 用 boundary packet 过滤 workflow
- 产出
AnswerControlDecision - 再决定最终主链:
query.answer(status)query.answer(recommendation)draft_pending_confirmexecute
也就是说,signal_source_flow 可以被识别出来,但如果:
allow_draft = falseallow_execute = false
最终仍然只能落到:
query.answer(recommendation)
负向边界优先级
必须明确:
- 负向边界优先于系统自己的升级冲动
- 负向边界低于用户后续显式升级确认
例如:
场景 A
先别出草稿,只给我推荐几个高价值外部信号源。
预期:
- recommendation 可以回答
- draft / execute 必须被 block
场景 B
后续用户再说:
可以,把第 1 个起草成接入草稿。
预期:
- 显式升级到 draft
- 仍不自动 execute
澄清、纠错、再次思考
1. 澄清
每一挡都允许澄清。
适用情况:
- 项目不清
- 业务对象不清
- 用户到底要 status / recommendation / draft / execute 不清
- 当前约束冲突
需要结构化字段:
needs_clarificationclarification_reasonclarification_questions
2. 纠错
用户必须能低成本纠错:
- 不是这个项目
- 不是这个对象
- 不是这个方向
- 我现在不是要草稿,只要建议
- 我改了,现在直接出草稿
要求:
- 收到纠错后,必须重建新的
InteractionBoundaryPacket - 不准带旧边界续写
- 输出里应承认:已按新纠正口径重算
3. 再次思考 / 自检
建议新增:
class SelfReviewResult(BaseModel):
project_aligned: bool = True
object_aligned: bool = True
level_aligned: bool = True
leaked_internal_terms: bool = False
overstepped_boundary: bool = False
clarify_missing: bool = False
notes: list[str] = Field(default_factory=list)
至少要检查:
- 我是不是答错项目了
- 我是不是把 recommendation 偷偷升级成 draft 了
- 我是不是泄漏内部术语了
- 我是不是没有分析,只是在说“信息不足”
- 我是不是漏了关键澄清点
自检失败时:
- 降级
- 或补澄清
- 或阻止出站
用户可见回复骨架
四挡统一成三段式:
- 当前判断
- 理由 / 缺口
- 纠错或升级入口
recommendation 例子
如果只是先给建议,我会先看这 3 类外部信号:
1. xxx,因为...
2. yyy,因为...
3. zzz,因为...
这些是候选建议,不代表已经接入,也还没完成验证。
如果方向不对,你可以直接改项目对象或业务目标;如果你要,我也可以下一步只把第 1 个起草成草稿。
sparse 项目例子
自动开票系统这个项目,我现在先不硬说它该落在哪一步。
我现在只看得到它的大致目标:收到开票请求后自动开票,并把发票图片发出去。但还看不到这条链路里谁触发、接什么输入、哪个结果算真正跑通。
如果你愿意,我们先把这条流程拆开:谁发起、系统接什么、最后产出什么,再往下判断最合适的信号放在哪。
高标准黄金案例(业务化 V3)
这批案例要替换掉旧的“架构味太重 / 问法太空”的样例。问题必须像业务同事会问的话。
01. 自动开票系统 / status
- 输入:
自动开票系统现在最容易卡在哪一步?你按现在项目情况直接说。 - 预期层级:
status - 预期:不出建议,不出草稿,只说明当前最容易卡的链路或当前缺口
02. 自动开票系统 / recommendation
- 输入:
自动开票系统除了现在这些数据,你觉得还应该盯哪些外部信号?先给建议,不要起草。 - 预期层级:
recommendation - 预期:给 3 个候选信号 + 理由,不进 draft
03. AI客服 / status
- 输入:
AI客服这个项目现在主要靠什么数据来做用户洞察? - 预期层级:
status - 预期:围绕当前数据源或已知对象回答,不偷换成推荐
04. AI客服 / recommendation
- 输入:
AI客服这个项目,除了现在这些数据,你觉得还应该补哪几类外部线索?直接说最有用的几个。 - 预期层级:
recommendation - 预期:给候选 + 业务理由
05. 门店库存异常日报助手 / recommendation
- 输入:
这个项目如果要更早发现库存异常,你会先多看哪几类外部信号?先给建议,不要出方案。 - 预期层级:
recommendation - 预期:业务化候选,不保守拒答
06. 直播复盘辅助工具 / recommendation
- 输入:
这个项目如果只补一个外部信号,你觉得先补哪个最值?直接说原因。 - 预期层级:
recommendation - 预期:优先级明确,不起草
07. 测试产能警告 / recommendation with negative boundary
- 输入:
我看这个项目现在还没有成型的信号源。你先别出草稿,只按当前项目情况,帮我推荐几个最值得接的外部信号源,并说清楚各自的价值。 - 预期层级:
recommendation - 预期:绝不发队列 ack、绝不建 draft
08. 测试产能警告 / explicit upgrade to draft
- 前置:上一轮 recommendation 已返回
- 输入:
可以,把第一个整理成接入草稿给我看。 - 预期层级:
draft - 预期:允许升级,但不 execute
09. 确认立项 / internal status
- 输入:
确认立项现在 assignee 推荐做到哪了? - 预期层级:
status - 预期:回答当前状态,不泄漏
status_summary / contract
10. 跨项目切换 / scope reset
- 前置:上一轮问的是
测试产能警告 - 输入:
AI客服这个项目里,用户洞察数据现在到底给谁看、解决什么事? - 预期层级:
status - 预期:必须切到 AI 客服,不允许带旧项目续写
11. 稀疏项目 / clarify
- 输入:
这个项目到底该怎么做,你先说。 - 预期层级:
clarify - 预期:必须澄清项目或对象,不能直接起草或乱答
12. execute 前确认
- 输入:
那就把第一个外部信号源直接新增进去。 - 预期层级:
execute - 预期:必须显式确认,不准直接写
今天和昨天的失败反例,必须转成自动化
Fail-01
- recommendation ask 误进
signal_source.onboard - 断言:必须失败
Fail-02
- recommendation ask 被答成现状核查
- 断言:必须失败
Fail-03
- recommendation ask 被答成“当前不能推荐”
- 断言:必须失败
Fail-04
- 客户可见文本泄漏
分析包 / missing_mapping / focus_objects - 断言:必须失败
Fail-05
- sparse 项目只会说“还缺业务步骤”
- 断言:必须失败
Fail-06
- 新项目问句被旧线程污染
- 断言:必须失败
Fail-07
- 用户说
不要执行,系统仍然进入 write flow - 断言:必须失败
Fail-08
- 用户说
只给建议,系统仍然进入draft_pending_confirm - 断言:必须失败
测试设计
1. schema / contract
test_interaction_boundary_packet_schematest_answer_control_decision_schema
2. gatekeeper
test_recommendation_boundary_blocks_signal_source_onboardtest_status_boundary_blocks_recommendation_upgradetest_explicit_upgrade_from_recommendation_to_draft_allowedtest_execute_requires_confirmation_even_after_prior_upgrade
3. mainline routing
test_query_answer_recommendation_only_stays_querytest_status_only_does_not_return_candidatestest_unclear_level_returns_clarifytest_negative_boundary_blocks_write_flow
4. Feishu outbox
test_feishu_recommendation_only_never_emits_queue_acktest_feishu_recommendation_reply_has_no_internal_termstest_feishu_negative_boundary_no_draft_pending_confirm
5. sparse project
test_sparse_project_status_uses_known_goal_not_packet_jargontest_sparse_project_recommendation_explains_known_goal_and_unknown_flow
6. correction / rethink
test_user_correction_rebuilds_boundary_packettest_self_review_blocks_overstep_to_drafttest_self_review_blocks_internal_term_leak
>9 分验收标准
自动化稳定性 > 9
- 新增 contract / gatekeeper / Feishu outbox / sparse project 测试全绿
- recommendation 相关高风险误路由 case 全部自动化覆盖
链路清晰度 > 9
- 任意一条 query 都能在结构化结果里明确看到:
requested_levelforbidden_levelseffective_levelblocked_workflows
项目贴合度 > 9
- 回复必须贴当前项目对象
- 稀疏项目也至少能拆出最小业务链
- 不允许长时间停留在“缺步骤 / 缺信号源”空话
回复自然度 > 9
- 文风像业务同事
- 不像架构师
- 不像系统模板
- 不泄漏 packet / contract / internal terms
高风险误路由单条结果 > 9
- recommendation ask 错升 draft/execute 这类 case 必须逐条变绿
- 不能再用“总体表现还行”掩盖单点失败
实施顺序
- 先补 schema:
InteractionBoundaryPacketAnswerControlDecision
- 再补 gatekeeper
- 再把 recommendation-only 从 query.answer 主链里独立出来
- 再补 clarify / correction / self-review
- 最后按新的业务化黄金案例跑验证
真源落点建议
backend/app/services/ai_pmo/semantic_context/decision_schema.pybackend/app/services/ai_pmo/workflow_semantic_planner/service.py- Feishu ingress / gatekeeper 主链
backend/app/services/ai_pmo/ai_pmo_typed_executor_execute/mixin_execute_signal_source.pydocs/architecture/RUNTIME_GUARDRAILS.mddocs/architecture/CODE_REFERENCE_INDEX.md
完成标准
只有当下面全部满足时,这版才算过线:
- recommendation 不再误进 draft / execute
- status / recommendation / draft / execute 四挡真的独立
- 稀疏项目不再只会打太极
- 用户可见回复自然业务化,不像架构师
- 今天和昨天这些失败案例都变成自动化绿灯