夜雨聆风学习资料网

ARTICLE · 1204984

同事要换掉 Office,我先去看它会坏在哪

同事要换掉 Office,我先去看它会坏在哪

上周末同事在群里甩了一个链接,配了一句:「Word、Excel、PPT、CAD、Pro Tools 全被人用纯 Rust 重写了一遍,免费,无订阅,无遥测。」

群里的反应很真实:有人已经准备下载了。理由也站得住——Office 订阅一年好几百,Pro Tools 更贵,现在有人把界面和功能点都做出来了,还是开源的,试试又不亏。

我当时做了一件事,就是把原文里的每个数字都去仓库里对了一遍。对完之后有两个结论,一个是意料之外的,一个是意料之中的。

意料之中的是:这些项目现在还不能用来干活。意料之外的是——这句话不是我说的,是项目自己写在仓库里的。它把自己的完成度标成「Ready for real work: ~60%」,还专门写了一份文档,逐条列出「我们离 Word 还差在哪」。

而真正让我们团队留下来看的,既不是它能不能替代 Word,也不是那些星数。是它给 Agent 留的那个接口。那个接口的设计,恰好命中我们自己流水线里反复踩的一个坑。这篇就把三件事讲清楚:那些数字为什么两天就废了、一个刚出生的热门项目该怎么判断、以及它的接口里哪一条最值得抄。

一、先说核实结果:原文的数字,48 小时就全废了

源文发布于 10 月 9 日,我核实的时间是 10 月 11 日。中间只隔了两天,但原文给的核心数据已经全部过时了。

核实本身很简单,不用装任何东西,一段脚本就够。这种事我建议都自己做一遍,因为一手数字和转述之间的差距,比想象中大:

# 核对星数 / fork / issue,不要信任何二手来源

# GitHub 未认证 API 限额 60 次/小时,五个仓库足够

import json, urllib.request

def repo(slug):

    req = urllib.request.Request(

        f"https://api.github.com/repos/{slug}",

        headers={"User-Agent": "curl/8"})

    d = json.loads(urllib.request.urlopen(req, timeout=30).read())

    return d["stargazers_count"], d["forks_count"], d["created_at"][:10]

for name in ["wordcraft", "gridcraft", "deckcraft", "cadcraft", "soundcraft"]:

    s, f, c = repo("storytold/" + name)

    print(f"{name:12s} star={s:6d} fork={f:5d} 建仓={c}")

跑出来的结果,和原文放在一起是这样:

     

源文数据与 48 小时后的实测对比

WordCraft 从 850 涨到 3428,四倍。五个仓库全部涨了两到四倍,原文里那个「我写的时候是 849,写完变成 850」的感慨,两天后看起来像另一个时代的事。

版本号也一样。原文说五个项目都是 v0.3.0,现在全都是 v0.5.0——两天发了四个版本。那个被当成「前作」的 Photoshop 重写版(PhotoCraft),原文说 17000 星,现在是 43229。

核实过程中还发现三处原文说得不准的地方,都值得单独提出来:

一、前作不止一个 Photoshop。原文说「之前他们就把 Photoshop 做出来了」,实际上 9 月 30 日那一批开的是七个 Adobe 系——除 Photoshop 外,还有 Illustrator、Premiere、Lightroom、Acrobat、After Effects、InDesign。到 10 月 7 日这一批 Office 系,一共是十二个应用。这不是「顺手又做了几个」,是一套流水线在批量产出。

二、许可不是单一的 Apache-2.0。原文写「授权协议是 Apache-2.0」,仓库 LICENSE 文件写的是 MIT 或 Apache-2.0,由使用者任选。这个差别对要在公司里用的人是实质性的——双许可是开源世界里对采用方最友好的一种安排,因为你可以选一个和自家法务最不冲突的。

三、DeckCraft 已经是 alpha 了,不是「还没到 alpha」。原文说它「离第一个 alpha 还差 80% 的路」,读起来像连 alpha 都没到。但它的 ROADMAP 第一行写着 Stage: alpha,下一站是 beta。方向上的判断(不成熟)是对的,程度上的描述差了一档。

这意味着:这类「国外又出了个神项目」的内容,保质期比它的发布周期还短。不是作者不认真,而是当一个项目两天发四个版本的时候,任何写下来的数字在发布那一刻就在贬值。所以看这类文章的正确姿势是:拿它当线索,不拿它当结论。

