<?xml version="1.0" encoding="utf-8"?><feed xmlns="http://www.w3.org/2005/Atom" xml:lang="zh-CN"><generator uri="https://jekyllrb.com/" version="3.10.0">Jekyll</generator><link href="https://caomengxuan666.github.io/feed.xml" rel="self" type="application/atom+xml" /><link href="https://caomengxuan666.github.io/" rel="alternate" type="text/html" hreflang="zh-CN" /><updated>2026-05-30T18:05:43+08:00</updated><id>https://caomengxuan666.github.io/feed.xml</id><title type="html">曹梦轩</title><subtitle>记录 cxxmcp、Windows/Linux 工具、Redis 兼容数据库和一些 C++/Rust 基础设施实验。</subtitle><author><name>曹梦轩</name></author><entry><title type="html">cxxmcp：async result 和 executor timer 这种小修最容易变成大 bug</title><link href="https://caomengxuan666.github.io/posts/2026/05/30/cxxmcp-async-timers/" rel="alternate" type="text/html" title="cxxmcp：async result 和 executor timer 这种小修最容易变成大 bug" /><published>2026-05-30T00:00:00+08:00</published><updated>2026-05-30T00:00:00+08:00</updated><id>https://caomengxuan666.github.io/posts/2026/05/30/cxxmcp-async-timers</id><content type="html" xml:base="https://caomengxuan666.github.io/posts/2026/05/30/cxxmcp-async-timers/"><![CDATA[<p><a href="https://github.com/caomengxuan666/cxxmcp/commit/689581b098da31d57167cb104a796ee0c54e0f10"><code class="language-plaintext highlighter-rouge">689581b</code></a> 的提交信息很短：<code class="language-plaintext highlighter-rouge">fix: harden async result and executor timers</code>。这种提交通常不适合写成“发布亮点”，但适合写进开发日志。</p>

<p>SDK 里的 async result 和 timer 不是孤立工具。它们通常挂在请求生命周期、超时、取消、回调调度和 executor 退出路径上。一个 timer 如果在错误线程触发，或者 result 在完成/取消之间没有清晰状态，最后表现出来可能是随机 hang、重复回调、析构时崩溃，或者测试里偶现的 timeout。</p>

<p>cxxmcp 现在的方向是把 <code class="language-plaintext highlighter-rouge">Peer</code>、<code class="language-plaintext highlighter-rouge">Service</code>、transport 和 handler 边界拆清楚。越是这种结构，越不能让底层 timer 偷偷拥有模糊生命周期。因为上层 API 看起来越干净，底层异步边界出错时就越难解释。</p>

<p>这类修复我会优先关注三件事：</p>

<ol>
  <li>result 是否只有一个完成路径。</li>
  <li>timer 取消和 executor shutdown 的顺序是否固定。</li>
  <li>测试失败时有没有证据说明是超时、取消还是 handler 本身失败。</li>
</ol>

<p>这篇先记到这里。后面如果这个区域继续改，应该把具体状态机画出来，而不是只在提交信息里写 harden。</p>]]></content><author><name>曹梦轩</name></author><category term="cxxmcp" /><category term="async" /><category term="timers" /><summary type="html"><![CDATA[689581b 修的是 async result 和 executor timers。它不像新功能显眼，但这类边界通常最影响 SDK 的稳定感。]]></summary></entry><entry><title type="html">cxxmcp v1.1.2：release gates 先要能留下证据</title><link href="https://caomengxuan666.github.io/posts/2026/05/30/cxxmcp-release-gates/" rel="alternate" type="text/html" title="cxxmcp v1.1.2：release gates 先要能留下证据" /><published>2026-05-30T00:00:00+08:00</published><updated>2026-05-30T00:00:00+08:00</updated><id>https://caomengxuan666.github.io/posts/2026/05/30/cxxmcp-release-gates</id><content type="html" xml:base="https://caomengxuan666.github.io/posts/2026/05/30/cxxmcp-release-gates/"><![CDATA[<p>今天 cxxmcp 的提交大多不在 API 表面，而在发布链路上。</p>

<p>相关提交：</p>

