OpenProgram 安装、打包、发布与升级设计

正式版本:v0.9.8

本文是 OpenProgram 安装与分发的规范来源。它分别定义用户类型与平台支持,覆盖 macOS/Windows 桌面包、macOS/Linux/Windows 命令行与服务器安装、浏览器访问、Python 运行时归属、Program 扩展环境、版本、升级和卸载。正式版本的检查、下载、平台安装边界和当前实现证据由正式版本自动更新设计细化。

设计状态:已确定实现状态:Windows Desktop 等待带签名 release 门禁桌面平台:macOS / Windows核心运行时:CPython

1. 已确定的设计约束

  1. Python 是 OpenProgram 后端、CLI、Runtime 和 Program 执行的核心运行时,不允许以删除 Python 的方式简化安装。
  2. macOS 桌面版通过明确标注 Unsigned 的 DMG/ZIP 分发;Windows 桌面版只通过 Authenticode 签名的 x64 NSIS installer 分发;Linux 只发布完整 CLI/server runtime。
  3. 所有非开发者安装使用同一份按平台与架构构建的完整 product runtime。Desktop 只是增加 Electron 外壳,CLI/server 只是增加命令行 launcher;二者不能安装不同的 Web、Provider、Channel、Browser、模型资产或第一方 Program 功能集合。
  4. 完整 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。
  5. 普通用户不需要预装 Python 或 Node.js。Session 与 Memory 的 Git history 需要 PATH 中可用的系统 Git,product runtime 不内嵌 Git。安装器可以下载与当前平台对应的完整 runtime archive,但不能把缺少 manifest capability 的产物标为完整安装。
  6. 桌面包与 CLI runtime 在运行期保持只读;配置、会话、缓存和用户新增的第三方 Program 写入 ~/.openprogram。
  7. 开发安装在完整产品能力之上增加 editable source、调试工具、本地 Web/Ink 构建、测试工具,以及 GUI perception、OCR、Browser 等显式配置的 backend overlay。依赖 PyTorch、OpenCV 或 EasyOCR 的 GUI perception 路径只在这类 overlay 中提供,不属于普通安装的 manifest capability。
  8. stable 表示已发布、已验证的版本,不表示 origin/main。main 只属于开发安装。
  9. 正式安装不使用 editable checkout,不在用户机器上构建 Web 或 Ink,不依赖仓库目录,也不通过 PyPI 解析产品依赖。
  10. pip install openprogram、pipx install openprogram 和 uv tool install openprogram 都不是受支持的产品安装入口。公开索引、入门文档和运行时修复提示只能指向正式安装器或完整安装包;wheel 仅用于 release runtime 组装、源码开发和测试。
  11. PyInstaller、Briefcase 和 py2app 只作为参考实现,不替换现有 Electron 桌面应用。
  12. 普通用户的 CLI/server 默认入口是 curl -fsSL https://openprogram.io/install | sh。站点脚本只解析最新稳定 release、校验版本格式并下载该不可变 tag 下的 installer;runtime checksum、capability manifest 和 cold-start 验证仍由版本化 installer 完成。
  13. macOS 本机安装态只有固定路径 /Applications/OpenProgram.app。本地桌面构建在未注册的临时目录生成并验证 App,随后替换该固定路径;临时 App 不启动、不保留,也不使用版本号或任务名作为 App 目录名。
  14. Windows x86_64 CLI/server 使用完整 ZIP runtime 与 PowerShell installer。Windows Desktop 使用同一 runtime archive、按用户 NSIS installer、ConPTY 与强制签名 release gate;Windows 沙箱仍是独立层级。
完整安装的定义:每个受支持的非开发者安装必须具有同一份 capability manifest,并包含所有 manifest 声明的已安装、已验证组件和资产。GUI/Research/Wiki 包、Playwright Chromium、GPA detector 与 Research PDF 支持属于该边界;PyTorch、torchvision、OpenCV、EasyOCR、sentence-transformers、triton 和 NVIDIA/CUDA distributions 不属于该边界。依赖这些排除项的 GUI perception 路径必须使用显式开发或配置 overlay,首次使用不会隐式下载依赖。第三方 Program 属于用户主动增加的新能力。