二、一个两天涨 3400 星的项目,该拿什么判断

第一个问题很难绕开:这 3428 个星,到底说明了什么?

说实话,说明不了太多。原文里其实已经点到了——「一半是情绪」。Office 订阅一年好几百,看到有人拿 Rust 全重写一遍,点个 star 就是一种表态。我翻了提交记录确认这波热度不是刷的:提交信息都带 PR 号,PR 编号已经排到 #480,提交人是多个不同账号,一天几十次提交。项目是真的在快速推进。

但「在快速推进」和「能用来干活」是两件事。星数是注意力,不是能力。那能力看什么?

这个东西给了一个我很少在开源项目里见到的答案:它把完成度拆成两个数,分开报。

     

两个完成度口径的落差

第一个数是 Ribbon / 菜单目录覆盖 402 / 434,即 92.6%。它旁边标着 measured——这个词很关键,意思是这个数不是估的,是跑命令算出来的,有对应的 checklist 文件和测试守着,而且测试里写了一个只升不降的下限。

第二个数是 Ready for real work,约 60%,区间 55% 到 63%。它旁边标的是 estimated——是估计的,多维度加权求和。

两个数差了 32 个点。这 32 个点不是水分,是它自己拆开算给你看的:功能深度(对话框里的选项、样式体系、多语言)、稳定性、文件交换。同一份 ROADMAP 里还有按人群细分的三档——主流从业者约 55%,日常必需用户约 63%。

我觉得这个做法值得抄,因为它精准地解决了一个我们自己也常犯的问题。我们在周报里说「这个功能做完了」,说的其实是第一个数——代码写了、接口通了、点了能跑。但业务方关心的是第二个数——能不能真的替代掉原来那套。两个数用同一个「完成了」去表达,后面必然要吵架。

更值得学的是它把 measured 和 estimated 明确标出来的习惯。能被命令算出来的,和只能靠人估的,混在一张表里就是耍流氓。前者可以设下限、可以进 CI、可以卡发布;后者只能作为判断依据。这个区分一标出来,读者立刻知道该信到什么程度。

这意味着:判断一个刚火起来的项目,别看星,看它敢不敢把自己的完成度分口径报出来。只报一个漂亮数字的,通常那个数字是按最宽松的口径算的。

三、它罕见地把「还差在哪」写成了结构化清单

比完成度更少见的是这个:仓库里有一个 docs/gaps.md,文件标题直译过来是《WordCraft 哪里不如 Word》。

它不是一句「项目还很早期,功能有待完善」的免责声明,而是一个缺口一行,每行都带证据、影响面、工时估计和跟踪文档,并且按「这条有多阻碍一个 Word 用户切换过来」排序。文件名旁边还有个 B 标记,意思是这一条会卡住 beta。

     

WordCraft 官方缺口清单前五条

前五条里,有两条我看到的时候是有点意外的,因为这类话通常是竞品替你说的,不是自己说的:

第一条:DOCX 从未在真实文件上测过。原话是——仓库里没有来自 Word、Google Docs、LibreOffice、Pages 的文件语料库,现有的测试全是合成构造的样例。它自己写了句更狠的总结:「人们收到的文件,就是会坏的那些文件。」而这件事从 10 月 6 日起就挂在「未启动」状态。

第二条:墨迹与绘图画布,打开时被丢弃、保存时丢失,而且不报错。原文用了一个词 silently。用 Word 画的图或者手写批注,打开再保存就没了,过程中一声不响。这种问题比崩溃更难查——崩溃你会知道,静默丢内容你可能几个月后才发现。

但这份文档里最冷的一句,藏在一个我被绕了好几个链接才找到的地方。它统计了外部用户给它提的反馈:120 个 issue,4 个称赞,0 个人说「我从 Word 切过来了」,约 21 个核心路径的 bug 还没修。

3428 个星,120 个 issue,0 个真实迁移者。这三个数放在一起,比任何功能列表都更能说明它现在处在哪个阶段。星是表态,issue 是尝试,迁移才是投票——而投票结果是零。

这意味着:评估一个项目,与其看它声称做了什么,不如看它愿意把「没做什么」写得多具体。愿意写「我们的测试数据是假的、我们的渲染器在这块会静默失败」的团队,它说「Ribbon 覆盖 92.6%」的时候你也能放心信。反过来,一份只讲能力的 README,无论写得多漂亮,都缺少那个让你判断风险的部分。

