---
title: 打包与发布
description: 安装包的组成、安装时和装好以后的校验、签名与信任级别,以及目前能用的分发方式。
section: dev
order: 80
updated: 2026-11-05
---
# 打包与发布
## 现在能怎么分发
- **装到自己的机器上**:在 Gem Studio 里点「安装」。Notochord 在本机把草稿打成一个安装包,走和商店里的 gem 相同的安装流程——同样的校验,装完同样到 gem 的页面上设置。只是这个包没有签名,按「Developer mode (unsigned)」处理。
- **分发给别人**:目前还没有把草稿导出成安装包、或者提交到商店的入口。应用里的商店现在列出的是我们自己维护的开源 gem。
## 安装包里有什么
一个 zip,根目录下是:
| 文件 | 说明 |
| --- | --- |
| `notochord.json` | 清单。除了[清单参考](/zh/dev/manifest.md)里的字段,还带打包时生成的两项:`agents[]`(从 `agents/` 下每个文件的头部生成)和 `integrity`(包里其余每个文件的 SHA-256 和大小)。 |
| `SIGNATURE.json` | 对清单的签名。从 Gem Studio 安装的草稿没有这个文件。 |
| 其余文件 | 工具(`tools/`)、agent(`agents/<名字>.md`:头部 + 系统提示词)、SOP(`workflows/`)、页面(`pages/`)、集合的迁移模块(`data.collections.<集合>.migrations` 指向的文件)等。`db/` 放 `rawSqlite` 数据库的表结构和迁移(`db/schema.sql`、`db/migrations/`);有它的 gem 启动时就打开这个数据库,表结构或迁移出错,gem 就启动不了。下面两个文件夹不用在清单里声明,放在那里就算:`skill/`(`SKILL.md` 和 `references/` 下的文本文件,见 [skill](/zh/dev/manifest.md#skill)),`docs/`(商店介绍页,只有 Markdown,见 [docs](/zh/dev/manifest.md#docs);Gem Studio 打包时去掉其中不是 `.md` 的文件)。 |
## 安装时检查什么
安装和升级都按下面的顺序检查,任何一项不过,这个包就不会被装上:
1. **解包**。包里不能有绝对路径、`..`、符号链接、只差大小写的重名文件;文件数不能超过 10000;解压出来的内容不能超过清单声明的总大小。
2. **签名**(见下一节)。在读取清单里的任何内容之前进行。
3. **清单格式**。清单里出现不认识的字段会被拒绝,而不是被忽略。gem 的 id 不能以 `draft-test.` 开头,这个前缀留给 Gem Studio 的测试。
4. **版本**。不能比已安装的版本低。版本号相同就是重装:用包里的文件替换已安装的文件,gem 的数据和设置保留。
5. **完整性**。`integrity` 列出的文件和包里实际的文件必须一一对应:多一个、少一个、大小或 SHA-256 对不上,都不行。没有签名的包也必须有 `integrity`(Gem Studio 打包时自动算出)。
6. **声明是否合法**。权限的写法、agent 引用的工具是否存在、`resources` 的 `id` 是否重复、每个 SOP 的调用目标和触发器、`skill/` 和 `docs/` 里的文件类型,以及 [`data`](/zh/dev/manifest.md#data) 段:不合规报 `E_PERM_INVALID`,消息以 `data:` 开头(`data` 段里不认识的键、写错的 `type` 在第 3 步就被拒绝);集合的迁移模块必须是包里的文件。
从商店或 Gem Studio 安装时,这些检查都通过才会装上;没有给用户的确认步骤。装好后打开这个 gem 的页面,需要配置的(账号、邮箱、知识库)都还是关着的,等用户设置。
**升级会迁移数据。** 检查都通过后,新版本被激活。新版本提高了某个集合的 `version` 时,激活时先运行[迁移](/zh/dev/storage.md#版本与迁移)。迁移失败,或者 `data` 的改动不合[改字段的规则](/zh/dev/manifest.md#改字段的规则),整个升级回滚:数据恢复原样,旧版本继续运行,报 `E_ACTIVATION_FAILED`。
常见的报错:
| 报错 | 原因 |
| --- | --- |
| `E_PATH_TRAVERSAL` | 包里有不允许的路径或文件类型,或者文件太多 |
| `E_SIG_INVALID` | `SIGNATURE.json` 格式不对,或者签名和清单对不上(清单被改过) |
| `E_UNKNOWN_KEY` | 签名用的密钥不是这台机器信任的 |
| `E_PUBLISHER_MISMATCH` | `SIGNATURE.json` 的 `publisherId` 和清单的 `author.publisherId` 不一致 |
| `E_PERM_INVALID` | 清单格式不对(报错里会指出哪个字段),或者某项声明不合法 |
| `E_VERSION_OLDER` | 包的版本号比已安装的低 |
| `E_HASH_MISMATCH`、`E_SIZE_MISMATCH` | 包里的文件和 `integrity` 对不上 |
| `E_WORKFLOW_INVALID`、`E_INPUT_INVALID` | SOP 或它的触发器有问题,见[事件与触发](/zh/dev/events.md#排查) |
| `E_ACTIVATION_FAILED` | 检查都通过了,但升级或同版本重装后这个版本激活失败,多半是 `data`:迁移失败,或者改动不合[改字段的规则](/zh/dev/manifest.md#改字段的规则)。原因(如 `E_DATA_SCHEMA: …`)写在报错里。升级时已经回滚到旧版本。第一次安装时报的是原来的错误。 |
## 签名与信任级别
签名是对 `notochord.json` 做的:Ed25519,签名前先按 RFC 8785 把 JSON 规范化。清单里改动任何一处内容——权限、工具说明、`integrity` 里某个文件的哈希——签名都会失效;包里其余的文件则由 `integrity` 逐个钉住。两者合起来,一个签过名的包,清单和它引用的每个文件都不能在不被发现的情况下改动。
安装时,一个包按下面三级之一处理(应用里目前不显示是哪一级):
| 级别 | 含义 |
| --- | --- |
| Official signature | 签名能用 Notochord 的官方公钥验证。官方公钥内置在应用里,不从磁盘或网络读取。 |
| Signed by a trusted developer | 签名来自这台机器信任的某个开发者密钥,并且 `SIGNATURE.json` 的 `publisherId` 和清单的 `author.publisherId` 一致。**应用里目前还没有添加开发者密钥的入口,这一级暂时用不上。** |
| Developer mode (unsigned) | 没有验证签名。从 Gem Studio 安装草稿就是这一级。签名以外的检查照常进行。 |
- 从商店下载的包必须通过签名验证,通不过就装不上。
- **装好以后也会检查文件。** 激活时、每次调用工具、SOP 启动和恢复、读 skill 文件之前,Notochord 都把这个 gem 目录里的文件和安装时的 `integrity` 比对:多一个、少一个、改了一个(系统生成的 `.DS_Store`、`Thumbs.db`、`desktop.ini` 不算,打包时也不列入清单),这个 gem 就停止运行(报 `E_FILES_CHANGED`),用户在 gem 的页面上点「重新下载」修复,数据和设置都保留。安装后磁盘上的 `notochord.json` 不再被读取,清单以安装时的那份为准。开发时不要直接改已安装 gem 的文件,在 Gem Studio 里改完重新安装。