2. 当前实现与已验证缺口

范围当前实现与本设计的差异
安装脚本scripts/install.sh 克隆仓库,创建或复用 Python 环境,执行 editable install,并在本机运行 npm 构建。这是开发安装行为,不能作为正式 release installer。
Python wheelpyproject.toml 定义 CLI entry point 和 package data;release staging 会把预编译 Web 资源写入 wheel,并把独立 Ink bundle 放进平台 runtime。已完成 Web 资源的 clean-wheel 验收;Ink 由 runtime 内的平台 Node.js 执行,不要求用户安装 npm 依赖。
Web UIfrontend.py 在 release wheel 中优先读取 Server package 内的 _frontend;源码 checkout 仍使用 apps/web/out。当前源码版本基线为 v0.9.8;仓库保留的 v0.7.0 clean-wheel/runtime 验收属于历史证据。普通用户机器不执行 npm build。
TUIopenprogram_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 增加。
Electronapps/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 目标 / AppImageAppImage、deb、rpm、Snap 和 Flatpak 等 Linux 产物;AppImage 是无需 root 的单文件产物。不解决 Python runtime、不同 glibc 基线或 OpenProgram 功能验收;当前完整 AppImage 在 electron-builder block-map 阶段失败,未形成可验收产物。当前拒绝发布:不发布精简包,也不把未通过公共入口验收的 AppImage 标为支持。Linux 通过完整 CLI/server runtime 提供产品功能。
BeeWare BriefcasePython 应用、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 当前不发布桌面包。

CLI / 服务端

macOS、Linux 与 Windows 命令行用户

运行固定 release installer,下载完整 runtime archive。产品能力集合与受支持 Desktop 相同,只是不包含 Electron 窗口。

开发

开发者

克隆仓库,在完整产品能力之上增加 editable source、测试、调试、本地前端构建和可替换 OCR/Browser 后端。开发者 wheel 不是普通用户安装方式。

属性桌面CLI / 服务端开发
版本来源GitHub Release同一 GitHub ReleaseGit 检出目录
产品 Runtime平台 runtime archive + Electron同一平台 runtime archive同等产品能力 + 开发 overlay
系统 Python / Node.js不需要不需要需要开发工具链
系统 GitSession/Memory history 需要Session/Memory history 需要开发与 history 均需要
功能集合完整 capability manifest相同 capability manifest相同产品功能并允许显式 backend overlay
升级目标已发布完整 runtime相同已发布完整 runtime明确 Git ref
默认通道stablestabledev

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。

一次 release 构建vX.Y.Z
固定源码、lockfile、第一方 Program commits、模型、CPython 与 uv
→
平台 product runtimeCPython + 完整依赖
Web + Browser + OCR/模型
GUI / 研究 / Wiki 程序
→
受支持公开入口macOS 桌面端:DMG/ZIP
Windows 桌面端:签名 EXE
macOS/Linux CLI:tar.gz + 启动器
Windows CLI:ZIP + PowerShell 启动器

每次 release 至少生成:

首个正式版本分别构建 arm64 和 x64,不生成 universal2。Python native wheels、Browser、OCR、模型和 Electron helper 都具有平台或架构差异;每个平台分别生成 runtime,但同一 capability manifest 的所有条目必须为 present 和 verified,否则整个平台不发布。

版本化产物与安装态不是同一个概念:GitHub Release 中的 DMG、ZIP、runtime archive 和 checksum 必须带版本号并永久对应已发布 tag;本机 Applications 目录只保留无版本后缀的 OpenProgram.app。本地构建产生的中间 App 在安装事务结束后删除,不作为历史版本保存。

6. macOS 与 Windows 桌面包

