路线图
为了让 XTL 1.0(规范)和 xl3 1.0(参考实现)成型,需要落地哪些事项。
在 0.x 阶段仍可能引入不兼容变更。根据 ADR-0079,1.0 以技术稳定性和 90 天浸泡期为门槛。G13、G14、G15、G18 继续作为公开的 1.x 采用轨道,但不阻塞 1.0。
深度的版本规划收录在
docs/internal/blueprint-to-1.0.md——包含差距分析、哲学边界(xl3 ≠ JXLS)以及逐版本的步骤规划。本文档是"电梯演讲"版本;蓝图文档承载完整的论证依据。1.0 关卡的单一可信来源是下方表格。 当本文件与蓝图文档冲突时,以本表格为准;蓝图随之更新对齐。
1.0 对 xl3 意味着什么
1.0 的目标是让运维人员能够"看得懂、信得过":规范不再漂移,参考实现不再带来意外,整体表面足够小,让运维同学不用读代码就能审阅一个模板。它不是要在功能完备性上和 JXLS 比拼——xl3 有意保持更小的能力面(ADR-0043 + ADR-0048)。预设的核心用户是管理大量客户专属票据格式的韩国运营团队(거래명세서、정산서、발주서);引擎本身可以泛化到这个领域之外,但这个细分场景是切入点。
1.0 技术关卡与 1.x 采用轨道
每个关卡都有所有者、用于关闭它的产出物、判定通过/失败的标准、关卡不可达时的降级方案,以及目标里程碑。下方逐版本步骤规划通过 ID 引用这些关卡。
| ID | 关卡 | 所有者 | 产出物 | 通过标准 | 降级方案 | 目标 |
|---|---|---|---|---|---|---|
| G1 | 一致性语料 ≥ 140 | 维护者 | conformance/fixtures/ | ls conformance/fixtures/ | wc -l ≥ 140 | — | DONE(160 个;ADR-0066 在 0.7.x 中途新增 141-145,ADR-0067 |
| G2 | Stage 2 OOXML 规范化完成 | 维护者 | ADR-0006 + src/ 中的 canonicalizer | 由测试用例 024-027、093 + ADR-0006 修订覆盖 | — | DONE |
| G3 | 错误码目录冻结 | 维护者 | impl/js/src/__tests__/error-codes.test.ts 快照 | 目录快照 30 天保持不变 | — | ✅ 已于 2026-06-23 勾选(最后一次目录变更为 2026-05-24 a8f7ad3 新增 3 个错误码 xl3/block/overlap、xl3/block/empty-table、xl3/directive/orphan;89bee51 于 2026-05-23 新增 xl3/expression/bracket-outside-block。30 天冻结期已过——05-24 之后触及该文件的提交仅涉及注释/JSDoc,EXPECTED_CODES 未变) |
| G4 | 发布 JXLS 边界 | 维护者 | ADR-0048 | 文件存在并引用 PORTERS_GUIDE | — | DONE |
| G5 | 延期实现的 ADR 落地 | 维护者 | ADR-0038 实现 ✅(2026-05-18)+ ADR-0040 PE 实现 | ✅ 已完成——ADR-0038 由测试用例 132-135 覆盖;ADR-0040 的 CF/DV 范围扩展和大纲级别由测试用例 171、172 覆盖 | — | 已于 2026-08-16 完成 |
| G6 | 公开 API 表面冻结 | 维护者 | impl/js/src/__tests__/api-surface.test.ts 快照 | 快照 30 天保持不变 | — | ✅ 已于 2026-06-17 勾选(快照自 2026-05-18 16f0608 起未变) |
| G7 | @stable 导出项的 JSDoc 示例 | 维护者 | TypeDoc 输出 | 每一个 @stable 符号都附带 @example 区块 | — | ✅ 已于 2026-06-21 完成——13/13 个 @stable 可调用项均带 @example(PR #59);0.11.0 新增 convertJson / previewJson 后以 15/15 复核(previewJson 发布时缺 @example,已于 2026-07-27 修复) |
| G8 | 性能特性描述 | 维护者 | scripts/BENCH.md | 发布 1k/10k/100k 行 × 5/10/20 列矩阵 + 内存上限 + parse/eval/write 分项数据 | — | 0.7.1 |
| G9 | 性能回归测试用例 | 维护者 | 一致性语料 | ≥ 2 个大体量 fixture,使用基于比率的断言 | — | 0.7.1 |
| G10 | 跨浏览器冒烟测试 | 维护者 | ci.yml | Safari + Firefox 校验共享清单中的 19 个 runtime export,并各运行一次 convert() | — | ✅ 已完成 |
| G11 | Stage 2 接入 CI | 维护者 | ci.yml | 每个 PR 都运行 npm run conformance:stage2 | — | 0.7.1 |
| G12 | 未定行为定锚(pivot/sparkline/ListObject/分页) | 维护者 | 一致性测试用例 + 每项一份 ADR | 每项:要么有 fixture 锚定当前行为,要么有 ADR 显式延期到 1.x | 配 ADR 推迟到 1.1 | 0.7.1 / 0.8 |
| G13 | **1.x 采用、非阻塞:**第二语言实现验证 | 外部(xl3-py) | conformance/reports/*.json | 针对当前语料通过 Stage 1 或 Stage 2 ≥ 80% | — | 等待新的报告 |
| G14 | **1.x 采用、非阻塞:**外部贡献者 ADR | 外部 | spec/decisions/NNNN-*.md | ≥ 1 份符合作者标准的外部 ADR | — | 开放 |
| G15 | **1.x 采用、非阻塞:**生产参考案例 | 外部(维护者协助) | IMPLEMENTATIONS.md 中“生产用户”一行 | ≥ 1 名获准公开的具名用户 | — | 开放 |
| G16 | 维护者集合扩大 | 维护者 | GOVERNANCE.md | ≥ 2 人拥有 ADR 和实现 PR 的接受/拒绝权限 | 通过对 GOVERNANCE 的修订,显式接受单维护者形态的 1.0 治理结构 | 0.8 |
| G17 | 韩文 cookbook 国际化完成 | 维护者 | website/i18n/ko/.../guides/ | 全部 cookbook 配方均有韩文翻译 | — | 配方 01-18 已完成(0.6)——1.0 前的待决问题: docs/guides/19-jxls-to-xl3.md 是后来新增的,没有 ko / ja / zh-CN 翻译。需要先确定迁移指南是否算作 "cookbook 配方";若算,则 G17 需重新勾选 |
| G18 | **1.x 采用、非阻塞:**README 中的生产用例 | 维护者 | README.md | G15 后发布具体生产案例 | — | 开放 |
| G19 | 0.x → 1.0 迁移指南 | 维护者 | docs/migration-0.x-to-1.0.md | 记录每一个行为变更,或确认是纯新增式变更 | 若确认为纯新增式变更,则降级为 CHANGELOG 备注 | 0.8 |
| G20 | SECURITY.md + 威胁模型 | 维护者 | SECURITY.md + 规范修订 | 文档化对 zip 炸弹 / 超大工作簿 / 公式执行的立场和 limits API | — | 0.7.1 |
| G21 | 硬限制文档化(1.1 前不支持流式) | 维护者 | spec/evaluation.md | 行数 / 内存 的硬限制值 + AbortSignal API 已记录在文档中 | — | 0.7.1 |
| G22 | API 表面——内部模型类型剥离 | 维护者 | impl/js/src/index.ts 导出 + STABILITY.md | 只保留 convert/preview/analyze + 标注为 @stable 的稳定接口;模型/解析器类型标注为 @experimental 或迁移到 xl3/internal | — | DONE(0.6) |
| G23 | RC 浸泡期 | 维护者 | git 标签 | RC 已发布;浸泡期 ≥ 21 天(根据评审反馈,从 7 天延长);0 个严重问题 | — | ✅ 已于 2026-06-16 勾选(自 rc.1 2026-05-26 起浸泡 21 天;0 个严重问题——浸泡期修复 #49–52 已并入 0.9.0,按 G23 的不兼容变更定义均不重置时钟) |
| G24 | 技术稳定窗口 | 维护者 | 发布日历 | 从最后一个阻塞性技术关卡关闭或最后一次破坏性变更(二者取较晚)起 90 天;不含采用轨道 | 破坏性变更 → 重启 | ⏳ 2026-08-30 → 2026-11-28;因 OutputFile.data 的公开类型修正为实际的 Uint8Array 运行时契约而重启 |
定义(可测试)
- 外部贡献者(G14): 在 PR 打开时,既不在
GOVERNANCE.md维护者集合中,也未出现在已合入 ADR 提交的Co-authored-by历史中。顺手改错别字的编辑不计入;需以 Author 身份出现在 ADR 前置元数据中;按行数计,Context/Decision 章节 ≥ 60% 由其撰写。 - 不兼容变更(G24、G23): 对以下任一项的修改:(a) 公开 API 表面快照;(b) 错误码目录(重命名/删除/重新用途化);(c) ADR
accepted→rejected,或与原状态冲突的状态翻转。补丁版本和纯新增式 ADR 不重置季度时钟。 - 关键 bug 修复(G23 RC 例外): (a)
convert()中的静默数据丢失;(b) 文档和运行时之间的错误码目录不一致;或 (c) 某个acceptedADR 中的 MUST 按现有写法无法实现。维护者需在 PR 中标明命中的是 (a)/(b)/(c) 中的哪一项。 - 数据丢失测试(G24 可测试形式): 语料中存在专门的
data-loss/fixture 分组(≥ 8 个 fixture),覆盖静默字符串化、numFmt 丢失、公式改写、日期往返路径;全部在参考实现上通过。 - 季度时钟起点(G24 与 G23): G24 的 90 天季度从最后一个关卡 ✅ 的当天开始计时。RC 发布不启动时钟;时钟必须在 RC 发布之前已经开始。若 RC 浸泡期间发生不兼容变更,则浸泡期(G23)和季度(G24)双双重置。
逐版本步骤规划
基于关卡,而非基于日期。日历估时已移除——每个里程碑在它列出的关卡全部关闭时才算关闭。
0.6.0 —— 延期实现,范围收窄
主题:干净利落地关闭影响最大的延期实现关卡。
关闭的关卡:G5(仅 @group/@subtotal 实现——ADR-0040 PE 的其余部分移入 0.6.1)、G17(韩文 cookbook 还缺 16/17 篇翻译)、G22(在 @group 暴露新的内部类型之前先收敛 API 表面)。
按工程可行性评审的反馈,原先"在一个 0.6.0 里塞下所有东西"的计划范围过大。仅 ADR-0038 的实现就涉及一次完整的管线插入(新增指令、分组边界状态机、transform-pass 切分、渲染器重写、分组作用域的聚合求值)。把 0.6.0 拆开能让这个里程碑可以真正交付。
0.6.1 —— 延期实现的剩余部分(已规划,尚未发布)
关闭的关卡:G5 完结(ADR-0040 PE:CF/DV sqref 扩展),以及 pivot/分页行为 fixture 朝 G12 推进。
0.7.0 发布时的状态:本里程碑被规范审计批次(0.7.0)跳过。G5/G12 的工作被合并到 0.7.1。
0.7.0 —— 规范审计批次(已于 2026-05-22 发布)
主题:关闭一次深度审计揭示出的 17 个语法冲突 缺口,覆盖词法分析、单元格分类、指令组合、聚合参数和保留工作表语义。原关卡表中未计划;原本挂在 0.7.0 上的性能/CI/limits 工作移入 0.7.1。
已发布的产出物:
- 15 份新 ADR(0051–0065)+ ADR-0021(group-order 目录条目)和 ADR-0041(表头单元格多行规范化)的修订。
- 4 个新错误码——
xl3/parser/unbalanced-literal、xl3/lists/invalid-use、xl3/eval/bad-aggregate-arg、xl3/expression/unknown-name。 - 语法补充:
positive_integer、group_directive、subtotal_directive、aggregate_call,以及一段词法消歧义说明。 src/directive-parser.ts对前导零整数加严。- 双通道并行评审(claude-general + codex);所有 CRITICAL/HIGH 发现已在打 tag 前关闭。
对关卡的影响:
- G1 —— 当前 139 个 fixture。0.7.0 的 ADR 预留了 fixture 编号 141–187;实现仍在进行中。这些 fixture 在 0.7.1 落地后 G1 即关闭。
- G3 —— 30 天错误码目录时钟于 2026-05-22 因新增 4 个错误码而重置。
- G6 —— 公开 API 表面无变化;G6 时钟不受影响。
0.7.1 —— 性能 + 外部验证启动(从旧的 0.7.0 重命名而来)
关闭的关卡 :G5 完结(ADR-0040 CF/DV sqref 区间)、G8(性能基准)、G9(性能回归测试用例)、G10(跨浏览器)、G11(Stage 2 进 CI)、G20(SECURITY.md 草案 + 威胁模型)、G21(硬限制 + AbortSignal 文档)。
同时通过落地 0.7.0 ADR 预留的 141–187 号 fixture,关闭 G1 ≥ 140 fixture 的底线。
推进进度:G12(未定行为定锚)、G13(xl3-py)。
重新标注:在 G8 发布且 xl3-py 在 Stage 1 达到 ≥ 50% 后,将 alpha 改为 beta。
0.8.0 —— 数据块设计大改(已于 2026-05-23 发布)
主题:原关卡表中未计划。0.7.x 后期对数据块展开做的一次审计暴露出两个结构性 bug(#46 共享公式 owner 重复、#47 被挤开的旁侧单元格引用变旧),必须先做一次按列作用域的重写,才能继续做后续功能。原先"0.8.0 = 社会性关卡"的计划移入 0.8.x 补丁。
已发布的产出物:
- ADR-0066 —— 数据块改为按列作用域:把
{{...}}标记的包围盒沿连续的非空单元格扩展。块展开时,该范围之外的单元格保持各自的行位置。从构造上关闭 #46 / #47。 - ADR-0067 —— 显式
@block指令的三种形式(裸写、A:D列区间、A2:D7矩形)。 - ADR-0068 —— 在选择启用的工作表上做严格的多块检测:每个
[Column]标记都必须落在某个块内;块矩形之间不得重叠。 - ADR-0069 —— 按邻近度做逐块的指令作用域:
@filter/@sort/@top/@source/@join/@group/@repeat会挂到列区间与该指令所在列重叠、且距离最近的那个数据块上。 - 4 个新错误码:
xl3/expression/bracket-outside-block、xl3/block/overlap、xl3/block/empty-table、xl3/directive/orphan。 - 一致性测试用例 146-155(多块、使用不同数据源的并排块、纵向堆叠块、逐块过滤、逐块
ROW()作用域,以及三条新错误路径)。
对关卡的影响:
- G1 —— 语料从 139 增至 154 个。底线再次达成。
- G3 —— 30 天错误码目录时钟因这 4 个新错误码于 2026-05-23 重置。最早可勾选时间为 2026-06-22,前提是 0.8.x 补丁期间不再新增或重命名错误码。
0.8.x —— 社会性关卡(进行中)
关闭的关卡:G14(外部 ADR)、G15(生产案例;通过维护者所在公司的部署推进中)、G16(维护者扩员,或显式接受单维护者形态)、G19(迁移指南)、G20 完结。
计划是在招募期间持续发布 0.8.x 补丁版本,而不是默不作声地等待 。G3 的季度纪律: 社会性关卡推进期间,错误码的新增与重命名一律延后——任何新增都会重置 G3 时钟,并把 0.9-rc 的目标往后推。0.8.x 窗口期内只允许新增符合本文件定义的"关键 bug 修复"类错误码。
0.9.0-rc.x —— 1.0 前的冻结期
关闭的关卡:G3、G6、G7、G23(≥ 21 天的 RC 浸泡期)。
G23 启动后,G24 的季度时钟开始(它必须在 G3/G6/G7 等关卡关闭过程中就已经走起来——见上方定义)。
0.9.0 —— 最终冻结版本(2026-06-23)
1.0 前的四个冻结关卡全部勾选:G3(2026-06-23 —— 最后一次目录变更 2026-05-24 + 30 天)、G6(2026-06-17)、G7(2026-06-21,PR #59)、G23(2026-06-16 —— 21 天浸泡,0 个严重问题)。并入 RC 浸泡期修复 #49–52;#54/#56/#57 延后到 post-1.0 里程碑(POST-1.0 纯新增式 —— 该里程碑在本次发布时名为"0.10.0",因 0.10.0 与 0.11.0 均未包含这些事项就已发布,故于 2026-07-27 重命名;#57 已因 #82 的宿主驱动 __inputs__ 源元数据方案取代而关闭)。G24 的 90 天季度时钟自最后一个关卡勾选之日(2026-06-23,经由 G3)开始计时;若无规范/API/错误码的不兼容变更,1.0 最早约为 2026-09-21。
0.10.0 —— 组织迁移 + @subtotal 正确性(已于 2026-07-19 发布)
仓库已迁入 xl3-lang GitHub 组织,npm 包从 @jinyoung4478/xl3 重命名为 @xl3-lang/xl3(仅安装名变化;旧包已在 npm 上标记 deprecated 并指向新名)。同时并入 @subtotal 的正确性修复 #66(ADR-0073)与 #69(ADR-0074):带有当前行 [Column] 引用的 @subtotal 行,以及显式 @block 模式下的分组 + 小计,此前都会静默产出看似合理却错误的结果——现在各自抛出专门的错误。
对关卡的影响:
- G1 —— 语料从 157 增至 160 个(159 mixed-row 错误、160 公式缓存不是标记的保证、161 显式块的拒绝)。
- G3 / G24 —— 新增 2 个错误码(
xl3/subtotal/mixed-row、xl3/subtotal/explicit-block-unsupported);没有重命名、删除或重新用途化。按上文不兼容变更的定义属于纯新增,因此季度时钟不重置。 - G6 —— 公开 API 表面快照未变。重命名只影响安装名:
convert/preview/analyze、子路径导出以及xl3-conformancebin 完全一致。
0.11.0 —— JSON 源输入(已于 2026-07-19 发布)
convertJson / previewJson 可以接受与语言无关的 xl3-source-json/0.1 传输格式来替代 data.xlsx,让非 Excel 宿主(Python、DB/ETL 服务)跳过工作簿往返(ADR-0075,#71,实现见 #80)。同时把 JS 参考实现迁移到根 npm workspace 下的 impl/js/(#79)——仅目录结构调整,行为无变化。
对关卡的影响:
- G3 / G24 —— 新增 1 个错误码(
xl3/source-json/invalid);纯新增,时钟不重置。 - G6 —— 冻结的 API 表面新增两个导出(
convertJson、previewJson,已记录在spec/STABILITY.md)。纯新增:没有删除或改签任何既有导出,.xlsx路径也未触动。 - G24 窗口 —— 两次发布都落在 2026-06-23 启动的季度窗口之内(2026-07-19)。按上文定义两者都不属于不兼容变更,因此 1.0 最早时间仍约为 2026-09-21。
1.0.0 —— 最终发布
关闭的关卡:G24(最后一个关卡 ✅ 之后的 90 天季度走完)。
招募与外联
社会性关卡(G13/G14/G15/G16)需要的是人,而不是代码。项目有两个截然不同的招募面向:
韩国运营受众(G15、未来的 cookbook 贡献者)
渠道:韩国开发者社区(Naver Café、Kakao 오픈톡、LinkedIn KR)、公司内部 / 供应商模板作者调研。每个小版本发布都会配套一篇与发布节奏绑定的韩文文章(0.6 = @group/@subtotal 在票据小计场景的演示;0.7 = 性能数据;0.8 = 案例研究)。
英文 OSS 受众(G13、G14)
渠道:HN、lobste.rs、r/excel、各类大会 CFP(JSConf、面向 xl3-py 的 EuroPython)。每个重大节点都会配套一份具体的对外产物:
- 0.7.0 发布:"Show HN: xl3 0.7 —— 10 万行级别的 Excel 模板引擎"
- 0.8.0 发布:案例研究 + xl3-py 一致性面板
- 1.0.0 发布:规范 + 多实现交叉验证
1.0 的非目标
这些内容是有意延期的。每一项都有对应 ADR 说明原因:
- 超出 Y/M/D/EOMONTH/EDATE/DATEDIF 之外的日期运算 —— 该家族其余部分按 ADR-0019 修订延期。
- 区域感知的字符串排序 —— ADR-0020。
- 多表 join、左连接、多行匹配 —— ADR-0014 的范围外章节。
- XLOOKUP 通配符 / 近似匹配 / 反向搜索 —— ADR-0013 的范围外章节。
- 动态图片插入 —— ADR-0037。
- 运行时单元格变更 —— ADR-0042。
- 按 ADR-0043 关卡被拒绝的函数 —— 数学扩展、类型判定(按 ADR-0047 例外保留
ISBLANK)、NOW / WEEKDAY 等、条件聚合、TEXT() 格式 token 扩展。详见 ADR-0045。 - 流式输出 / SXSSF 类似物。 延期至 1.1+。在 1.0,作为替代会文档化硬性的内存/行数上限(G21)。
- 模板编译缓存 API。 延期至 1.1+。
- PDF / HTML 输出。 范围外;xl3 的契约是 xlsx-in、xlsx-out。
- 超出
093的跨写入器 Stage 2 fixture —— ADR-0006 修订。 - 输出侧模板 schema(
produces)与设计时链接 —— xl3#109 中的输入校验提案 (validateSource():复用既有的xl3/source/*错误码来回答“这份源数据是否满足 这个模板”)先只限定在输入侧。与之对应的输出侧 —— 携带输出列标签的TemplateModel.produces,也就是能让宿主在不执行一次转换的前提下校验templateA → templateB这条边的东西 —— 延期。它需要一项本项目尚未确定的约定: 工作表模板中哪一行字面量行才是输出表头。与requires不同,这一点无法从解析器 已解析的结果中推导出来,因此必须明确决定并写下来,而不是让每个引擎各自推测。 目前还没有 ADR;设计讨论在 xl3#109。
这些仍然是 XTL 1.1、1.2、1.x 的候选项,取决于需求强度。
如何帮助关闭事项
| 事项 | 如何帮忙 |
|---|---|
| G13 第二实现 ≥ 80% | 参与 xl3-py,或启动一个新的移植(Rust、Java、Go)。参见 PORTERS_GUIDE.md。 |
| G14 外部 ADR | 挑选一个延期项(pivot 表保留、分页符、ADR-0045 切出的函数等),在 spec/decisions/ 中起草一份 ADR。参见 GOVERNANCE.md 中"变更如何进入项目"。GitHub 上以 good-first-ADR 标签提供了若干"入门 ADR 草稿"议题。 |
| G15 生产案例 | 在内部使用 xl3,并分享行得通 / 行不通的地方。如果合适,在 IMPLEMENTATIONS.md 中加一行。如果维护者所在公司(Snack24h)发布公开案例研究,也可作为生产参考案例计入。 |
| G17 指南国际化 | docs/guides/19-jxls-to-xl3.md(JXLS → xl3 迁移指南)没有 ko / ja / zh-CN 翻译;配方 01-18 已完成。 |
| G8 基准测试 | 在有代表性的模板上运行 npm run bench,分享结果。 |
| G10 跨浏览器 | 把 Safari + Firefox 加入 bundle 冒烟测试。 |
| 函数再提案 | 如果你需要某个被 ADR-0045 拒绝的函数,请使用 Function re-proposal 议题模板提交。 |
本路线图如何演进
本文档是公开的"电梯演讲" + 关卡表是单一可信来源。更深层的
docs/internal/blueprint-to-1.0.md
承载差距分析、哲学边界以及逐版本的论证依据。随着关卡逐个 ✅,两份文档都会更新。每当 出现新的缺口,两份文档都会补上。
对 1.0 关卡表格的删减和新增,与其他任何事项一样,通过相同的 ADR / 议题流程讨论。