四、真正值钱的,是它给 Agent 留的那个接口

前面三节都是关于「怎么判断」。从这一节开始说为什么我们最后真的去读了它的源码——因为这个软件从第一行代码起,就是按「人和 Agent 都是使用者」设计的。

它的架构分了七层,从 L0(几何与度量)到 L6(可替换的界面)。L5 这一层就是 MCP server。一个正经的桌面办公软件,把 MCP 放在了和渲染层、排版层、文档模型层平级的位置上。

     

WordCraft 分层架构与命令分发

支撑这个设计的原则只有一句话,但执行得很彻底:Everything is a command(一切皆命令)。

WordCraft 里一共有 433 个命令,每个命令有稳定的 id。ribbon 上的按钮、键盘快捷键、命令搜索、命令行工具、JSON 控制通道、MCP server——这六个入口全部按同一份注册表、按 id 分发。你在界面上点「加粗」和让 Agent 通过 MCP 调「加粗」,走到的是同一个实现。

这里面有一条约束,我认为是整篇文章里最该记住的一句话:

# AGENTS.md 里关于命令层的两条硬约束

Programmatic calls never open dialogs.   // 永不弹框、不阻塞等输入

Everything is a command.   // 用户可见行为 = 一个 CommandSpec

    // CommandSpec = id / 标签 / 快捷键 / 参数 / 启用条件 / 实现

「永不弹对话框」这五个字,凡是让 Agent 驱动过桌面软件的人都懂它的分量。GUI 自动化的经典死法,就是 Agent 点了一个按钮,弹出一个模态框,然后整个流程静默挂在那里——没有报错,没有超时,就是永远停住了。这个项目从设计上把这条路堵死了:要么执行,要么返回错误,绝不等待人类输入。

接入方式也确实简单:

# 无头模式:不需要开界面,直接操作文档

claude mcp add wordcraft -- wordcraft-cli mcp

# 或者:把已打开的桌面应用挂上控制通道,再让 Agent 接进来

wordcraft --control 7981 &

claude mcp add wordcraft-app -- wordcraft-cli mcp --connect 127.0.0.1:7981

但真正让我把它记下来的,是下面这一条。

它暴露给 Agent 的工具里有一个叫 inspect_document。README 里对它的说明是一句非常朴素的话:

Agents can check their work through inspect_document

without screenshots.

Agent 可以通过 inspect_document 检查自己的工作,不需要截图。

     

Agent 验收方式的选择

这一条对我们不是理论,是上周刚发生的事。

我们让一个 Agent 跑跨渠道对账补单,它跑完吐出一份报告,写着「补单流程已完成」。人工核对才发现:第一个渠道处理完了,第二个渠道一张没动,第三个处理到一半开始重复处理同一批单。而那份报告是它自己写的。

当时的思路是给它加截图能力,让它在关键节点截个图自己看。后来没做,因为试下来问题很多:截图要占大量上下文,分辨率一变结论就变,而且「看起来对」和「结构上对」是两件事——一个渠道列表少了一行,截图里可能只是窄了一点,肉眼和多模态模型都不一定发现。

这个项目的答案给了我们一个更好的方向:让 Agent 验收的时候看结构,不看像素。我按这个思路把那个验证器重写了一遍,核心就一个纯函数,不渲染、不截图、不调模型:

/**

 * 对账报告的结构视图。与 WordCraft 的 inspect_document 同一条思路:

 * 让 Agent 自己验收,靠结构,不靠截图,也不靠它自己的话。

 */

public record ReconReportView(

        String batchNo,

        List<ChannelResult> channels,   // 顺序即执行顺序

        int expected, int handled, int deferred, int failed) {

    public List<String> assertConsistent() {

        List<String> problems = new ArrayList<>();

        // 判据一:总数必须闭合。差一张就是有问题,没有「差不多」

        if (handled + deferred + failed != expected) {

            problems.add("对账不平:expected=%d,但 handled+deferred+failed=%d"

                    .formatted(expected, handled + deferred + failed));

        }

        // 判据二:「某个渠道一张没动,报告却写着已完成」正是这条抓出来的

        for (ChannelResult c : channels) {

            if (c.total() > 0 && c.handled() == 0) {

                problems.add("渠道 %s 应处理 %d 张,实际一张未处理"

                        .formatted(c.channel(), c.total()));

            }

        }

        return problems;

    }

}