<ul>
  <li><a href="https://github.com/caomengxuan666/cxxmcp/commit/1fdbec02841d85dcb98b39593cac0e5f6f38ecf7"><code class="language-plaintext highlighter-rouge">1fdbec0</code></a>：把 release gate 的 JUnit evidence 写到会被上传的路径。</li>
  <li><a href="https://github.com/caomengxuan666/cxxmcp/commit/994993785b01001d245e86be4e9df076af1b3017"><code class="language-plaintext highlighter-rouge">9949937</code></a>：把 external consumer templates 放进 SDK source release。</li>
  <li><a href="https://github.com/caomengxuan666/cxxmcp/commit/3ceaf5ce8e43e662ce316a001a0a9f6edb9d7df3"><code class="language-plaintext highlighter-rouge">3ceaf5c</code></a>：校验 split release gate archives。</li>
  <li><a href="https://github.com/caomengxuan666/cxxmcp/commit/000430d2f9c1b113ee61f9e5cbb2d5073078a5d7"><code class="language-plaintext highlighter-rouge">000430d</code></a>：加 release preparation script。</li>
  <li><a href="https://github.com/caomengxuan666/cxxmcp/releases/tag/v1.1.2"><code class="language-plaintext highlighter-rouge">v1.1.2</code></a>：对应发布。</li>
</ul>

<p>我现在更倾向于把 SDK 的发布看成一组可复查的证据，而不是一次打 tag。尤其是 cxxmcp 这种要给下游 CMake consumer 用的库，源码包里少一个模板、artifact 路径写错、归档层级多一层，都会变成用户侧的安装问题。</p>

<p>这类 CI 修复看起来琐碎，但它们决定了发布是否能被别人复现。README 里写支持 Conan、vcpkg、FetchContent 没什么用，真正要紧的是 release artifact 里有没有足够的消费样例，以及 gate 失败时能不能定位到哪个包、哪个 layout 出了问题。</p>

<p>后面应该继续把 release gate 的输出做得更像审计记录：版本、包内容、consumer smoke test、conformance evidence，各自有稳定路径。这样发布以后回头看，不需要靠记忆解释“当时为什么能发”。</p>]]></content><author><name>曹梦轩</name></author><category term="cxxmcp" /><category term="ci" /><category term="release" /><summary type="html"><![CDATA[这次 cxxmcp 发布前，主要在修 release gates、归档检查和外部 consumer 模板，目标是让发布不是只看一次 CI 绿灯。]]></summary></entry><entry><title type="html">cxxmcp conformance 跑出来的 SEP-2243 问题</title><link href="https://caomengxuan666.github.io/posts/2026/05/29/mcp-sep2243-conformance/" rel="alternate" type="text/html" title="cxxmcp conformance 跑出来的 SEP-2243 问题" /><published>2026-05-29T00:00:00+08:00</published><updated>2026-05-29T00:00:00+08:00</updated><id>https://caomengxuan666.github.io/posts/2026/05/29/mcp-sep2243-conformance</id><content type="html" xml:base="https://caomengxuan666.github.io/posts/2026/05/29/mcp-sep2243-conformance/"><![CDATA[<p>这次问题不是 cxxmcp 自己的单点 bug，而是 conformance、spec 和多个 SDK 之间的互操作问题。</p>

<p>SEP-2243 要求 MCP HTTP POST 请求带这些 header：</p>

<ul>
  <li><code class="language-plaintext highlighter-rouge">Mcp-Method</code>：每个 POST 都要带，值来自 JSON-RPC <code class="language-plaintext highlighter-rouge">method</code>。</li>
  <li><code class="language-plaintext highlighter-rouge">Mcp-Name</code>：当请求里有 <code class="language-plaintext highlighter-rouge">params.name</code> 或 <code class="language-plaintext highlighter-rouge">params.uri</code> 时带上。</li>
</ul>

<p>跑 cxxmcp conformance 时出现了一个矛盾：<code class="language-plaintext highlighter-rouge">http-header-validation / ServerRejectsMissingMethodHeader</code> 测试要求服务器拒绝缺失 <code class="language-plaintext highlighter-rouge">Mcp-Method</code> 的请求；但 conformance 里其他场景用的 TypeScript SDK <code class="language-plaintext highlighter-rouge">StreamableHTTPClientTransport</code> 本身没有发送这个 header。</p>

