Skip to content

PLAN-FNOS-019 FPK 版本方案固定前缀与插件基线小尾巴 ​

字段内容
计划编号PLAN-FNOS-019
对应需求FNOS-019 FPK 版本方案固定前缀与插件基线小尾巴
计划状态已完成(三阶段全部完成,含真实设备升级复验)
影响范围tooling/fnos-dsh-cli(新增版本方案模块、改写 project 版本流程、单测)、apps/fn-deepseek-harness/manifest、docs/build/versioning.md
前置依赖catalog 中已声明 '@deepseek-ai/dsh'(当前 0.2.1-rc.2)

目标与范围 ​

把项目/FPK 版本从「语义化档位递增」改为「固定前缀 + 迭代号递增」,并让 DSH 基线由 catalog 自动承载。插件版本流程保持原样。

关键设计决定 ​

版本拆解不能用「按 - 切一刀」 ​

版本串 5.9.0-0.2.1-rc.2.5 里出现两个 -:第一个分隔基础版本与尾部,第二个属于基线自身的预发布段(rc.2)。因此基线边界只能从尾部定位:末尾的 . 之后是迭代号,其余为基线。

一处固有歧义及其消解方式 ​

5.9.0-0.2.1-rc.2 既可读作「基线 0.2.1-rc.2、缺迭代号」,也可读作「基线 0.2.1-rc、迭代号 2」——两者产生完全相同的字符串,仅凭版本串无法区分。

消解方式:拆解函数接受可选的「已知基线」参数。提供时按基线前缀唯一匹配——尾部恰好等于基线即视为缺迭代号(迭代号 0),否则按 <基线>.<数字> 取迭代号。计算下次版本时必须传入基线,否则缺迭代号的版本会被误读成迭代号 2,导致下次跳号到 3。

基线变化时迭代号重置为 0 ​

基线变化(DSH 升级)时迭代号从 0 重新开始:5.9.0-0.2.1-rc.2.5 → 5.9.0-0.2.1-rc.5.0。迭代号只在同一基线内才有比较意义——基线变了,先后由基线本身决定(…-0.2.1-rc.5.0 必然大于 …-0.2.1-rc.2.5),所以重置不会造成排序倒退。真正会倒退的是同一基线内把迭代号改小,那种情况必须继续 +1。

基础段用正则校验形态,不写代码常量 ​

「5.9.0 静态不动」的落法有两种:把它写成代码常量并在不符时报错,或只校验形态、值由版本号自身承载。选后者:常量会让「调整基础段」必须改代码,且常量与实际版本号可能悄悄不一致;校验形态则让版本文件成为唯一事实来源,代码不认识那个字面量。

同样的判断适用于串内基线:它可能与 catalog 当前基线不同(DSH 刚升级、版本文件还是旧基线)。这是合法过渡态——若把它判成非法,基线升级那次发布会解析不出当前版本,迭代号被迫归零,正好撞上本方案要避免的排序倒退。

显式版本交给 bumpp,不用语义化档位 ​

bumpp 的 release 选项接受具体版本串。因此自行算出目标版本后以显式值传入,仍由 bumpp 负责文件替换、release 提交与本地 tag——不引入新的版本工具,也不改提交与 tag 行为。

档位关键字(patch/minor/major)保留参数形态,语义统一收敛为「迭代号 +1」;传入完整版本串时按其字面值写入。

任务列表 ​

阶段一:版本方案模块 ​

任务 ID对应验收实现内容验收
T01-01AC-01新增 tooling/fnos-dsh-cli/src/core/project-version.ts:parseProjectVersion(正则整体匹配 + 已知基线消歧)、formatProjectVersion、nextProjectVersion(基础段原样继承)、readDshBaselineFromCatalog、assertProjectVersionShape。不导出基础版本常量——代码不持有该字面量模块可被导入,类型检查通过
T01-02AC-01readDshBaselineFromCatalog 只认顶层 catalog 的 '@deepseek-ai/dsh' 条目,拒绝把分组内子包(如 dsh: 下的 dsh-agent)当作基线用真实 pnpm-workspace.yaml 读出 0.2.1-rc.2;分组内容不被误取
T01-03AC-02nextProjectVersion 实现:基础段原样继承、基线取自入参;基线未变时迭代号 +1,基线变化时重置为 0;缺迭代号的旧串按 0 处理;非法基线抛错单测覆盖:.5→.6、缺迭代号→.1、基线变化→.0

阶段二:接入版本命令 ​