6.1 图标资产

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 启动

  1. Electron 读取 app 内的 runtime manifest,并验证完整 capability manifest 与所需文件。
  2. Electron 使用 app 内的 Python worker launcher,调用明确的绝对路径,不查询 PATH。
  3. Python 使用 -I -B 启动,忽略系统 PYTHONPATH、用户 site-packages 和系统 Python 配置,并禁止向 app 写入 bytecode。
  4. launcher 设置 runtime 内 Playwright Chromium 与 GPA detector 资产路径,导入随 runtime 固定的第一方 Programs。
  5. worker 监听本机端口并通过 /healthz 返回运行状态与 capability manifest hash。
  6. Electron 获取认证 URL 后加载 Web UI;启动失败时显示错误类别、日志位置和修复动作。

6.4 不允许发生的行为

6.5 Windows 封装与签名

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 执行同一事务:

  1. 解析 Program 来源和声明,写入临时目录;
  2. 使用 app 内的 uv 和 CPython 创建 staging environment;
  3. 从全部已启用 Program manifest 解析并安装依赖,记录精确版本和 artifact hash;
  4. 执行 import probe、Program 注册检查和 worker cold-start probe;
  5. 全部通过后原子切换 current;失败时删除 staging environment,继续使用原环境。
信任边界:随 release 固定的第一方 Programs 属于受 hash 验证的产品 runtime;运行期新增的第三方 Program 不属于 release 完整性范围,必须写入独立 environment,不能覆盖 openprogram 或产品依赖。macOS unsigned 产物不提供 Apple 开发者身份与 notarization 保证,用户必须按文档手动允许打开,并以 GitHub Release checksum 验证文件。

8. 安装、升级和卸载

8.1 桌面安装

  1. macOS 用户下载对应架构且文件名含 unsigned 的 DMG,验证 SHA-256,将唯一的 OpenProgram.app 复制到 Applications 并替换旧版,再通过“隐私与安全性 → 仍要打开”完成首次授权。
  2. Windows 用户只下载 release 附带的精确 win-x64.exe,同时验证 SHA-256 与 Authenticode,再运行按用户 NSIS 安装向导;没有带签名 EXE 的版本使用 CLI/server。
  3. 本地 macOS 开发者执行 npm --prefix apps/desktop run dist 时,脚本在随机临时目录构建一个 unpacked App,校验 bundle identifier、版本、主 executable 和内嵌 runtime,然后停止正在运行的正式 App 及默认 worker。候选版本低于当前固定 App 时必须在任何 App、worker 或 Launch Services 修改前拒绝安装。
  4. scripts/refresh-local-app.sh 只用于同版本 macOS 源码刷新:checkout 的 Python/desktop 版本、现有 bundle、runtime manifest 和内置 Python distribution metadata 必须完全一致。任一版本不同即在构建 wheel、停止 App 或写入 runtime 前失败;版本升级必须重新封装并安装完整 App。
  5. macOS 封装使用与 worktree 无关的用户级锁;安装器另在目标 Applications 目录持有覆盖完整事务的原子锁。并发调用必须在修改 App 或服务前明确失败,锁清理只删除当前 PID 持有的锁。
  6. 若默认 profile 已安装 launchd 服务,替换前先卸载 KeepAlive 服务,再停止实际持锁 worker;成功后用新 App 的内嵌 Python 和 -I -B 重新安装服务,并等待 /healthz 成功后再打开 App。服务的 ProgramArguments 不得继续指向 conda、源码 checkout 或已删除 App。
  7. macOS 脚本先在 Applications 所在卷完成 staging;只有 staging 完整后才将旧 App 临时移入同一事务目录并激活新 App。激活失败时恢复旧 App、launchd 服务及替换前的 App/worker 运行状态;成功后删除旧 App、Python wheel 构建缓存、runtime staging、构建目录与事务目录。
  8. macOS 激活后显式将固定 /Applications/OpenProgram.app 注册到 Launch Services;后续步骤失败并恢复旧 App 时,以 best-effort 重新注册恢复后的固定路径,同时保留原始失败状态。
  9. 两个平台的 Desktop artifact 都内嵌已经通过完整 capability probe 的平台 runtime archive;首次启动只创建配置和状态目录,worker 从桌面包内置 CPython 启动。packaged mode 的认证 URL 同样只由内置 Python 生成,不依赖系统 CLI。
  10. 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 安装

  1. macOS/Linux 使用 curl -fsSL https://openprogram.io/install | sh,Windows 使用 irm https://openprogram.io/install.ps1 | iex;短 bootstrap 在未指定 OPENPROGRAM_VERSION 时通过 GitHub latest release 解析稳定版本。
  2. bootstrap 只接受三段数字版本,随后下载对应不可变 tag 下的平台兼容入口 scripts/install-release.sh 或 scripts/install-release.ps1,再取得同一 tag 下的正式实现。
  3. 正式 installer 从同一 GitHub Release 下载与 OS/architecture 精确匹配的 runtime archive 和 checksum,不访问 PyPI。
  4. 校验后解压到用户状态目录下的 runtime/cli/releases/X.Y.Z;macOS Desktop 使用同一 archive 作为构建输入,Linux 与 Windows 直接以完整 archive 作为正式产品入口。
  5. 安装器使用 runtime 的绝对路径执行版本、capability、first-party Program、Browser/OCR asset 和 worker cold-start probes。
  6. 全部成功后,macOS/Linux 原子切换 current symlink;Windows 原子替换 PowerShell launcher 并保留上一份 launcher。失败时继续使用旧版本。