这段代码本身平平无奇,关键是它取代了什么:它取代了「让 Agent 自己说完成了」,也取代了「让 Agent 截图确认一下」。Agent 拿到的不是一段自然语言描述,是一个可以断言的字段集合:

// MCP 工具 inspect_recon_report 返回的是结构,不是渲染结果

{

  "batchNo": "R20261011",

  "expected": 214,

  "handled": 89,

  "deferred": 0,

  "failed": 0,

  "problems": ["对账不平:expected=214,但 handled+deferred+failed=89"]

}

如果当时是这个形态,那份「已完成」的报告在第二步就会自己暴露:214 张差异单,只有 89 张有下落,剩下 125 张去哪了?第二、第三个渠道那两张没动的单子,也会被逐渠道的判据点出来。不需要人去核对,也不需要多模态模型去解读一张截图。

还有一条设计我觉得可以顺手学过来:它的宏是可录制的——任意命令序列都能记下来回放(tools.recordMacro / tools.macros)。因为一切皆命令,所以「录制」这个动作几乎是免费的——你在界面上操作一遍就是一段可以回放的命令序列,同时它也是给 Agent 的示例。这个思路如果搬到我们自己的后台系统上,意味着运营点一遍就能生成一条可自动化的流水线初稿,比让他们写需求文档高效得多。

这意味着:给 Agent 做接口的时候,验收方式的选择比工具数量重要得多。工具给二十个,但让 Agent 靠截图或靠自述来确认结果,等于没做验收。反过来,工具只给三个,但有一个是返回可断言结构的 inspect,Agent 的可靠度是完全不同的量级。

五、他们为什么要从零写:不是洁癖,是许可

还有一个问题一直没解答:已经有 LibreOffice 了,为什么还要从零重写一遍?

答案不在宣传页上,在仓库的 AGENTS.md 里——这是一份写给 AI Agent 的开工须知。里面有整整一节规定了 clean-room(净室)的具体纪律,读起来像一份法律合规文件:

一、开发机上装了正版 Word,但只能黑盒观察。可以运行它、用构造的文档操作界面、截图,但截图只能按窗口 id 截它自己的窗口,理由是「这台机器还跑着别的工作,绝不截整个桌面」,而且截图只存在一个被 gitignore 的本地目录里,永不提交。同时明确写了:绝不读、反汇编或复制 Word 包内的任何东西,只能看文件名和列表。

二、格式全部来自公开规范。OOXML 走 ECMA-376 / ISO 29500,富文本走公开的 RTF 规范,开放文档走 OASIS ODF 1.3。凡是公开标准里写着的,都可以照着实现。

三、绝不复制 GPL / LGPL / AGPL 的代码。括号里点名了三个项目:LibreOffice、AbiWord、pandoc。

第三条才是真正的答案。LibreOffice 是 MPL/LGPL 系许可证,商业产品要集成它,会碰到许可传染的问题——你改过的部分要开放,链接方式稍有不当就有风险,法务能跟你拉扯很久。而 MIT 或 Apache-2.0 没有这个包袱,你甚至可以直接把它嵌进商业产品里,不需要开放自己的代码。

所以「无订阅、无授权服务器、无遥测」这个口号是表层的,深层的动机是:现有替代品的许可能力不够,那就自己造一套许可能力足够的。这不是情怀,是给企业采用方扫清障碍——而这恰好也是它自己说的「clean-room 重写,看着挺硬核,不过确实也就是个表态」的另一面:表态的对象不只是订阅制,还有许可证。

顺带说一个我核实到的、原文没提的细节,能看出这个团队做事的方式:它的崩溃日志机制是这样的——每次启动把上一次的日志挪成 .1.log,再上一次的挪成 .2.log,这样崩掉那一次的日志能活过下次启动,单文件上限 16 MiB;并且明确写着文档正文永不写入日志,连崩溃消息里引用的文本也会被脱敏掉。一个才出生四天的项目把这些想清楚,说明它的工程规范是先立规矩再写代码的。

六、对比与注意事项

把该踩的坑和该记的结论列一下:

⭐ 一、别信任何转述的数字,包括这篇文章。你自己跑一遍那十行脚本,成本不到一分钟,拿到的是一手数据。48 小时前的 850 星和今天的 3428 星,对你的决策完全是两个信号。

