OpenProgram 安装、打包、发布与升级设计
正式版本:v0.9.8
本文是 OpenProgram 安装与分发的规范来源。它分别定义用户类型与平台支持,覆盖 macOS/Windows 桌面包、macOS/Linux/Windows 命令行与服务器安装、浏览器访问、Python 运行时归属、Program 扩展环境、版本、升级和卸载。正式版本的检查、下载、平台安装边界和当前实现证据由正式版本自动更新设计细化。
1. 已确定的设计约束
- Python 是 OpenProgram 后端、CLI、Runtime 和 Program 执行的核心运行时,不允许以删除 Python 的方式简化安装。
- macOS 桌面版通过明确标注
Unsigned的 DMG/ZIP 分发;Windows 桌面版只通过 Authenticode 签名的 x64 NSIS installer 分发;Linux 只发布完整 CLI/server runtime。 - 所有非开发者安装使用同一份按平台与架构构建的完整 product runtime。Desktop 只是增加 Electron 外壳,CLI/server 只是增加命令行 launcher;二者不能安装不同的 Web、Provider、Channel、Browser、模型资产或第一方 Program 功能集合。
- 完整 product runtime 包含固定 CPython、OpenProgram、预编译 Web、Channels、Search、GUI/Research/Wiki 第一方 Programs、Playwright Chromium、GPA detector 权重,以及 Research 的 PDF 支持和其他 manifest 依赖。GUI Program 使用
--no-deps安装;product runtime 明确排除 PyTorch、torchvision、OpenCV、EasyOCR、sentence-transformers、triton 和 NVIDIA/CUDA distributions。 - 普通用户不需要预装 Python 或 Node.js。Session 与 Memory 的 Git history 需要 PATH 中可用的系统 Git,product runtime 不内嵌 Git。安装器可以下载与当前平台对应的完整 runtime archive,但不能把缺少 manifest capability 的产物标为完整安装。
- 桌面包与 CLI runtime 在运行期保持只读;配置、会话、缓存和用户新增的第三方 Program 写入
~/.openprogram。 - 开发安装在完整产品能力之上增加 editable source、调试工具、本地 Web/Ink 构建、测试工具,以及 GUI perception、OCR、Browser 等显式配置的 backend overlay。依赖 PyTorch、OpenCV 或 EasyOCR 的 GUI perception 路径只在这类 overlay 中提供,不属于普通安装的 manifest capability。
stable表示已发布、已验证的版本,不表示origin/main。main只属于开发安装。- 正式安装不使用 editable checkout,不在用户机器上构建 Web 或 Ink,不依赖仓库目录,也不通过 PyPI 解析产品依赖。
pip install openprogram、pipx install openprogram和uv tool install openprogram都不是受支持的产品安装入口。公开索引、入门文档和运行时修复提示只能指向正式安装器或完整安装包;wheel 仅用于 release runtime 组装、源码开发和测试。- PyInstaller、Briefcase 和 py2app 只作为参考实现,不替换现有 Electron 桌面应用。
- 普通用户的 CLI/server 默认入口是
curl -fsSL https://openprogram.io/install | sh。站点脚本只解析最新稳定 release、校验版本格式并下载该不可变 tag 下的 installer;runtime checksum、capability manifest 和 cold-start 验证仍由版本化 installer 完成。 - macOS 本机安装态只有固定路径
/Applications/OpenProgram.app。本地桌面构建在未注册的临时目录生成并验证 App,随后替换该固定路径;临时 App 不启动、不保留,也不使用版本号或任务名作为 App 目录名。 - Windows x86_64 CLI/server 使用完整 ZIP runtime 与 PowerShell installer。Windows Desktop 使用同一 runtime archive、按用户 NSIS installer、ConPTY 与强制签名 release gate;Windows 沙箱仍是独立层级。
2. 当前实现与已验证缺口
| 范围 | 当前实现 | 与本设计的差异 |
|---|---|---|
| 安装脚本 | scripts/install.sh 克隆仓库,创建或复用 Python 环境,执行 editable install,并在本机运行 npm 构建。 | 这是开发安装行为,不能作为正式 release installer。 |
| Python wheel | pyproject.toml 定义 CLI entry point 和 package data;release staging 会把预编译 Web 资源写入 wheel,并把独立 Ink bundle 放进平台 runtime。 | 已完成 Web 资源的 clean-wheel 验收;Ink 由 runtime 内的平台 Node.js 执行,不要求用户安装 npm 依赖。 |
| Web UI | frontend.py 在 release wheel 中优先读取 Server package 内的 _frontend;源码 checkout 仍使用 apps/web/out。 | 当前源码版本基线为 v0.9.8;仓库保留的 v0.7.0 clean-wheel/runtime 验收属于历史证据。普通用户机器不执行 npm build。 |
| TUI | openprogram_cli/_impl/ink.py 在源码 checkout 定位 apps/cli/dist,在正式 runtime 定位 assets/tui/index.cjs 与 bin/node。启动按 raw-input 能力判断,不按操作系统禁用。 | 正式 CLI 同时提供自带 Node.js 的完整 Ink 界面和不依赖 Node.js raw mode 的 Rich 回退;Windows Terminal / ConPTY 已纳入本地验收。 |
| Program 安装 | product-runtime.json 固定 GUI、Research、Wiki commits、capability IDs 和 GPA detector 来源;runtime builder 在构建期安装三项 Program,其中 GUI 使用 --no-deps,Research 使用 [pdf],Wiki 安装其声明依赖。 | 普通用户不再选择或补装第一方 Program;PyTorch、OpenCV、EasyOCR 等 GUI perception 依赖不进入 product runtime,只能通过显式 overlay 增加。 |
| Electron | apps/desktop/main.js 在 packaged mode 验证 schema 2 capability manifest,从 resources 解析包内 CPython 和 Browser/OCR/model 路径,并以隔离模式启动 worker;apps/desktop/package.json 声明 macOS DMG/ZIP 与 Windows x64 NSIS,并包含 Windows PowerShell/ConPTY 接缝。 | macOS arm64/x64 DMG 与 ZIP 已通过发布验收;Windows 在原生 runner 组装同一完整 runtime,要求应用和 installer 签名并执行包内 smoke。Linux AppImage 已从发布配置移除。 |
| 版本 | pyproject.toml 是规范版本来源;Electron metadata 保留构建工具要求的副本。 | release gate 必须拒绝 tag、Python metadata 和 Electron metadata 的任何不一致。 |
| 发布 | tag workflow 先按平台与架构构建完整 runtime archive,再由 Desktop job 与 CLI installer job 下载同名 archive;只发布 GitHub Release,不运行 PyPI 或 macOS notarization job。Windows Desktop job 必须使用签名凭证。 | Windows Desktop 代码和本地 package/runtime smoke 已实现;公开发布还必须通过带真实证书的 Authenticode 门禁。 |
| 升级 | CLI release installer 下载新 runtime archive,在独立目录验证 checksum、capabilities、Browser、Programs 和 worker cold-start 后切换 current;source checkout 的升级继续属于开发通道。 | v0.7.0 的四个原生 CLI installer job 和隔离 macOS arm64 安装是历史验收证据;当前源码/打包基线为 v0.9.8,远端 latest 与 installed-client 交互需单独核验。 |
3. 官方规范与工具比较
本设计以 Electron 和 electron-builder 组装 macOS 桌面外壳,以 uv 和标准 wheel 组装内部 product runtime,并以 GitHub Release 分发 macOS/Linux/Windows 按平台与架构固定的完整 runtime archive。Apple、Linux 桌面打包与 PyPA 规范继续用于说明被明确拒绝或限制的分发选择。
| 参考 | 提供的能力 | 缺少或不适用的能力 | OpenProgram 采用方式 |
|---|---|---|---|
| Apple 分发 | DMG、PKG、ZIP 的适用边界;Developer ID 签名;嵌套代码签名;notarization。 | Developer ID 需要付费账号,且不负责 Python 或 Electron 的项目级组装。 | 当前拒绝签名服务:保留 DMG 结构,但产物与安装文档必须标注 unsigned 和 Gatekeeper 手动放行步骤;不得声称 Apple 已验证。 |
| Apple 应用图标指南 / Icon Composer 指南 | 当前分层格式使用 1024×1024 未遮罩画布,由 Icon Composer 和 Xcode 生成平台外形;legacy ICNS 需要提供 16–1024 px 的完整 representations。 | 本项目当前受支持的 macOS 15 构建机只有 Command Line Tools,没有完整 Xcode 的 actool,不能直接把 .icon 编译为 Electron 可消费的产物;Electron 对 .icns 原样打包。 | 采用兼容实现:AppIcon.icon 保存 Apple 分层维护源,经过审核的 icon.icns 作为 Electron 的受版本控制打包输入;门禁同时验证分层源、ICNS representations 和最终系统轮廓,禁止回退到手绘外框 SVG。 |
| Electron 分发 / electron-builder 签名 | Electron 资源打包、macOS 签名、发布和自动更新集成。 | 不提供 Python runtime、Programs、模型或 Python dependency resolution。 | 采用并扩展:Electron 只提供 Desktop 外壳,读取与 CLI 完全相同的 product runtime archive。 |
| electron-builder Linux 目标 / AppImage | AppImage、deb、rpm、Snap 和 Flatpak 等 Linux 产物;AppImage 是无需 root 的单文件产物。 | 不解决 Python runtime、不同 glibc 基线或 OpenProgram 功能验收;当前完整 AppImage 在 electron-builder block-map 阶段失败,未形成可验收产物。 | 当前拒绝发布:不发布精简包,也不把未通过公共入口验收的 AppImage 标为支持。Linux 通过完整 CLI/server runtime 提供产品功能。 |
| BeeWare Briefcase | Python 应用、CPython support package、签名 app、DMG/PKG/ZIP 和 notarization。 | 它本身生成应用容器;与现有 Electron 应用职责重复。 | 采用结构原则:Python 和依赖进入 app bundle;不采用 Briefcase 作为顶层构建器。 |
| PyInstaller | 把解释器、应用和依赖组装成无需预装 Python 的产物。 | 独立可执行打包不适合 OpenProgram 的 Python 库入口、动态 Program 发现和可变扩展依赖。 | 拒绝:不采用 PyInstaller;保留标准 CPython 与 wheel 语义。 |
| py2app | 创建包含 Python.framework 和 Mach-O 依赖的独立 macOS app。 | 同样会形成第二套 app 构建层,不能替代 Electron shell。 | 参考:用于核对 Python.framework、Mach-O 和 app bundle 布局,不直接采用。 |
| uv 环境 | 不依赖 Python 的独立二进制、虚拟环境、固定解释器安装目标、Python 下载与依赖同步。 | uv tool 环境不应被 pip 直接修改,与当前 Program 安装行为不兼容。 | 采用并限制:CLI 安装和 Program 环境使用受控 uv;不把 uv tool install openprogram 作为正式安装方式。 |
| PyPA 打包 / PyPI 可信发布 | wheel/sdist、entry point、构建隔离和基于 OIDC 的发布。 | wheel 不包含 CPython、浏览器、模型和完整第一方 Programs,不能满足普通用户的统一安装契约。 | 限制为开发者产物:构建过程继续使用 wheel 作为内部 Python 代码输入;普通用户不通过 pip install 或 PyPI 获得产品安装。 |
4. 用户类型与平台支持
三类用户描述安装目的,平台矩阵描述产品承诺。两者分别维护,不能以用户类型代替平台覆盖。
macOS 与 Windows 桌面用户
macOS 下载 unsigned DMG;Windows 只安装带签名 EXE。Desktop 内含完整 product runtime,不读取系统 Python、Node.js 或 Git。Linux 当前不发布桌面包。
macOS、Linux 与 Windows 命令行用户
运行固定 release installer,下载完整 runtime archive。产品能力集合与受支持 Desktop 相同,只是不包含 Electron 窗口。
开发者
克隆仓库,在完整产品能力之上增加 editable source、测试、调试、本地前端构建和可替换 OCR/Browser 后端。开发者 wheel 不是普通用户安装方式。
| 属性 | 桌面 | CLI / 服务端 | 开发 |
|---|---|---|---|
| 版本来源 | GitHub Release | 同一 GitHub Release | Git 检出目录 |
| 产品 Runtime | 平台 runtime archive + Electron | 同一平台 runtime archive | 同等产品能力 + 开发 overlay |
| 系统 Python / Node.js | 不需要 | 不需要 | 需要开发工具链 |
| 系统 Git | Session/Memory history 需要 | Session/Memory history 需要 | 开发与 history 均需要 |
| 功能集合 | 完整 capability manifest | 相同 capability manifest | 相同产品功能并允许显式 backend overlay |
| 升级目标 | 已发布完整 runtime | 相同已发布完整 runtime | 明确 Git ref |
| 默认通道 | stable | stable | dev |
4.1 平台支持矩阵
| 平台 | 原生桌面 | CLI / 服务端 | 浏览器访问 | 开发 |
|---|---|---|---|---|
| macOS arm64 / x64 | 正式支持:DMG | 正式支持 | 本地或远程 | 正式支持 |
| Linux x86_64 | 不发布桌面包 | 完整 runtime 已验证 | 本地或远程 | 正式支持 |
| Linux arm64 | 不发布桌面包 | 完整 runtime 已验证 | 本地或远程 | 按 Python/Linux gate 验证 |
| Windows x86_64 | 带签名 EXE;发布门禁 | 完整 ZIP runtime + PowerShell installer | 本机或远程访问 | 沙箱暂缓 |
| iOS / Android / iPadOS | 无原生应用 | 不适用 | 只访问受支持主机;不承诺移动端布局 | 不适用 |
浏览器访问不把客户端操作系统提升为原生支持平台。服务端必须运行在受支持的 macOS、Linux 或 Windows 安装中;只有经过浏览器和响应式验收的组合才能标为正式支持。
5. 一个版本与一组发布产物
pyproject.toml 中的项目版本是规范版本来源。Electron metadata 由于构建工具要求保留副本,release gate 验证它、runtime manifest、release manifest 和 tag 完全一致。tag 必须指向被构建的 commit。
vX.Y.Z固定源码、lockfile、第一方 Program commits、模型、CPython 与 uv
Web + Browser + OCR/模型
GUI / 研究 / Wiki 程序
Windows 桌面端:签名 EXE
macOS/Linux CLI:tar.gz + 启动器
Windows CLI:ZIP + PowerShell 启动器
每次 release 至少生成:
- macOS arm64/x64、Linux x86_64/arm64 与 Windows x86_64 的完整 runtime archives;
- macOS arm64/x64 unsigned DMG/ZIP 与 Windows x64 signed EXE;
- 开发者使用的 wheel/sdist,但不作为普通用户安装入口;
- 包含版本、capability IDs、第一方 Program commits、模型标识、文件大小和 SHA-256 的 release manifest。
首个正式版本分别构建 arm64 和 x64,不生成 universal2。Python native wheels、Browser、OCR、模型和 Electron helper 都具有平台或架构差异;每个平台分别生成 runtime,但同一 capability manifest 的所有条目必须为 present 和 verified,否则整个平台不发布。
OpenProgram.app。本地构建产生的中间 App 在安装事务结束后删除,不作为历史版本保存。6. macOS 与 Windows 桌面包
6.1 图标资产
apps/desktop/build/AppIcon.icon是 Apple 分层维护源,四个 SVG layer 使用 1024×1024 未遮罩画布;apps/desktop/build/icon.icns是受版本控制、供 Electron 打包的兼容产物。- legacy ICNS 保留经过系统 App 对照验收的可见范围、圆角轮廓、透明四角和受控阴影;分层
.icon本身不得预绘系统外框。 - 薰衣草色细胞和其中三个扁平圆片保持居中并位于安全区域,不增加文字、问号或嵌入 raster。标志定义见 App 图标规范。
- 构建门禁验证分层源结构、品牌图形约束、ICNS representations、256 px 轮廓与实心面积、透明四角和 ICNS round trip;最终只通过安装后的
/Applications/OpenProgram.app检查 Dock、Finder 和 Launchpad 显示。
6.2 逻辑内容
OpenProgram.dmg → OpenProgram.app/Contents/
macOS 桌面资源目录
├── MacOS/
│ └── OpenProgram # Electron launcher
├── Frameworks/
│ ├── Electron Framework.framework
│ └── Electron helpers
└── Resources/
├── app.asar # Electron main/preload
└── runtime/
├── python/ # 固定 portable CPython + 完整产品依赖
├── bin/uv # 固定 uv
├── wheel/ # 构建时 wheel 证据
├── assets/playwright/ # 固定 Playwright Chromium
├── assets/gpa/model.pt # GPA detector 权重
└── runtime-manifest.json
macOS 和 Linux 的 portable CPython 都来自固定 uv 版本所索引的 python-build-standalone 产物。runtime manifest 记录 OpenProgram、Python、uv、capability 结果、第一方 Program commits、资产路径和 product manifest SHA-256;product-runtime.json 记录模型 source 与 revision;release manifest 记录最终 artifact hash。不允许从打包机系统 Python 复制任意运行时。
6.3 启动
- Electron 读取 app 内的 runtime manifest,并验证完整 capability manifest 与所需文件。
- Electron 使用 app 内的 Python worker launcher,调用明确的绝对路径,不查询 PATH。
- Python 使用
-I -B启动,忽略系统PYTHONPATH、用户 site-packages 和系统 Python 配置,并禁止向 app 写入 bytecode。 - launcher 设置 runtime 内 Playwright Chromium 与 GPA detector 资产路径,导入随 runtime 固定的第一方 Programs。
- worker 监听本机端口并通过
/healthz返回运行状态与 capability manifest hash。 - Electron 获取认证 URL 后加载 Web UI;启动失败时显示错误类别、日志位置和修复动作。
6.4 不允许发生的行为
- 不调用 PATH 中的
openprogram、python、node或git。 - 运行中的 App 和自动更新器不直接修改自身 bundle;只有本地安装事务或经验证的正式更新事务可以替换固定
/Applications/OpenProgram.app。 - 本地安装器取得固定路径安装锁后,先复制并验证候选 App,再以不可变的事务副本版本重新读取、比较当前 App;若候选版本更低,必须在停止 worker 或移动文件前拒绝。版本段按十进制任意精度整数比较。固定路径已经存在但无法验证时必须保留原内容并失败,不能跳过比较。
- 同版本开发刷新必须同步 Electron main/preload、正式 updater 实现及其运行依赖,不能生成引用当前源码但保留旧模块的
app.asar。刷新构建完成后必须校验 wheel metadata,并在与完整安装器共享的固定路径锁内重新核对源码、wheel 与当前 App,之后才能停止 worker 或写入 Python/asar。 - 不在首次使用时下载 Python、Web、默认 Browser、默认 OCR、detector 权重或第一方 Programs。
- 不从仓库目录读取
apps/web/out、Program checkout 或开发配置。 - 不在用户机器上执行 npm build、pip dependency resolution 或 git clone。
6.5 Windows 封装与签名
- Electron-builder 生成 x64、按用户安装、可选择目录的 NSIS installer,并以
asInvoker运行。 - 封装输入是正式 Windows runtime ZIP;先通过 PowerShell release installer 完成 archive、manifest、capability 和 worker cold-start 验证,再移动到 Desktop resources。
- 应用 executable 与 installer 都必须通过 Authenticode。缺少证书或签名无效时 release job 失败,不能上传 unsigned Windows Desktop。
- 本地 unsigned build 只用于开发 package smoke,不是公开安装入口。
- Terminal 使用 Windows PowerShell/ConPTY;浏览器资料导入使用 Windows 正常安装与 Local AppData 位置;这些路径不修改用户 ACL。
7. 完整产品 Runtime 与开发扩展
只读完整产品
平台 runtime archive 中的 CPython、OpenProgram、Web、Channels、Search、Playwright Chromium、GPA detector、Research PDF 支持,以及 GUI、Research、Wiki 第一方 Programs。GUI Program 以 --no-deps 安装;runtime 不包含 PyTorch、torchvision、OpenCV、EasyOCR、sentence-transformers、triton 或 NVIDIA/CUDA distributions。Desktop 与 CLI 复用该目录,不允许按入口删减。
开发者与用户新增内容
~/.openprogram 中的配置、会话和缓存;开发者可以显式配置 GUI perception、OCR 或 Browser backend overlay 并启用调试,用户可以显式安装不属于产品 manifest 的第三方 Program。
~/.openprogram/ ├── programs/ │ ├── src/<program-id>/ │ ├── manifests/<program-id>.json │ └── environments/ │ └── <runtime-id>/ │ ├── releases/<generation>/ │ └── current -> releases/<generation> ├── config/ ├── sessions/ ├── logs/ └── cache/
runtime-id 至少包含 CPython minor version、CPU architecture、dependency lock、第一方 Program commits 和模型标识。Desktop 与 CLI 在相同平台架构上的 runtime ID 和 capability manifest hash 必须一致。
第三方 Program 的 install、upgrade 和 remove 执行同一事务:
- 解析 Program 来源和声明,写入临时目录;
- 使用 app 内的 uv 和 CPython 创建 staging environment;
- 从全部已启用 Program manifest 解析并安装依赖,记录精确版本和 artifact hash;
- 执行 import probe、Program 注册检查和 worker cold-start probe;
- 全部通过后原子切换
current;失败时删除 staging environment,继续使用原环境。
openprogram 或产品依赖。macOS unsigned 产物不提供 Apple 开发者身份与 notarization 保证,用户必须按文档手动允许打开,并以 GitHub Release checksum 验证文件。8. 安装、升级和卸载
8.1 桌面安装
- macOS 用户下载对应架构且文件名含
unsigned的 DMG,验证 SHA-256,将唯一的OpenProgram.app复制到 Applications 并替换旧版,再通过“隐私与安全性 → 仍要打开”完成首次授权。 - Windows 用户只下载 release 附带的精确
win-x64.exe,同时验证 SHA-256 与 Authenticode,再运行按用户 NSIS 安装向导;没有带签名 EXE 的版本使用 CLI/server。 - 本地 macOS 开发者执行
npm --prefix apps/desktop run dist时,脚本在随机临时目录构建一个 unpacked App,校验 bundle identifier、版本、主 executable 和内嵌 runtime,然后停止正在运行的正式 App 及默认 worker。候选版本低于当前固定 App 时必须在任何 App、worker 或 Launch Services 修改前拒绝安装。 scripts/refresh-local-app.sh只用于同版本 macOS 源码刷新:checkout 的 Python/desktop 版本、现有 bundle、runtime manifest 和内置 Python distribution metadata 必须完全一致。任一版本不同即在构建 wheel、停止 App 或写入 runtime 前失败;版本升级必须重新封装并安装完整 App。- macOS 封装使用与 worktree 无关的用户级锁;安装器另在目标 Applications 目录持有覆盖完整事务的原子锁。并发调用必须在修改 App 或服务前明确失败,锁清理只删除当前 PID 持有的锁。
- 若默认 profile 已安装 launchd 服务,替换前先卸载 KeepAlive 服务,再停止实际持锁 worker;成功后用新 App 的内嵌 Python 和
-I -B重新安装服务,并等待/healthz成功后再打开 App。服务的 ProgramArguments 不得继续指向 conda、源码 checkout 或已删除 App。 - macOS 脚本先在 Applications 所在卷完成 staging;只有 staging 完整后才将旧 App 临时移入同一事务目录并激活新 App。激活失败时恢复旧 App、launchd 服务及替换前的 App/worker 运行状态;成功后删除旧 App、Python wheel 构建缓存、runtime staging、构建目录与事务目录。
- macOS 激活后显式将固定
/Applications/OpenProgram.app注册到 Launch Services;后续步骤失败并恢复旧 App 时,以 best-effort 重新注册恢复后的固定路径,同时保留原始失败状态。 - 两个平台的 Desktop artifact 都内嵌已经通过完整 capability probe 的平台 runtime archive;首次启动只创建配置和状态目录,worker 从桌面包内置 CPython 启动。packaged mode 的认证 URL 同样只由内置 Python 生成,不依赖系统 CLI。
- Linux 不提供桌面安装;用户安装完整 CLI/server runtime 后使用 Web UI 或 TUI。
8.1.1 同版本本地刷新完成条件
本地刷新只启动一次新内嵌 worker:已有 launchd 服务时,服务安装负责提交启动请求;否则由内嵌 CLI 启动一个后台 worker。默认端口 18100 的健康轮询限时一百二十秒,每次探测单独限制时长;轮询不会反复启动 worker。超时记录失败的健康端点与 worker 日志位置,并保留失败状态。完整 App 通过代码签名验证后,即使健康或 worker 身份验证失败,退出清理仍尝试重开同一 App。重开仅执行一次,保留最初的失败状态,并单独报告重开失败。签名验证前的失败不启动部分更新或未验证的 App。清理保留临时目录删除错误,并继续尝试其他清理;已有主错误时保留主错误,否则返回清理错误。清理失败不输出刷新成功。已有提交源码、版本、外部签名和锁限制继续适用。
8.2 CLI / Server 安装
- macOS/Linux 使用
curl -fsSL https://openprogram.io/install | sh,Windows 使用irm https://openprogram.io/install.ps1 | iex;短 bootstrap 在未指定OPENPROGRAM_VERSION时通过 GitHub latest release 解析稳定版本。 - bootstrap 只接受三段数字版本,随后下载对应不可变 tag 下的平台兼容入口
scripts/install-release.sh或scripts/install-release.ps1,再取得同一 tag 下的正式实现。 - 正式 installer 从同一 GitHub Release 下载与 OS/architecture 精确匹配的 runtime archive 和 checksum,不访问 PyPI。
- 校验后解压到用户状态目录下的
runtime/cli/releases/X.Y.Z;macOS Desktop 使用同一 archive 作为构建输入,Linux 与 Windows 直接以完整 archive 作为正式产品入口。 - 安装器使用 runtime 的绝对路径执行版本、capability、first-party Program、Browser/OCR asset 和 worker cold-start probes。
- 全部成功后,macOS/Linux 原子切换
currentsymlink;Windows 原子替换 PowerShell launcher 并保留上一份 launcher。失败时继续使用旧版本。
8.3 开发安装
开发文档使用仓库 checkout、uv sync、Web/Ink build 和测试工具。开发环境必须能执行与 release 相同的 capability probe,并允许以显式配置替换 OCR/Browser 后端、编辑第一方 Program 源码和启用诊断;这些 overlay 不改变产品 manifest。
8.4 升级
- macOS 桌面:自动检查最新正式 Release;设置页按架构下载完整 DMG,验证字节数和 SHA-256 后打开,由用户确认替换 App。
- Windows 桌面:选择精确 signed EXE,验证字节数、SHA-256 与 Authenticode 后打开,由用户确认安装。
- CLI / 服务端:
openprogram upgrade下载新的完整 runtime archive,在新 version directory 验证后切换current;失败时保留旧版本,运行中的 worker 由用户显式重启。 - 开发:同一命令在 source checkout 中保留 fetch、build、完整 capability probe 和 restart 流程,目标 ref 必须显式。
- 兼容命令:旧
update是upgrade的兼容别名;worker 启动不自动应用产品更新。
GUI、Research、Wiki 第一方 Programs 与产品 runtime 原子升级;任一第一方 Program 或默认资产验证失败时,整个新 runtime 不得激活。第三方 Program 使用独立 environment 迁移;迁移失败只停用对应第三方 Program,不改变已验证的产品 capability manifest。
8.5 卸载
- 删除
OpenProgram.app只卸载桌面应用,默认保留~/.openprogram。 - CLI uninstall 删除启动入口和 OpenProgram 管理的 CLI runtime,默认保留状态。
- 只有显式
purge操作删除配置、会话、Program 和缓存;执行前必须显示精确目录并要求确认。
9. 安全、完整性和失败处理
| 情况 | 检测 | 结果 |
|---|---|---|
| runtime 文件缺失或 manifest 不匹配 | Desktop/CLI 启动前验证 hash | 不启动 worker;显示重新安装说明。 |
| 某项产品 capability、默认 backend 或资产缺失 | 平台 runtime build 与 public-entry probe | 整个平台 artifact 禁止发布,不允许降级安装。 |
| 旧 checkout 或旧 App 覆盖当前 App | 安装前比较三段数字版本;源码刷新要求全部版本完全一致 | 在构建、停止服务或文件写入前失败;保留当前 App。 |
| macOS 文件来源无法由 Apple 验证 | unsigned 文件名、安装说明和 SHA-256 | 明确提示用户手动放行;不声称 Developer ID 或 notarization。 |
| 系统环境注入 Python 路径 | 隔离启动参数和显式 sys.path | 忽略系统环境与 user site。 |
| 第三方 Program 依赖覆盖核心包 | reserved package rules、path ordering 和 import probe | 拒绝 environment activation。 |
| 新 runtime 不能启动或 capability probe 失败 | 切换前完整 probe | 不改变 CLI current,Desktop artifact 不发布。 |
| 发布 tag、runtime、Python 和 Electron 版本不一致 | 发布工作流版本检查 | 禁止构建或发布。 |
发布不需要 Apple 或 PyPI 凭据;Windows Desktop publication 需要代码签名证书 secret。GitHub Actions 使用仓库提供的短期 token 创建 Release。第一方 Program commits、模型来源和 runtime archive hash 进入 release manifest。本文不增加系统 Keychain、keyring 或 Credential Manager 集成。
10. 公共入口验收标准
10.1 平台 product runtime
- 在原生 runner 从固定 OpenProgram commit、dependency lock、第一方 Program commits 和模型来源构建。
openprogram --version、worker 冷启动、/healthz、/chat和 hashed Web asset 成功。- GUI、Research、Wiki Functions 全部注册;Channels、Search、Playwright Chromium、GPA detector 与 Research PDF 支持的 import/asset probe 成功。
- 验证已安装 distributions 不含 PyTorch、torchvision、OpenCV、EasyOCR、sentence-transformers、triton 或 NVIDIA/CUDA 项。
- 生成 capability manifest 和 runtime archive SHA-256;缺少任一项即失败。
10.2 macOS DMG
- 分别在未安装 OpenProgram、Python 和 Node.js、但具有系统 Git 的干净 arm64 与 x64 环境验证。
- 文件名、Release 说明和安装页明确标注 unsigned,并验证“隐私与安全性 → 仍要打开”流程。
- 断网后完成首次启动、worker、Web、第一方 Program 注册、Playwright Chromium、GPA detector 和 Research PDF probes;GUI perception overlay 不得由首次使用隐式安装。
- Electron 启动的 Python 路径与 capability manifest hash 必须来自内嵌 runtime archive。
本地完整打包先由 electron-builder 对 Electron 组件执行 ad-hoc 签名,补全组件资源签名;随后使用固定本地证书签署 OpenProgram 主 App 与 runtime helper,并执行严格的递归签名校验。构建模式不得因为无需发布证书而跳过组件签名。完整 App 构建、严格签名验证、运行时检查、固定路径安装和默认 worker 刷新均已验证。
10.2.1 本地固定 App 替换
- 连续执行两次本地桌面构建后,Applications 中只存在
OpenProgram.app,不存在带版本号、commit、任务名或before后缀的 App。 - 两个 worktree 或安装器并发执行时,只有一个进程进入目标 App 事务;另一个在修改 App 或服务前失败,不产生嵌套 App,成功日志版本与最终安装版本一致。
- 损坏的新 bundle、复制失败或激活失败不得删除可用旧 App;成功替换后不得保留旧 bundle 或构建 bundle。
- 构建与 staging 路径中的 App 从不执行
open,最终启动命令只接受固定安装路径。 - 安装版的 bundle identifier、版本、主 executable、ICNS 和内嵌 runtime 验证通过;bundle、runtime manifest、
openprogram --version与内置 Python distribution metadata 必须报告同一版本;Launch Services 只需注册固定安装路径。 - 版本为 X 的 checkout 对版本 Y 的固定 App 执行源码刷新时,仅 X=Y 允许继续;X<Y 和 X>Y 均要求完整 App 构建。版本低于当前 App 的完整候选也必须在停止 App 和 worker 前被拒绝。
10.2.2 Windows 签名 EXE
- 原生 Windows runner 使用与 CLI installer 相同的完整 runtime ZIP,并从
win-unpacked验证 runtime manifest、内置 Python、worker health 与 Web chat。 OpenProgram.exe和 NSIS installer 的 Authenticode 状态必须为 Valid;没有签名凭证时 release 直接失败。- Terminal 的 Windows PowerShell 与 Claude preset 通过 ConPTY 启动;Chrome、Edge、Brave 与 Chromium profile discovery 通过 Windows 路径测试。
- Updater 只选择精确 x64 EXE,size/hash/签名任何一项失败都删除临时文件并禁止打开。
10.3 Linux 桌面发布门禁
- Linux 桌面产物必须封装与 CLI/server 相同的完整 runtime,不能删减任何 capability、Program、OCR、模型或 Browser 资产。
- 必须在无系统 OpenProgram、Python、Node.js 和 Git 的干净 x86_64 Linux 环境从公开入口启动,并在断网环境完成完整 probes。
- 当前 AppImage 在完整 runtime 的 electron-builder block-map 阶段失败,因此没有产物通过本门禁;release 配置不得构建或发布 AppImage。
- 只有新的完整桌面产物通过本节全部条件后,才能恢复 Linux 桌面支持声明。
10.4 第三方 Program 与开发 overlay
- 第一方 GUI/Research/Wiki 不允许显示为未安装,也不由首次启动 wizard 补装。
- 第三方 Program 只修改
~/.openprogram/programs和独立 environment,不能覆盖产品 runtime。 - 开发者替换 OCR/Browser backend 或启用调试后,基础 capability manifest 仍能通过。
10.5 CLI / 服务端
- macOS/Linux shell bootstrap 与 Windows PowerShell bootstrap 都能在干净用户环境解析最新稳定 release 并下载固定 runtime archive,不访问 PyPI、不克隆仓库。
- 短 bootstrap 的自动版本解析和显式
OPENPROGRAM_VERSION固定版本路径均需通过无网络的入口测试;解析结果必须限定为三段数字版本,下载地址必须使用对应不可变 tag。 - 安装后的 runtime archive hash 和 capability manifest hash 与 release manifest 一致;macOS 与 Windows Desktop 使用相同平台构建输入。
- 安装器使用 runtime 绝对路径执行完整 probes;升级失败时旧版本仍能启动。
10.6 发布
发布说明先列出用户可见的变化,提供按平台和架构组织的下载表并直接链接已发布产物,将升级说明与开发者恢复细节分开。安装命令保留在可复制代码块中。仅修正文档的发布说明变更同步修改规范说明与公开发布正文,不移动标签或替换产物。
- tag、runtime archive、Electron package、manifest 和 health endpoint 报告相同版本。
- GitHub Release 包含 macOS runtime archives 与 unsigned DMG/ZIP、Linux runtime archives、Windows runtime ZIP 与 signed Desktop EXE、checksums 和 capability manifest;不包含未通过门禁的 Linux 桌面包或 unsigned Windows Desktop。
- 公开 GitHub Release 的标题与正文统一使用英文;workflow 在发布前拒绝包含中日韩文字的 release notes。
- 普通用户文档、站点索引和产品运行时错误不出现
pip install openprogram、PyPI 产品下载入口、缺省 optional Program 或组件补装步骤;缺失内置依赖时要求重新安装完整产品。 - 已发布 tag 不允许移动;修复使用更高 patch version。
实施记录:任务拆分、RED/GREEN、审查和 gate 记录位于 安装与分发实施计划。该记录不改变本文的概念边界。
11. 实现状态
| 能力 | 状态 | 当前证据或缺口 |
|---|---|---|
| 单端口 worker 托管 Web | 已实现 | worker 与单端口设计共同提供 API、WebSocket 和预构建 Web UI。 |
| Electron worker 监测与恢复 | 已实现 | 健康检查、恢复逻辑和内嵌 Python 启动均已接入。 |
| Web 随 wheel/runtime 发布 | 已实现 | release asset staging、clean-wheel package-resource 和平台 runtime probe 共用同一预构建资源。 |
| 统一完整 capability manifest | 已实现 | schema 2 manifest 固定 capability、lock hash、第一方 Program commits、实际 distributions 和资产路径。 |
| 第一方 Programs、默认 OCR 与模型进入 runtime | 已实现 | GUI/Research/Wiki、GPA detector、Research PDF 与 Playwright Chromium 都由 runtime verifier 覆盖。 |
| Desktop 与 CLI 复用同一平台 runtime archive | 已实现 | release workflow 每个平台架构只构建一次 runtime archive,macOS/Windows Desktop 与 CLI jobs 消费同名 artifact。 |
| 本地单一 App 构建与覆盖 | 已实现 | npm run dist 构建完整 runtime,并只覆盖 Applications 中固定路径的 OpenProgram.app。 |
| macOS 图标资源 | 已实现 | 分层 AppIcon.icon 与受版本控制的 legacy ICNS 均受构建门禁约束。 |
| macOS DMG/ZIP 内置 CPython | 已实现 | arm64/x64 DMG 与 ZIP 使用受控 CPython 和完整 product runtime。 |
| macOS 未签名 DMG/ZIP | 已发布 | 当前渠道明确标注 unsigned,并同时发布 SHA-256 清单。 |
| Windows 签名 NSIS EXE | 已实现,待发布门禁 | 原生 workflow 要求签名 secret,验证 app/installer Authenticode,并运行 package runtime smoke。 |
| Linux 桌面包 | 不发布 | Linux 使用完整 CLI/server runtime,不提供精简 Desktop 替代品。 |
| CLI 发布安装器 | 已实现 | macOS/Linux shell installer 与 Windows PowerShell installer 都执行 checksum、完整 verifier、worker cold-start 和原子激活。 |
| tag 驱动 GitHub Release | 已实现 | release workflow 上传平台 runtime archives、checksums、Desktop artifacts、开发者 Python artifacts 和 release manifest。 |
| pip / PyPI 产品安装 | 不支持 | 普通用户只使用正式安装器或平台安装包;wheel 保留为构建、源码开发和测试输入。 |
| Windows 分发 | CLI/server 与 Desktop 已实现 | Windows x86_64 使用完整 ZIP runtime、PowerShell installer 和原子 launcher;Desktop 使用同一 runtime、signed NSIS、ConPTY、更新签名验证与原生 CI。沙箱单独推进。 |
| 系统 credential store 集成 | 明确不在范围内 | 本文不规划 Keychain、keyring 或 Credential Manager。 |
| 本地刷新完成条件 | 待验收 | 本地刷新完成条件:隔离公开脚本回归用例与受影响发行测试通过。Contracts 包含一项可选模型目录缓存缺失的跳过。独立评审和已安装 App 验收待完成。 |
12. 明确不在范围内
- macOS App Store、Developer ID 签名与 notarization;
- 系统 Keychain、keyring、Credential Manager 或同类 credential-store 集成;
- 把 OpenProgram 改写成不需要 Python 的应用;
- 以 PyInstaller、Briefcase、py2app 或 Tauri 替换现有 Electron;
- 第一阶段实现 per-Program 进程隔离;
- 自动安装任意第三方 Program;
- 把可替换 OCR、stealth/agent-browser backend 或调试工具作为普通用户产品依赖。
相关设计:单端口 worker 与前端;自更新。安装与分发的冲突内容以本文为准,并在相关设计中引用本文。
发布构建输入
干净的发布执行器从草稿发布取得固定版本的 Office 资源归档。归档只包含清单登记的编辑器资源、源材料和许可证。构建器在暂存前验证其 SHA-256 与 Office manifest。重试发布可通过较新的构建控制器调度现有不可变标签;每个产品检出目录仍固定在该标签。只有全部原生构建与安装器检查通过后,发布流程才上传完整产物清单并完成草稿发布。已公开的发布不会被覆盖。