From a37a2f5c3aec9bf0b64c3f6cc8a21743cd5af47e Mon Sep 17 00:00:00 2001 From: Jintao Date: Wed, 5 Aug 2026 00:34:44 +0800 Subject: [PATCH 1/2] Prepare v0.2.0 source release --- .github/workflows/ci.yml | 1 - CHANGELOG.en.md | 33 ++++++------ CHANGELOG.md | 25 +++++----- Compliance/Release/RELEASE-DECISIONS.json | 8 +-- .../experimental-v0.2.0/COMPOSITION.json | 4 +- .../experimental-v0.2.0/READINESS.json | 15 +++--- .../Release/experimental-v0.2.0/README.md | 4 +- .../experimental-v0.2.0/RELEASE-CHECKLIST.md | 12 ++--- .../experimental-v0.2.0/SBOM.spdx.json | 6 +-- .../Release/experimental-v0.2.0/SHA256SUMS | 10 ++-- Docs/IntegrationGuide.md | 11 ++-- Docs/README.md | 13 ++--- Docs/ReleaseCompliance.md | 16 +++--- Docs/Releases/0.2.0.md | 34 ++++++------- Docs/Testing.md | 14 +++--- Docs/en/IntegrationGuide.md | 12 ++--- Docs/en/README.md | 12 ++--- Docs/en/ReleaseCompliance.md | 20 ++++---- Docs/en/Releases/0.2.0.md | 50 ++++++++----------- Docs/en/Testing.md | 21 ++++---- README.en.md | 18 +++---- README.md | 17 +++---- Scripts/generate-release-compliance.rb | 12 ++--- Tests/Scripts/ReleaseComplianceTests.rb | 28 +++++------ .../Scripts/SourceReleaseVerificationTests.rb | 32 ++++-------- 25 files changed, 193 insertions(+), 235 deletions(-) diff --git a/.github/workflows/ci.yml b/.github/workflows/ci.yml index 2a62a15..59562e6 100644 --- a/.github/workflows/ci.yml +++ b/.github/workflows/ci.yml @@ -110,7 +110,6 @@ jobs: ruby Scripts/verify-source-release.rb \ --version 0.2.0 \ --ref HEAD \ - --allow-source-blocked \ --report "$RUNNER_TEMP/pocketroot-v0.2.0-source-candidate.json" - name: Upload source candidate audit report diff --git a/CHANGELOG.en.md b/CHANGELOG.en.md index 39eb545..541972a 100644 --- a/CHANGELOG.en.md +++ b/CHANGELOG.en.md @@ -6,6 +6,22 @@ All notable PocketRoot changes are recorded here. Semantic Versioning begins wit ## Unreleased +There are no unreleased changes. + +## 0.2.0 - 2026-08-04 + +### Added + +- Interactive SwiftTerm PTYs now show an iPhone-friendly Esc, Tab, Ctrl-C, + Ctrl-D, history up/down, and keyboard-dismiss key row by default; hosts can + hide it with `showsAccessoryView: false`. Unit tests pin every emitted byte, and the Host + App lifecycle smoke launches BusyBox `top`, observes live output, and uses + Ctrl-C to recover the shell. +- Bilingual security and community-conduct policies, support routing, + structured bug/integration/feature Issue forms, and a pull request checklist. + Documentation validation now requires these open-source collaboration files + and complete root-level Chinese/English mirrors. + ### Changed - Tiered the CI UI matrix by platform: ordinary PRs and default manual runs @@ -74,23 +90,6 @@ All notable PocketRoot changes are recorded here. Semantic Versioning begins wit with the same runtime/device type for one bounded retry; caller-owned devices and assertion failures are never retried. Coverage is unchanged while PR wall-clock time no longer accumulates every UI smoke serially. - -## 0.2.0 - Unreleased - -### Added - -- Interactive SwiftTerm PTYs now show an iPhone-friendly Esc, Tab, Ctrl-C, - Ctrl-D, history up/down, and keyboard-dismiss key row by default; hosts can - hide it with `showsAccessoryView: false`. Unit tests pin every emitted byte, and the Host - App lifecycle smoke launches BusyBox `top`, observes live output, and uses - Ctrl-C to recover the shell. -- Bilingual security and community-conduct policies, support routing, - structured bug/integration/feature Issue forms, and a pull request checklist. - Documentation validation now requires these open-source collaboration files - and complete root-level Chinese/English mirrors. - -### Changed - - RootFS delivery-candidate output bounding now tolerates macOS `EPERM` from a process-group exit race only after Open3 confirms the child has exited and a signal-zero probe confirms the whole group is gone. Surviving or unsignalable diff --git a/CHANGELOG.md b/CHANGELOG.md index 2aa5d6a..cd7b97b 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,18 @@ PocketRoot 的重要变化记录在这里,并从首个公开版本开始遵循 ## Unreleased +当前暂无未发布变更。 + +## 0.2.0 - 2026-08-04 + +### Added + +- 为交互式 SwiftTerm PTY 默认加入适配 iPhone 软键盘的 Esc、Tab、Ctrl-C、Ctrl-D、 + 上/下历史键与收起键盘按钮;宿主可通过 `showsAccessoryView: false` 隐藏。单元测试固定发送字节, + Host App lifecycle smoke 真实启动 BusyBox `top`、观察动态输出并用 Ctrl-C 回到 shell。 +- 加入双语安全策略与社区行为准则、支持入口、结构化 Bug/接入/功能请求表单和 + PR 检查表;文档校验现在要求这些开源协作文件存在,并保持根级中英文镜像完整。 + ### Changed - CI UI matrix 改为平台分层:普通 PR 与默认手动运行只执行外部消费者、Quick Start @@ -50,19 +62,6 @@ PocketRoot 的重要变化记录在这里,并从首个公开版本开始遵循 每路失败诊断使用独立 artifact 名称。runner 自建 Simulator 明确从 Xcode destination 消失时可按相同 runtime/device type 重建并有界重试一次;调用方设备和断言失败不重试。 测试覆盖不减少,PR 墙钟时间不再由全部 UI smoke 串行累加。 - -## 0.2.0 - Unreleased - -### Added - -- 为交互式 SwiftTerm PTY 默认加入适配 iPhone 软键盘的 Esc、Tab、Ctrl-C、Ctrl-D、 - 上/下历史键与收起键盘按钮;宿主可通过 `showsAccessoryView: false` 隐藏。单元测试固定发送字节, - Host App lifecycle smoke 真实启动 BusyBox `top`、观察动态输出并用 Ctrl-C 回到 shell。 -- 加入双语安全策略与社区行为准则、支持入口、结构化 Bug/接入/功能请求表单和 - PR 检查表;文档校验现在要求这些开源协作文件存在,并保持根级中英文镜像完整。 - -### Changed - - RootFS delivery candidate 的命令输出上限处理只会在 Open3 确认子进程已退出、且 signal 0 探测确认整个进程组已消失后,容忍 macOS 在退出竞态中返回的 `EPERM`;残留或不可发送 信号的后代仍然 fail-closed,同时 CI 可以正常回收已退出命令,不再泄漏平台异常。 diff --git a/Compliance/Release/RELEASE-DECISIONS.json b/Compliance/Release/RELEASE-DECISIONS.json index 2286a90..8b5303a 100644 --- a/Compliance/Release/RELEASE-DECISIONS.json +++ b/Compliance/Release/RELEASE-DECISIONS.json @@ -1,12 +1,12 @@ { "schemaVersion": 1, "releaseVersion": "0.2.0", - "status": "no-release-authorization-granted", + "status": "source-release-authorized", "sourceRelease": { "topLevelLicenseSpdx": "MIT", "contributorPolicyApproved": true, "releaseNoticeApproved": true, - "sourceReleaseAuthorized": false + "sourceReleaseAuthorized": true }, "runtimeDistribution": { "rootFSDeliveryModel": "caller-provided-local-input", @@ -21,7 +21,7 @@ }, "approval": { "approvedBy": "jacklv-coder", - "approvedAt": "2026-07-31T08:21:14Z", - "notes": "PocketRoot v0.2.0 Developer Preview preparation inherits the approved MIT, contributor, and NOTICE policies, but no v0.2.0 source tag or runtime, App, binary, third-party artifact, or RootFS distribution is authorized by this preparation PR." + "approvedAt": "2026-08-04T15:55:00Z", + "notes": "PocketRoot v0.2.0 original source and Swift Package metadata are authorized for release under MIT. Runtime, App, binary, third-party artifact, XCFramework, and RootFS distribution remain unauthorized." } } diff --git a/Compliance/Release/experimental-v0.2.0/COMPOSITION.json b/Compliance/Release/experimental-v0.2.0/COMPOSITION.json index 24d4bfa..37c30fb 100644 --- a/Compliance/Release/experimental-v0.2.0/COMPOSITION.json +++ b/Compliance/Release/experimental-v0.2.0/COMPOSITION.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "generatedAt": "2026-08-03T00:00:00Z", + "generatedAt": "2026-08-04T00:00:00Z", "release": { "name": "PocketRoot", "version": "0.2.0", @@ -14,7 +14,7 @@ "CONTRIBUTING.md": "0beaceb8d56f1c43fa458d0b121d3d005c4a9cedb12b32029b35e74aff7b3d0b", "CONTRIBUTING.en.md": "0f619a667ea5ae4749f77f9afe5a9583447fcdab8a0985c11dcc4c935dead94a", "Compliance/SPDX/LICENSE-LIST-3.28.0.json": "7376db20698ff21511fe802aded9b5d7145520a86133b74f68b0c1568dd6dd1c", - "Compliance/Release/RELEASE-DECISIONS.json": "93ef573069e44ea8d74f43c4fb380ec694dea700ddb2881e2b76e646020d86f2", + "Compliance/Release/RELEASE-DECISIONS.json": "7e89cd0a3903d681251bc87da19697d34b4fef0bd8f9205e283e1086ad1ad6c6", "Package.resolved": "a121fd0f287bcb42e22d1860f915203447dd552fddc82461e9d385b957fb3718", "Package.swift": "9ec4f31f7a91c5c001b6e5826c5ab2824e98c06eb61444027485a70f1efccfff", "Examples/PocketRootDemo/project.yml": "8547227f488ce384600e01202f3c74778e1be99b1cee8b952ead61e043e1f3e0", diff --git a/Compliance/Release/experimental-v0.2.0/READINESS.json b/Compliance/Release/experimental-v0.2.0/READINESS.json index ada3d40..e373880 100644 --- a/Compliance/Release/experimental-v0.2.0/READINESS.json +++ b/Compliance/Release/experimental-v0.2.0/READINESS.json @@ -1,13 +1,13 @@ { "schemaVersion": 1, - "generatedAt": "2026-08-03T00:00:00Z", + "generatedAt": "2026-08-04T00:00:00Z", "releaseVersion": "0.2.0", "overallStatus": "blocked", "authorizationSource": "Compliance/Release/RELEASE-DECISIONS.json", "tracks": { "sourcePackageRelease": { "scope": "PocketRoot source and Swift Package metadata only; no RootFS, XCFramework mirror, App, archive, IPA, or binary SDK asset.", - "status": "blocked", + "status": "ready", "gates": [ { "id": "source-boundary-excludes-rootfs", @@ -58,7 +58,7 @@ "id": "source-release-authorized", "title": "PocketRoot source release is explicitly authorized", "titleZh": "PocketRoot 源码发布已明确授权", - "satisfied": false, + "satisfied": true, "evidence": "Compliance/Release/RELEASE-DECISIONS.json", "owner": "project-owner", "requiredAction": "Record the approving owner and date after every source-release gate is satisfied." @@ -154,7 +154,6 @@ } }, "blockedGateIds": [ - "source-release-authorized", "rootfs-external-input-boundary", "release-artifact-built-and-scanned", "complete-license-notice-bundle-approved", @@ -165,9 +164,9 @@ "runtime-distribution-authorized" ], "nextRequiredDecision": { - "id": "source-release-authorized", - "owner": "project-owner", - "reason": "Record the approving owner and date after every source-release gate is satisfied." + "id": "rootfs-external-input-boundary", + "owner": "engineering", + "reason": "Scan the exact final artifact, record its reviewed SHA-256, and verify its inventory contains no RootFS payload." }, - "warning": "Engineering validation is not distribution authorization. A ready source track would not authorize runtime, RootFS, App, or binary distribution." + "warning": "Engineering validation is not distribution authorization. A Ready source track does not authorize runtime, RootFS, App, or binary distribution." } diff --git a/Compliance/Release/experimental-v0.2.0/README.md b/Compliance/Release/experimental-v0.2.0/README.md index cf0fe04..5c122c2 100644 --- a/Compliance/Release/experimental-v0.2.0/README.md +++ b/Compliance/Release/experimental-v0.2.0/README.md @@ -10,7 +10,7 @@ IshEmbed/XCFramework、精确 iSH gitlink、静态 supervisor 使用的 musl sou 默认 Demo 显式链接 IshEmbed,但仓库不包含 RootFS;只有本地 Debug 构建可把 精确固定的仓库外资产注入 App,Release 明确跳过。RootFS 不由库下载。 -PocketRoot 原创源码使用 MIT 许可证;0.2.0 源码发布尚未获得明确授权。 Runtime 的完整 LICENSE/NOTICE、 +PocketRoot 原创源码使用 MIT 许可证;0.2.0 源码发布已明确授权。 Runtime 的完整 LICENSE/NOTICE、 对应源码交付、App Store 2.5.2、法律审查和发行授权仍未完成。由于没有最终 archive,本目录明确保持 `completeReleaseArtifactSBOM=false`、`distributionAuthorized=false`。 @@ -42,7 +42,7 @@ asset into two independent, fail-closed tracks. The default Demo explicitly links IshEmbed, but the repository contains no RootFS. Only a local Debug build may inject the exact pinned external asset; Release skips it. The library never downloads the RootFS. The -Original PocketRoot source is licensed under MIT, but the 0.2.0 source release is not explicitly authorized. The Runtime's +Original PocketRoot source is licensed under MIT, and the 0.2.0 source release is explicitly authorized. The Runtime's complete LICENSE/NOTICE set, corresponding-source delivery, App Store 2.5.2 disposition, legal review, and distribution authorization remain open. Because no final archive was scanned, this evidence keeps diff --git a/Compliance/Release/experimental-v0.2.0/RELEASE-CHECKLIST.md b/Compliance/Release/experimental-v0.2.0/RELEASE-CHECKLIST.md index 39a3c6c..b636b02 100644 --- a/Compliance/Release/experimental-v0.2.0/RELEASE-CHECKLIST.md +++ b/Compliance/Release/experimental-v0.2.0/RELEASE-CHECKLIST.md @@ -6,14 +6,14 @@ runtime、App 或二进制 SDK 分发”分为两条独立轨道。工程测试通过不等于获得 额外分发授权;源码轨道 Ready 不会自动解除 runtime 轨道。 -## 源码与 Swift Package 发布(Blocked / 未就绪) +## 源码与 Swift Package 发布(Ready / 已就绪) - [x] `source-boundary-excludes-rootfs` — 源码发布不包含 RootFS 载荷 - [x] `public-api-status-declared` — 公共 API 状态已声明为 Experimental - [x] `top-level-license-finalized` — PocketRoot 顶层许可证已确定 - [x] `contributor-policy-approved` — 贡献者与版权政策已批准 - [x] `release-notice-approved` — 源码发行 NOTICE 已批准 -- [ ] `source-release-authorized` — PocketRoot 源码发布已明确授权 +- [x] `source-release-authorized` — PocketRoot 源码发布已明确授权 PocketRoot 原创源码的顶层许可证已由项目所有者确定为 MIT;贡献政策与 `NOTICE.md` 同步生效。源码轨道 Ready 不授权 Runtime、RootFS、App 或二进制 @@ -51,7 +51,7 @@ ruby Scripts/generate-release-compliance.rb --require-source-ready ruby Scripts/generate-release-compliance.rb --require-runtime-ready ``` -两个 `--require-*-ready` 命令分别反映各自轨道;源码轨道当前故意返回非零状态, +两个 `--require-*-ready` 命令分别反映各自轨道;源码轨道当前返回成功, Runtime 轨道仍故意返回非零状态。 ## English @@ -63,14 +63,14 @@ App, archive, or binary SDK distribution that excludes every RootFS asset. Passing engineering tests is not additional distribution authorization, and the Ready source track does not unblock the runtime track. -### Source and Swift Package release (Blocked) +### Source and Swift Package release (Ready) - [x] `source-boundary-excludes-rootfs` — Source release excludes the RootFS payload - [x] `public-api-status-declared` — Public API status is declared experimental - [x] `top-level-license-finalized` — Top-level PocketRoot license is finalized - [x] `contributor-policy-approved` — Contributor and copyright policy is approved - [x] `release-notice-approved` — Source-release notice is approved -- [ ] `source-release-authorized` — PocketRoot source release is explicitly authorized +- [x] `source-release-authorized` — PocketRoot source release is explicitly authorized The project owner selected MIT for original PocketRoot source. The contributor policy and `NOTICE.md` apply with it. A Ready source track @@ -102,5 +102,5 @@ content-based RootFS absence evidence; a content-tree digest, path, filename, or extension check is not sufficient. The two `--require-*-ready` commands report their tracks independently; -the source command intentionally remains nonzero, and the Runtime command intentionally remains +the source command currently succeeds, and the Runtime command intentionally remains nonzero. diff --git a/Compliance/Release/experimental-v0.2.0/SBOM.spdx.json b/Compliance/Release/experimental-v0.2.0/SBOM.spdx.json index 6486855..9d1ec97 100644 --- a/Compliance/Release/experimental-v0.2.0/SBOM.spdx.json +++ b/Compliance/Release/experimental-v0.2.0/SBOM.spdx.json @@ -3,9 +3,9 @@ "dataLicense": "CC0-1.0", "SPDXID": "SPDXRef-DOCUMENT", "name": "PocketRoot experimental full-graph composition 0.2.0", - "documentNamespace": "https://github.com/jacklv-coder/PocketRoot/sbom/release/experimental-v0.2.0/05495d05d69b4ddec325abb9b712c6bd632df73213c7c0ac51db6b2f036a6ba4", + "documentNamespace": "https://github.com/jacklv-coder/PocketRoot/sbom/release/experimental-v0.2.0/0049373bdf849047d56579b2c2245c2c996f767576a577e300085bfc0b84d643", "creationInfo": { - "created": "2026-08-03T00:00:00Z", + "created": "2026-08-04T00:00:00Z", "creators": [ "Tool: PocketRoot Scripts/generate-release-compliance.rb" ] @@ -25,7 +25,7 @@ "licenseDeclared": "MIT", "copyrightText": "NOASSERTION", "primaryPackagePurpose": "LIBRARY", - "sourceInfo": "Original PocketRoot source is licensed under MIT, but the 0.2.0 source release is not explicitly authorized. No Runtime, RootFS, App, archive, IPA, or binary distribution is asserted.", + "sourceInfo": "Original PocketRoot source is licensed under MIT, and the 0.2.0 source release is explicitly authorized. No Runtime, RootFS, App, archive, IPA, or binary distribution is asserted.", "licenseComments": "The top-level MIT license covers original PocketRoot source only. Third-party components retain their respective upstream licenses." }, { diff --git a/Compliance/Release/experimental-v0.2.0/SHA256SUMS b/Compliance/Release/experimental-v0.2.0/SHA256SUMS index 80dbcc7..99ce56f 100644 --- a/Compliance/Release/experimental-v0.2.0/SHA256SUMS +++ b/Compliance/Release/experimental-v0.2.0/SHA256SUMS @@ -1,5 +1,5 @@ -05495d05d69b4ddec325abb9b712c6bd632df73213c7c0ac51db6b2f036a6ba4 COMPOSITION.json -9fe270ba11160051d13f99cfe4ce6ee03c52882b88339dd6e4c1b4923ae30755 READINESS.json -6d41126608b019b46332a7957889f41e3c3ec6c6e9e2b884dca5ffc6d405e943 README.md -fab07621b5188930bfd2a38117e206815d94f755e667d65fc182ee55d14d2d40 RELEASE-CHECKLIST.md -888fffde64e4eed026296939334500cdc52d98694708e4edcb2a4130916bfe37 SBOM.spdx.json +0049373bdf849047d56579b2c2245c2c996f767576a577e300085bfc0b84d643 COMPOSITION.json +7e5f680af7756e009af6767b97b924232c4e9dc1258d247fa85824707eb2489d READINESS.json +25bb81f5603af23912af09fdce99da8b510150f6ffe2b0052ff8668b40d342b5 README.md +be29fcf8824509526ae6c1c809408bdc74640d1a06071db0cff5b6138d75e095 RELEASE-CHECKLIST.md +bac13d92bced596ddb0929e32db0f3d732c1971e463b59852e73827b5f80cb95 SBOM.spdx.json diff --git a/Docs/IntegrationGuide.md b/Docs/IntegrationGuide.md index 0252073..63a894f 100644 --- a/Docs/IntegrationGuide.md +++ b/Docs/IntegrationGuide.md @@ -30,17 +30,14 @@ PocketRoot 暴露八个产品: `PocketRootIshRuntimeIntegration`。只有直接使用底层 runtime factory 时才需要再显式选择 `PocketRootIshRuntime`;推荐的宿主控制器不需要业务 App 直接导入它。 -首个源码版本为 `v0.1.0`。公共 API 仍处于 Experimental 阶段,因此远程接入建议 +当前源码版本为 `v0.2.0`。公共 API 仍处于 Experimental 阶段,因此远程接入建议 固定精确版本,避免自动接收后续可能包含破坏性 API 调整的 `0.x` 版本: -`main` 上的 `v0.2.0` 仍是未授权、未打 tag 的候选;发布门禁完成前,远程业务 App -继续固定公开 `0.1.0`,候选验证只使用完整 Git SHA。 - ```swift dependencies: [ .package( url: "https://github.com/jacklv-coder/PocketRoot.git", - exact: "0.1.0" + exact: "0.2.0" ) ], targets: [ @@ -61,7 +58,7 @@ targets: [ 1. 选择 **File → Add Package Dependencies**; 2. 输入 `https://github.com/jacklv-coder/PocketRoot.git`; -3. 选择 **Exact Version** 并填写 `0.1.0`; +3. 选择 **Exact Version** 并填写 `0.2.0`; 4. 默认接入选择 `PocketRoot`; 5. 真实 runtime 另外选择 `PocketRootIshRuntimeIntegration`。 @@ -72,7 +69,7 @@ targets: [ ``` 不要依赖浮动分支;Experimental `0.x` 阶段也不建议使用会自动接收后续 minor 版本的 -`from: "0.1.0"`。源码 tag 不包含 RootFS、App、IPA、XCFramework 镜像或二进制 SDK, +`from: "0.2.0"`。源码 tag 不包含 RootFS、App、IPA、XCFramework 镜像或二进制 SDK, 也不解除 Runtime 分发门禁。 ## 2. 平台可用性 diff --git a/Docs/README.md b/Docs/README.md index 7fd011a..df1d659 100644 --- a/Docs/README.md +++ b/Docs/README.md @@ -17,8 +17,8 @@ 1. [产品规划](ProductPlan.md):目标用户、核心场景、价值、非目标和版本定义。 2. [路线图](Roadmap.md):当前完成度、开放门禁和后续优先级。 3. [发行与合规](ReleaseCompliance.md):许可证、RootFS、SBOM 与 App Store 限制。 -4. [v0.2.0 候选说明](Releases/0.2.0.md):核心闭环、真机证据、未授权边界和发布前门禁。 -5. [v0.1.0 发布说明](Releases/0.1.0.md):当前公开源码版本的能力、接入方式与发布边界。 +4. [v0.2.0 发布说明](Releases/0.2.0.md):当前公开源码版本、核心闭环、真机证据与发布边界。 +5. [v0.1.0 发布说明](Releases/0.1.0.md):首个公开源码版本的能力、接入方式与发布边界。 6. [ADR-001](Decisions/ADR-001-IshEmbed-Feasibility.md):为什么当前只以实验性方式采用 IshEmbed。 ### 应用接入者 @@ -54,8 +54,8 @@ | [测试与验证](Testing.md) | 测试命令、环境、覆盖范围和证据 | | [上游依赖清单](UpstreamDependencies.md) | revision、gitlink、URL、大小和哈希 | | [发行与合规](ReleaseCompliance.md) | 许可证、NOTICE、对应源码、SBOM 与商店门禁 | -| [v0.2.0 候选说明](Releases/0.2.0.md) | 核心能力、真机证据、候选边界与发布前门禁 | -| [v0.1.0 发布说明](Releases/0.1.0.md) | 当前公开版本能力、Swift Package 接入、发布边界与已知限制 | +| [v0.2.0 发布说明](Releases/0.2.0.md) | 当前公开能力、Swift Package 接入、真机证据、发布边界与已知限制 | +| [v0.1.0 发布说明](Releases/0.1.0.md) | 首个公开版本能力、接入方式与发布边界 | | [ADR](Decisions/ADR-001-IshEmbed-Feasibility.md) | 已冻结的技术决策、理由与后果 | | [变更日志](../CHANGELOG.md) | 每次版本或未发布变更 | @@ -74,8 +74,9 @@ - iOS 18.2 arm64 Simulator:原生 smoke 已通过。 - 默认 boot identity gate:已验证 `aarch64`、Alpine 身份、可选版本与 guest 工作目录后才 ready。 - Terminal、Files 与共享 Workspace 核心闭环已通过公开 SHA 外部消费者、Xcode 16、 - iPhone/iPad Simulator UI 和 Jack iPhone 90×2 秒稳定性门禁;v0.2.0 仍是未授权、 - 未打 tag 的候选,iPad 真机、真实 pressure/jetsam/断电和公开 runtime 分发继续开放。 + iPhone/iPad Simulator UI 和 Jack iPhone 90×2 秒稳定性门禁;v0.2.0 源码与 + Swift Package 轨道为 Ready,iPad 真机、真实 pressure/jetsam/断电和公开 runtime + 分发继续开放。 最新动态状态只在[路线图](Roadmap.md)维护。 diff --git a/Docs/ReleaseCompliance.md b/Docs/ReleaseCompliance.md index e260937..16c5d47 100644 --- a/Docs/ReleaseCompliance.md +++ b/Docs/ReleaseCompliance.md @@ -22,9 +22,9 @@ PocketRoot 的实验性 iSH runtime、XCFramework 和候选 RootFS 当前仅用 源码已经依据根目录 [`LICENSE`](../LICENSE) 中的 MIT License 获准发布;第三方 组件仍适用各自许可证,范围说明见 [`NOTICE.md`](../NOTICE.md)。 -## v0.2.0 候选双轨发布闸门 +## v0.2.0 双轨发布闸门 -仓库把未打 tag 的 `v0.2.0` Developer Preview 候选拆为两条互不替代的轨道: +仓库把 `v0.2.0` 拆为两条互不替代的轨道: 1. **源码与 Swift Package 发布**:只包含 PocketRoot 源码和 Swift Package 元数据,不包含 RootFS、App、IPA、XCFramework 镜像或二进制 SDK; @@ -32,9 +32,8 @@ PocketRoot 的实验性 iSH runtime、XCFramework 和候选 RootFS 当前仅用 runtime 制品,但明确不包含任何 RootFS 资产;RootFS 仍只能由调用方在本地取得 并自行确认授权。 -当前候选的源码与 Swift Package 轨道为 **Blocked**,因为尚未授予 `v0.2.0` -源码发布授权;Runtime 分发轨道同样为 **Blocked**。已公开的 `v0.1.0` 历史状态 -仍保存在原版本快照中。当前机器可读状态见 +源码与 Swift Package 轨道为 **Ready**;Runtime 分发轨道仍为 **Blocked**。 +已公开的 `v0.1.0` 历史状态仍保存在原版本快照中。当前机器可读状态见 [`READINESS.json`](../Compliance/Release/experimental-v0.2.0/READINESS.json), 人工复核入口见 [`RELEASE-CHECKLIST.md`](../Compliance/Release/experimental-v0.2.0/RELEASE-CHECKLIST.md), @@ -51,9 +50,10 @@ ruby Scripts/generate-release-compliance.rb --require-source-ready ruby Scripts/generate-release-compliance.rb --require-runtime-ready ``` -后两个命令分别反映各自轨道;在候选 PR 中二者都返回非零。源码轨道必须经过明确 -授权并再次评审后才能打 tag。下一项 Runtime 工程门禁是扫描精确的最终 -制品、记录人工复核的 SHA-256,并以内容级证据确认制品不包含 RootFS。 +后两个命令分别反映各自轨道:`--require-source-ready` 返回成功, +`--require-runtime-ready` 仍返回非零。源码 tag 还必须通过独立的 archive、annotated +tag 与外部精确 SwiftPM 解析门禁。下一项 Runtime 工程门禁是扫描精确的最终制品、 +记录人工复核的 SHA-256,并以内容级证据确认制品不包含 RootFS。 `RELEASE-DECISIONS.json` 是受代码评审的授权输入,不是自动授权开关。任何非空许可 证或批准项都必须同时记录非空 `approvedBy`、UTC RFC 3339 `approvedAt` 和说明; diff --git a/Docs/Releases/0.2.0.md b/Docs/Releases/0.2.0.md index 2a14512..96acc38 100644 --- a/Docs/Releases/0.2.0.md +++ b/Docs/Releases/0.2.0.md @@ -2,15 +2,13 @@ [简体中文](0.2.0.md) | [English](../en/Releases/0.2.0.md) | [文档中心](../README.md) -状态:**Developer Preview 候选,尚未发布或创建 Git tag**。 +发布日期:2026-08-04 -`v0.1.0` 仍是当前公开源码与 Swift Package 版本。本页描述 `main` 上正在审核的 -`v0.2.0` 候选;只有项目所有者后续明确授权、候选日期冻结且源码 tag 门禁通过后, -它才会成为可解析的精确版本。 +`v0.2.0` 是 PocketRoot 的第二个公开源码与 Swift Package 版本。 **Embed a local Linux Terminal and Files workspace in any iOS app.** -## 候选能力 +## 主要能力 - 宿主可直接打开 UIKit / SwiftUI Terminal、Files 或共享会话的 Workspace 页面; - `PocketRootIshWorkspaceHost` 自动完成调用方 RootFS 的 prepare、boot 与页面接入; @@ -21,7 +19,8 @@ - RootFS 安装器提供固定清单校验、snapshot、安全解包、容量预检、事务 promotion、 复用、回滚和异常恢复; - 外部消费者 App 按公开 Git SHA 验证冷启动 Terminal/Files、前后台恢复和 shutdown; -- Xcode 16 / iOS 18 CI 持续覆盖 RootFS、原生 runtime、iPhone/iPad UI 和公开接入路径。 +- Xcode 16 / iOS 18 CI 持续覆盖 RootFS、原生 runtime、iPhone UI 和公开接入路径; + iPad Simulator 在里程碑与发布候选时集中验证。 ## 真机证据 @@ -30,36 +29,35 @@ Jack iPhone(iPhone 14 Pro / iOS 26.6)使用 Xcode 26.6 完成默认 90×2 带唯一边界的零字节流,并交叉执行一次性命令、Files 预览和 stdout 上限故障恢复。 热身后 `phys_footprint` 增长 0.0 MiB,生命周期峰值 83.2 MiB,低于 256 MiB 门禁。 -## 当前接入方式 +## Swift Package 接入 -候选尚未发布,因此正式使用仍应固定现有 `0.1.0`: +公共 API 仍为 Experimental,建议固定精确版本: ```swift dependencies: [ .package( url: "https://github.com/jacklv-coder/PocketRoot.git", - exact: "0.1.0" + exact: "0.2.0" ) ] ``` -维护者可在审核期间通过公开 Git 完整 SHA 验证候选;业务 App 不应把未发布分支当作 -稳定版本约束。 +默认 `PocketRoot` 产品提供 Core、Resources、Terminal 和现成 UI;需要真实 iSH +runtime 时,额外显式选择 `PocketRootIshRuntimeIntegration`。 ## 发布边界 -候选只准备 PocketRoot 源码和 Swift Package 元数据。它不授权或附加 RootFS、App、 -archive、IPA、XCFramework 镜像或二进制 SDK,也不创建 tag 或 GitHub Release。 +本版本只发布 Git tag 对应的 PocketRoot 源码与 Swift Package 元数据。它不授权或 +附加 RootFS、App、archive、IPA、XCFramework 镜像或二进制 SDK;GitHub Release +不附加这些制品。 RootFS 继续由调用方合法取得、审核并作为本地输入提供;Runtime/App/二进制分发和 RootFS 再分发保持 fail-closed。 -未打 tag 的候选审计只容许 `source-release-authorized` 这一项尚未满足;源码边界、 -公开 API 状态、LICENSE、贡献者政策和 NOTICE 必须全部通过。CI 生成带 commit、 -archive SHA-256、文件统计和精确阻塞项的 JSON 报告,但不保留或上传源码 tar。 +源码发布审计要求全部源码门禁 Ready,并生成带 commit、archive SHA-256、文件统计和 +精确授权状态的 JSON 报告,但不保留或上传源码 tar。 -## 尚未关闭 +## 已知限制 -- v0.2.0 源码发布的项目所有者授权、发布日期、annotated tag 和外部精确版本解析; - iPad 真机、真实 storage pressure、jetsam 和强制断电; - RootFS 完整 NOTICE、对应源码交付和法律/分发批准; - 原生 Agent UI、streaming 与会话持久化(按产品决定暂停)。 diff --git a/Docs/Testing.md b/Docs/Testing.md index feb2bb5..2e7e3b1 100644 --- a/Docs/Testing.md +++ b/Docs/Testing.md @@ -19,7 +19,7 @@ PocketRoot 把验证分成宿主逻辑、真实 RootFS、iOS 构建、完整原 | Host App UI smoke | `./Scripts/run-host-app-ui-smoke.sh` | Apple Silicon + iOS 18 Simulator + archive | iPhone/iPad Simulator 上的公开宿主 Boot、SwiftTerm PTY、生命周期、Workspace 会话持续性、Files 增删改/预览、系统 document picker 导入、share sheet 保存与再次导入 round-trip,以及有序 shutdown | 真机系统文件交互、真机键盘、iPad 真机或发行可用 | | Host App 真机 UI smoke | `./Scripts/run-host-app-device-ui-smoke.sh` | Xcode 可解析的 development-signed iPhone/iPad + archive | 同一 Host App 生命周期 UI 测试的真机执行、签名与 development entitlement | iPad、真实压力或发行可用 | | 物理设备原生 smoke | `./Scripts/run-runtime-device-smoke.sh` | 签名 iOS 18+ iPhone/iPad + archive | 同一 17 项检查、可选进程暂停/恢复、UIKit 前后台、强制重启持久化、受限存储故障、有界内存警告恢复或持久 PTY 稳定性,development entitlement 与 shutdown 返回 | 真实 storage/memory pressure、断电、jetsam、iPad 或发行可用 | -| 源码发布审计 | `ruby Scripts/verify-source-release.rb --version 0.2.0 --allow-source-blocked` | Git commit | 除最终源码发布授权外的门禁全部满足,候选版本文档齐全,`git archive` 不含 RootFS、App、IPA、XCFramework 镜像、压缩载荷或原生二进制 | 已授予源码发布授权或 Runtime/App/RootFS 分发授权 | +| 源码发布审计 | `ruby Scripts/verify-source-release.rb --version 0.2.0` | Git commit | 源码轨道已授权且全部 Ready,版本文档已冻结,`git archive` 不含 RootFS、App、IPA、XCFramework 镜像、压缩载荷或原生二进制 | Runtime/App/RootFS 分发授权 | | 文档检查 | `./Scripts/check-docs.sh` | macOS/Linux shell | 中英文成对、中文覆盖和相对链接 | 技术实现正确 | ## 2. 宿主 Swift Package 测试 @@ -600,13 +600,11 @@ runtime 与 device type 重建该临时 Simulator。这些基础设施恢复合 失败,也保留首次 `xcodebuild` 的诊断结果。 这些 Simulator 结果不证明签名真机或发行可用。 -当前候选 PR 只允许以 `--allow-source-blocked` 审计未打 tag 的 `v0.2.0` commit。 -这个模式不是绕过门禁:它要求固定的源码门禁集合和顺序完全一致,并且唯一未满足项 -必须是 `source-release-authorized`;NOTICE、许可证、公开 API 状态或源码边界出现任何 -回退都会失败。审计报告记录 schema、commit、archive SHA-256、文件统计、精确阻塞项 -和授权状态;CI 只保留该 JSON 报告 14 天,不保留或上传临时源码 tar。 -`--require-source-ready` 与 tag 工作流保持失败关闭。只有明确授予源码发布授权并再次 -评审后,才可推送 `v0.2.0` annotated tag,并从受保护的 `main` 手动调度 +`v0.2.0` 源码发布审计要求固定的源码门禁集合和顺序全部满足;NOTICE、许可证、公开 +API 状态、授权或源码边界出现任何回退都会失败。审计报告记录 schema、commit、 +archive SHA-256、文件统计、精确阻塞项和授权状态;CI 只保留该 JSON 报告 14 天, +不保留或上传临时源码 tar。合并发布 PR 后,才可推送 `v0.2.0` annotated tag,并从 +受信任的 `main` 手动调度 `.github/workflows/source-release.yml`。工作流使用 `main` checkout 里的可信校验工具审计独立的 tag checkout,要求 annotated tag 的 commit 位于该 `main` 历史上,重新生成并扫描 `git archive`,随后从仓库外以 `exact: "0.2.0"` diff --git a/Docs/en/IntegrationGuide.md b/Docs/en/IntegrationGuide.md index 0e5e9da..461ea66 100644 --- a/Docs/en/IntegrationGuide.md +++ b/Docs/en/IntegrationGuide.md @@ -32,19 +32,15 @@ approval-gated command adapter documented in [Lightweight Agent Loop](Agent.md). A real guest requires the explicit integration product. Add `PocketRootIshRuntime` only when calling the lower-level runtime factory directly; the recommended host controller does not require the App to import -it. The first source release is `v0.1.0`. The API remains Experimental, so pin +it. The current source release is `v0.2.0`. The API remains Experimental, so pin the exact version instead of automatically accepting a later, potentially breaking `0.x` release: -The `v0.2.0` work on `main` remains an unauthorized, untagged candidate. -Remote application integrations should keep pinning public `0.1.0` until the -release gates close; candidate validation uses only a complete Git SHA. - ```swift dependencies: [ .package( url: "https://github.com/jacklv-coder/PocketRoot.git", - exact: "0.1.0" + exact: "0.2.0" ) ], targets: [ @@ -62,12 +58,12 @@ targets: [ ``` In Xcode, choose **File → Add Package Dependencies**, enter the repository -URL, select **Exact Version** `0.1.0`, add `PocketRoot` for the safe API, and +URL, select **Exact Version** `0.2.0`, add `PocketRoot` for the safe API, and explicitly add `PocketRootIshRuntimeIntegration` for Experimental runtime work. Local development may use `.package(path: "../PocketRoot")`. Do not use a floating branch. During the Experimental `0.x` period, avoid -`from: "0.1.0"` when later minor releases could break API compatibility. The +`from: "0.2.0"` when later minor releases could break API compatibility. The source tag contains no RootFS, App, IPA, XCFramework mirror, or binary SDK and does not open the Runtime distribution gate. diff --git a/Docs/en/README.md b/Docs/en/README.md index 92f525b..bce6f60 100644 --- a/Docs/en/README.md +++ b/Docs/en/README.md @@ -13,8 +13,8 @@ This is the English documentation hub for PocketRoot. The Chinese documents at t 1. [Product plan](ProductPlan.md) for users, use cases, value, non-goals, and release definitions. 2. [Roadmap](Roadmap.md) for current completion, gates, and priorities. 3. [Release and compliance](ReleaseCompliance.md) for licensing, RootFS, SBOM, and App Store constraints. -4. [v0.2.0 candidate notes](Releases/0.2.0.md) for the core closure, physical evidence, authorization boundary, and remaining release gates. -5. [v0.1.0 release notes](Releases/0.1.0.md) for the current public source release, integration, and release boundary. +4. [v0.2.0 release notes](Releases/0.2.0.md) for the current public source release, core closure, physical evidence, and release boundary. +5. [v0.1.0 release notes](Releases/0.1.0.md) for the first public source release, integration, and release boundary. 6. [ADR-001](Decisions/ADR-001-IshEmbed-Feasibility.md) for the Experimental IshEmbed decision. ### Application integrators @@ -50,8 +50,8 @@ This is the English documentation hub for PocketRoot. The Chinese documents at t | [Testing](Testing.md) | Test commands, environments, scope, and evidence | | [Upstream dependencies](UpstreamDependencies.md) | Revisions, gitlinks, URLs, sizes, and hashes | | [Release and compliance](ReleaseCompliance.md) | License, NOTICE, source, SBOM, and store gates | -| [v0.2.0 candidate notes](Releases/0.2.0.md) | Core capabilities, physical evidence, candidate boundary, and pre-release gates | -| [v0.1.0 release notes](Releases/0.1.0.md) | Current public capabilities, Swift Package integration, release boundary, and known limitations | +| [v0.2.0 release notes](Releases/0.2.0.md) | Current public capabilities, Swift Package integration, physical evidence, release boundary, and known limitations | +| [v0.1.0 release notes](Releases/0.1.0.md) | First public capabilities, integration, and release boundary | | [ADR](Decisions/ADR-001-IshEmbed-Feasibility.md) | Frozen decisions, rationale, and consequences | | [Changelog](../../CHANGELOG.en.md) | Versioned and unreleased changes | @@ -74,8 +74,8 @@ Code, `Package.resolved`, committed manifests, and the designated source-of-trut - Default boot identity gate: ready now requires matching `aarch64`, Alpine identity, optional version, and guest working directory. - The Terminal, Files, and shared Workspace core loop passes the public-SHA external consumer, Xcode 16, iPhone/iPad Simulator UI, and the Jack iPhone - 90×2-second stability gate. v0.2.0 remains an unauthorized, untagged - candidate; physical iPad, real pressure/jetsam/power loss, and public runtime + 90×2-second stability gate. The v0.2.0 source and Swift Package track is + Ready; physical iPad, real pressure/jetsam/power loss, and public runtime distribution remain open. See the [roadmap](Roadmap.md) for the current status. diff --git a/Docs/en/ReleaseCompliance.md b/Docs/en/ReleaseCompliance.md index eb45566..ded689c 100644 --- a/Docs/en/ReleaseCompliance.md +++ b/Docs/en/ReleaseCompliance.md @@ -18,9 +18,9 @@ release under the MIT License in the repository-root [`LICENSE`](../../LICENSE). Third-party components retain their respective licenses; see [`NOTICE.md`](../../NOTICE.md) for the scope boundary. -## v0.2.0 candidate two-track release gates +## v0.2.0 two-track release gates -The untagged `v0.2.0` Developer Preview candidate is split into two independent tracks: +The `v0.2.0` release is split into two independent tracks: 1. **Source and Swift Package release** includes only PocketRoot source and Swift Package metadata, with no RootFS, App, IPA, mirrored XCFramework, or @@ -30,10 +30,9 @@ The untagged `v0.2.0` Developer Preview candidate is split into two independent RootFS asset. The RootFS remains a caller-obtained, caller-authorized local input. -The candidate source and Swift Package track is currently **Blocked** because -`v0.2.0` source-release authorization has not been granted. The Runtime -distribution track is also **Blocked**. The historical state of the published -`v0.1.0` remains in its versioned snapshot. The current machine-readable state is +The source and Swift Package track is **Ready**. The Runtime distribution track +remains **Blocked**. The historical state of the published `v0.1.0` remains in +its versioned snapshot. The current machine-readable state is [`READINESS.json`](../../Compliance/Release/experimental-v0.2.0/READINESS.json), the review entry is [`RELEASE-CHECKLIST.md`](../../Compliance/Release/experimental-v0.2.0/RELEASE-CHECKLIST.md), @@ -52,10 +51,11 @@ ruby Scripts/generate-release-compliance.rb --require-source-ready ruby Scripts/generate-release-compliance.rb --require-runtime-ready ``` -The last two commands report their tracks independently; both remain nonzero -in this candidate PR. The source track requires explicit authorization and a -fresh review before tagging. The next Runtime engineering gate is -to scan the exact final artifact, record its reviewed SHA-256, and provide +The last two commands report their tracks independently: +`--require-source-ready` succeeds, while `--require-runtime-ready` remains +nonzero. The source tag must also pass the independent archive, annotated-tag, +and external exact SwiftPM-resolution gates. The next Runtime engineering gate +is to scan the exact final artifact, record its reviewed SHA-256, and provide content-based evidence that it contains no RootFS. `RELEASE-DECISIONS.json` is a code-reviewed authorization input, not an diff --git a/Docs/en/Releases/0.2.0.md b/Docs/en/Releases/0.2.0.md index dd703e0..9d0a5a5 100644 --- a/Docs/en/Releases/0.2.0.md +++ b/Docs/en/Releases/0.2.0.md @@ -2,16 +2,13 @@ [简体中文](../../../Docs/Releases/0.2.0.md) | [English](0.2.0.md) | [Documentation](../README.md) -Status: **Developer Preview candidate; no release or Git tag exists yet**. +Release date: 2026-08-04 -`v0.1.0` remains the current public source and Swift Package release. This page -describes the `v0.2.0` candidate under review on `main`. It becomes an exact -resolvable version only after explicit owner authorization, a frozen release -date, and successful source-tag gates. +`v0.2.0` is the second public PocketRoot source and Swift Package release. **Embed a local Linux Terminal and Files workspace in any iOS app.** -## Candidate capabilities +## Highlights - Ready-made UIKit and SwiftUI Terminal, Files, and shared-session Workspace screens. @@ -26,8 +23,9 @@ date, and successful source-tag gates. and interrupted recovery. - A public-Git-SHA external consumer gate covering cold Terminal/Files boot, foreground recovery, and shutdown. -- Continuous Xcode 16 / iOS 18 validation of RootFS, native runtime, - iPhone/iPad UI, and public integration paths. +- Continuous Xcode 16 / iOS 18 validation of RootFS, native runtime, iPhone UI, + and public integration paths, with iPad Simulator coverage at milestones and + release candidates. ## Physical-device evidence @@ -38,42 +36,38 @@ output, one-shot command and Files cross-checks, and stdout-limit recovery. Post-warm-up `phys_footprint` growth was 0.0 MiB and the lifecycle peak was 83.2 MiB, below the 256 MiB gate. -## Current integration version +## Swift Package integration -Because the candidate is not published, production integration should continue -to pin the existing `0.1.0` release: +The public API remains Experimental. Pin the exact release: ```swift dependencies: [ .package( url: "https://github.com/jacklv-coder/PocketRoot.git", - exact: "0.1.0" + exact: "0.2.0" ) ] ``` -Maintainers may validate the candidate by a complete public Git SHA during -review. Applications should not treat an unreleased branch as a stable version -constraint. +The default `PocketRoot` product provides Core, Resources, Terminal, and +ready-made UI. Select `PocketRootIshRuntimeIntegration` explicitly when the App +needs the native iSH runtime. ## Release boundary -The candidate prepares only PocketRoot source and Swift Package metadata. It -does not authorize or attach a RootFS, App, archive, IPA, XCFramework mirror, -or binary SDK, and it creates no tag or GitHub Release. Callers must continue to -lawfully obtain and review a local RootFS input. Runtime/App/binary distribution -and RootFS redistribution remain fail-closed. +This release publishes only PocketRoot source and Swift Package metadata at the +Git tag. It neither authorizes nor attaches a RootFS, App, archive, IPA, +XCFramework mirror, or binary SDK; the GitHub Release attaches none of those +artifacts. Callers must continue to lawfully obtain and review a local RootFS +input. Runtime/App/binary distribution and RootFS redistribution remain +fail-closed. -The untagged candidate audit permits only `source-release-authorized` to remain -unsatisfied. Source boundaries, public API status, LICENSE, contributor policy, -and NOTICE must all pass. CI writes a JSON report containing the commit, -archive SHA-256, file counts, and exact blockers, but neither retains nor -uploads the source tar. +The source-release audit requires every source gate to be Ready. CI writes a +JSON report containing the commit, archive SHA-256, file counts, and exact +authorization state, but neither retains nor uploads the source tar. -## Still open +## Known limitations -- Owner authorization, release date, annotated tag, and external exact-version - resolution for the v0.2.0 source release. - Physical iPad, real storage pressure, jetsam, and forced power loss. - Complete RootFS NOTICE, corresponding-source delivery, and legal/distribution approval. diff --git a/Docs/en/Testing.md b/Docs/en/Testing.md index eca89cf..4f7b3e2 100644 --- a/Docs/en/Testing.md +++ b/Docs/en/Testing.md @@ -19,7 +19,7 @@ PocketRoot separates host logic, real RootFS, iOS build, native final-link, and | Host App UI smoke | `./Scripts/run-host-app-ui-smoke.sh` | Public-host boot, SwiftTerm PTY, lifecycle, Workspace persistence, Files mutations/previews, system document-picker import, share-sheet save and re-import round trip, and ordered shutdown on iPhone/iPad iOS 18 Simulators | Physical-device system file interaction, physical keyboards, physical iPad, distribution | | Physical Host App UI smoke | `./Scripts/run-host-app-device-ui-smoke.sh` | The same lifecycle UI test on an Xcode-resolved, development-signed iPhone/iPad, including signature and development entitlements | iPad, real pressure, distribution | | Physical native smoke | `./Scripts/run-runtime-device-smoke.sh` | Same 17 checks with optional process suspend/resume, UIKit lifecycle, forced-relaunch persistence, bounded storage-failure recovery, bounded memory-warning recovery, or persistent-PTY stability; development entitlements and returning soft shutdown | Real storage/memory pressure, power cut, jetsam, iPad, distribution | -| Source-release audit | `ruby Scripts/verify-source-release.rb --version 0.2.0 --allow-source-blocked` | Every gate except final source-release authorization is satisfied, candidate documents are complete, and `git archive` contains no RootFS, App, IPA, XCFramework mirror, compressed payload, or native binary content | Granted source-release authorization or Runtime/App/RootFS distribution authorization | +| Source-release audit | `ruby Scripts/verify-source-release.rb --version 0.2.0` | The source track is authorized and fully Ready, release documents are frozen, and `git archive` contains no RootFS, App, IPA, XCFramework mirror, compressed payload, or native binary content | Runtime/App/RootFS distribution authorization | | Documentation | `./Scripts/check-docs.sh` | Pairs, Chinese coverage, relative links | Implementation correctness | ## Package tests @@ -555,17 +555,14 @@ the retry or restart also fails, the failure artifact retains the first and final logs plus both available `.xcresult` bundles. This Simulator evidence does not prove signed-device or distribution readiness. -This candidate PR audits only an untagged `v0.2.0` commit with -`--allow-source-blocked`. That mode does not bypass gates: it requires the -exact pinned source-gate set and order, with `source-release-authorized` as the -only unsatisfied gate. Any NOTICE, license, public-API-status, or source-boundary -regression fails the audit. The JSON report records its schema, commit, archive -SHA-256, file counts, exact blockers, and authorization status. CI retains only -that JSON report for 14 days and neither retains nor uploads the temporary -source tar. `--require-source-ready` and the tag workflow remain fail closed. -Only after explicit source-release authorization and another review may an -annotated `v0.2.0` tag be pushed and -`.github/workflows/source-release.yml` dispatched from protected `main`. The workflow +The `v0.2.0` source-release audit requires the exact pinned source-gate set and +order to be fully satisfied. Any NOTICE, license, public-API-status, +authorization, or source-boundary regression fails the audit. The JSON report +records its schema, commit, archive SHA-256, file counts, exact blockers, and +authorization status. CI retains only that JSON report for 14 days and neither +retains nor uploads the temporary source tar. After the release PR is merged, +an annotated `v0.2.0` tag may be pushed and +`.github/workflows/source-release.yml` dispatched from trusted `main`. The workflow uses trusted verifier tooling from the `main` checkout against a separate tag checkout, requires the annotated tag commit to belong to that trusted `main` history, regenerates and audits the `git archive`, then resolves the public diff --git a/README.en.md b/README.en.md index 2eda4a8..ae2116b 100644 --- a/README.en.md +++ b/README.en.md @@ -200,20 +200,16 @@ See [Getting Started](Docs/en/GettingStarted.md). ## Experimental application use -Select `PocketRootIshRuntimeIntegration` explicitly. The first source release is -`v0.1.0`. Because the public API remains Experimental, pin the exact version +Select `PocketRootIshRuntimeIntegration` explicitly. The current source release +is `v0.2.0`. Because the public API remains Experimental, pin the exact version instead of automatically accepting a later `0.x` release that may contain breaking API changes: -`main` is preparing an unauthorized, untagged `v0.2.0` Developer Preview -candidate. External Apps should continue to use the public `0.1.0` below until -the release gates are complete. - ```swift dependencies: [ .package( url: "https://github.com/jacklv-coder/PocketRoot.git", - exact: "0.1.0" + exact: "0.2.0" ) ] ``` @@ -388,11 +384,11 @@ third-party boundaries. The Experimental runtime links GPL-identified upstream code, and the candidate RootFS contains multiple copyleft and permissive licenses; PocketRoot's MIT License does not relicense those materials. -The untagged `v0.2.0` Developer Preview -[machine-readable candidate status](Compliance/Release/experimental-v0.2.0/READINESS.json) +The `v0.2.0` +[machine-readable release status](Compliance/Release/experimental-v0.2.0/READINESS.json) separates source/Swift Package release from Runtime/App distribution that -excludes every RootFS asset. Both tracks are currently **Blocked**, with the -source track awaiting explicit release authorization. The published `v0.1.0` +excludes every RootFS asset. The source and Swift Package track is **Ready**; +the Runtime distribution track remains **Blocked**. The published `v0.1.0` state remains available as a [historical snapshot](Compliance/Release/experimental-v0.1.0/READINESS.json). Package-level, maximal Experimental engineering-composition, and unsigned engineering-App diff --git a/README.md b/README.md index 44e772b..993eb56 100644 --- a/README.md +++ b/README.md @@ -187,18 +187,15 @@ App Bundle,首次点击 Boot 时再由 installer 校验并安装。未配置 ## 在应用中使用实验性运行时 -在 Swift Package 依赖中显式选择 `PocketRootIshRuntimeIntegration`。首个源码版本为 -`v0.1.0`;由于公共 API 仍处于 Experimental 阶段,建议固定精确版本,避免自动接收 +在 Swift Package 依赖中显式选择 `PocketRootIshRuntimeIntegration`。当前源码版本为 +`v0.2.0`;由于公共 API 仍处于 Experimental 阶段,建议固定精确版本,避免自动接收 后续可能包含破坏性 API 调整的 `0.x` 版本: -`main` 正在准备未授权、未打 tag 的 `v0.2.0` Developer Preview 候选;在正式发布 -门禁完成前,外部 App 仍应使用下面的公开 `0.1.0`。 - ```swift dependencies: [ .package( url: "https://github.com/jacklv-coder/PocketRoot.git", - exact: "0.1.0" + exact: "0.2.0" ) ] ``` @@ -351,10 +348,10 @@ PocketRoot 贡献者拥有版权的原创源码依据 [MIT License](LICENSE) 发 候选 RootFS 包含多种 copyleft 与 permissive 许可证;PocketRoot 的 MIT License 不会重新许可这些材料。 -未打 tag 的 `v0.2.0` Developer Preview -[机器可读候选状态](Compliance/Release/experimental-v0.2.0/READINESS.json) -把源码/Swift Package 与不含 RootFS 资产的 Runtime/App 分为两个独立轨道;二者当前 -均为 **Blocked**,其中源码轨道等待明确发布授权。已公开的 `v0.1.0` 状态保留在 +`v0.2.0` 的 +[机器可读发布状态](Compliance/Release/experimental-v0.2.0/READINESS.json) +把源码/Swift Package 与不含 RootFS 资产的 Runtime/App 分为两个独立轨道:源码与 +Swift Package 轨道为 **Ready**,Runtime 分发轨道仍为 **Blocked**。`v0.1.0` 状态保留在 [历史快照](Compliance/Release/experimental-v0.1.0/READINESS.json)。RootFS 包级、最大实验工程组合和 unsigned 工程 App 文件级 SPDX SBOM 已生成,但生产、 TestFlight 和公开二进制分发仍需完成 Runtime LICENSE/NOTICE、对应源码、最终签名/ diff --git a/Scripts/generate-release-compliance.rb b/Scripts/generate-release-compliance.rb index bfaeb5f..dbbe754 100644 --- a/Scripts/generate-release-compliance.rb +++ b/Scripts/generate-release-compliance.rb @@ -13,7 +13,7 @@ module PocketRootReleaseCompliance RELEASE_VERSION = "0.2.0" - GENERATED_AT = "2026-08-03T00:00:00Z" + GENERATED_AT = "2026-08-04T00:00:00Z" OUTPUT_RELATIVE = "Compliance/Release/experimental-v0.2.0" MIT_LICENSE_TEXT = <<~LICENSE.freeze MIT License @@ -259,7 +259,7 @@ module PocketRootReleaseCompliance "Compliance/SPDX/LICENSE-LIST-3.28.0.json" => "7376db20698ff21511fe802aded9b5d7145520a86133b74f68b0c1568dd6dd1c", "Compliance/Release/RELEASE-DECISIONS.json" => - "93ef573069e44ea8d74f43c4fb380ec694dea700ddb2881e2b76e646020d86f2", + "7e89cd0a3903d681251bc87da19697d34b4fef0bd8f9205e283e1086ad1ad6c6", "Package.resolved" => "a121fd0f287bcb42e22d1860f915203447dd552fddc82461e9d385b957fb3718", "Package.swift" => @@ -2046,8 +2046,8 @@ def readiness(composition_document, inputs) end ), "warning" => - "Engineering validation is not distribution authorization. A ready " \ - "source track would not authorize runtime, RootFS, App, or binary " \ + "Engineering validation is not distribution authorization. A Ready " \ + "source track does not authorize runtime, RootFS, App, or binary " \ "distribution." } end @@ -2150,8 +2150,8 @@ def validate_readiness(document) document.fetch("blockedGateIds") == expected_blocked && document.fetch("nextRequiredDecision") == expected_next_decision && document.fetch("warning") == - "Engineering validation is not distribution authorization. A ready " \ - "source track would not authorize runtime, RootFS, App, or binary " \ + "Engineering validation is not distribution authorization. A Ready " \ + "source track does not authorize runtime, RootFS, App, or binary " \ "distribution." && valid_gate_shapes unless valid_document diff --git a/Tests/Scripts/ReleaseComplianceTests.rb b/Tests/Scripts/ReleaseComplianceTests.rb index 0a672cd..82b0654 100644 --- a/Tests/Scripts/ReleaseComplianceTests.rb +++ b/Tests/Scripts/ReleaseComplianceTests.rb @@ -142,7 +142,7 @@ def test_full_graph_has_exact_packages_relationships_and_closed_gates refute composition.dig("coverage", "distributionAuthorized") assert_equal "blocked", readiness.fetch("overallStatus") assert_equal( - "source-release-authorized", + "rootfs-external-input-boundary", readiness.dig("nextRequiredDecision", "id") ) end @@ -153,18 +153,18 @@ def test_release_readiness_has_independent_fail_closed_tracks source = readiness.dig("tracks", "sourcePackageRelease") runtime = readiness.dig("tracks", "runtimeDistribution") - assert_equal "blocked", source.fetch("status") + assert_equal "ready", source.fetch("status") assert_equal "blocked", runtime.fetch("status") assert_includes( JSON.parse(outputs.fetch("SBOM.spdx.json")) .fetch("packages") .find { |package| package.fetch("name") == "PocketRoot" } .fetch("sourceInfo"), - "0.2.0 source release is not explicitly authorized" + "0.2.0 source release is explicitly authorized" ) assert_includes runtime.fetch("scope"), "excludes every RootFS asset" assert_equal( - [true, true, true, true, true, false], + [true, true, true, true, true, true], source.fetch("gates").map { |gate| gate.fetch("satisfied") } ) assert_equal( @@ -173,11 +173,10 @@ def test_release_readiness_has_independent_fail_closed_tracks ) assert_includes( readiness.fetch("warning"), - "source track would not authorize runtime" + "Ready source track does not authorize runtime" ) assert_equal( - ["source-release-authorized"] + - runtime.fetch("gates").drop(1).map { |gate| gate.fetch("id") }, + runtime.fetch("gates").drop(1).map { |gate| gate.fetch("id") }, readiness.fetch("blockedGateIds") ) end @@ -632,9 +631,9 @@ def test_release_checklist_documents_both_tracks_and_enforcement_commands "Runtime / App / binary distribution (RootFS excluded" assert_includes checklist, "--require-source-ready" assert_includes checklist, "--require-runtime-ready" - assert_includes checklist, "源码轨道当前故意返回非零状态" + assert_includes checklist, "源码轨道当前返回成功" assert_includes checklist, - "the source command intentionally remains nonzero" + "the source command currently succeeds" assert_includes checklist, "项目所有者确定为 MIT" end @@ -844,26 +843,25 @@ def test_spdx_expression_accepts_pinned_ids_operators_and_exception ) end - def test_readiness_cli_reports_both_candidate_tracks_blocked + def test_readiness_cli_reports_source_ready_and_runtime_blocked status_output, status_error = capture_io do assert_equal 0, PocketRootReleaseCompliance.execute(["--status"]) end assert_empty status_error assert_includes status_output, "release readiness: BLOCKED" - assert_includes status_output, "sourcePackageRelease: BLOCKED" + assert_includes status_output, "sourcePackageRelease: READY" assert_includes status_output, "runtimeDistribution: BLOCKED" source_output, source_error = capture_io do assert_equal( - 2, + 0, PocketRootReleaseCompliance.execute(["--require-source-ready"]) ) end - assert_empty source_output - assert_includes source_error, "sourcePackageRelease is BLOCKED" - assert_includes source_error, "source-release-authorized" + assert_empty source_error + assert_includes source_output, "Source and Swift Package release track is READY" runtime_output, runtime_error = capture_io do diff --git a/Tests/Scripts/SourceReleaseVerificationTests.rb b/Tests/Scripts/SourceReleaseVerificationTests.rb index 2de0107..fe92f38 100755 --- a/Tests/Scripts/SourceReleaseVerificationTests.rb +++ b/Tests/Scripts/SourceReleaseVerificationTests.rb @@ -20,24 +20,18 @@ def teardown FileUtils.remove_entry(@temporary_directory) if @temporary_directory.exist? end - def test_current_release_candidate_passes_source_archive_audit_while_blocked + def test_current_release_commit_passes_source_archive_audit result = PocketRootSourceRelease.verify( root: REPOSITORY_ROOT, ref: "HEAD", - version: "0.2.0", - require_source_ready: false + version: "0.2.0" ) - assert_equal "blocked", result.fetch("sourceTrack") + assert_equal "ready", result.fetch("sourceTrack") assert result.fetch("sourceCandidateReady") - assert_equal( - ["source-release-authorized"], - result.fetch("sourceBlockedGateIds") - ) - assert_equal( - "no-release-authorization-granted", + assert_empty result.fetch("sourceBlockedGateIds") + assert_equal "source-release-authorized", result.fetch("authorizationStatus") - ) assert_equal 1, result.fetch("schemaVersion") refute result.fetch("rootFSIncluded") refute result.fetch("runtimeArtifactIncluded") @@ -107,6 +101,7 @@ def test_ci_and_tag_workflows_publish_json_verification_reports_only assert_includes ci, '--report "$RUNNER_TEMP/pocketroot-v0.2.0-source-candidate.json"' + refute_includes ci, "--allow-source-blocked" assert_includes ci, "Upload source candidate audit report" assert_includes ci, "path: ${{ runner.temp }}/pocketroot-v0.2.0-source-candidate.json" @@ -120,16 +115,11 @@ def test_ci_and_tag_workflows_publish_json_verification_reports_only refute_match(/path:.*\.tar\s*$/i, release) end - def test_current_release_candidate_fails_closed_without_source_authorization - error = assert_raises(PocketRootSourceRelease::VerificationError) do - PocketRootSourceRelease.verify( - root: REPOSITORY_ROOT, - ref: "HEAD", - version: "0.2.0" - ) - end - - assert_includes error.message, "does not declare release 0.2.0" + def test_current_release_documents_declare_frozen_version + PocketRootSourceRelease.verify_release_documents( + REPOSITORY_ROOT, + "0.2.0" + ) end def test_rejects_git_archive_export_filtering_in_candidate_ref From bdf4714378eb602ab94e187a5bb57de7cc8e7f0a Mon Sep 17 00:00:00 2001 From: Jintao Date: Wed, 5 Aug 2026 08:04:27 +0800 Subject: [PATCH 2/2] Align release evidence with source approval --- Compliance/Release/experimental-v0.2.0/COMPOSITION.json | 2 +- Compliance/Release/experimental-v0.2.0/READINESS.json | 2 +- Compliance/Release/experimental-v0.2.0/SBOM.spdx.json | 4 ++-- Compliance/Release/experimental-v0.2.0/SHA256SUMS | 6 +++--- Scripts/generate-release-compliance.rb | 2 +- 5 files changed, 8 insertions(+), 8 deletions(-) diff --git a/Compliance/Release/experimental-v0.2.0/COMPOSITION.json b/Compliance/Release/experimental-v0.2.0/COMPOSITION.json index 37c30fb..95b7634 100644 --- a/Compliance/Release/experimental-v0.2.0/COMPOSITION.json +++ b/Compliance/Release/experimental-v0.2.0/COMPOSITION.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "generatedAt": "2026-08-04T00:00:00Z", + "generatedAt": "2026-08-04T15:55:00Z", "release": { "name": "PocketRoot", "version": "0.2.0", diff --git a/Compliance/Release/experimental-v0.2.0/READINESS.json b/Compliance/Release/experimental-v0.2.0/READINESS.json index e373880..284d416 100644 --- a/Compliance/Release/experimental-v0.2.0/READINESS.json +++ b/Compliance/Release/experimental-v0.2.0/READINESS.json @@ -1,6 +1,6 @@ { "schemaVersion": 1, - "generatedAt": "2026-08-04T00:00:00Z", + "generatedAt": "2026-08-04T15:55:00Z", "releaseVersion": "0.2.0", "overallStatus": "blocked", "authorizationSource": "Compliance/Release/RELEASE-DECISIONS.json", diff --git a/Compliance/Release/experimental-v0.2.0/SBOM.spdx.json b/Compliance/Release/experimental-v0.2.0/SBOM.spdx.json index 9d1ec97..a6b9677 100644 --- a/Compliance/Release/experimental-v0.2.0/SBOM.spdx.json +++ b/Compliance/Release/experimental-v0.2.0/SBOM.spdx.json @@ -3,9 +3,9 @@ "dataLicense": "CC0-1.0", "SPDXID": "SPDXRef-DOCUMENT", "name": "PocketRoot experimental full-graph composition 0.2.0", - "documentNamespace": "https://github.com/jacklv-coder/PocketRoot/sbom/release/experimental-v0.2.0/0049373bdf849047d56579b2c2245c2c996f767576a577e300085bfc0b84d643", + "documentNamespace": "https://github.com/jacklv-coder/PocketRoot/sbom/release/experimental-v0.2.0/289f1a63f0e9f66806ffc6a0c43fc1182993826f570eed773428c69fd9a50e4e", "creationInfo": { - "created": "2026-08-04T00:00:00Z", + "created": "2026-08-04T15:55:00Z", "creators": [ "Tool: PocketRoot Scripts/generate-release-compliance.rb" ] diff --git a/Compliance/Release/experimental-v0.2.0/SHA256SUMS b/Compliance/Release/experimental-v0.2.0/SHA256SUMS index 99ce56f..2d91063 100644 --- a/Compliance/Release/experimental-v0.2.0/SHA256SUMS +++ b/Compliance/Release/experimental-v0.2.0/SHA256SUMS @@ -1,5 +1,5 @@ -0049373bdf849047d56579b2c2245c2c996f767576a577e300085bfc0b84d643 COMPOSITION.json -7e5f680af7756e009af6767b97b924232c4e9dc1258d247fa85824707eb2489d READINESS.json +289f1a63f0e9f66806ffc6a0c43fc1182993826f570eed773428c69fd9a50e4e COMPOSITION.json +bddd71afb4f871ad66a0a8cbb188616971649dcbd83fdce4e8d1f86ae55ecbcd READINESS.json 25bb81f5603af23912af09fdce99da8b510150f6ffe2b0052ff8668b40d342b5 README.md be29fcf8824509526ae6c1c809408bdc74640d1a06071db0cff5b6138d75e095 RELEASE-CHECKLIST.md -bac13d92bced596ddb0929e32db0f3d732c1971e463b59852e73827b5f80cb95 SBOM.spdx.json +129afa86f16f9d837e3ce4323a15a88ab4568852ace62b2804e5eca2bde10f3c SBOM.spdx.json diff --git a/Scripts/generate-release-compliance.rb b/Scripts/generate-release-compliance.rb index dbbe754..00160cd 100644 --- a/Scripts/generate-release-compliance.rb +++ b/Scripts/generate-release-compliance.rb @@ -13,7 +13,7 @@ module PocketRootReleaseCompliance RELEASE_VERSION = "0.2.0" - GENERATED_AT = "2026-08-04T00:00:00Z" + GENERATED_AT = "2026-08-04T15:55:00Z" OUTPUT_RELATIVE = "Compliance/Release/experimental-v0.2.0" MIT_LICENSE_TEXT = <<~LICENSE.freeze MIT License