⭐ 二、「无订阅」不等于「无成本」。软件免费,但迁移成本、培训成本、格式往返丢内容的成本、出了问题没人兜的成本,都是真金白银。那个「0 个人说从 Word 切过来了」的数字,就是这些成本还没被付过的证据。真要用,先放在不阻塞主干的场景上——比如个人文档、内部草稿,而不是等着一份要盖章的合同。

⭐ 三、v0.5.0 这个版本号,在两边都意味着不稳定。两天从 v0.1.0 走到 v0.5.0,说明迭代很快,也说明任何两个相邻版本之间的行为都可能有变化。如果你要基于它做二次开发,把版本 pin 死,别用 latest。

⭐ 四、它的 docs/gaps.md 比它的 README 有价值。README 告诉你它想成为什么,gaps.md 告诉你它现在是什么。看任何一个新项目,先翻有没有这份文件、写得够不够具体——愿意列出「我们的测试数据是假的」的团队,它的其他声明才值得信。

⭐ 五、Agent 主导开发的项目,读法不一样。这个项目的 AGENTS.md 开头就是「给 Agent 的指示」,ROADMAP 用「Opus 5.5 agent wall-clock 小时」来计量剩余工作量——到 beta 还需约 150 到 230 小时,到与 Word 完全对齐还需约 750 到 1250 小时(70% 到 80% 可并行)。读这类项目,先看三份文件:gaps.md 定缺口、AGENTS.md 定规矩、ROADMAP.md 定工时。PR 编号两天冲到 #480,也是这个机制的产物,不是靠人多。

⭐ 六、它真正可能先落地的地方,不是替代 Word。替代 Word 要面对的是插件生态、宏、团队协作、格式细节,这些它自己承认还差得远。但作为一个可以被 Agent 驱动的文档处理引擎,它现在的完成度已经能覆盖不少场景了:批量格式转换、按模板生成文档、结构化检查、自动化排版。换个用法,它的可用性立刻上一个台阶。

七、总结

现阶段适合用它的场景:

  • 把它当成「可被 Agent 驱动的文档处理引擎」用,而不是当成 Word 的替代品
  • 需要命令行批量转换、结构化提取、按模板生成文档的自动化流程
  • 公司对许可敏感、又不想为 Office 订阅付费的场景,可以开始做技术预研
  • 想学「给 Agent 做接口」该怎么设计的,它的架构和 AGENTS.md 是一份现成的教材

现阶段不适合的场景:

  • 日常主力办公——DOCX 还没在真实文件上验证过,这条它自己写在缺口清单第一位
  • 带手绘批注、图表、SmartArt 的文档往返,会静默丢内容
  • 对分页和排版有严格要求的场景(合同、法律文书、学术论文),页数和 Word 不一致
  • 团队协作链条上的正式交付,修订追踪和内容控件目前不保留

我们最后的结论是:不用它替代 Office,但把它那条「Agent 验收看结构不看截图」的思路抄进了自己的对账流程。那个 assertConsistent() 上线之后,原来需要人工核对半天的报告,现在 Agent 自己就能判断哪一步没走完——判据是字段,不是它自己的话,也不是一张截图。

这一趟让我改了一个习惯。以前看到热门项目,第一反应是看它能做什么;现在第一反应是翻它的 gaps.md,看它承认自己不能做什么。因为能力列表是营销,缺口清单才是工程——而这个项目最让我信服的地方,恰恰是它把缺口写得太具体了,具体到连「我们的测试数据都是合成的」都写进去了。

回到开头那句「免费,无订阅」。这话没错,但它不是选型依据。真正决定一个工具能不能进你生产环境的,从来不是它收不收费,而是它敢不敢告诉你它在哪儿会坏。


注:本文基于 ArtCraft(GitHub 组织 storytold)旗下 WordCraft / GridCraft / DeckCraft / CADCraft / SoundCraft / PhotoCraft 各仓库的 README.md、ROADMAP.md、docs/gaps.md、AGENTS.md 原始内容,以及 GitHub API、getartcraft.com 官网在 2026 年 10 月 11 日的实测数据核实编写;星数、fork 数、版本号、完成度数字均以核实当日仓库实际状态为准,这类项目的数字变动很快,请以你查看时的仓库为准;落地代码为我们在实际项目中的简化形态,已去掉业务细节

本文来源于互联网,如有侵权,请联系作者删除

谢谢关注!

相关学习资料