8.3 开发安装

开发文档使用仓库 checkout、uv sync、Web/Ink build 和测试工具。开发环境必须能执行与 release 相同的 capability probe,并允许以显式配置替换 OCR/Browser 后端、编辑第一方 Program 源码和启用诊断;这些 overlay 不改变产品 manifest。

8.4 升级

GUI、Research、Wiki 第一方 Programs 与产品 runtime 原子升级;任一第一方 Program 或默认资产验证失败时,整个新 runtime 不得激活。第三方 Program 使用独立 environment 迁移;迁移失败只停用对应第三方 Program,不改变已验证的产品 capability manifest。

8.5 卸载

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

  1. 在原生 runner 从固定 OpenProgram commit、dependency lock、第一方 Program commits 和模型来源构建。
  2. openprogram --version、worker 冷启动、/healthz、/chat 和 hashed Web asset 成功。
  3. GUI、Research、Wiki Functions 全部注册;Channels、Search、Playwright Chromium、GPA detector 与 Research PDF 支持的 import/asset probe 成功。
  4. 验证已安装 distributions 不含 PyTorch、torchvision、OpenCV、EasyOCR、sentence-transformers、triton 或 NVIDIA/CUDA 项。
  5. 生成 capability manifest 和 runtime archive SHA-256;缺少任一项即失败。

10.2 macOS DMG

  1. 分别在未安装 OpenProgram、Python 和 Node.js、但具有系统 Git 的干净 arm64 与 x64 环境验证。
  2. 文件名、Release 说明和安装页明确标注 unsigned,并验证“隐私与安全性 → 仍要打开”流程。
  3. 断网后完成首次启动、worker、Web、第一方 Program 注册、Playwright Chromium、GPA detector 和 Research PDF probes;GUI perception overlay 不得由首次使用隐式安装。
  4. Electron 启动的 Python 路径与 capability manifest hash 必须来自内嵌 runtime archive。

本地完整打包先由 electron-builder 对 Electron 组件执行 ad-hoc 签名,补全组件资源签名;随后使用固定本地证书签署 OpenProgram 主 App 与 runtime helper,并执行严格的递归签名校验。构建模式不得因为无需发布证书而跳过组件签名。完整 App 构建、严格签名验证、运行时检查、固定路径安装和默认 worker 刷新均已验证。