<p>所以结果会变成两难：</p>

<ul>
  <li>如果服务器严格实现 SEP-2243，很多 SDK-backed 场景会失败。</li>
  <li>如果服务器为了兼容 TypeScript SDK 放宽校验，<code class="language-plaintext highlighter-rouge">ServerRejectsMissingMethodHeader</code> 又会失败。</li>
</ul>

<p>我把这个问题拆成了几组 issue：</p>

<ul>
  <li><a href="https://github.com/modelcontextprotocol/conformance/issues/323">modelcontextprotocol/conformance#323</a>：conformance suite 自相矛盾。</li>
  <li><a href="https://github.com/modelcontextprotocol/typescript-sdk/issues/2176">modelcontextprotocol/typescript-sdk#2176</a>：TypeScript SDK 没有发送 <code class="language-plaintext highlighter-rouge">Mcp-Method</code> / <code class="language-plaintext highlighter-rouge">Mcp-Name</code>。</li>
  <li><a href="https://github.com/modelcontextprotocol/python-sdk/issues/2715">python-sdk#2715</a>、<a href="https://github.com/modelcontextprotocol/ruby-sdk/issues/366">ruby-sdk#366</a>、<a href="https://github.com/modelcontextprotocol/java-sdk/issues/990">java-sdk#990</a>、<a href="https://github.com/modelcontextprotocol/kotlin-sdk/issues/787">kotlin-sdk#787</a>、<a href="https://github.com/modelcontextprotocol/swift-sdk/issues/228">swift-sdk#228</a>：让各语言 SDK 补齐同一组 header。</li>
</ul>

<p>这件事对 cxxmcp 的意义是：conformance 不是“跑过就完了”。当测试、reference client 和 spec 互相打架时，SDK 要么把问题记录清楚，要么就在实现里留下一个说不清的兼容分支。</p>

<p>我现在更倾向于把这类问题写进 release evidence：哪些失败来自自己，哪些来自上游，哪些是 spec/SDK 之间的行为差异。否则 109/110、447/447 这种数字看起来很清楚，实际解释成本仍然很高。</p>]]></content><author><name>曹梦轩</name></author><category term="cxxmcp" /><category term="mcp" /><category term="conformance" /><summary type="html"><![CDATA[cxxmcp 在跑 MCP conformance 时发现一个矛盾：测试要求服务器拒绝缺失 Mcp-Method 的请求，但 reference client 自己没有发送这个 header。]]></summary></entry><entry><title type="html">AstraDB：OBJECT、MEMORY STATS、LATENCY 这些命令不好糊弄</title><link href="https://caomengxuan666.github.io/posts/2026/05/27/astradb-memory-latency/" rel="alternate" type="text/html" title="AstraDB：OBJECT、MEMORY STATS、LATENCY 这些命令不好糊弄" /><published>2026-05-27T00:00:00+08:00</published><updated>2026-05-27T00:00:00+08:00</updated><id>https://caomengxuan666.github.io/posts/2026/05/27/astradb-memory-latency</id><content type="html" xml:base="https://caomengxuan666.github.io/posts/2026/05/27/astradb-memory-latency/"><![CDATA[<p>Redis 兼容不是只把常用读写命令跑通。客户端、监控系统和压测工具会问很多“状态类”命令，返回值不准也会造成兼容问题。</p>

<p>这次 AstraDB 的相关提交：</p>

<ul>
  <li><a href="https://github.com/caomengxuan666/AstraDB/commit/9fb44c9e1172b76ada53be7dbe9b93ccbf0d6908"><code class="language-plaintext highlighter-rouge">9fb44c9</code></a>：增强 <code class="language-plaintext highlighter-rouge">OBJECT</code>、<code class="language-plaintext highlighter-rouge">MEMORY STATS</code> 和 <code class="language-plaintext highlighter-rouge">LATENCY</code>。</li>
  <li><a href="https://github.com/caomengxuan666/AstraDB/commit/9355ae6dff5361c4d6b4ff7edd05666b1ea381b2"><code class="language-plaintext highlighter-rouge">9355ae6</code></a>：<code class="language-plaintext highlighter-rouge">MEMORY STATS</code> 使用正确的 <code class="language-plaintext highlighter-rouge">EvictionPolicy</code> 名称转换。</li>
