Files
agent-pet-companion/docs/release/macos-release.md
T
xjxandgd-ops 790046d9a8 Add protected parallel delivery workflow (#6)
## Development lane / 开发通道

- Lane: `direct-to-main` bootstrap
- Base branch: `main`
- Active train: `n/a`
- Owning Agent/session: workflow coordinator

## Change / 改动

- Split authoritative CI into parallel static, contract, Rust lint/test
shards, Swift interaction, stress, overlay, bundle, and stable `Required
CI` jobs.
- Make every ready PR to `main` a complete gate while keeping task PRs
to `gd-ops/train/*` path-scoped.
- Add direct/train worktree coordination, bounded changelog fragments,
protected main/train ruleset automation, and safe same-repository squash
auto-merge.
- Let GitHub Release promote an exact successful main commit, reuse its
source proof, and create a missing release tag only after proof
validation.
- Keep local pre-push validation bounded to basic syntax, formatting,
contracts, and compilation; complete duplicate proof stays in GitHub CI.

This is the one bootstrap PR: the auto-merge workflow and required rules
do not exist on the base branch yet. After this PR passes and is merged
once, the exact `main` push must pass `Required CI`; then the
fail-closed applicator can activate both rulesets and all later ready
`gd-ops/*` PRs follow the automated path.

## Validation / 验证

- `actionlint .github/workflows/ci.yml .github/workflows/release.yml
.github/workflows/auto-merge.yml`
- `./script/validate_source_syntax.sh`
- `./script/validate_build_scripts_safety.sh --skip-source-syntax`
- Exact staged diff was reapplied to a clean detached worktree before
the final validation run.
- 28 validation-tooling tests, 40 release-distribution tests, macOS
build-contract tests, Release shell contracts, and test-isolation
validation passed.

## Risk / 风险

- No product runtime or credential access is added.
- `pull_request_target` never checks out or executes PR code and only
enables auto-merge after API verification of active PR and `Required CI`
rules.
- Full ruleset activation fails closed until the exact remote main
commit has a trusted successful GitHub Actions push run.
- Reversible repository settings are already enabled: auto-merge,
squash-only, update branch, and delete merged branches.

---------

Co-authored-by: gd-ops <gd-ops@xmfunny.com>
2026-08-11 20:28:02 +08:00

14 KiB
Raw Blame History

macOS GitHub Release / macOS GitHub Release 流程

One release contains the App, PetCore, CLI, runtime manifest, bundled Skills, and bundled pets. It publishes two thin archives (arm64, x86_64) plus one checksum file. / 一个版本将 App、PetCore、CLI、runtime manifest、内置 Skills 和宠物作为同一发布单元,生成两个 thin 归档和一份校验和文件。

Distribution boundary / 分发边界

GitHub Releases is the only official V1 channel. Archives are ad-hoc signed, not Developer ID signed or notarized, and have no stapled ticket. The project does not use Mac App Store, TestFlight, Apple distribution credentials, or a protected GitHub release environment.

Published Apps therefore require explicit first-open consent through Finder Open or System Settings → Privacy & Security → Open Anyway. Do not instruct users to disable Gatekeeper or remove quarantine from the command line. / 正式 App 首次打开需要通过 Finder 的打开或系统设置 → 隐私与安全性 → 仍要打开确认;不得要求用户关闭 Gatekeeper 或通过命令行绕过。

GitHub Immutable Releases is not required. Protected v*.*.* tags and fail-closed automation provide commit identity, while users verify downloaded ZIPs against the published checksum before replacement.

Release identity / 发布身份

Choose semantic version X.Y.Z and a positive build number. The exact release commit must have:

  • source version X.Y.Z;
  • one matching ## [X.Y.Z] - YYYY-MM-DD changelog section;
  • protected tag vX.Y.Z pointing to the full commit;
  • a clean worktree;
  • the validation required for that release.

The runtime build ID is X.Y.Z.BUILD.FULL_40_CHARACTER_COMMIT. App, PetCore, CLI, manifest, and both archives must agree. One version maps to one tag, one changelog section, and one GitHub Release. / 版本、tag、CHANGELOG、完整 commit、build ID 与两个架构产物必须一一对应。

The Codex plugin keeps an independent semantic version. Any change under plugins/codex, skills/agent-pet-studio, or skills/agent-pet-maker requires a greater plugin version than the previous release. Every bundled Skill front matter must declare that same version, while the hooks template is restricted to Codex-supported top-level fields. Hook version presentation binds an exact current rendered template to the plugin manifest; current source/cache digests prove convergence and are never a historical ownership registry. / Codex 插件独立版本必须递增;所有内置 Skill 的 front matter 必须声明同一版本;hooks 模板只能使用 Codex 支持的顶层字段。Hook 的版本展示通过当前完整渲染模板与插件清单绑定;当前源与缓存摘要只用于证明收敛,绝不是历史归属注册表。

The previous release baseline is the current latest stable GitHub Release, not merely the nearest semantic-version Git tag. A protected candidate tag whose workflow fails before publication remains an immutable audit marker, but it is not a shipped upgrade or retired-Skill ownership baseline. The next candidate uses a new semantic version and continues from the actual latest stable Release. / 上一版本基线取 GitHub 当前 latest stable Release,而不是距离最近的语义版本 Git tag。若受保护的候选标签在公开发布前失败,该标签会作为不可变审计标记保留,但不会成为已发布升级或退役 Skill 所有权基线;下一候选使用新的语义版本,并继续以实际 latest stable Release 为基线。

Prerequisites and gates / 环境与门禁

Build hosts need Apple Swift 6.2 or newer with the macOS 26 SDK or newer, the pinned Rust toolchain and both Apple targets, Python 3 with the pinned visual-validation dependencies, rg, ditto, codesign, lipo, nm, otool, and shasum. The App remains deployed to macOS 14: official App binaries must report minos 14.0, an SDK of at least 26, and weak-linked SwiftUI/AppKit Liquid Glass symbols. This lets one archive render native Liquid Glass on macOS 26 while running the authored system-material fallback on macOS 14 and 15. / 构建主机必须提供 Apple Swift 6.2+ 与 macOS 26+ SDK;App 的最低运行版本仍为 macOS 14。正式 App 二进制必须同时证明 minos 14.0、SDK 至少为 26,且 SwiftUI/AppKit Liquid Glass 符号保持弱链接,因此同一归档可在 macOS 26 呈现原生液态玻璃,并在 macOS 14、15 运行既定的系统材质回退。

rustup target add aarch64-apple-darwin x86_64-apple-darwin

No Apple account, certificate, private key, notarization profile, release Variable, or release Secret is used.

Merge the exact candidate commit to protected main and wait for the post-merge required CI check. The main-bound PR has already passed the complete gate before auto-merge; the trusted main push binds the same release-grade inventory to the exact immutable main commit and uploads its source proof. A manual dispatch may create the release tag only after validating that proof. The one-time ruleset migration procedure is owned by Validation profiles. / 将精确候选 commit 合并到受保护的 main 并等待合并后的必选 CI。面向 main 的 PR 已在自动合并前通过完整门禁;受信任的 main push 会将同一 Release 级清单绑定到精确且不可变的 main commit 并上传源码证明。手动 dispatch 只有在验证该证明后才能创建发布 tag。一次性 ruleset 迁移步骤由验证文档维护。

The complete local command remains available only for diagnosis; it is not a release prerequisite when the exact remote proof exists:

APC_VALIDATE_HOST_UI=0 \
APC_VALIDATE_REAL_AGENT_CONNECTORS=0 \
APC_VALIDATE_REAL_APP_SERVER=0 \
./script/test_all.sh --source-only --include-stress

Then run the environment-dependent connector, App Server, visible-UI, renderer, and profiling gates required by Validation profiles. The executing Agent selects a suitable live-App inspection method. A gate not run is skipped, never passed. / 随后按发布范围运行环境门禁;可见 App 的验收方法由执行 Agent 选择,未运行的门禁只能标记为 skipped。

The complete Swift CI shard generates a source-build interaction attestation. source-proof.json binds its bytes to the repository, full commit/tree, latest stable baseline, trusted main push run, complete gate inventory, and toolchain contract. Release downloads it only from the successful exact-commit CI run, validates it, and rebinds the interaction attestation to the final release build ID before supplying it to both architecture builds. / 完整 Swift CI 分片会生成源码 build 的交互证明;source-proof.json 将其字节绑定到仓库、完整 commit/tree、latest stable 基线、受信任 main push run、完整门禁清单与工具链合同。Release 只从成功的同 commit CI run 下载并校验,再将交互证明重新绑定到最终发布 build ID,供两个架构构建复用。

Development artifacts / 开发产物

./script/build_app_bundle.sh
./script/build_app_bundle.sh --archive

These produce development Apps or handoff archives. Renaming or uploading them does not make them official release artifacts. / 这些命令只生成开发或交接产物,不能通过改名替代正式发布。

Build the candidate / 构建候选产物

On the tagged commit:

export APC_RELEASE_VERSION='X.Y.Z'
export APC_RELEASE_BUILD='1'
./script/build_release.sh --github-release --arch all

Normally the previous baseline is inferred from Git history for local builds. If an intervening protected candidate tag never became a GitHub Release, set APC_PREVIOUS_RELEASE_TAG to the actual latest stable Release tag; GitHub automation resolves and supplies this value from /releases/latest automatically. / 本地构建通常从 Git 历史推断上一基线;若中间存在从未成为 GitHub Release 的受保护失败候选标签,请将 APC_PREVIOUS_RELEASE_TAG 设为实际 latest stable Release 标签。GitHub 自动化会从 /releases/latest 解析并传入该值。

Local complete mode uses --arch all, applies ad-hoc signatures, performs native packaged acceptance for the host architecture, and produces exactly:

dist/AgentPetCompanion-X.Y.Z-macos-arm64.zip
dist/AgentPetCompanion-X.Y.Z-macos-x86_64.zip
dist/AgentPetCompanion-X.Y.Z-SHA256SUMS.txt

SHA256SUMS.txt contains exactly the two ZIP entries. No signature or notarization sidecar belongs in the asset set.

The GitHub workflow runs --arch arm64 and --arch x86_64 in parallel. It adds the internal --source-gate-proven handoff only after reusing and validating the successful exact-commit main proof. Each command produces one source-proven ZIP component; neither component is publishable alone. The assemble job downloads both, creates the shared checksum, rejects any extra file, and emits the three trusted digests. / GitHub workflow 仅在复用并校验成功的同 commit main 证明后,才使用内部 --source-gate-proven 交接并行构建两个架构;单件不可单独发布。

Validate a clean local or downloaded three-file directory with:

./script/validate_github_release_artifacts.sh \
  --directory /path/to/artifacts \
  --version X.Y.Z \
  --build BUILD_NUMBER \
  --commit FULL_40_CHARACTER_COMMIT

Validation rejects missing/extra assets, unsafe or malformed ZIPs, checksum/identity disagreement, invalid ad-hoc signatures, mixed/universal binaries, unexpected Mach-O content, and architecture mismatch. Native packaged acceptance also starts the bundled runtime in an isolated home and proves all three included pets, canonical covers, and every authored frame for all nine actions.

GitHub automation / GitHub 自动化

.github/workflows/release.yml runs from a protected vX.Y.Z tag or an explicit dispatch that promotes a successful main commit. The fast path is: / .github/workflows/release.yml 可由受保护 vX.Y.Z tag 或显式 dispatch 晋级一个成功的 main commit。快速路径如下:

gh workflow run release.yml \
  -f tag=vX.Y.Z \
  -f build=BUILD_NUMBER \
  -f commit=FULL_40_CHARACTER_MAIN_COMMIT

Omit commit to use current main. Dispatch verifies source version, changelog, ancestry, latest stable baseline, and the successful exact-commit main proof before it creates a missing lightweight tag through GitHub's API. An existing tag must already target the same commit. Tag creation cannot make an unproven commit releasable, and any later job rechecks the remote identity. / 省略 commit 时使用当前 main。dispatch 会先验证源码版本、CHANGELOG、祖先关系、latest stable 基线及同 commit 的成功 main 证明,再通过 GitHub API 创建缺失的轻量 tag;已有 tag 必须已指向同一 commit。创建 tag 不能让未经证明的 commit 进入发布,后续任务仍会复核远端身份。

In order the workflow:

  1. verifies source version, changelog, full main commit, latest stable baseline, and Codex plugin/Skill version discipline;
  2. resolves the successful trusted main push CI run for that exact commit, rejects PR/fork/failed or ambiguous runs and artifacts, validates the two-file source proof, then rebinds its interaction attestation to the final release build ID;
  3. creates a missing tag only after proof validation, or verifies the existing tag, then rechecks its remote commit;
  4. restores dependency/build caches and builds arm64 and x86_64 ZIP components in parallel on macOS 26 from the proven commit and rebound proof;
  5. assembles the exact three-file candidate once and records trusted digests;
  6. validates the exact SDK/deployment/weak-link contract in every App archive;
  7. runs the matching ZIP on macOS 15 arm64 and Intel hosts to prove the compatibility path, then runs the arm64 ZIP again on macOS 26 to prove the packaged modern-system path;
  8. creates a non-prerelease draft with bilingual installation and first-open guidance after exact-inventory and digest checks;
  9. downloads the draft assets and verifies exact inventory plus byte-for-byte equality with all three trusted digests, without rerunning the already completed native package suites;
  10. publishes it as latest stable only after all checks pass; and
  11. verifies through GitHub's API that the tag Release and /releases/latest are the same public stable Release with the trusted assets and digests.

Native compatibility validation on both architectures and packaged macOS 26 validation are hard dependencies; cross-building or static symbol inspection is not a substitute for runtime acceptance. Existing Releases are never overwritten. / 双架构原生兼容验收与 macOS 26 打包产物验收都是硬门禁;交叉构建或静态符号检查不能替代运行时验收,已有 Release 不会被覆盖。

User installation contract / 用户安装合同

The App, README, and Release notes use the same flow:

  1. download the architecture ZIP and SHA256SUMS.txt, then verify the ZIP;
  2. quit Agent Pet Companion, move the new App to /Applications, and choose Replace;
  3. open it from Applications and complete the macOS first-open approval if requested.

Installation requires no source toolchain. The App may open validated asset/Release URLs and Finder locations, but it never downloads or installs the App itself. A browser-open failure keeps the verified release available with retry and Release-page actions.

In-App update and replacement / App 内更新与替换

Automatic and manual checks use GitHub's public /releases/latest response and accept only a newer stable Release with the exact asset contract. Automatic checks are ETag-aware and run at most once per 24 hours after healthy startup; App menu and About actions bypass the interval.

After manual replacement, the bundled identity drives the existing runtime transaction. It converges PetCore, CLI, runtime manifest, missing/updated trusted bundled pets, and only integrations already managed by Agent Pet Companion. Core failure restores a compatible last-known-good runtime; an individual Agent failure remains isolated and repairable.

If the old App is still running, handoff waits for protected user mutations and convergence work, then revalidates the canonical replacement immediately before quit/relaunch. Invalid, changed, or ambiguous candidates leave the old App running with manual recovery. See Runtime and IPC.