PMFlow/docs/superpowers/specs/2026-04-19-interaction-boun...

401 lines
13 KiB
Markdown
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# Interaction Boundary 四挡合同 IO 审阅稿
## 目的
这份文档不讲实现细节,只把这次真正跑过的 interaction boundary 相关测试,按“输入是什么、系统最终产出什么、我们到底在验什么”重新摊开。
对应本次实际跑过的自动化入口:
- [backend/tests/test_semantic_decision_service.py](/Users/yuuuu/Documents/AIProjectManger/.worktrees/codex/unified-project-ai-handoff/backend/tests/test_semantic_decision_service.py)
- [backend/tests/test_workflow_semantic_planner.py](/Users/yuuuu/Documents/AIProjectManger/.worktrees/codex/unified-project-ai-handoff/backend/tests/test_workflow_semantic_planner.py)
- [backend/tests/test_ai_pmo_ingress_mainline.py](/Users/yuuuu/Documents/AIProjectManger/.worktrees/codex/unified-project-ai-handoff/backend/tests/test_ai_pmo_ingress_mainline.py)
- [backend/tests/test_external_query_planner.py](/Users/yuuuu/Documents/AIProjectManger/.worktrees/codex/unified-project-ai-handoff/backend/tests/test_external_query_planner.py)
- [backend/tests/test_feishu_card_action_contract.py](/Users/yuuuu/Documents/AIProjectManger/.worktrees/codex/unified-project-ai-handoff/backend/tests/test_feishu_card_action_contract.py)
## 高标准判定
我的评分口径不是“断言过了就算过”,而是按能不能支撑正式合同基线来打:
- `9.0` 以下:有价值,但还不够让我放心收进正式基线
- `9.0 - 9.2`:过线,但偏合同层/局部层证明
- `9.3 - 9.5`:扎实,已经能证明主链行为
- `9.6+`:非常硬,几乎就是这次需求最关键的验收证据
每条案例都至少要证明一件事:
1. recommendation ask 不会再偷偷滑进 draft / execute。
2. 显式升级到 draft 时,系统能保留 draft,不会被误压回 query。
3. planner 识别出的底层 workflow 与最终允许执行的层级是两回事,最终以 boundary/control 为准。
4. 这组 boundary/control 元数据不会在 ingress/query 链中途丢失。
5. 外部 recommendation 的最终客户可见文案仍是“建议”,不是拒答、不是现状核查、也不是起草确认。
按这个口径,这份审阅稿里我接受的最低门槛是:单条案例要 `> 9.0` 才算能过我的标准。
## 审阅案例
### 01. 负向边界 schema:recommendation 明确禁止 draft / execute
- 输入:
```json
{
"requested_level": "recommendation",
"forbidden_levels": ["draft", "execute"],
"allow_status": true,
"allow_recommendation": true,
"allow_draft": false,
"allow_execute": false,
"correction_targets": ["project", "level"],
"confidence": 0.91
}
```
- 实际输出:
```json
{
"requested_level": "recommendation",
"forbidden_levels": ["draft", "execute"],
"allow_draft": false,
"allow_execute": false,
"correction_targets": ["project", "level"]
}
```
- 通过点:
- recommendation 被结构化收成正式 level
- draft / execute 的负向边界被完整保留
- 后续可纠错目标明确包含 `project / level`
- 评分:`9.1 / 10`
- 结论:能过我的标准
- 原因:这条把“recommendation 明确禁止 draft / execute”这个负向边界固定成了正式 schema,合同层很干净;但它还只是结构层证明,不单独覆盖 planner/runtime 的真实执行,所以分不会更高。
### 02. Answer control schema:底层 workflow 被挡住时要显式写出来
- 输入:
```json
{
"effective_level": "recommendation",
"blocked_levels": ["draft", "execute"],
"blocked_workflows": ["signal_source_flow:onboard"],
"allowed_workflows": ["query_flow:answer"],
"downgraded_from": "draft"
}
```
- 实际输出:
```json
{
"effective_level": "recommendation",
"blocked_workflows": ["signal_source_flow:onboard"],
"allowed_workflows": ["query_flow:answer"],
"downgraded_from": "draft"
}
```
- 通过点:
- 系统不会只说“被挡了”,而是能说清楚到底挡掉了哪个 workflow
- query.answer 成为最终允许主链
- 评分:`9.1 / 10`
- 结论:能过我的标准
- 原因:这条把“被挡住的不是抽象 level,而是具体 workflow”说清楚了,后面做审计、诊断、回放都靠它;短板同样是它偏合同表达层,真正把分数抬高的是后面的 runtime case。
### 03. recommendation-only:识别到 signal_source_flow,但最终降回 query.answer
- 输入:
```text
先别出草稿,只按当前项目情况推荐几个最值得接的外部信号源。
```
- planner 初始识别:
```json
{
"workflow_type": "signal_source_flow",
"workflow_action": "onboard",
"operation_codes": ["signal_source.onboard"]
}
```
- interaction boundary:
```json
{
"requested_level": "recommendation",
"forbidden_levels": ["draft", "execute"],
"allow_draft": false,
"allow_execute": false
}
```
- 最终输出 bundle:
```json
{
"primary_workflow": "query_flow",
"workflows": [
{
"workflow_type": "query_flow",
"workflow_action": "answer",
"operation_codes": ["query.answer"]
}
],
"diagnostics": {
"interaction_boundary": {
"requested_level": "recommendation"
},
"answer_control": {
"effective_level": "recommendation",
"blocked_workflows": ["signal_source_flow:onboard"],
"downgraded_from": "draft"
}
}
}
```
- 通过点:
- 允许“识别到底层 write workflow”
- 但最终主链明确停在 `query.answer`
- `signal_source_flow:onboard` 没有再误滑进 draft pending confirm
- 评分:`9.7 / 10`
- 结论:明显过线,而且是这次最关键的验收点之一
- 原因:这条直接证明“先识别 workflow,再按 boundary 收口”的核心设计真的落地了。它不是模糊地避免误判,而是允许识别到底层草稿动作,再明确降回 recommendation,可解释性和行为正确性都很强。
### 04. 显式升级到 draft:不再被 recommendation guard 误伤
- 输入:
```text
可以,把第一个整理成接入草稿给我看。
```
- interaction boundary:
```json
{
"requested_level": "draft",
"forbidden_levels": ["execute"],
"allow_draft": true,
"allow_execute": false
}
```
- 最终输出 bundle:
```json
{
"primary_workflow": "signal_source_flow",
"workflows": [
{
"workflow_type": "signal_source_flow",
"workflow_action": "onboard",
"operation_codes": ["signal_source.onboard"]
}
],
"diagnostics": {
"answer_control": {
"effective_level": "draft",
"blocked_workflows": []
}
}
}
```
- 通过点:
- recommendation-only guard 不会误挡掉用户后续显式升级
- draft 允许,execute 仍未放行
- 评分:`9.5 / 10`
- 结论:能稳稳过我的标准
- 原因:如果只有上一条降级,没有这一条升级,整个合同就会变成“只会压,不会放”。这条证明四挡合同不是一刀切保护壳,而是真的尊重用户显式升级指令,行为上是完整的。
### 05. 写请求原样保留:正常 signal source 草稿请求仍走 onboard
- 输入:
```text
给项目ID: 2 接一个 YouTube 录屏加评论回放的信号源,先不要执行,先出草稿。
```
- fake planner 输出:
```json
{
"primary_workflow": "signal_source_flow",
"workflow_type": "signal_source_flow",
"workflow_action": "onboard",
"operation_codes": ["signal_source.onboard"],
"project_id": 2
}
```
- ingress resolve 后实际输出:
```json
{
"intent_name": "signal_source.onboard",
"project_id": 2,
"source_request": true
}
```
- 通过点:
- 正常“先出草稿”的写请求没有被新 boundary 逻辑误压成 query
- 兼容旧的无 boundary bundle 透传
- 评分:`9.3 / 10`
- 结论:能过我的标准
- 原因:这条主要是在守兼容性,证明新合同没有把本来正确的 draft 请求打坏。它不像 03/04 那样直接验证新能力核心,但对上线安全性很重要,所以我给中高分。
### 06. recommendation 降级后,boundary/control 元数据不会在 ingress 丢失
- 输入:
```text
你先别出草稿,只按当前项目情况推荐几个最值得接的外部信号源。
```
- planner bundle 输入:
```json
{
"primary_workflow": "query_flow",
"workflow_action": "answer",
"operation_codes": ["query.answer"],
"diagnostics": {
"interaction_boundary": {
"requested_level": "recommendation",
"forbidden_levels": ["draft", "execute"]
},
"answer_control": {
"effective_level": "recommendation",
"blocked_workflows": ["signal_source_flow:onboard"]
}
}
}
```
- resolve intent 后实际输出:
```json
{
"intent_name": "query.read_only",
"workflow_route": "query.answer",
"interaction_boundary": {
"requested_level": "recommendation"
},
"answer_control": {
"effective_level": "recommendation",
"blocked_workflows": ["signal_source_flow:onboard"]
}
}
```
- 通过点:
- `intent.name` 仍是现有体系里的 `query.read_only`
- 但业务 route 已明确是 `query.answer`
- boundary/control 没在 `workflow_bundle -> canonical intent` 这段链路里丢掉
- 评分:`9.4 / 10`
- 结论:能过我的标准
- 原因:planner 里算对还不够,这条证明 metadata 能穿过 ingress 主链继续活着,不会“前面识别对了、后面又掉光了”。这属于真正的链路级证明,不是单点断言。
### 07. external recommendation presenter:外部证据在校验中,也要直接给建议
- 输入:
```text
测试产能警告这个项目,如果只考虑外部信号源,你会优先推荐哪 3 类?直接给推荐结果和理由。
```
- 外部上下文:
```json
{
"retrieval_status": "verifier_blocked",
"impact_status": "no_direct_impact",
"recommendation_goal": "给测试产能警告推荐最值得先看的外部信号源。"
}
```
- presenter 实际输出:
```json
{
"prompt_variant_id": "external_signal_source_recommendation",
"answer_text": "如果只看外部信号源,我会先盯三类:1. 测试执行结果或失败告警... 2. 发布与变更记录... 3. 工单或异常反馈..."
}
```
- 通过点:
- recommendation ask 不再被压成 `external_verifier_blocked` 拒答
- 输出是候选建议 + 理由,不是现状核查,也不是草稿入口
- 评分:`9.4 / 10`
- 结论:能过我的标准
- 原因:这条把合同效果推到了 presenter 层,证明 recommendation 问法在外部证据校验未完成时,仍能输出“建议型答案”。它很好地对齐了用户真正看到的产品行为。
### 08. Feishu 最终客户可见文本:优先直出 recommendation,不回 packet fallback
- 输入:
```text
测试产能警告这个项目,如果只考虑外部信号源,你会优先推荐哪 3 类?直接给推荐结果和理由,不要复述当前现状,不要起草需求。
```
- direct_reply_text:
```text
外部实时查询:如果只看外部信号源,我会先看测试执行结果或失败告警、发布与变更记录、工单或异常反馈这三类,因为它们最容易直接反映产能异常。
```
- 最终 Feishu 文本输出:
```text
如果只看外部信号源,我会先看测试执行结果或失败告警、发布与变更记录、工单或异常反馈这三类,因为它们最容易直接反映产能异常。
来源:项目库 + 外部公开资料(当前仍在校验)
```
- 通过点:
- 直接优先吃 recommendation 正文
- 不回落到 analysis packet fallback
- 不出现 `External Freshness Guard`
- 也不把 recommendation ask 说成“已收到需求/准备起草”
- 评分:`9.5 / 10`
- 结论:能稳稳过我的标准
- 原因:这是最贴近客户可见结果的一条。前面所有 schema、planner、ingress、presenter 做得再好,只要 Feishu 落地文案退回旧 fallback,就都不算真的完成;这条证明最终用户看到的文本已经站对位置了。
## 实际运行结果
执行命令:
```bash
cd /Users/yuuuu/Documents/AIProjectManger/.worktrees/codex/unified-project-ai-handoff/backend
/Users/yuuuu/Documents/AIProjectManger/backend/venv/bin/python -m pytest \
tests/test_semantic_decision_service.py \
tests/test_workflow_semantic_planner.py \
tests/test_ai_pmo_ingress_mainline.py::test_kernel_intent_resolve_uses_workflow_bundle_for_signal_source_request \
tests/test_ai_pmo_ingress_mainline.py::test_kernel_intent_resolve_preserves_interaction_boundary_when_recommendation_downgrades_to_query \
tests/test_external_query_planner.py::test_presenter_prefers_recommendation_answer_for_signal_source_recommendation_question \
tests/test_feishu_card_action_contract.py::test_render_feishu_qa_direct_reply_text_prefers_recommendation_answer_for_external_signal_recommendation \
-vv
```
实际结果:
```text
collected 15 items
15 passed, 8 warnings in 3.59s
```
说明:
- warning 全是现有环境里的旧 warning,主要是 Pydantic V2 deprecation、`lark_oapi` 和 `websockets` 的 deprecation。
- 这次 interaction boundary 改动相关 case 全部通过。
## 总结判断
- 8 条里我给得最低的是 `9.1`,所以都能过我的标准。
- 最硬的三条是 `03 / 04 / 08`:分别对应“降级正确”“升级正确”“最终客户可见文本正确”。
- 相对偏弱的是 `01 / 02`,不是因为它们做得差,而是它们偏 schema/合同层,单独看还不算完整行为闭环。