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

本文是 OpenProgram 安装与分发的规范来源。它分别定义用户类型与平台支持,覆盖 macOS 桌面包、macOS/Linux 命令行与服务器安装、浏览器访问、Python 运行时归属、Program 扩展环境、版本、升级和卸载。实施任务单独记录,不与概念设计混合。

设计状态:已确定实现状态:部分实现桌面平台:macOS核心运行时:CPython

1. 已确定的设计约束

  1. Python 是 OpenProgram 后端、CLI、Runtime 和 Program 执行的核心运行时,不允许以删除 Python 的方式简化安装。
  2. macOS 桌面版通过明确标注 Unsigned 的 DMG/ZIP 分发;Linux 只发布完整 CLI/server runtime,完整桌面包通过公共入口验收前不发布任何 Linux 桌面产物。
  3. 所有非开发者安装使用同一份按平台与架构构建的完整 product runtime。Desktop 只是增加 Electron 外壳,CLI/server 只是增加命令行 launcher;二者不能安装不同的 Web、Provider、Channel、Browser、OCR 或第一方 Program 功能集合。
  4. 完整 product runtime 包含固定 CPython、OpenProgram、预编译 Web、默认 Browser/Chromium、Channels、Search、GUI/Research/Wiki 第一方 Programs、默认 OCR、GUI detector 权重及其运行依赖。首次使用这些默认能力不再触发组件安装。
  5. 普通用户不需要预装 Python、Node.js 或 Git。安装器可以下载与当前平台对应的完整 runtime archive,但安装完成后不能因缺少可选依赖而形成降级版本。
  6. 桌面包与 CLI runtime 在运行期保持只读;配置、会话、缓存和用户新增的第三方 Program 写入 ~/.openprogram
  7. 开发安装在完整产品能力之上增加 editable source、调试工具、本地 Web/Ink 构建、测试工具,以及 OCR、Browser 等后端替换能力;开发模式不能用于补齐普通安装缺失的产品功能。
  8. stable 表示已发布、已验证的版本,不表示 origin/mainmain 只属于开发安装。
  9. 正式安装不使用 editable checkout,不在用户机器上构建 Web 或 Ink,不依赖仓库目录,也不通过 PyPI 解析产品依赖。
  10. PyInstaller、Briefcase 和 py2app 只作为参考实现,不替换现有 Electron 桌面应用。
  11. 普通用户的 CLI/server 默认入口是 curl -fsSL https://openprogram.io/install | sh。站点脚本只解析最新稳定 release、校验版本格式并下载该不可变 tag 下的 installer;runtime checksum、capability manifest 和 cold-start 验证仍由版本化 installer 完成。
  12. Windows 原生安装不进入当前 release,但不是被拒绝的方向。现有 runtime、manifest、installer 和 Desktop 分层必须避免引入阻止后续 Windows 实现的假设;是否支持及采用何种产物由后续独立决策确定。
完整安装的定义:每个受支持的非开发者安装必须具有同一份 capability manifest,并为每项用户功能提供一个已安装、已验证的默认实现。可替换 OCR、stealth/agent-browser 后端、源码编辑和调试工具属于开发者附加能力;第三方 Program 属于用户主动增加的新能力。硬件或无图形会话可以让 GUI 操作在当前机器上不可执行,但不能让安装器静默省略 GUI Program、默认 OCR 或模型。

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