</ul>

<p><code class="language-plaintext highlighter-rouge">OBJECT ENCODING</code> 这类命令看起来只是返回字符串，但它要知道底层数据结构：string 是 int 还是 raw，hash 是 hashtable，sorted set 是 b+tree，stream 是 stream。这里如果随便返回一个固定值，很多调试工具会被误导。</p>

<p><code class="language-plaintext highlighter-rouge">MEMORY STATS</code> 更麻烦，它不能只给一个估算数字。至少要接上实际 memory tracker，还要把 <code class="language-plaintext highlighter-rouge">maxmemory</code>、<code class="language-plaintext highlighter-rouge">maxmemory-policy</code> 这类配置暴露出来。后续那个 enum 名称修复也说明了一个问题：兼容命令里的字符串就是 API，不是内部实现细节。</p>

<p><code class="language-plaintext highlighter-rouge">LATENCY</code> 的子命令也类似。<code class="language-plaintext highlighter-rouge">LATEST</code>、<code class="language-plaintext highlighter-rouge">HISTORY</code>、<code class="language-plaintext highlighter-rouge">RESET</code>、<code class="language-plaintext highlighter-rouge">EVENTS</code>、<code class="language-plaintext highlighter-rouge">GRAPH</code>、<code class="language-plaintext highlighter-rouge">DOCTOR</code> 都会被运维脚本当作可观测性接口。实现这些命令，比补一个普通数据结构命令更能暴露系统内部是否有足够的事件记录。</p>]]></content><author><name>曹梦轩</name></author><category term="AstraDB" /><category term="redis" /><category term="compatibility" /><summary type="html"><![CDATA[9fb44c9 给 AstraDB 补了 OBJECT ENCODING、MEMORY STATS 和 LATENCY 子命令，后面又修了 EvictionPolicy 名称映射。]]></summary></entry><entry><title type="html">ferryllm：thinking_delta 不能被当成 text_delta</title><link href="https://caomengxuan666.github.io/posts/2026/05/27/ferryllm-thinking-delta/" rel="alternate" type="text/html" title="ferryllm：thinking_delta 不能被当成 text_delta" /><published>2026-05-27T00:00:00+08:00</published><updated>2026-05-27T00:00:00+08:00</updated><id>https://caomengxuan666.github.io/posts/2026/05/27/ferryllm-thinking-delta</id><content type="html" xml:base="https://caomengxuan666.github.io/posts/2026/05/27/ferryllm-thinking-delta/"><![CDATA[<p><a href="https://github.com/caomengxuan666/ferryllm/commit/00cb7e54ca0b8243190a05cd0c2534493c1f0e5b"><code class="language-plaintext highlighter-rouge">00cb7e5</code></a> 修的是一个很典型的协议网关问题：Anthropic 后端会发 <code class="language-plaintext highlighter-rouge">thinking_delta</code> SSE event，但 ferryllm 的 IR 里没有对应的 <code class="language-plaintext highlighter-rouge">ThinkingDelta</code> variant。</p>

<p>结果是 adapter 把它悄悄转成了 <code class="language-plaintext highlighter-rouge">TextDelta</code>。这看起来像“内容还在”，但协议语义已经变了。客户端期望的是 thinking block 的增量，收到 text delta 以后可能直接认为 stream 违规，然后断开。</p>

<p>这次修复做了几件事：</p>

<ul>
  <li>在 IR 的 <code class="language-plaintext highlighter-rouge">ContentDelta</code> 里加入 <code class="language-plaintext highlighter-rouge">ThinkingDelta</code>。</li>
  <li>Anthropic adapter 把后端的 thinking delta 映射到 IR thinking delta。</li>
  <li>Anthropic entry 发出正确的 <code class="language-plaintext highlighter-rouge">thinking_delta</code> SSE event。</li>
  <li>streaming index remap 逻辑也要认识 thinking block。</li>
</ul>

<p>ferryllm README 里写的是 <code class="language-plaintext highlighter-rouge">Client protocol -&gt; ferryllm IR -&gt; provider protocol</code>。这条路径的前提是 IR 不能丢语义。如果 IR 为了省事把不同 event 合并成普通 text，后面每个 provider/client adapter 都要靠猜来补，最后还是回到 N x M 的坑里。</p>