任务 ID对应验收实现内容验收
T02-01AC-01改写 versionProject:从 pnpm-workspace.yaml 读基线,计算目标版本后以显式值传给 bumpp;基线缺失时报错命令产出的版本号形如 5.9.0-0.2.1-rc.2.<x>
T02-02AC-01用正则校验当前版本串符合 <基础段>-<基线>.<迭代号> 形态;不合形态(如裸 MAJOR.MINOR.PATCH)时报错裸版本号被拒绝;换个基础段的合法版本号照样通过
T02-03AC-03保持版本文件清单与 tag 行为不变:manifest、根 package.json、docs/package.json、tag 前缀均为新版本串--no-commit 下文件被写入;tag 仍本地不推送

阶段三:验证与文档 ​

任务 ID对应验收实现内容验收
T03-01AC-03新增 tooling/fnos-dsh-cli/tests/project-version.spec.ts,覆盖拆解、组装、递增、消歧与 catalog 读取单测全绿;变异检查确认断言有牙齿
T03-02AC-03真实打包验证:用新版本串执行 pnpm run build -- --fpk,核对 FPK 内 manifest 版本与文件名fnpack 成功,FPK 内版本与根 package.json、tag 一致
T03-03AC-04、AC-05真实设备验证:同基线不同迭代号可覆盖安装;已装历史 5.9.0 的升级路径给出结论记录实测结果;无法验证时如实标为阻塞并写明原因
T03-04AC-01更新 docs/build/versioning.md 的项目版本小节,说明新方案、递增规则、基线来源与预发布排序的既有语义文档与实现一致,SDD 检查通过

测试用例 ​

测试用例登记在测试用例文档 FNOS-019,覆盖版本拆解与组装、迭代号递增、基线变化、catalog 读取、打包一致性与真实设备升级。

风险与决策 ​

项目风险或决策处理方式
预发布排序5.9.0-* 按 semver 小于 5.9.0,已装正式 5.9.0 的设备可能拒装新版本列为必测项(AC-05);实测确认平台行为后再定处置,不默认可用
平台比较实现未知fnOS 应用中心如何比较版本未从文档确认只做实测,不假设;两版各打一个 FPK 在设备上验证
尾部歧义…rc.2 既可读作缺迭代号也可读作迭代号 2拆解时传入已知基线消歧,并在单测中固定该行为
基线来源手工维护基线副本会与 catalog 漂移一律从 pnpm-workspace.yaml 读取,缺失时报错
基础段常量把 5.9.0 写成常量会让调整基础段必须改代码,且常量可能与版本文件不一致代码只校验形态,基础段从当前版本串原样继承
迭代号上限迭代号为单段整数,无上限设计当前无实际约束;若未来溢出可按需扩展,不在本次范围

完成状态 ​

阶段状态完成条件
阶段一 版本方案模块已完成模块实现并通过单测
阶段二 接入版本命令已完成命令产出新形态并保持提交/tag 行为
阶段三 验证与文档已完成单测、真实打包与文档更新完成;设备升级结论如实记录

变更记录 ​

日期变更说明
2026-10-19阶段三完成,计划收尾真实 fnOS NAS 复验通过:同基线迭代号覆盖安装成功、已装裸 5.9.0 可升级到带小尾巴版本。三阶段全部完成,计划状态改为已完成。阶段三的完成条件「设备升级结论如实记录」由测试文档 TC-016/TC-017 承载。
2026-10-19基线变化时迭代号重置按用户要求改为:基线一变迭代号归零(…rc.2.5 → …rc.5.0、…rc.5.1 → …0.2.2-rc.1.0),同基线内才 +1。原设计「不重置」是担心排序倒退,实测确认该担心在换基线时不成立(基线本身决定先后);同基线内改小才真的会降级,那种情况仍 +1。
2026-10-18基础段改为形态校验原设计导出 PROJECT_BASE_VERSION = '5.9.0' 并在漂移时报错;改为正则校验形态、基础段原样继承,代码不持有该字面量。连带修一处设计缺陷:串内基线为旧基线时必须能解析(否则基线升级时迭代号会归零)。
2026-10-18建立 PLAN-FNOS-019依据 FNOS-019 拆出三个阶段:版本方案模块、接入版本命令、验证与文档。明确三处关键设计:尾部定位基线边界、已知基线消歧、基线变化不重置迭代号。把预发布排序对已装 5.9.0 设备的影响列为必测风险,不默认可用。

基于 VitePress 构建