FNOS-019 FPK 版本方案固定前缀与插件基线小尾巴
| 项目 | 内容 |
|---|---|
| 需求编号 | FNOS-019 |
| 提出日期 | 2026-10-18 |
| 需求状态 | 已通过验收(本地与真实 fnOS NAS) |
| 关联计划 | PLAN-FNOS-019 FPK 版本方案固定前缀与插件基线小尾巴 |
| 影响范围 | tooling/fnos-dsh-cli(版本命令、构建校验)、apps/fn-deepseek-harness/manifest、文档站版本展示 |
| 关联需求 | FNOS-014(DSH 运行时基线的来源) |
需求背景
FPK 的应用版本此前由 pnpm run version -- project <patch|minor|major> 通过语义化档位递增,前三段随每次发布变化。用户要求改为版本前缀固定、只有小尾巴变化:
5.9.0:基础段,从今以后静态不动(发布时原样继承,代码不主动改写);0.2.1-rc.2:跟随 DSH 运行时基线,表达本应用适配的上游版本;- 末尾的
x:本应用自身的迭代号,每次发布只递增这一段。
这样做的价值在于:看到版本号就能判断它适配的上游基线,而应用自身迭代次数单独可数,不必从不断增长的补丁号里反推。
需要先讲清的一处语义
5.9.0-0.2.1-rc.2.5 里 - 之后整体是 semver 的 prerelease(预发布标识)。按语义化版本规则,预发布版永远小于同号正式版,即:
text
5.9.0-0.2.1-rc.2.5 < 5.9.0本方案不发布 5.9.0 正式版,因此比较只发生在两个预发布版本之间——此时末尾迭代号能正确分出先后(…2.6 > …2.5)。这意味着设备上已装的历史 5.9.0(无小尾巴)会被判为更新,凡是装了它的设备,升级到新方案需要先处理这一点(见「行为约束」)。
调研结论
fnOS 侧的格式约束(fnpack 实测):
| 候选写法 | fnpack 是否接受 | semver 判序 | 与 5.9.0 比较 |
|---|---|---|---|
5.9.0-0.2.1-rc.2.5 | 接受,版本原样写入 FPK | 合法预发布版 | 更小 |
5.9.0+0.2.1-rc.2.5 | 接受 | 合法,build metadata 不参与比较 | 相等 |
5.9.0.5 | 接受 | 非法(四段) | 取决于平台实现 |
官方文档给出的版本示例包含 2.1.3-beta 形态,属于同一类预发布写法,因此格式本身合规。
本仓库现状:
pnpm-workspace.yaml顶层 catalog 已有'@deepseek-ai/dsh': 0.2.1-rc.2,是 DSH 基线的唯一权威来源;各插件peerDependencies用catalog:dsh引用它,版本命令不应再维护第二份常量。- 项目版本当前由
bumpp的语义化档位递增,会移动前三段,与本需求冲突。 - 版本命令已支持以显式版本号交给
bumpp(其release选项接受具体版本串),因此不必引入新的版本工具。
需求目标
- 项目/FPK 版本号统一为
<固定基础>-<DSH 基线>.<迭代号>,当前即5.9.0-0.2.1-rc.2.<x>。 - 基础段与 DSH 基线两段由系统维护:基础段在发布时原样继承,不随发布推进,也不写成代码常量(调整基础段只需改版本文件);基线随 catalog 中的
'@deepseek-ai/dsh'自动跟随,不手工维护副本。 - 每次发布只递增末尾迭代号,其余各段保持不变。
- 版本命令在两种调用下都产出该形态:给档位关键字(
patch/minor/major)时按「迭代号 +1」处理;给完整版本串时按其字面值写入。 - 版本号可被
fnpack打包接受,并原样出现在 FPK 的manifest与 Git tag 中。
功能列表
| 编号 | 功能 | 说明 |
|---|---|---|
| FNOS-019-01 | 版本号拆解与组装 | 把 <基础>-<基线>.<迭代号> 三段解析与生成;基线自带预发布段(含 .)时仍能唯一定位迭代号 |
| FNOS-019-02 | 下次版本计算 | 基础段原样继承、基线取自 catalog;基线未变时迭代号 +1,基线变化时重置为 0 |
| FNOS-019-03 | 版本命令接入 | project 目标不再走语义化档位移动前三段,改为写入计算出的显式版本 |
| FNOS-019-04 | 基线唯一来源 | 从 pnpm-workspace.yaml 读取 catalog 基线条目;缺失或非法时报错而不是退回猜测 |
| FNOS-019-05 | 打包与发布一致性 | fnpack 接受该版本号;FPK 内 manifest、Git tag 与根 package.json 三处一致 |
| FNOS-019-08 | 基线切换入口 | --baseline <版本> 一步切换 DSH 基线:改写 catalog 条目、基线段切新值、迭代号重置为 0;只改版本号,不碰插件里的 DSH 依赖声明 |
| FNOS-019-07 | 同号约束 | 发布前核对插件与项目是否同号;不同号时报错并点名,不静默拉平。minor/major 档位被拒绝(本方案只有迭代号可递增) |
| FNOS-019-06 | 单一版本入口 | 版本命令不再区分「项目/插件」两个区域:一次执行把项目与全部插件统一推进到同一个迭代号,落同一条提交;插件版本 = 项目版本去掉基础段前缀 |
行为约束
- 基础段不得被发布流程主动推进。版本命令从当前版本串里读它、原样写回;代码不持有它的字面量,因此调整基础段只需改版本文件,不会与代码里的常量产生漂移。
- 版本号必须符合
<基础段>-<DSH 基线>.<迭代号>形态,其中基础段与基线各为MAJOR.MINOR.PATCH(基线可带预发布段)。不符合形态时版本命令报错——校验的是形态,不是某个具体值。 - 串内基线可能与 catalog 当前基线不同(DSH 刚升级、版本文件还停在旧基线)。这是合法的过渡态:解析按串内基线进行,发布时换成新基线并把迭代号重置为 0。
- 基线变化(如 DSH 升到
0.2.2-rc.1)时迭代号重置为 0。迭代号只在同一基线内才有比较意义,基线变了由基线本身决定先后(…-0.2.2-rc.1.0必然大于…-0.2.1-rc.x.y),所以重置不会造成排序倒退;真正会倒退的是同一基线内把迭代号改小,那种情况必须继续 +1。 - 已装
5.9.0(无小尾巴)的设备升级到新方案时,由于预发布版排序更小,安装可能被判降级。该情形需要显式验证并给出处置(升级、卸载重装或调整方案),不得默认它可用。 - 版本号必须是单行、无空格的纯 ASCII 串,可安全用于目录名、tag 与文件名。
- 不改动插件自身版本流程:插件版本仍为
<DSH 基线>.<修订号>,与项目版本是两套独立发布。
不在本次范围内
- 插件版本号的形态调整(插件版本仍随统一命令一起递增,见版本管理)。
- 应用市场或应用中心侧的版本比较实现(属平台行为,本仓库不对其做假设,只做实测验证)。
- 历史 FPK 与本方案前版本号的重命名或迁移。
既有功能变更关系
- 替换:项目/FPK 版本由「语义化档位递增」改为「固定前缀 + 迭代号递增」。档位参数形态保留,但语义收敛为「迭代号 +1」,不再移动前三段。
- 沿用:
bumpp仍负责版本文件替换、release 提交与本地 tag;插件版本流程完全不变。 - 沿用:catalog 中的
'@deepseek-ai/dsh'仍是 DSH 基线唯一来源,构建校验DSH_VERSION与它的一致性维持现状。
验收条件与完成状态
| 编号 | 验收条件 | 状态 |
|---|---|---|
| AC-01 | 版本命令产出的版本号形如 <基础段>-<catalog 基线>.<整数>;基础段原样继承当前版本,基线取自 catalog;形态非法(如仍是裸 MAJOR.MINOR.PATCH)时报错 | 已通过 |
| AC-02 | 同基线内连续发布迭代号严格 +1;基线变化时迭代号归零并重新计数 | 已通过 |
| AC-03 | 携带该版本号的 FPK 可被 fnpack 打包,且 FPK 内 manifest、根 package.json 与 Git tag 三处版本一致 | 已通过 |
| AC-04 | 真实设备上,新版本可覆盖安装旧版本(同基线不同迭代号),不被判为同版本或降级 | 已通过 |
| AC-05 | 已装历史 5.9.0(无小尾巴)的设备升级路径已实测,并记录该情形的处置结论 | 已通过 |
变更记录
| 日期 | 变更 | 说明 |
|---|---|---|
| 2026-10-18 | 初始登记 | 依据用户要求建立本需求:FPK 版本前缀固定为 5.9.0,0.2.1-rc.2 跟随 DSH 基线,末尾 x 为应用迭代号。登记 fnpack 对三种候选写法的实测结论、预发布排序的既有语义及其对已装 5.9.0 设备的升级影响,并把该影响列为必须实测的验收条件。 |
| 2026-10-19 | 新增基线切换入口 | 补 --baseline <版本>。此前基线变更没有可用入口:手工改 catalog 后 pnpm run 会在脚本执行前的依赖校验里失败(新版本通常尚未安装),连命令都进不来。改为在命令内部改写 catalog,校验看到的是变化前状态。明确只改版本号与那一行 catalog,依赖升级仍由 pnpm install 单独完成。 |
| 2026-10-19 | 基线变化时迭代号重置为 0 | 按用户给定规则调整:DSH 发新基线(含同 minor 内新 rc)时迭代号归零,同基线内修 bug 才 +1。登记三个示例:…rc.2.5→…rc.5.0、…rc.5.0→…rc.5.1、…rc.5.1→…0.2.2-rc.1.0。原「不重置」的理由是怕排序倒退,实测该担心在换基线时不成立。 |
| 2026-10-19 | 统一为同一迭代号 | 把「统一管理」落实为约束:插件版本直接取自项目版本(去掉基础段前缀),迭代号只算一次。取代此前「插件各自递增」的做法——那种做法起点相同时能同步,但有人手工改过其中之一就会永久错位。配套两条:不同号时报错并点名而非静默拉平;拒绝 minor/major 档位(只有迭代号能递增,静默当成 +1 会误导)。 |
| 2026-10-18 | 版本命令合并为单一入口 | 移除「选择要维护版本的区域」菜单(project/plugin 两套入口合并),一次执行同时推进项目迭代号与全部插件版本。明确插件各自递增、不强行对齐(各插件独立演进过,对齐会让未改动的插件凭空跳号)。同时修掉一处会降级的陷阱:插件版本带预发布段,字面 patch 会把 0.2.1-rc.2.5 变成 0.2.1,命令在插件侧改用 prerelease。 |
| 2026-10-18 | 基础段改为形态校验 | 最初把 5.9.0 写成代码常量并在基础段变化时报错。该做法让「调整基础段」必须改代码,且常量会与实际版本号悄悄不一致。改为:代码只校验 <基础段>-<基线>.<迭代号> 形态,基础段从当前版本串读取并原样继承。同时明确串内基线为旧基线是合法过渡态(否则 DSH 基线升级那次发布会解析失败、迭代号被迫归零)。 |
| 2026-10-19 | 验收通过 | 需求状态改为已完成,AC-01~AC-05 全部标记已通过。设备侧两项由需求提出人在真实 fnOS NAS 上实测:同基线迭代号覆盖安装(.5 → .6)成功,未被判同版本或降级;已装裸 5.9.0 的设备升级到带小尾巴版本成功,未被预发布排序判降级。后者是登记时就标为「不默认可用」的风险点(semver 中预发布版本排序低于同号正式版),实测结论为平台未按该规则拒绝——属平台实测结论而非文档保证,平台调整比较实现时需重验。 |