Repository navigation
fix(mcp): close post-#30 catalog, re-tick, steer, and watermark residuals - #31
Merged
Merged
Conversation
…uals Advertise tools.listChanged and send tools/list_changed after initialize so hosts refresh a catalog that already lists swarm_doctor. Omit gate_soft_continue on unfinished soft-gap tick and fuse envelopes (never write false) and set soft_gap.tick=false. Drop bench freeze and baseline from those solidify steers. Fast-skip a watermark only when the full hash matches, so a same-size rewrite is not a silent skip. Co-authored-by: Steper Lin <linker.lin@live.com>
The catalog refresh notification has no id. The e2e recv treated the next stdout line as the JSON-RPC result, so tools/call and prompts/get raised KeyError on result. Read until the matching id, and pin that pairing with a regression. Co-authored-by: Steper Lin <linker.lin@live.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
#30 之后还剩四件事:宿主目录经常看不到
swarm_doctor、只认gate_soft_continue=true的宿主在未完成软缺口上会再 tick、软固化引导仍把bench freeze/bench baseline列成当前步骤、以及test_identical_rewrite_is_noop在部分文件系统上失败。这一支把四件都收进同一份改动。Four residuals left after #30 are closed together: the host catalog lag on
swarm_doctor, soft-continue-only hosts re-ticking an unfinished soft gap, freeze/baseline still offered as the current solidify step, and the material watermark treating an identical rewrite asskipped.CI follow-up
notifications/tools/list_changed没有id。e2e 的recv把握手后的下一行当成 JSON-RPC 响应,于是tools/call和prompts/get在["result"]上KeyError(run 41606679556:3.13 十处、slow 两处、Windows 同一形态)。协议测试客户端本来就会跳过无id的notifications/*。e2e 客户端现在同样跳过,并按请求id配对。test_00_list_changed_does_not_desync_the_next_response钉住:通知被收进侧账,下一次tools/list与prompts/get仍带result。本地uv run pytest tests/e2e/test_swarm_full_e2e.py -q --tb=short -m "not llm"为 12 passed;协议 / usability / mcp_server 48 passed。服务端仍在 initialized 之后发这条通知,没有改成不发。What changed per residual
1. DEBUG #61 —
swarm_doctor在宿主目录里消失服务端
tools/list本来就在同一页列出只读swarm_doctor(探测:29 个工具、无nextCursor、载荷约 25KB、doctor 在中部、带 cursor 再要一页仍然在)。注册没有漏,也没有按名字过滤。握手用默认NotificationOptions(),tools.listChanged为 false。把「列表永不变」当成可以跨重启留目录的宿主,调用打到新进程,目录仍停在旧快照上。现在初始化广告
tools.listChanged=true(prompts / resources 一并标可变),并在notifications/initialized之后发一次notifications/tools/list_changed。不另注册一个假工具。仍忽略该通知、也不在新会话重读tools/list的宿主,目录仍旧;这是仓外行为,DEBUG #76 写明了。2. 只看
gate_soft_continue=true的宿主会再 tick#30 把这个键写回第一次未完成软缺口 tick 和保险丝,软缺口重新可见,但只在该键为严格 true 时再 tick 的宿主又会空转。写成 false 会重开 DEBUG #67(严格 false 被当成整段会话失败)。
这次只在 tick 与保险丝上 去掉 这个键,绝不写成 false。同时写结构字段
soft_gap:present=true、advisory=true、tick=false,有缺口码时带code。boot / status 仍写gate_soft_continue=true,且不带soft_gap。doctor 仍不写gate_soft_continue、session_not_failed、soft_gap。保险丝仍是ok=false、没有error、loop_fuse=pending_redirect_loop、session_not_failed=true,preserve 三元组不动。3. 软固化引导上的 freeze / baseline
_commands_without_current_doctor_fix现在同时丢掉精确的evolver doctor --fix、evolver bench freeze、evolver bench baseline。next_steps里点名 freeze 或 baseline 的句子改成「先swarm_solidify,不要现在跑这两条」。作用面是未完成 run 的 boot / status / doctor / 第一次 tick / 保险丝。没有未完成 run 时这三条仍在。本路径不执行--fix,不冻结包,不写 Parent baseline,不放宽固化门。4. 水印
test_identical_rewrite_is_noop快跳过原先只比
mtime_ns和size。本环境的文件系统在write()时把 mtime 拨回创建时刻,os.utime会被下一次写入盖掉,于是相同字节重写被记成skipped而不是rewrite_noop。GitHub 上 master 的 ext4 会推进 mtime,所以 CI 是绿的;同一套只看 mtime 的快跳过,在 mtime 被还原时会把同长度的真实改写静默跳过。现在快跳过还要比全文哈希。相同字节且 mtime 变了仍是rewrite_noop。同长度、mtime 被拨回去、字节不同则走全量重扫。How to test
uv run pytest tests/e2e/test_swarm_full_e2e.py -q --tb=short -m "not llm" uv run pytest tests/test_mcp_protocol.py tests/test_mcp_host_usability_pending_smoke.py tests/test_mcp_server.py -q --tb=line uv run pytest tests/gep/test_material.py tests/test_mcp_protocol.py \ tests/test_mcp_host_usability_pending_smoke.py \ tests/test_mcp_host_usability_p0.py tests/test_mcp_host_usability_p1.py \ tests/test_mcp_server.py tests/test_open_box_setup_doctor.py tests/test_swarm.py uv run ruff check src tests uv run ruff format --check src tests uv run mypy src本地结果:e2e(不含 llm)12 passed;协议 / usability / mcp_server 48 passed;早先相关套件 167 passed;ruff 与 mypy 通过。未设置
DEEPSEEK_API_KEY,live-LLM 三条用-m "not llm"跳过。Risk
Medium。改的是 MCP 宿主契约和物料摄取,不是固化门、Parent baseline 或评分器。
gate_soft_continue is True时才 tick 的宿主,在未完成软缺口的 tick / 保险丝上会停,并应去swarm_solidify。boot / status 上这个键仍为 true,那些宿主仍可能从 boot 再进一次 tick;tick 信封本身不再用 true 邀请下一次。notifications/tools/list_changed的宿主仍要新开一次会话才能看到swarm_doctor。How we fixed each residual
可直接贴回聊天:
DEBUG #61。 根因在本仓库的握手,不在工具注册。同一进程的
tools/list已经包含只读swarm_doctor(一整页、无nextCursor)。默认广告是tools.listChanged=false,宿主因此把目录当成永不变,重启后的新进程调用打得到、目录仍是旧的。修复是广告listChanged=true,并在notifications/initialized之后发送notifications/tools/list_changed。没有造假工具。不听这个通知的宿主仍须新开会话;这一点写在 DEBUG #76 和协议测试里。只认 soft-continue 的宿主再 tick。 未完成软缺口的第一次
swarm_tick和loop_fuse=pending_redirect_loop省略gate_soft_continue,从不写成 false。新增soft_gap.advisory=true与soft_gap.tick=false,让「缺口还在」和「不要再 tick」分开。boot / status 继续写gate_soft_continue=true,让需要看见软缺口的宿主不受影响。doctor 仍不写这个键、不写session_not_failed、不写soft_gap。保险丝保持ok=false+session_not_failed+loop_fuse=pending_redirect_loop,没有error字段。preserve 三元组仍在。freeze / baseline 瘦身。 未完成 run 的软固化引导(boot、status、doctor、第一次 tick、保险丝)从
commands/fixes去掉精确的evolver bench freeze和evolver bench baseline,next_steps改成先固化。没有未完成 run 时这两条和evolver doctor --fix仍列出。不执行--fix,不写 Parent baseline,不放宽固化门。水印。
ingest_file的快跳过改为(mtime_ns, size, full_hash)三者都相符才skipped。相同字节的重写仍是rewrite_noop,不追加记录。同长度但内容变了、mtime 又被文件系统拨回去时走全量重扫。测试在写入之后再utime,这样在会还原 mtime 的文件系统上也能走到 memo 路径;另有一条同长度、还原 mtime、字节不同的用例钉住重扫。没有删测试,也没有 skip。CI。 上述目录通知没有
id。e2e 客户端把它读成下一次调用的响应。recv现在跳过notifications/*,直到匹配请求id的帧。回归测试确认tools/list与prompts/get仍有result,通知记在侧账里。Harness/evaluator governance
Upstream governance surface: MCP swarm host catalog and unfinished-run envelopes (
swarm_tick/swarm_boot/swarm_status/swarm_doctor); material watermark ingest. Not GEP scoring, solidify accept, or Parent baseline.Downstream EvoX impact: hosts that tick only while
gate_soft_continueis strictly true stop on the unfinished soft-gap tick and fuse. Boot and status still expose that bit. No bridge contract change.Rollout-local scope: protocol and ingest behavior on this branch; no cohort flag.
Promotion boundary: merge to master. No separate rollout switch.
Evaluator mismatch sets: N/A -- observation envelopes and file ingest only.
Non-regression evidence: 167 related tests passed locally, including pending-smoke host simulators, MCP protocol list/notification, doctor key absence, and both watermark cases. e2e stdio suite 12 passed with live-LLM tests deselected. ruff and mypy clean.
Fix-severity review: medium
Owner approval: swarm / MCP host contract reviewer
Security boundary: no new secrets, network, or tool. Catalog notification asks the host to re-list tools the server already implements. Soft steer still does not run
evolver doctor --fixor write a Parent baseline.Rollback: revert this commit. Omitting
gate_soft_continueis absence, not false, so reverting restores the #30 true bit on tick and fuse.Live promotion: no
Autonomous evaluator self-editing: no
Self-check
uv run pytest(related suites, 167 passed; e2e without llm, 12 passed),uv run ruff check src tests,uv run ruff format --check src tests,uv run mypy src.