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

13 KiB
Raw Blame History

Interaction Boundary 四挡合同 IO 审阅稿

目的

这份文档不讲实现细节,只把这次真正跑过的 interaction boundary 相关测试,按“输入是什么、系统最终产出什么、我们到底在验什么”重新摊开。

对应本次实际跑过的自动化入口:

高标准判定

我的评分口径不是“断言过了就算过”,而是按能不能支撑正式合同基线来打:

  • 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

  • 输入:
{
  "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
}
  • 实际输出:
{
  "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 被挡住时要显式写出来

  • 输入:
{
  "effective_level": "recommendation",
  "blocked_levels": ["draft", "execute"],
  "blocked_workflows": ["signal_source_flow:onboard"],
  "allowed_workflows": ["query_flow:answer"],
  "downgraded_from": "draft"
}
  • 实际输出:
{
  "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

  • 输入:
先别出草稿,只按当前项目情况推荐几个最值得接的外部信号源。
  • planner 初始识别:
{
  "workflow_type": "signal_source_flow",
  "workflow_action": "onboard",
  "operation_codes": ["signal_source.onboard"]
}
  • interaction boundary:
{
  "requested_level": "recommendation",
  "forbidden_levels": ["draft", "execute"],
  "allow_draft": false,
  "allow_execute": false
}
  • 最终输出 bundle:
{
  "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 误伤

  • 输入:
可以,把第一个整理成接入草稿给我看。
  • interaction boundary:
{
  "requested_level": "draft",
  "forbidden_levels": ["execute"],
  "allow_draft": true,
  "allow_execute": false
}
  • 最终输出 bundle:
{
  "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

  • 输入:
给项目ID: 2 接一个 YouTube 录屏加评论回放的信号源,先不要执行,先出草稿。
  • fake planner 输出:
{
  "primary_workflow": "signal_source_flow",
  "workflow_type": "signal_source_flow",
  "workflow_action": "onboard",
  "operation_codes": ["signal_source.onboard"],
  "project_id": 2
}
  • ingress resolve 后实际输出:
{
  "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 丢失

  • 输入:
你先别出草稿,只按当前项目情况推荐几个最值得接的外部信号源。
  • planner bundle 输入:
{
  "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 后实际输出:
{
  "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:外部证据在校验中,也要直接给建议

  • 输入:
测试产能警告这个项目,如果只考虑外部信号源,你会优先推荐哪 3 类?直接给推荐结果和理由。
  • 外部上下文:
{
  "retrieval_status": "verifier_blocked",
  "impact_status": "no_direct_impact",
  "recommendation_goal": "给测试产能警告推荐最值得先看的外部信号源。"
}
  • presenter 实际输出:
{
  "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

  • 输入:
测试产能警告这个项目,如果只考虑外部信号源,你会优先推荐哪 3 类?直接给推荐结果和理由,不要复述当前现状,不要起草需求。
  • direct_reply_text:
外部实时查询:如果只看外部信号源,我会先看测试执行结果或失败告警、发布与变更记录、工单或异常反馈这三类,因为它们最容易直接反映产能异常。
  • 最终 Feishu 文本输出:
如果只看外部信号源,我会先看测试执行结果或失败告警、发布与变更记录、工单或异常反馈这三类,因为它们最容易直接反映产能异常。

来源:项目库 + 外部公开资料(当前仍在校验)
  • 通过点:
    • 直接优先吃 recommendation 正文
    • 不回落到 analysis packet fallback
    • 不出现 External Freshness Guard
    • 也不把 recommendation ask 说成“已收到需求/准备起草”
  • 评分:9.5 / 10
  • 结论:能稳稳过我的标准
  • 原因:这是最贴近客户可见结果的一条。前面所有 schema、planner、ingress、presenter 做得再好,只要 Feishu 落地文案退回旧 fallback,就都不算真的完成;这条证明最终用户看到的文本已经站对位置了。

实际运行结果

执行命令:

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

实际结果:

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/合同层,单独看还不算完整行为闭环。