docs(catalog): add IP-034 unstaffable team lane is a typed gap - #4641
Conversation
A team plan may contain a lane this host cannot staff: the Agent registration, capability grant, or action kind does not exist here. The shipped behavior (loopx-project#4569) keeps the plan admitted, names the lane as a typed gap, and creates only the lanes that can run, but no catalog entry named that boundary. IP-034 fills it in the Planning Governance family: name the gap instead of inventing the lane, keep the admitted plan, show the lane instead of dropping it silently, and require explicit new intent before a gap is filled. IP-018 owns plan-to-todo writeback and IP-024 owns the repair delta; neither covers part of an admitted plan having no honest owner. Adds the family table row, the family-to-canary matrix entry, and three durable assertions to examples/interaction-pattern-catalog-smoke.py. Closes loopx-project#4638 Refs GH-C37 Signed-off-by: BigDataDZ <76271875+BigDataDZ@users.noreply.github.com>
huangruiteng
left a comment
There was a problem hiding this comment.
Reviewed exact head: 84c9b49e296640b3e6b0f831558ea914e37b73d0 (docs/ip-034-unstaffable-lane-gap).
动机
交互模式目录(docs/concepts/interaction-pattern-catalog.md)记录可复用的 user/agent/state 交互形状,它自己的维护规则写明:只有当这套行为本身是可复用交互、且有 trigger / 渠道 / 状态契约 / bad smell / validation 时才分配新 IP;若已被某个 IP 覆盖,就应该把新的 smoke、fixture 或说明追加到那个 IP 里。steward/manager 的 team plan 路径在已发布代码里已经把「准入(admission)」和「配人(staffing)」分开处理,但目录里没有这条形状,于是 reviewer 每次都要重新推导,canary/readiness 的分组表也没有可指向的条目。
我按这条维护规则先去找「不加新 IP」的更强理由:目录里已有 33 个模式,最近邻是 IP-031(manager context 不是 turn authority,讲的是权威绑定)、IP-018(plan→todo writeback)和 IP-024(repair delta),它们分别拥有权威、写回与前沿修复,没有谁拥有「已被准入的计划里有一条 lane 没有诚实归属」这件事。新章节也明确写出与这两个相邻 IP 的边界,所以新增 IP 是正确层级,而不是往旧条目里塞。
改动思路
改动只有两个文件:目录文档与它的守卫 smoke。文档侧把 IP-034 注册到该出现的三处(Planning Governance 分组行、P1 行列表、完整模式章节),结构与其兄弟条目完全一致(Trigger / Expected behavior / Visual Model / Bad smell / Validation);examples/interaction-pattern-catalog-smoke.py 增加三条必需字符串,让「条目被删掉」变成红灯——这和站内其它 IP 的登记方式一致(我核对了 IP-033 的三处出现方式,完全相同)。
行为侧我不看作者总结,而是直接找被点名的证据层次:apply 侧由 tests/test_steward_team_plan_apply.py 拥有(计划仍被准入、只创建一条可运行 lane 的 Todo、不可配的 lane 不落 Todo),preview 侧由 tests/test_steward_team_plan_preview.py 拥有(该 lane 的 staffing == "gap"、gap_reason_code、保留 declined_first_todo、preview["gaps"] 列出它),引导文案由 tests/test_manager_team_plan_guidance.py 对 manager_skill_text() 做 prose 断言。这三层我都实际跑过。
具体改动
2 个文件、+86/-1:docs/concepts/interaction-pattern-catalog.md +83/-1(分组行就地扩展、P1 行新增、完整章节新增)、examples/interaction-pattern-catalog-smoke.py +3(三条必需字符串)。没有生产代码、没有 canary、没有授权面变化。
关键代码讲解
- 分组行(
docs/concepts/interaction-pattern-catalog.md:93):把 IP-034 放进 Planning Governance,使这条形状能被 canary/readiness 分组选择到——这是「写目录」而不是「写一段说明」的实际作用点。 - 完整章节(
:2771起):四条 expected behavior 正好对应「不发明 lane/Agent/capability/action kind」「整份计划仍然被准入」「不静默丢弃 lane」「gap 不会自愈」,并配 mermaid 图与 bad smell,符合目录模板。 - smoke(
examples/interaction-pattern-catalog-smoke.py:149):三条require字符串把这个条目纳入既有守卫,而不是新建一份只服务于本 PR 的检查。
对主干的风险
我跑了:python examples/interaction-pattern-catalog-smoke.py → ok;pytest tests/test_steward_team_plan_apply.py tests/test_manager_team_plan_guidance.py -q → 19 passed。头部 CI 14 项成功、0 失败,review 时 4 项仍在排队(test-shard 1/2、stage2c e2e 1、checks),merge_state=BEHIND 属于待更新分支。
我也扫了同类产物:rg 显示 "unstaffable" 只出现在新章节、smoke 和那两个测试文件里,没有第二份文档重复描述这条形状;作者批量上,BigDataDZ 的目录类 PR 分布在 09-13、09-14、09-17 多天(IP-029/IP-028/IP-031/IP-034),中间夹着其它合并,不属于几分钟内同形状连发(同日的 #4642 是已关闭的 CLI 重构,与本文档无关)。
两条非阻塞问题:
-
Validation 一节的层次归属不准(P2)。它写「
tests/test_manager_team_plan_guidance.pypins the preview contract」,但那个文件断言的是 SKILL.md 的文案,真正机器强制的 preview 契约由tests/test_steward_team_plan_preview.py::test_an_unsupported_action_kind_gaps_that_lane_instead_of_refusing_the_plan拥有(staffing == "gap"、gap_reason_code == "action_kind_not_supported"、保留declined_first_todo、first_todo不存在、preview["gaps"]列出该 lane),而这一条没有被引用。读者按 Validation 去找证据,会把机器强制的半边误当成只有文案守护——这正是仓库反复强调的 guidance 与 obligation 不能混。建议补上该 preview 测试的引用,并把 guidance 测试明确标注为文案契约。 -
分组行的 evidence 列没有跟着更新(P3)。Planning Governance 行现在选择了 IP-034,但该行的典型证据仍只写「two-turn stalled fixture plus repair/writeback delta assertion」,没有体现这条形状的证据是「preview 的 staffing gap + apply receipt」。这行存在的意义就是把行映射到 canary archetype,建议把这句补进 evidence 列。
我的整体评价
结论 APPROVE。这是一次边界正确、层级正确的目录补充:它没有为新 IP 而新 IP(先论证了三个最近邻 IP 都不拥有这条形状),登记位置与该目录既有约定一致,并且我逐条验证了它宣称的行为在 head 上有真实可运行的证据(preview / apply / guidance 三层,19 项测试通过)。smoke 的 3 行新增是把条目纳入既有守卫,而不是再造一份只服务本 PR 的检查,符合「薄而持久」的要求。
两条问题都不影响这个判断:它们都是「读者会顺着目录找到错误层次/不完整映射」的文档精度问题,最小修法已经写明,不需要改运行时行为。按仓库规则,本评审只给出 exact-head 结论;合并就绪度(CI 收敛、BEHIND 更新)属于另一道关卡。
English verdict: APPROVE - exact head 84c9b49; IP-034 is registered in the same three places as its siblings, its claims are backed by shipped tests I ran (apply-side exactly-one-Todo, preview-side per-lane staffing gap, guidance prose; 19 passed plus the catalog smoke ok), and the 3-line smoke addition extends the existing guard instead of adding a one-off check. Two non-blocking findings: the Validation section attributes the preview contract to the guidance-text test and omits tests/test_steward_team_plan_preview.py that actually enforces it (P2), and the Planning Governance group row's evidence column was not extended for the new pattern (P3).
Goal And Delivered Outcome
examples/interaction-pattern-catalog-smoke.pyfails if the entry's core sentence, its family table row, or its family-to-canary matrix cell is removed.main.Scope And Continuation
Validation
84c9b49e2(rebased onto currentmain)staticpassedpython3 examples/interaction-pattern-catalog-smoke.py—ok; asserts IP-034 owns exactly one family table row and one matrix cell and that "An unstaffable lane is a typed gap, not an invented lane." plus the missing-registration wording surviveunitpassedpython3 -m pytest -q tests/test_manager_team_plan_guidance.py tests/test_steward_team_plan_apply.py— 19 passed;test_a_lane_whose_kind_the_host_does_not_ship_creates_nothingis the shipped behavior IP-034 documents (plan admitted, one Todo created for the lane that can run, none for the unstaffable lane)real_entrypointpassedpython3 -m loopx.entrypoint check --scan-path docs/concepts/interaction-pattern-catalog.md—ok, errors=0, public boundary scan clean; the 2 warnings are the pre-existing missing local registry on this checkout, unrelated to the diffregression_paritynot_applicableFrontend / Visual Evidence
Type of Change
LoopX Area
Technical Direction
Shared-authority RFC fixture impact
Boundary Checklist
.loopx/,.codex/goals/, and liveACTIVE_GOAL_STATE.md).none.Signed-off-bytrailer (git commit -s).