DSH-PackForge 规范仓库

DSH-PackForge specs repository

别名:规范仓库、规范与协议仓库、契约仓库、DSH-PackForge/specs

生态里所有契约的定义者:`manifest`(清单)、`pack-structure`(`.dspack` 容器)、`index`(市场索引)、`publishing`(发布流程)、`launcher-registry`(启动器 canonical ID 表)、`workspace-config`(`.dshpkcfg`)六份规范都在 `DSH-PackForge/DSH-PackForge` 这一个仓库里。本站「有争议时以规范为准」指的就是它。

一句话

生态里所有「契约」都写在同一个仓库里:DSH-PackForge/DSH-PackForge 的 specs/ 目录。所以本站说的「有争议时以规范仓库的文件为准」,指的是这一个仓库,而不是某个实现、某个启动器或某个包的现状。

把它们拆成八条词条没有必要——它们同属一个仓库、互相引用:manifest 决定容器里装什么,pack-structure 决定怎么装进去,index 决定市场怎么索引,publishing 决定怎么才会被收录。这一条做总览,需要细节再点进去看。

仓库里有哪些

规范管什么状态
manifest清单契约:包里声明什么、字段什么意思现行 v5
pack-structure容器契约:.dspack 长什么样、文件落到哪现行 v3
index市场索引契约:index.json 放什么、什么懒加载现行(schemaVersion 2)
publishing发布契约:怎么建仓、怎么发 Release 才会被自动收录现行 v1
launcher-registry启动器 canonical ID 认领表 + 版本比较规则现行
workspace-config.dshpkcfg:导出工作区快照的本地文件格式现行 v1
manifest/v1–v4、pack-structure/v1–v2历史版本,读旧包时用历史

六份现行规范各自的外链:manifest v5 · pack-structure v3 · index · publishing v1 · launcher-registry · workspace-config v1

清单契约:manifest v5

(原先单独成条的 manifest v5,按评审并进这里。)

manifest v5 是 .dspack 的清单头契约,也是「一切字段争议的最终裁判」:有争议时以规范仓库的文件为准,而不是以某个包的现状或某个启动器的实现为准。

一句话概括 v5 相对 v4 的变化:v4 只会描述「一个 profile」,v5 用 type 同时描述「一个 profile」和「一整个 $DSH_HOME」。

type: "profile"type: "dshhome"
是什么单 profile 的层栈(即 v4 契约)整个 $DSH_HOME 快照
必需字段bundles、dependenciesdefaultProfile、profiles
可选字段profileName、patch、filespresets、skills、instructions、files
承载容器.dspack v3(overrides/ → profile 根,可选 home/ → home 根).dspack v3(overrides/ → $DSH_HOME 根)

两条容易踩的:

  • "collection" 仍然预留、校验器直接拒绝——看到 type: "collection" 的包,它不是新形态,是无效包;
  • dshhome 的范围是硬约束:明确排除 ~/.agents(另一个共享 agent 配置根),也排除项目级内容(项目根下的 .dsh/、.agents/、AGENTS.md / CLAUDE.md 跟随 cwd,不随包分发);
  • profiles 只含用户自定义 profile,不得含 web / headless——这两个是 DSH 安装自带的模板,由 dshVersion 决定、不进包,校验器会拒。

r2 追加的两组可选字段

dshVersions:枚举,不是 range。 它是作者实测过的兼容版本枚举集(string[])。规范不用 semver range 的理由是:range 会诱导声明未实测的未来版本,而 DSH 版本带 rc 后缀、range 比较易错。安装决策是确定性的:dshVersions ∩ 本机已装 非空 → 命中多个时优先 dshVersion 指定者、其次集合内最新;交集为空 → 按 dshVersion 提示安装;两者全缺省 → 本机最新已装。老消费者只读 dshVersion,行为不变。

launchers:提示机制,不是门禁。 简式与全式语义等价(归一化后只剩全式);全式锁定三个字段:supported(唯一权威判定位)、minVersion(语义是「≥」,不精确钉死——启动器会自动更新)、reason(supported:false 时的理由)。未列出的 ID = 未声明(第三态),不等于「不支持」;判定核心是警告放行、不硬拒,且放行要在安装日志留痕。

导入时按什么顺序决策

两形态共有的前置是两步:启动器判定(警告放行)与 DSH 版本决策(上面的交集规则)。之后 profile 形态走「建实例 → overrides/ 落 profile 根 → pnpm install → 重建 profile → 可选 home/ 落 $DSH_HOME 根」;dshhome 形态要先确保 dshVersion 的 DSH 已安装(未装直接报错),再逐 profile 各自安装,最后设 defaultProfile。files[] / skills[] 下载校验失败会整体回滚。

读旧包的正确姿势

你看到的该怎么办
manifestVersion: 4 的包按 v4 的规则读它,别拿 v5 判它。v4 没有 launchers 字段,也没有 dshhome 形态
manifestVersion: 5 但没有 dshVersions正常。缺省视同 [dshVersion],老消费者本来就只读这个
type: "collection"无效包,校验器拒绝

「按声明的版本读」不是洁癖:市场里实测有包声明 manifestVersion: 4(快照 2026-09-30),它的 manifest 里连 launchers 字段都不存在——这不是它「拒绝了所有启动器」,而是那个版本根本没有这个字段。同样地,市场里 8 个包只有 2 个写了 launchers(一个全式、一个简式),其余 6 个一个都没写——所以「没写」是常态,不是不支持。