范围当前实现与本设计的差异
安装脚本scripts/install.sh 克隆仓库,创建或复用 Python 环境,执行 editable install,并在本机运行 npm 构建。这是开发安装行为,不能作为正式 release installer。
Python wheelpyproject.toml 定义 CLI entry point 和 package data;release staging 会把预编译 Web 资源写入 wheel。已完成 Web 资源的 clean-wheel 验收;Ink bundle 仍仅属于源码开发界面。
Web UIfrontend.py 在 release wheel 中优先读取包内 _frontend;源码 checkout 仍使用 web/out基础分发路径已消除用户机器上的 npm build;正式 release 仍需 CI 重复验收。
TUIcli_ink.py 从仓库根目录定位 cli/dist,缺失时调用 npm。正式 CLI 必须有不依赖 Node.js 的基础界面;Ink 只作为开发安装中的增强界面。
Program 安装product-runtime.json 固定 GUI、Research、Wiki commits、capability IDs 和默认模型来源;runtime builder 在构建期安装三项 Program、GUI OCR/model 和 Research PDF 依赖。普通用户不再选择或补装第一方 Program;运行期 Program 命令只管理第三方或开发者源码 overlay。
Electrondesktop/main.js 在 packaged mode 验证 schema 2 capability manifest,从 resources 解析包内 CPython 和 Browser/OCR/model 路径,并以隔离模式启动 worker;desktop/package.json 只声明 macOS DMG 与 ZIP。macOS arm64 完整 runtime 已本机验证;完整 DMG 仍需要原生 workflow 证据。Linux AppImage 的完整 runtime 构建通过,但 Electron packaging gate 失败,已从发布配置移除。
版本pyproject.toml 是规范版本来源;Electron metadata 保留构建工具要求的副本。release gate 必须拒绝 tag、Python metadata 和 Electron metadata 的任何不一致。
发布tag workflow 先按平台与架构构建完整 runtime archive,再由 Desktop job 与 CLI installer job 下载同名 archive;只发布 GitHub Release,不运行 PyPI、签名或 notarization job。workflow 结构与本机 macOS arm64 runtime/CLI 入口已验证;各原生 runner 与正式 tag 仍需实际执行。
升级CLI release installer 下载新 runtime archive,在独立目录验证 checksum、capabilities、Browser、Programs 和 worker cold-start 后切换 current;source checkout 的升级继续属于开发通道。macOS arm64 本机归档与 CLI 原子切换已验证;公开升级命令与原生 runner 证据仍需完成。

3. 官方规范与工具比较

本设计以 Electron 和 electron-builder 组装 macOS 桌面外壳,以 uv 和标准 wheel 组装内部 product runtime,并以 GitHub Release 分发 macOS/Linux 按平台与架构固定的完整 runtime archive。Apple、Linux 桌面打包与 PyPA 规范继续用于说明被明确拒绝或限制的分发选择。

参考提供的能力缺少或不适用的能力OpenProgram 采用方式
Apple distributionDMG、PKG、ZIP 的适用边界;Developer ID 签名;嵌套代码签名;notarization。Developer ID 需要付费账号,且不负责 Python 或 Electron 的项目级组装。当前拒绝签名服务:保留 DMG 结构,但产物与安装文档必须标注 unsigned 和 Gatekeeper 手动放行步骤;不得声称 Apple 已验证。
Electron distribution / electron-builder signingElectron 资源打包、macOS 签名、发布和自动更新集成。不提供 Python runtime、Programs、模型或 Python dependency resolution。采用并扩展:Electron 只提供 Desktop 外壳,读取与 CLI 完全相同的 product runtime archive。
electron-builder Linux targets / 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 environments不依赖 Python 的独立二进制、虚拟环境、固定解释器安装目标、Python 下载与依赖同步。uv tool 环境不应被 pip 直接修改,与当前 Program 安装行为不兼容。采用并限制:CLI 安装和 Program 环境使用受控 uv;不把 uv tool install openprogram 作为正式安装方式。
PyPA packaging / PyPI Trusted Publishingwheel/sdist、entry point、构建隔离和基于 OIDC 的发布。wheel 不包含 CPython、浏览器、模型和完整第一方 Programs,不能满足普通用户的统一安装契约。限制为开发者产物:构建过程继续使用 wheel 作为内部 Python 代码输入;普通用户不通过 pip install 或 PyPI 获得产品安装。

4. 用户类型与平台支持

三类用户描述安装目的,平台矩阵描述产品承诺。两者分别维护,不能以用户类型代替平台覆盖。

DESKTOP

macOS 桌面用户

下载 unsigned DMG。Desktop 内含完整 product runtime,不读取系统 Python、Node.js 或 Git。Linux 当前不发布桌面包。

CLI / SERVER

macOS 与 Linux 命令行用户

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

DEVELOPMENT

开发者

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