10.2.1 本地固定 App 替换

  1. 连续执行两次本地桌面构建后,Applications 中只存在 OpenProgram.app,不存在带版本号、commit、任务名或 before 后缀的 App。
  2. 两个 worktree 或安装器并发执行时,只有一个进程进入目标 App 事务;另一个在修改 App 或服务前失败,不产生嵌套 App,成功日志版本与最终安装版本一致。
  3. 损坏的新 bundle、复制失败或激活失败不得删除可用旧 App;成功替换后不得保留旧 bundle 或构建 bundle。
  4. 构建与 staging 路径中的 App 从不执行 open,最终启动命令只接受固定安装路径。
  5. 安装版的 bundle identifier、版本、主 executable、ICNS 和内嵌 runtime 验证通过;bundle、runtime manifest、openprogram --version 与内置 Python distribution metadata 必须报告同一版本;Launch Services 只需注册固定安装路径。
  6. 版本为 X 的 checkout 对版本 Y 的固定 App 执行源码刷新时,仅 X=Y 允许继续;X<Y 和 X>Y 均要求完整 App 构建。版本低于当前 App 的完整候选也必须在停止 App 和 worker 前被拒绝。

10.2.2 Windows 签名 EXE

  1. 原生 Windows runner 使用与 CLI installer 相同的完整 runtime ZIP,并从 win-unpacked 验证 runtime manifest、内置 Python、worker health 与 Web chat。
  2. OpenProgram.exe 和 NSIS installer 的 Authenticode 状态必须为 Valid;没有签名凭证时 release 直接失败。
  3. Terminal 的 Windows PowerShell 与 Claude preset 通过 ConPTY 启动;Chrome、Edge、Brave 与 Chromium profile discovery 通过 Windows 路径测试。
  4. Updater 只选择精确 x64 EXE,size/hash/签名任何一项失败都删除临时文件并禁止打开。

10.3 Linux 桌面发布门禁

  1. Linux 桌面产物必须封装与 CLI/server 相同的完整 runtime,不能删减任何 capability、Program、OCR、模型或 Browser 资产。
  2. 必须在无系统 OpenProgram、Python、Node.js 和 Git 的干净 x86_64 Linux 环境从公开入口启动,并在断网环境完成完整 probes。
  3. 当前 AppImage 在完整 runtime 的 electron-builder block-map 阶段失败,因此没有产物通过本门禁;release 配置不得构建或发布 AppImage。
  4. 只有新的完整桌面产物通过本节全部条件后,才能恢复 Linux 桌面支持声明。

10.4 第三方 Program 与开发 overlay

  1. 第一方 GUI/Research/Wiki 不允许显示为未安装,也不由首次启动 wizard 补装。
  2. 第三方 Program 只修改 ~/.openprogram/programs 和独立 environment,不能覆盖产品 runtime。
  3. 开发者替换 OCR/Browser backend 或启用调试后,基础 capability manifest 仍能通过。

10.5 CLI / 服务端

  1. macOS/Linux shell bootstrap 与 Windows PowerShell bootstrap 都能在干净用户环境解析最新稳定 release 并下载固定 runtime archive,不访问 PyPI、不克隆仓库。
  2. 短 bootstrap 的自动版本解析和显式 OPENPROGRAM_VERSION 固定版本路径均需通过无网络的入口测试;解析结果必须限定为三段数字版本,下载地址必须使用对应不可变 tag。
  3. 安装后的 runtime archive hash 和 capability manifest hash 与 release manifest 一致;macOS 与 Windows Desktop 使用相同平台构建输入。
  4. 安装器使用 runtime 绝对路径执行完整 probes;升级失败时旧版本仍能启动。

10.6 发布

发布说明先列出用户可见的变化,提供按平台和架构组织的下载表并直接链接已发布产物,将升级说明与开发者恢复细节分开。安装命令保留在可复制代码块中。仅修正文档的发布说明变更同步修改规范说明与公开发布正文,不移动标签或替换产物。

  1. tag、runtime archive、Electron package、manifest 和 health endpoint 报告相同版本。
  2. GitHub Release 包含 macOS runtime archives 与 unsigned DMG/ZIP、Linux runtime archives、Windows runtime ZIP 与 signed Desktop EXE、checksums 和 capability manifest;不包含未通过门禁的 Linux 桌面包或 unsigned Windows Desktop。
  3. 公开 GitHub Release 的标题与正文统一使用英文;workflow 在发布前拒绝包含中日韩文字的 release notes。
  4. 普通用户文档、站点索引和产品运行时错误不出现 pip install openprogram、PyPI 产品下载入口、缺省 optional Program 或组件补装步骤;缺失内置依赖时要求重新安装完整产品。
  5. 已发布 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. 明确不在范围内

