跳到正文

可以逐条查证的部分。

四块参考材料:点击命中的到底是什么,预检拿什么规范去量,AI agent 接在哪一环,以及六条承重决定,每一条都给得出仓库里能打开的文件。

一次点击命中的是什么。

普通矢量编辑器看到的

  • 路径
  • 字形轮廓
  • 矩形
  • 裁剪组

Tavotto 看到的

  • 标题 “Reaction kinetics” axes_0.title
  • 图例 axes_0.legend
  • 曲线 axes_0.lines_2
  • 刻度标签 axes_0.xticks
  • 标注箭头 axes_0.texts_0.arrow

一次点击,解析到画出它的对象。

命中判据跟着真实几何走:曲线按到渲染路径的距离算,填充区域按渲染器填色用的同一条缠绕规则算。不看包围盒。

出版要求是物理量。

栏宽以毫米计,字号下限以 pt 计,位图下限以 dpi 计。Tavotto 拿排好的版面逐项去量,依据是一份引擎与界面共读的带版本 profile;期刊栏宽不同,一行覆盖即可,覆盖会记进 proof report。

80 / 150 mm
默认 profile 的单栏与双栏宽度
8.5 pt
严格字号下限,按最终物理尺寸判;8 pt 是绝对底线
300 dpi
栅格化输出的最低要求
0.5-1.5 pt
边框与曲线比对的线宽档位

面板缩到 60%:按 9 pt × 0.6 = 5.4 pt 判。不过。

阻断
在你书面确认之前不让导出。
警告
一定展示,绝不静默略过。
无法核验
真的查不了的那些,比如外部位图内部的文字。需要人来看。
建议
绝不替你做决定。

同一份渲染事实。

每次导出都从同一份 PDF 合成出发:PDF 里是真文字,PNG 是这份 PDF 的栅格化。两种格式不可能各说各话。

AI 在哪一环

编程助手写的第一版 matplotlib 已经够好,剩下的是视觉活:图例高了两行、标签压住了数据点。这一层归 Tavotto,agent 写的脚本仍然是源头。在任何终端把图递过来:

tavotto open figures/Fig1_kinetics.pdf

它会把这张图所在的图库当项目打开,把图送进已经开着的窗口,不另起一套。

Codex 插件

一个 skill、一个本地 MCP server,加一块与桌面应用同一份前端代码构建的内嵌画布。Codex Desktop 里的部分集成尚未在真实环境验证过,插件 README 写明了是哪些。

图底下的工程。

六条承重决定,每一条都能在仓库里查证。

渲染

全部本地。跑脚本、渲染、排版、导出都在你的机器上,图和脚本不上传。

docs/privacy.md
网络

应用自己只发两类请求:每天一次的版本检查,和明确同意后才开启的匿名用量统计。两个开关彼此独立。统计的事件结构里没有任何字段装得下文件名、路径或图内文字。

docs/analytics/telemetry-events.md
重放验证

CI 持续证明:当前会话、全量重放、全新进程、写回后重开,四者的 manifest 逐元素一致。

tests/test_equivalence_matrix.py
黄金向量

patch 规范化在 Python 与 Rust 各有一份实现,由同一份向量文件钉到逐字节一致;预检同理,Python 与 TypeScript 各一份。

tests/golden/
内置运行时

桌面安装包自带钉死版本的 CPython 与科学栈,各平台锁定完全相同的包版本。

packaging/runtime-lock.json
发布测试

发布前,打包产物必须真启动、真渲染、真导出、干净退出。每晚再把 Windows 安装包装一遍、冒烟、升级、卸载,用户名是中文。

.github/workflows/nightly.yml

开源,AGPL-3.0 许可;这些决定的来龙去脉在仓库的 ADR 里。 docs/adr