容器契约:pack-structure v3

.dspack = 纯 ZIP 内核 + 根 dspack.json({"format":"dspack","version":3})标记,同一个容器承载两种形态:

type: "profile"type: "dshhome"
装的是单个 profile 的层栈整个 $DSH_HOME 快照
overrides/ 落到$DSH_HOME/profiles/<name>/$DSH_HOME/(按相对路径平铺)
home/(可选)落到 $DSH_HOME/(上一级目录)不用(overrides/ 本身就是 home 根)

加载器判定四步:能当 ZIP 打开 → 有根 dspack.json → format/version 对 → 再按 manifest 的 type 分形态。overrides/ 与 home/ 的语义是文件级复制替换,不是字段级合并——真正的合并式覆盖由 cordis.patch.yml(concept/1)承担。

home/ 的存在理由值得单独说:skill 与 agent preset 在 DSH 里是 home 级(profile 目录的上一级,见 concept/3),v2 的容器装不进它们,只能升级成整个 dshhome 快照;v3 让「单 profile 包顺带带几个全局单元」成为可能。

安全过滤:打包时排除凭据与运行时状态(.credentials.yaml、.anonymous-user-id、attachments/、settings.yaml、skills/.system/,以及 dshhome 形态下的 profiles/web/、profiles/headless/)。重内容(大文件、重技能)不进包体,走 files[] / skills[] 下载,按 sha256 + size 校验,任一失败整体回滚。

市场索引:index

「精简指针制」两段式——索引文件只放列表、搜索、安装命令必需的字段(下载三要素 downloadUrl + sha256 + size,加上展示元数据与计数),不含 bundles[] / dependencies{} / profiles / presets / skills 这些可能很大的字段;完整 manifest 与源仓库 README 拆到 packs/<owner>.<repo>/,点开详情时懒加载。它是本站整合包分区的数据上游。

发布契约:publishing v1

目标是零人工登记:作者只要按规范建仓 + 发 Release,采集器就能自动发现并收录,不用向任何地方提 PR。三个「必需」:

  1. 仓库公开(采集器读不到私有仓库);
  2. 打主题标签 dsh-pack(这是全网唯一的发现入口,没打就永远扫不到);
  3. 默认分支根部放 manifest.json。

Release 是默认下载来源,配 sha256 侧车文件;也可以用 downloadUrl 直链替代。进索引的下载三要素就是 downloadUrl + sha256 + size。

启动器注册表:launcher-registry

manifest v5 的 launchers 字段引用的 canonical ID 认领表(安装端判定见 pack-structure §9.1),当前 5 条:

ID是谁
dshlPCL-Deepseek-Harness-Launcher(PCL2 魔改)
hdslHDSL · Hello DeepSeek Launcher(HMCL 内核 JavaFX)
dsh-packforge-appDSH PackForge GUI / dspack CLI
official-desktopDeepSeek Harness 官方桌面端
dsh-cli裸 dsh 命令行(无启动器)

⚠️ 别混淆:dshl(PCL 系)与 hdsl(Hello 系)只差一个字母、完全无关——本站启动器分区里这两条也各是各的。

版本比较规则:按 . 分段、逐段数值比较、缺段视为 0,不做 rc 之类预发布语义;启动器要自报版本号。不满足 minVersion 只提示、不硬拒。

工作区配置:workspace-config v1(.dshpkcfg)

PackForge 桌面端在导出流程里持久化的「导出工作区快照」——保存整合包名、版本、作者、内容开关、输出目录等,下次点「读取」恢复。它是工具本地文件、不进入整合包(打包时命中安全过滤清单被排除);一个目录一份,形态由所在目录区分(文件内没有 kind 字段)。

历史版本

manifest 有 v1–v4、pack-structure 有 v1–v2,都保留在仓库里可读——读它们不是为了守着旧写法,而是为了两件事:

  1. 读旧包:市场里实测仍有包声明 manifestVersion: 4(甚至 .tgz 时代的包)。读旧包要按它声明的版本去读对应文件,别拿 v5 的规则去判它。
  2. 理解字段怎么长出来的:v5 的 type / dshhome 形态、v3 的 home/,都是前面几版长出问题的答案。

本站怎么用它

  • 词条里凡是写「以规范为准」的地方,指的都是这个仓库的对应文件;
  • 分区页把每份规范按「现行 / 历史」列出来,外链直达仓库里的文件;
  • 规范要改,就向该仓库提 PR——不要在实现里私自分叉,这是这一层存在的意义。

未核实

  • 本页按公开 URL 逐份读到 specs/ 下 12 个文件,没有本机 checkout 副本对照;
  • 「发布契约」与「市场索引」描述的是规范要求,不是「采集器当前实现完全符合」的实测结论;
  • 上游最后一次提交是 2026-10-01(快照日),此后若有改动,以仓库里的文件为准。

谁引用了这一条

信息表

category
ecosystem.spec
maintainers
hxh230802
repo
DSH-PackForge/DSH-PackForge
titleEn
DSH-PackForge specs repository
updatedAt
2026-10-02
url
https://github.com/DSH-PackForge/DSH-PackForge

被 2 条词条引用

最后更新 2026-10-02