属性桌面CLI / Server开发
版本来源GitHub Release同一 GitHub ReleaseGit checkout
产品 Runtime平台 runtime archive + Electron同一平台 runtime archive同等产品能力 + 开发 overlay
系统 Python/Node/Git不需要不需要需要开发工具链
功能集合完整 capability manifest相同 capability manifest相同产品功能并允许后端替换
升级目标已发布完整 runtime相同已发布完整 runtime明确 Git ref
默认通道stablestabledev

4.1 平台支持矩阵

平台原生桌面CLI / Server浏览器访问开发
macOS arm64 / x64正式支持:DMG正式支持本地或远程正式支持
Linux x86_64不发布桌面包完整 runtime 已验证本地或远程正式支持
Linux arm64不发布桌面包完整 runtime 已验证本地或远程按 Python/Linux gate 验证
Windows当前 release 暂缓当前 release 暂缓目前可访问受支持主机保留后续实现可行性
iOS / Android / iPadOS无原生应用不适用只访问受支持主机;不承诺移动端布局不适用

浏览器访问不把客户端操作系统提升为原生支持平台。服务端必须运行在受支持的 macOS 或 Linux 安装中;只有经过浏览器和响应式验收的组合才能标为正式支持。

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/Research/Wiki Programs
受支持公开入口macOS Desktop: DMG/ZIP
macOS/Linux CLI: archive + launcher
checksums + capability manifest

每次 release 至少生成:

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

6. macOS 桌面包

6.1 逻辑内容

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 证据
                ├── browser/                 # 默认 Chromium
                ├── models/                  # 默认 OCR 与 detector 数据
                └── runtime-manifest.json

macOS 和 Linux 的 portable CPython 都来自固定 uv 版本所索引的 python-build-standalone 产物。runtime manifest 记录 OpenProgram、Python、uv、capability manifest、第一方 Program commits、Browser 与模型标识;release manifest 记录最终 artifact hash。不允许从打包机系统 Python 复制任意运行时。

6.2 启动

  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 内默认 Browser、OCR 与 detector 资产路径,导入随 runtime 固定的第一方 Programs。
  5. worker 监听本机端口并通过 /healthz 返回运行状态与 capability manifest hash。
  6. Electron 获取认证 URL 后加载 Web UI;启动失败时显示错误类别、日志位置和修复动作。

6.3 不允许发生的行为

7. 完整产品 Runtime 与开发扩展

只读完整产品

平台 runtime archive 中的 CPython、OpenProgram、Web、默认 Browser、Channels、Search、默认 OCR/模型,以及 GUI、Research、Wiki 第一方 Programs。Desktop 与 CLI 复用该目录,不允许按入口删减。

开发者与用户新增内容

~/.openprogram 中的配置、会话和缓存;开发者可以使用 editable checkout、替换 OCR/Browser 后端并启用调试,用户可以显式安装不属于产品 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,复制 App 后通过“隐私与安全性 → 仍要打开”完成首次授权。
  2. Desktop artifact 内嵌已经通过完整 capability probe 的平台 runtime archive;首次启动只创建配置和状态目录。
  3. worker 从桌面包内置 CPython 启动。
  4. Linux 不提供桌面安装;用户安装完整 CLI/server runtime 后使用 Web UI 或 TUI。

8.2 CLI / Server 安装

  1. 默认命令 curl -fsSL https://openprogram.io/install | sh 从项目域名取得短 bootstrap;bootstrap 在未指定 OPENPROGRAM_VERSION 时通过 GitHub 的 latest release redirect 解析稳定版本。
  2. bootstrap 只接受三段数字版本,随后下载对应不可变 tag 下的 scripts/install-release.sh。需要可复现安装时可在 sh 进程上显式设置 OPENPROGRAM_VERSION=X.Y.Z
  3. 版本化 installer 从同一 GitHub Release 下载与 OS/architecture 精确匹配的 runtime archive 和 checksum,不访问 PyPI。
  4. 校验后解压到 ~/.openprogram/runtime/cli/releases/X.Y.Z;macOS Desktop 使用同一 archive 作为构建输入,Linux 直接以该完整 archive 作为正式产品入口。
  5. 安装器使用 runtime 的绝对路径执行版本、capability、first-party Program、Browser/OCR asset 和 worker cold-start probes。
  6. 全部成功后原子切换 current,并在 ~/.local/bin/openprogram 创建 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 禁止发布,不允许降级安装。
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 版本不一致release workflow version gate禁止构建或发布。