<p>所以这类 bug 的教训很直接：协议网关的中间表示宁愿多几个细粒度 variant，也不要把上游语义压扁。</p>]]></content><author><name>曹梦轩</name></author><category term="ferryllm" /><category term="llm" /><category term="protocol" /><summary type="html"><![CDATA[00cb7e5 修了 Anthropic thinking_delta 被错误映射的问题。协议网关里，中间表示少一个 variant 就可能让客户端断流。]]></summary></entry><entry><title type="html">WinuxCmd v0.11.1：补 GNU coreutils 命令比想象中更像兼容性工程</title><link href="https://caomengxuan666.github.io/posts/2026/05/27/winuxcmd-coreutils-0111/" rel="alternate" type="text/html" title="WinuxCmd v0.11.1：补 GNU coreutils 命令比想象中更像兼容性工程" /><published>2026-05-27T00:00:00+08:00</published><updated>2026-05-27T00:00:00+08:00</updated><id>https://caomengxuan666.github.io/posts/2026/05/27/winuxcmd-coreutils-0111</id><content type="html" xml:base="https://caomengxuan666.github.io/posts/2026/05/27/winuxcmd-coreutils-0111/"><![CDATA[<p>WinuxCmd 的 <a href="https://github.com/caomengxuan666/WinuxCmd/releases/tag/v0.11.1"><code class="language-plaintext highlighter-rouge">v0.11.1</code></a> 不是只加几个命令。</p>

<p>这轮相关提交里有三类工作：</p>

<ul>
  <li><a href="https://github.com/caomengxuan666/WinuxCmd/commit/a12a73344f120b8de9af3963c453ebacef633515"><code class="language-plaintext highlighter-rouge">a12a733</code></a>：把 20 多个命令里“解析了但没真正生效”的选项接到逻辑里。</li>
  <li><a href="https://github.com/caomengxuan666/WinuxCmd/commit/4fe10c810abcba48eb2f0e98565162e63268a50a"><code class="language-plaintext highlighter-rouge">4fe10c8</code></a>：加 <code class="language-plaintext highlighter-rouge">stty</code>、<code class="language-plaintext highlighter-rouge">dir</code>、<code class="language-plaintext highlighter-rouge">vdir</code>、<code class="language-plaintext highlighter-rouge">dircolors</code>、<code class="language-plaintext highlighter-rouge">chgrp</code>。</li>
  <li><a href="https://github.com/caomengxuan666/WinuxCmd/commit/4caaf6174b97f1188fef3a33ca838881b1933f2c"><code class="language-plaintext highlighter-rouge">4caaf61</code></a>：加 <code class="language-plaintext highlighter-rouge">strings</code>、<code class="language-plaintext highlighter-rouge">hexdump</code>、<code class="language-plaintext highlighter-rouge">col</code>、<code class="language-plaintext highlighter-rouge">more</code>。</li>
</ul>

<p>做这类工具时，最容易低估的是“选项存在”和“行为可用”之间的差距。CLI 可以接受 <code class="language-plaintext highlighter-rouge">--sort-keys</code>、<code class="language-plaintext highlighter-rouge">--strict</code>、<code class="language-plaintext highlighter-rouge">--one-file-system</code>，但如果解析完没有进入输出逻辑，那它对用户来说就是假兼容。</p>

<p>Windows 上实现 GNU coreutils 还会遇到另一层问题：有些语义本来就不是一一对应的。比如权限、组、终端模式、设备文件、管道行为，都不能简单照搬 Unix 实现。这里更像是在做一组实用兼容层，而不是追求字面复刻。</p>

<p>所以我觉得 v0.11.1 的重点不是“命令数量增加到多少”，而是开始把 option wiring、测试和文档一起补齐。命令越多，越需要靠测试证明某个参数真的改变了行为。</p>]]></content><author><name>曹梦轩</name></author><category term="WinuxCmd" /><category term="windows" /><category term="coreutils" /><summary type="html"><![CDATA[v0.11.1 增加了 stty、dir、vdir、dircolors、chgrp、strings、hexdump、col、more，也把很多已解析但没生效的选项接到实现里。]]></summary></entry></feed>