相关设计:单端口 worker 与前端;自更新。安装与分发的冲突内容以本文为准,并在相关设计中引用本文。

发布构建输入

干净的发布执行器从草稿发布取得固定版本的 Office 资源归档。归档只包含清单登记的编辑器资源、源材料和许可证。构建器在暂存前验证其 SHA-256 与 Office manifest。重试发布可通过较新的构建控制器调度现有不可变标签;每个产品检出目录仍固定在该标签。只有全部原生构建与安装器检查通过后,发布流程才上传完整产物清单并完成草稿发布。已公开的发布不会被覆盖。

Windows 公开安装器发布

网站组装步骤将 install.ps1 发布到域名根目录,与 POSIX /install 入口并列。行为测试使用临时站点输入执行真实组装步骤,逐字节检查两个根目录安装器。引导安装使用不可变发布标签,不会静默回退到源码检出目录。缺少 Windows 发布安装器时,说明所选版本没有完整 Windows 发布,并引导用户查阅源码开发安装文档。

实现状态:根目录安装器组装回归与独立源码审查通过。恢复网站入口需要发布站点;可用的托管 Windows 安装还要求发布中包含版本化安装器、完整 runtime ZIP 与校验和。本地源码验证不能证明这两项发布已经完成。

发布平台选择

发布矩阵默认包含 macOS 与 Linux。设置仓库变量 OPENPROGRAM_RELEASE_WINDOWS=true 即可包含 Windows runtime、安装器与桌面端任务。Windows 桌面端发布仍要求 WINDOWS_CSC_LINK 和 WINDOWS_CSC_KEY_PASSWORD;缺少签名凭证会使所选发布失败。Runtime 与安装器任务共用平台选择。

系统 shell 兼容性

macOS 打包 runtime 的冒烟检查支持系统 Bash 3.2。验证器参数数组始终包含 runtime 目录;仅在明确请求时追加可选的浏览器延迟检查标志。正常发布验证执行完整浏览器检查。

本地桌面端刷新权限

刷新脚本提取已安装的 ASAR、替换桌面模块,并将 node-pty 作为未打包文件重新封装。Electron ASAR 只记录打包文件的可执行元数据;提取未打包文件时使用默认权限,导致 node-pty spawn-helper 丢失执行权限,无法创建终端。

暂存步骤在重新打包前,从已安装的未打包目录恢复原文件权限。prebuilds 与 build/Release 下已知的 node-pty spawn-helper 文件会补齐执行位,即使先前刷新已损坏安装权限。其他文件保留已安装权限。权限修复不跟随符号链接。

参考:已安装的 @electron/asar 中 insertFile 与 extractAll 实现。采用保留未打包源文件元数据的方式,不递归添加执行权限,也不更改操作系统隐私权限。签名与安装沿用现有刷新流程。

本地刷新源码完整性

默认 /Applications/OpenProgram.app 只从已提交且干净的 checkout 刷新,并要求包含本地 main 和已获取的 origin/main。目标路径在选择源码检查、runtime 路径和安装锁前完成解析:默认 App 的尾斜杠、点路径及符号链接别名使用相同的检查和锁。实际指向其他位置的自定义 App 保留原有源码检查行为。tracked 修改、暂存修改以及未被忽略的 untracked 文件均在打包前拒绝。打包结束后和安装锁内、修改 App、PATH 安装或 worker 前再次检查。打包期间已提交的 HEAD 变化仍按现有逻辑重新构建;产物固定后再次变化则终止安装。被忽略的构建产物和本地验收记录不会使源码检查失败。GUI Harness 继续使用固定提交的归档,源码、wheel 与 App 的版本检查继续生效。源码完整性回归使用临时 Git 仓库和假的 App/runtime 命令,不更新已安装 App。独立审查与合并后的实现验收仍待完成。