发布不需要 Apple 或 PyPI 凭据;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 cold-start、/healthz/chat 和 hashed Web asset 成功。
  3. GUI、Research、Wiki Functions 全部注册;Channels、Search、默认 Playwright Chromium、EasyOCR 与 detector weight 的 import/asset probe 成功。
  4. 生成 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 注册、默认 Browser/OCR/model probe。
  4. Electron 启动的 Python 路径与 capability manifest hash 必须来自内嵌 runtime archive。

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 / Server

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

10.6 release

  1. tag、runtime archive、Electron package、manifest 和 health endpoint 报告相同版本。
  2. GitHub Release 包含 macOS runtime archives 与 unsigned DMG/ZIP、Linux runtime archives、checksums 和 capability manifest;不包含未通过门禁的 Linux 桌面包。
  3. 普通用户文档不出现 pip install openprogram、缺省 optional Program 或组件补装步骤。
  4. 已发布 tag 不允许移动;修复使用更高 patch version。

实施记录:任务拆分、RED/GREEN、审查和 gate 记录位于 Installation and distribution implementation plan。该记录不改变本文的概念边界。

11. 实现状态

能力状态当前证据或缺口
单端口 worker 托管 Web已实现现有 worker 和单端口设计已使用该结构。
Electron worker 监测与恢复已实现健康检查、恢复逻辑和嵌入式 Python 启动均已接入。
Web 随 wheel/runtime 发布已验证release asset staging、clean-wheel package-resource、macOS 与 Linux runtime probes 已通过。
统一完整 capability manifest原生平台已验证schema 2 manifest 固定 12 项 capability,记录 lock hash、第一方 Program commits、实际 distributions 和资产路径;macOS arm64、Linux x86_64/arm64 已通过。
第一方 Programs、默认 OCR 与模型进入 runtime原生平台已验证GUI/Research/Wiki、EasyOCR 中英文模型、GPA detector、Research PDF 与 Playwright Chromium 已完成 macOS arm64 与 Linux x86_64/arm64 构建和 probe。
macOS Desktop 与 CLI 复用同一 runtime archive实现完成release workflow 构建一次平台 archive,macOS Desktop 与 CLI jobs 下载同名 artifact;本机 archive 与 CLI 安装入口已验证。
macOS DMG/ZIP 内置 CPythonworkflow 已配置完整 macOS runtime 已验证,完整 DMG/ZIP 仍需原生 runner 验收。
macOS unsigned DMG/ZIPworkflow 已配置Apple secrets、签名、notarization 和 PyPI 发布已移除,产物重命名为 unsigned;完整 DMG/ZIP 仍需原生 runner 验收。
Linux 桌面包不发布run 31809407776 中完整 x86_64 runtime 通过,但 AppImage 在 electron-builder block-map 阶段失败;发布配置已移除,不提供精简替代品。
CLI release installermacOS arm64 与 Linux 双架构已验证本机 macOS arm64 以及最终全绿 run 31811091609 的 Linux x86_64/arm64 均通过 checksum、解压、完整 verifier、worker cold-start、原子切换与 launcher version。
tag 驱动 GitHub Release实现已更新,尚未执行 tagworkflow 只发布 GitHub Release,并上传完整 runtime archives、macOS Desktop artifacts、checksums 和 manifest;尚未创建新 release tag。
Windows 桌面打包与兼容当前 release 暂缓本次不构建 Windows 产物;保留后续实现可行性,支持范围和产物形式由后续独立决策确定。
系统 credential store 集成明确不在范围内本文不规划 Keychain、keyring 或 Credential Manager。

12. 明确不在范围内

相关设计:Single-port worker and frontendSelf-update。安装与分发的冲突内容以本文为准,并在相关设计中引用本文。