From 2cf851a9dd38028f4eff6d0c1fd3b8876f257048 Mon Sep 17 00:00:00 2001
From: Rafal Sikora <24563931+s1korrrr@users.noreply.github.com>
Date: Mon, 20 Jul 2026 21:39:44 +0200
Subject: [PATCH 1/3] Prepare Patchwright 0.2.0 community release
Signed-off-by: Rafal Sikora <24563931+s1korrrr@users.noreply.github.com>
---
.github/ISSUE_TEMPLATE/config.yml | 4 +-
CHANGELOG.md | 32 +-
CODE_OF_CONDUCT.md | 2 +-
Cargo.lock | 6 +-
Packaging/Info.plist | 6 +-
README.md | 16 +-
SECURITY.md | 2 +-
SUPPORT.md | 2 +-
.../community_release_contract.sh | 110 +++++
.../github_app_smoke_contract.sh | 11 +-
Tests/PackagingTests/promotion_contract.sh | 2 +-
Tests/PackagingTests/release_contract.sh | 30 +-
.../UpdateConfigurationTests.swift | 2 +-
crates/patchwright-core/Cargo.toml | 3 +-
crates/patchwright-engine/Cargo.toml | 2 +-
crates/patchwright-relay/Cargo.toml | 2 +-
docs/RELEASING.md | 36 +-
docs/architecture.md | 129 ++++++
.../2026-07-13-github-app-delivery-queue.md | 34 --
.../audits/2026-07-13-github-ingestion-e2e.md | 119 -----
.../2026-07-13-orchestrator-foundation.md | 64 ---
.../2026-07-13-patchwright-final-e2e.md | 35 --
docs/audits/2026-07-14-embedded-codex.md | 67 ---
.../2026-07-14-live-lifecycle-closure.md | 85 ----
.../2026-07-17-product-quality-hardening.md | 101 -----
docs/direct-download.md | 23 +-
docs/github-publication-plan.md | 69 ---
.../2026-07-13-durable-local-orchestrator.md | 42 --
docs/reflections/2026-07-13-stages-1-3.md | 25 --
...2026-07-14-review-thread-reconciliation.md | 42 --
docs/release-checklist.md | 9 +
docs/release-readiness.md | 2 +-
docs/releases/v0.1.1.md | 46 --
docs/releases/v0.2.0-community.1.md | 48 ++
.../plans/2026-07-13-developer-id-release.md | 134 ------
.../plans/2026-07-13-embedded-codex.md | 136 ------
.../2026-07-13-github-app-delivery-queue.md | 178 --------
.../plans/2026-07-13-github-ingestion.md | 64 ---
.../2026-07-13-orchestrator-foundation.md | 173 -------
.../2026-07-13-patchwright-stages-1-3.md | 119 -----
.../2026-07-14-live-workflow-e2e-closure.md | 66 ---
.../2026-07-15-direct-open-source-release.md | 349 ---------------
...7-17-release-security-audit-remediation.md | 89 ----
...07-13-durable-local-orchestrator-design.md | 422 ------------------
...026-07-13-patchwright-stages-1-3-design.md | 98 ----
...07-15-direct-open-source-release-design.md | 107 -----
...026-07-20-open-source-release-readiness.md | 101 -----
script/build_release_components.sh | 4 +-
script/generate_release_compliance.py | 2 +-
script/package_community_release.sh | 128 ++++++
script/package_release.sh | 8 +-
script/smoke_github_app.sh | 6 +-
script/verify.sh | 1 +
script/verify_release_evidence.py | 2 +-
54 files changed, 574 insertions(+), 2821 deletions(-)
create mode 100755 Tests/PackagingTests/community_release_contract.sh
create mode 100644 docs/architecture.md
delete mode 100644 docs/audits/2026-07-13-github-app-delivery-queue.md
delete mode 100644 docs/audits/2026-07-13-github-ingestion-e2e.md
delete mode 100644 docs/audits/2026-07-13-orchestrator-foundation.md
delete mode 100644 docs/audits/2026-07-13-patchwright-final-e2e.md
delete mode 100644 docs/audits/2026-07-14-embedded-codex.md
delete mode 100644 docs/audits/2026-07-14-live-lifecycle-closure.md
delete mode 100644 docs/audits/2026-07-17-product-quality-hardening.md
delete mode 100644 docs/github-publication-plan.md
delete mode 100644 docs/reflections/2026-07-13-durable-local-orchestrator.md
delete mode 100644 docs/reflections/2026-07-13-stages-1-3.md
delete mode 100644 docs/reflections/2026-07-14-review-thread-reconciliation.md
delete mode 100644 docs/releases/v0.1.1.md
create mode 100644 docs/releases/v0.2.0-community.1.md
delete mode 100644 docs/superpowers/plans/2026-07-13-developer-id-release.md
delete mode 100644 docs/superpowers/plans/2026-07-13-embedded-codex.md
delete mode 100644 docs/superpowers/plans/2026-07-13-github-app-delivery-queue.md
delete mode 100644 docs/superpowers/plans/2026-07-13-github-ingestion.md
delete mode 100644 docs/superpowers/plans/2026-07-13-orchestrator-foundation.md
delete mode 100644 docs/superpowers/plans/2026-07-13-patchwright-stages-1-3.md
delete mode 100644 docs/superpowers/plans/2026-07-14-live-workflow-e2e-closure.md
delete mode 100644 docs/superpowers/plans/2026-07-15-direct-open-source-release.md
delete mode 100644 docs/superpowers/plans/2026-07-17-release-security-audit-remediation.md
delete mode 100644 docs/superpowers/specs/2026-07-13-durable-local-orchestrator-design.md
delete mode 100644 docs/superpowers/specs/2026-07-13-patchwright-stages-1-3-design.md
delete mode 100644 docs/superpowers/specs/2026-07-15-direct-open-source-release-design.md
delete mode 100644 plans/active/2026-07-20-open-source-release-readiness.md
create mode 100755 script/package_community_release.sh
diff --git a/.github/ISSUE_TEMPLATE/config.yml b/.github/ISSUE_TEMPLATE/config.yml
index f943cc9..c80ed43 100644
--- a/.github/ISSUE_TEMPLATE/config.yml
+++ b/.github/ISSUE_TEMPLATE/config.yml
@@ -1,8 +1,8 @@
blank_issues_enabled: false
contact_links:
- name: Security vulnerability
- url: https://github.com/s1korrrr/patchwright/security/advisories/new
+ url: https://github.com/rsitech-ai/patchwright/security/advisories/new
about: Report suspected vulnerabilities privately. Do not open a public issue.
- name: Support policy
- url: https://github.com/s1korrrr/patchwright/blob/main/SUPPORT.md
+ url: https://github.com/rsitech-ai/patchwright/blob/main/SUPPORT.md
about: Review supported questions, diagnostics, and privacy guidance before opening an issue.
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 8b2503e..b5245b8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -2,6 +2,33 @@
All notable user-facing and distribution changes are documented here. Patchwright follows semantic versioning for public releases.
+## [0.2.0] - 2026-07-20
+
+### Added
+
+- Add a reproducible community-prerelease packager that binds an ad-hoc-signed
+ app archive and checksum to the exact clean Git commit and release tag.
+- Publish machine-readable community release metadata that states the app
+ architecture, minimum macOS version, signing class, and notarization status.
+
+### Changed
+
+- Move the canonical public repository and release URLs to the RSI Tech
+ organization at `rsitech-ai/patchwright`.
+- Require the live GitHub App qualification smoke to reject both the canonical
+ organization repository and the legacy founder-account redirect.
+- Separate community prerelease downloads from the unchanged Developer ID,
+ notarization, clean-machine, and independent-promotion release contract.
+
+### Hardened
+
+- Require exact approved head and base identities immediately before supported
+ pull-request mutations.
+- Bound Codex protocol messages and request-wide resources, redact
+ credential-shaped durable content, and bind completion to exact active
+ request, thread, and turn identities.
+- Apply one global resource budget to nested GitHub snapshot fan-out.
+
## [0.1.1] - 2026-07-18
### Fixed
@@ -30,5 +57,6 @@ All notable user-facing and distribution changes are documented here. Patchwrigh
- Initial public technical-beta release of the local-first Patchwright app, engine, and relay.
-[0.1.1]: https://github.com/s1korrrr/patchwright/compare/v0.1.0...v0.1.1
-[0.1.0]: https://github.com/s1korrrr/patchwright/releases/tag/v0.1.0
+[0.2.0]: https://github.com/rsitech-ai/patchwright/compare/v0.1.1...v0.2.0-community.1
+[0.1.1]: https://github.com/rsitech-ai/patchwright/compare/v0.1.0...v0.1.1
+[0.1.0]: https://github.com/rsitech-ai/patchwright/releases/tag/v0.1.0
diff --git a/CODE_OF_CONDUCT.md b/CODE_OF_CONDUCT.md
index 96eaa4f..753de49 100644
--- a/CODE_OF_CONDUCT.md
+++ b/CODE_OF_CONDUCT.md
@@ -60,7 +60,7 @@ representative at an online or offline event.
Instances of abusive, harassing, or otherwise unacceptable behavior may be
reported privately through the repository's
-[private reporting form](https://github.com/s1korrrr/patchwright/security/advisories/new).
+[private reporting form](https://github.com/rsitech-ai/patchwright/security/advisories/new).
Do not include a conduct report in a public issue. Complaints will be reviewed
and investigated fairly as maintainer capacity allows; no response time is
promised.
diff --git a/Cargo.lock b/Cargo.lock
index c98a9f5..72c582c 100644
--- a/Cargo.lock
+++ b/Cargo.lock
@@ -967,7 +967,7 @@ dependencies = [
[[package]]
name = "patchwright-core"
-version = "0.1.1"
+version = "0.2.0"
dependencies = [
"chrono",
"serde",
@@ -979,7 +979,7 @@ dependencies = [
[[package]]
name = "patchwright-engine"
-version = "0.1.1"
+version = "0.2.0"
dependencies = [
"anyhow",
"axum",
@@ -1007,7 +1007,7 @@ dependencies = [
[[package]]
name = "patchwright-relay"
-version = "0.1.1"
+version = "0.2.0"
dependencies = [
"anyhow",
"axum",
diff --git a/Packaging/Info.plist b/Packaging/Info.plist
index 27a30bf..9069884 100644
--- a/Packaging/Info.plist
+++ b/Packaging/Info.plist
@@ -19,9 +19,9 @@
CFBundlePackageType
APPL
CFBundleShortVersionString
- 0.1.1
+ 0.2.0
CFBundleVersion
- 2
+ 3
LSApplicationCategoryType
public.app-category.developer-tools
LSMinimumSystemVersion
@@ -33,7 +33,7 @@
NSPrincipalClass
NSApplication
SUFeedURL
- https://github.com/s1korrrr/patchwright/releases/latest/download/appcast.xml
+ https://github.com/rsitech-ai/patchwright/releases/latest/download/appcast.xml
SUPublicEDKey
oMzk7aUjqsQFvrRBZDd5JsXaeTh8B4pQrJ7n6YHRWUA=
SURequireSignedFeed
diff --git a/README.md b/README.md
index 41aa15f..b1a9c77 100644
--- a/README.md
+++ b/README.md
@@ -2,14 +2,13 @@
Patchwright is a local-first, macOS-native engineering control plane for GitHub. It separates private language-model assistance from a durable coding-agent runtime and makes every approval, command, diff, test, and remote mutation auditable.
-**Status:** beta. The current source manifests are version `0.1.1`; the latest
-published artifact remains the version shown on GitHub Releases until a newer
-release completes signing, notarization, clean-machine verification, and
-promotion.
+**Status:** beta. The current source manifests are version `0.2.0`. GitHub may
+also carry a clearly labeled community prerelease for review and evaluation;
+that archive is ad-hoc signed and is not an Apple-notarized distribution.
Build Patchwright from [source](#build-and-verify). Official Developer ID-signed
and Apple-notarized downloads are published through
-[GitHub Releases](https://github.com/s1korrrr/patchwright/releases). See the
+[GitHub Releases](https://github.com/rsitech-ai/patchwright/releases). See the
[direct-download guide](docs/direct-download.md) for installation and
verification.
@@ -106,6 +105,11 @@ explicit promotion step. See the [direct-download guide](docs/direct-download.md
[release readiness](docs/release-readiness.md), and
[clean-machine test plan](docs/clean-machine-test-plan.md).
+When Developer ID and notarization credentials are unavailable,
+`script/package_community_release.sh` can package an already verified ad-hoc
+app from an exact clean tag. Its ZIP, checksum, and manifest are community
+prerelease artifacts only; they do not satisfy the official release gates.
+
## Safety
Merge is disabled by default and can execute only for a typed pull-request task after an exact action preview, a separate merge-class approval, a fresh exact-head-SHA precondition, and a single-use execution claim. GitHub writes, network access, dependency installation, and workflow changes require action-specific approval. Set `PATCHWRIGHT_AUTOMATION_DISABLED=1` to fail closed for every mutating capability while retaining read-only inspection.
@@ -117,4 +121,4 @@ still execute repository-controlled build scripts, plugins, and tests with the
current macOS user's file and network access. Review untrusted changes before
confirming verification.
-See [the product design](docs/superpowers/specs/2026-07-13-patchwright-stages-1-3-design.md), [production plan](docs/production-plan.md), and [security operations](docs/security.md).
+See [the architecture](docs/architecture.md), [production operations](docs/production-plan.md), and [security operations](docs/security.md).
diff --git a/SECURITY.md b/SECURITY.md
index fbe9b35..ba5216d 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -7,7 +7,7 @@ developer tooling and review action previews before approving them.
## Report a vulnerability privately
Do not open a public issue for a suspected vulnerability. Use GitHub's
-[private vulnerability reporting form](https://github.com/s1korrrr/patchwright/security/advisories/new).
+[private vulnerability reporting form](https://github.com/rsitech-ai/patchwright/security/advisories/new).
If that form is unavailable, contact a maintainer privately through the contact
method on their GitHub profile.
diff --git a/SUPPORT.md b/SUPPORT.md
index 0bee9f3..1f59fff 100644
--- a/SUPPORT.md
+++ b/SUPPORT.md
@@ -2,7 +2,7 @@
Patchwright is beta software provided without warranty or a service-level
agreement. Community support is offered on a best-effort basis through
-[GitHub Issues](https://github.com/s1korrrr/patchwright/issues). There is no
+[GitHub Issues](https://github.com/rsitech-ai/patchwright/issues). There is no
promise of response time, resolution, compatibility, continued maintenance, or
individual support.
diff --git a/Tests/PackagingTests/community_release_contract.sh b/Tests/PackagingTests/community_release_contract.sh
new file mode 100755
index 0000000..3901d96
--- /dev/null
+++ b/Tests/PackagingTests/community_release_contract.sh
@@ -0,0 +1,110 @@
+#!/usr/bin/env bash
+set -euo pipefail
+
+ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/../.." && pwd)"
+TMP_ROOT="$(mktemp -d "${TMPDIR:-/tmp}/patchwright-community-release-contract.XXXXXX")"
+trap '/usr/bin/trash "$TMP_ROOT" >/dev/null 2>&1 || true' EXIT
+
+fail() {
+ echo "community release contract failed: $*" >&2
+ exit 1
+}
+
+PACKAGER="$ROOT_DIR/script/package_community_release.sh"
+[[ -x "$PACKAGER" ]] || fail "missing executable script/package_community_release.sh"
+
+FIXTURE_REPO="$TMP_ROOT/repository"
+FIXTURE_APP="$TMP_ROOT/Patchwright.app"
+OUTPUT_DIR="$TMP_ROOT/output"
+mkdir -p "$FIXTURE_REPO/script" "$FIXTURE_APP/Contents/MacOS"
+cp "$PACKAGER" "$FIXTURE_REPO/script/package_community_release.sh"
+xcrun clang -arch arm64 -x c -o "$FIXTURE_APP/Contents/MacOS/Patchwright" - <<'C'
+int main(void) { return 0; }
+C
+chmod 755 "$FIXTURE_APP/Contents/MacOS/Patchwright"
+cat >"$FIXTURE_APP/Contents/Info.plist" <<'PLIST'
+
+
+
+
+ CFBundleExecutable
+ Patchwright
+ CFBundleIdentifier
+ ai.patchwright.app
+ CFBundlePackageType
+ APPL
+ CFBundleShortVersionString
+ 0.2.0
+ CFBundleVersion
+ 3
+ LSMinimumSystemVersion
+ 26.0
+
+
+PLIST
+/usr/bin/codesign --force --sign - "$FIXTURE_APP"
+
+git -C "$FIXTURE_REPO" init -q
+git -C "$FIXTURE_REPO" config user.name Fixture
+git -C "$FIXTURE_REPO" config user.email fixture@example.invalid
+git -C "$FIXTURE_REPO" add script/package_community_release.sh
+git -C "$FIXTURE_REPO" commit -qm fixture
+git -C "$FIXTURE_REPO" tag v0.2.0-community.1
+
+"$FIXTURE_REPO/script/package_community_release.sh" \
+ --app "$FIXTURE_APP" \
+ --output "$OUTPUT_DIR" \
+ --version 0.2.0 \
+ --build 3 \
+ --tag v0.2.0-community.1
+
+ARCHIVE="$OUTPUT_DIR/Patchwright-0.2.0-community.1-macos-arm64.zip"
+CHECKSUM="$ARCHIVE.sha256"
+MANIFEST="$OUTPUT_DIR/Patchwright-0.2.0-community.1-manifest.json"
+[[ -f "$ARCHIVE" && -f "$CHECKSUM" && -f "$MANIFEST" ]] \
+ || fail "packager did not emit the archive, checksum, and manifest"
+(cd "$OUTPUT_DIR" && shasum -a 256 -c "$(basename "$CHECKSUM")")
+
+EXPANDED="$TMP_ROOT/expanded"
+mkdir -p "$EXPANDED"
+/usr/bin/ditto -x -k "$ARCHIVE" "$EXPANDED"
+[[ -d "$EXPANDED/Patchwright.app" ]] || fail "archive did not preserve the app bundle"
+/usr/bin/codesign --verify --deep --strict "$EXPANDED/Patchwright.app"
+
+COMMIT="$(git -C "$FIXTURE_REPO" rev-parse HEAD)"
+jq -e \
+ --arg commit "$COMMIT" \
+ '.schema_version == 1 and
+ .kind == "patchwright.community-prerelease" and
+ .version == "0.2.0" and
+ .build == "3" and
+ .tag == "v0.2.0-community.1" and
+ .git_commit == $commit and
+ .signing == "ad-hoc" and
+ .notarized == false and
+ .minimum_macos == "26.0" and
+ .architecture == "arm64"' \
+ "$MANIFEST" >/dev/null || fail "manifest did not preserve the community release boundary"
+
+printf 'dirty\n' >"$FIXTURE_REPO/dirty.txt"
+if "$FIXTURE_REPO/script/package_community_release.sh" \
+ --app "$FIXTURE_APP" --output "$OUTPUT_DIR/dirty" \
+ --version 0.2.0 --build 3 --tag v0.2.0-community.1 \
+ >"$TMP_ROOT/dirty.out" 2>&1; then
+ fail "packager accepted a dirty release repository"
+fi
+grep -Fq 'community release worktree must be clean' "$TMP_ROOT/dirty.out" \
+ || fail "dirty-tree rejection was not explicit"
+
+git -C "$FIXTURE_REPO" add dirty.txt
+git -C "$FIXTURE_REPO" commit -qm newer
+if "$FIXTURE_REPO/script/package_community_release.sh" \
+ --app "$FIXTURE_APP" --output "$OUTPUT_DIR/tag-mismatch" \
+ --version 0.2.0 --build 3 --tag v0.2.0-community.1 \
+ >"$TMP_ROOT/tag-mismatch.out" 2>&1; then
+ fail "packager accepted a release tag that did not resolve to HEAD"
+fi
+grep -Fq 'community release tag must resolve to HEAD' "$TMP_ROOT/tag-mismatch.out" \
+ || fail "tag mismatch rejection was not explicit"
+
+echo "Patchwright community release contract passed"
diff --git a/Tests/PackagingTests/github_app_smoke_contract.sh b/Tests/PackagingTests/github_app_smoke_contract.sh
index 54d13cc..ee821a2 100755
--- a/Tests/PackagingTests/github_app_smoke_contract.sh
+++ b/Tests/PackagingTests/github_app_smoke_contract.sh
@@ -29,10 +29,15 @@ assert_blocked \
assert_blocked \
"the Patchwright production repository is forbidden" \
- PATCHWRIGHT_GITHUB_E2E_OWNER=S1KORRRR \
+ PATCHWRIGHT_GITHUB_E2E_OWNER=rsitech-ai \
+ PATCHWRIGHT_GITHUB_E2E_REPOSITORY=patchwright
+
+assert_blocked \
+ "the Patchwright production repository is forbidden" \
+ PATCHWRIGHT_GITHUB_E2E_OWNER=RSITECH-AI \
PATCHWRIGHT_GITHUB_E2E_REPOSITORY=Patchwright \
- PATCHWRIGHT_GITHUB_E2E_ALLOWLIST=S1KORRRR/Patchwright \
- PATCHWRIGHT_GITHUB_E2E_CONFIRM=authorize:S1KORRRR/Patchwright
+ PATCHWRIGHT_GITHUB_E2E_ALLOWLIST=RSITECH-AI/Patchwright \
+ PATCHWRIGHT_GITHUB_E2E_CONFIRM=authorize:RSITECH-AI/Patchwright
assert_blocked \
"PATCHWRIGHT_GITHUB_E2E_ALLOWLIST must exactly equal example/qualification" \
diff --git a/Tests/PackagingTests/promotion_contract.sh b/Tests/PackagingTests/promotion_contract.sh
index afb8893..bbd3c88 100755
--- a/Tests/PackagingTests/promotion_contract.sh
+++ b/Tests/PackagingTests/promotion_contract.sh
@@ -124,7 +124,7 @@ def appcast_content(archive_signature: str) -> str:
'- Patchwright 0.1.0'
'1'
'0.1.0'
- ''
'
\n'
diff --git a/Tests/PackagingTests/release_contract.sh b/Tests/PackagingTests/release_contract.sh
index c628a6d..37fb95e 100755
--- a/Tests/PackagingTests/release_contract.sh
+++ b/Tests/PackagingTests/release_contract.sh
@@ -51,27 +51,29 @@ require_text .github/workflows/ci.yml './script/smoke.sh'
require_text rust-toolchain.toml 'channel = "1.91.0"'
require_text README.md 'docs/direct-download.md'
require_text README.md 'CHANGELOG.md'
-require_text CHANGELOG.md '## [0.1.1] - 2026-07-18'
+require_text CHANGELOG.md '## [0.2.0] - 2026-07-20'
require_text docs/direct-download.md 'Developer ID Application'
require_text docs/direct-download.md 'Apple notarization'
require_text docs/direct-download.md 'GitHub Releases'
+require_text docs/direct-download.md 'community prerelease'
+require_text docs/direct-download.md 'not Developer ID signed or Apple notarized'
require_text docs/release-checklist.md 'notarized-candidate'
require_text docs/release-checklist.md 'promoted-release'
-[[ "$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' "$ROOT_DIR/Packaging/Info.plist")" == 0.1.1 ]] \
- || fail "default app version must be 0.1.1"
-[[ "$(/usr/libexec/PlistBuddy -c 'Print :CFBundleVersion' "$ROOT_DIR/Packaging/Info.plist")" == 2 ]] \
- || fail "default app build must be 2"
+[[ "$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' "$ROOT_DIR/Packaging/Info.plist")" == 0.2.0 ]] \
+ || fail "default app version must be 0.2.0"
+[[ "$(/usr/libexec/PlistBuddy -c 'Print :CFBundleVersion' "$ROOT_DIR/Packaging/Info.plist")" == 3 ]] \
+ || fail "default app build must be 3"
for manifest in \
crates/patchwright-core/Cargo.toml \
crates/patchwright-engine/Cargo.toml \
crates/patchwright-relay/Cargo.toml; do
- grep -Eq '^version = "0\.1\.1"$' "$ROOT_DIR/$manifest" \
- || fail "$manifest must use release version 0.1.1"
+ grep -Eq '^version = "0\.2\.0"$' "$ROOT_DIR/$manifest" \
+ || fail "$manifest must use release version 0.2.0"
done
-require_text script/package_release.sh 'VERSION="${PATCHWRIGHT_VERSION:-0.1.1}"'
-require_text script/package_release.sh 'BUILD="${PATCHWRIGHT_BUILD:-2}"'
-require_text script/build_release_components.sh 'VERSION="${PATCHWRIGHT_VERSION:-0.1.1}"'
-require_text script/build_release_components.sh 'BUILD="${PATCHWRIGHT_BUILD:-2}"'
+require_text script/package_release.sh 'VERSION="${PATCHWRIGHT_VERSION:-0.2.0}"'
+require_text script/package_release.sh 'BUILD="${PATCHWRIGHT_BUILD:-3}"'
+require_text script/build_release_components.sh 'VERSION="${PATCHWRIGHT_VERSION:-0.2.0}"'
+require_text script/build_release_components.sh 'BUILD="${PATCHWRIGHT_BUILD:-3}"'
if grep -En 'App Store|App Store Connect|Mac App Store' README.md docs/release-checklist.md docs/release-readiness.md docs/production-plan.md; then
fail "direct-distribution documentation must not claim an App Store release lane"
fi
@@ -143,7 +145,7 @@ BUNDLE_COPYRIGHT="$(/usr/libexec/PlistBuddy -c 'Print :NSHumanReadableCopyright'
|| fail "CFBundleIconFile must be Patchwright.icns"
SPARKLE_FEED="$(/usr/libexec/PlistBuddy -c 'Print :SUFeedURL' "$ROOT_DIR/Packaging/Info.plist" 2>/dev/null || true)"
-[[ "$SPARKLE_FEED" == 'https://github.com/s1korrrr/patchwright/releases/latest/download/appcast.xml' ]] \
+[[ "$SPARKLE_FEED" == 'https://github.com/rsitech-ai/patchwright/releases/latest/download/appcast.xml' ]] \
|| fail "Sparkle feed must target the latest GitHub release appcast"
for signed_feed_key in SUVerifyUpdateBeforeExtraction SURequireSignedFeed; do
@@ -160,7 +162,7 @@ KEY_BYTES="$(printf '%s' "$SPARKLE_PUBLIC_KEY" | /usr/bin/base64 -D 2>/dev/null
for target in \
'#build-and-verify' \
- 'https://github.com/s1korrrr/patchwright/releases' \
+ 'https://github.com/rsitech-ai/patchwright/releases' \
'LICENSE-MIT' \
'LICENSE-APACHE' \
'CONTRIBUTING.md' \
@@ -509,7 +511,7 @@ for packaging_text in \
'PATCHWRIGHT_SIGNING_KEYCHAIN' \
'security list-keychains -d user -s "$SIGNING_KEYCHAIN"' \
'restore_keychain_search_list' \
- '--download-url-prefix "https://github.com/s1korrrr/patchwright/releases/download/v$VERSION/"' \
+ '--download-url-prefix "https://github.com/rsitech-ai/patchwright/releases/download/v$VERSION/"' \
'sign_update' \
'--verify "$APPCAST_PATH"' \
'generate_candidate_evidence.py' \
diff --git a/Tests/PatchwrightCoreTests/UpdateConfigurationTests.swift b/Tests/PatchwrightCoreTests/UpdateConfigurationTests.swift
index aa76662..61370a3 100644
--- a/Tests/PatchwrightCoreTests/UpdateConfigurationTests.swift
+++ b/Tests/PatchwrightCoreTests/UpdateConfigurationTests.swift
@@ -2,7 +2,7 @@ import Foundation
import XCTest
final class UpdateConfigurationTests: XCTestCase {
- private let expectedFeedURL = "https://github.com/s1korrrr/patchwright/releases/latest/download/appcast.xml"
+ private let expectedFeedURL = "https://github.com/rsitech-ai/patchwright/releases/latest/download/appcast.xml"
private let expectedSparkleRevision = "6276ba2b404829d139c45ff98427cf90e2efc59b"
func testSparkleIsPinnedExactlyAndLinkedForAnAppBundle() throws {
diff --git a/crates/patchwright-core/Cargo.toml b/crates/patchwright-core/Cargo.toml
index 16c2df3..64cf94d 100644
--- a/crates/patchwright-core/Cargo.toml
+++ b/crates/patchwright-core/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "patchwright-core"
-version = "0.1.1"
+version = "0.2.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
@@ -19,4 +19,3 @@ unsafe_code = "warn"
[lints.clippy]
all = "warn"
pedantic = "warn"
-
diff --git a/crates/patchwright-engine/Cargo.toml b/crates/patchwright-engine/Cargo.toml
index 95f655b..815dc0a 100644
--- a/crates/patchwright-engine/Cargo.toml
+++ b/crates/patchwright-engine/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "patchwright-engine"
-version = "0.1.1"
+version = "0.2.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
diff --git a/crates/patchwright-relay/Cargo.toml b/crates/patchwright-relay/Cargo.toml
index bfbf505..f29965a 100644
--- a/crates/patchwright-relay/Cargo.toml
+++ b/crates/patchwright-relay/Cargo.toml
@@ -1,6 +1,6 @@
[package]
name = "patchwright-relay"
-version = "0.1.1"
+version = "0.2.0"
edition.workspace = true
rust-version.workspace = true
license.workspace = true
diff --git a/docs/RELEASING.md b/docs/RELEASING.md
index 4653447..70f525f 100644
--- a/docs/RELEASING.md
+++ b/docs/RELEASING.md
@@ -26,10 +26,40 @@ promotion, and public publication. A green source build is not a release.
7. Request approval for the exact push, pull request, merge, tag, GitHub Release,
repository settings, and profile actions. These are separate external
changes.
-8. After publication, follow the signed-out and settings verification in the
- [GitHub publication plan](github-publication-plan.md) and test installation
- using the public DMG and checksum, not local build output.
+8. After publication, inspect the repository signed out and verify the README,
+ licenses, security form, issue forms, pull-request template, release assets,
+ checksums, topics, description, branch rules, and Actions permissions. Test
+ installation using the public DMG and checksum, not local build output.
Do not publish an artifact assembled from a dirty tree, a different commit, or
evidence copied from another candidate. Do not bypass Gatekeeper, notarization,
the clean-machine gate, or independent promotion evidence.
+
+## Community prerelease path
+
+The community path is a separate, lower-trust lane for review and evaluation.
+It never replaces or relaxes the Developer ID path above.
+
+1. Merge the reviewed release change through a pull request and verify exact
+ local `main` equals `origin/main`.
+2. Create a versioned community tag on that exact commit.
+3. Run `./script/verify.sh`, `./script/smoke.sh`, and
+ `./script/build_and_run.sh --verify` from the clean tagged checkout.
+4. Package the staged app with:
+
+ ```sh
+ ./script/package_community_release.sh \
+ --app "$HOME/.patchwright/staged/Patchwright.app" \
+ --output "$PWD/dist/community" \
+ --version 0.2.0 \
+ --build 3 \
+ --tag v0.2.0-community.1
+ ```
+
+5. Verify the ZIP checksum and expanded app signature from a separate temporary
+ directory, then publish it only as a GitHub prerelease with the manifest and
+ an explicit not-notarized warning.
+
+Community artifacts must not include `appcast.xml`, use the GitHub `latest`
+release designation, or claim Gatekeeper, Developer ID, notarization,
+clean-machine, or promoted-release status.
diff --git a/docs/architecture.md b/docs/architecture.md
new file mode 100644
index 0000000..c0c98f0
--- /dev/null
+++ b/docs/architecture.md
@@ -0,0 +1,129 @@
+# Patchwright architecture
+
+Patchwright is a local-first engineering control plane for one macOS operator
+working across GitHub repositories. It turns local requests, issues, and pull
+requests into durable tasks, runs approved work in isolated worktrees, records
+verification evidence, and keeps every remote mutation behind an exact,
+short-lived approval.
+
+## System boundary
+
+Patchwright is composed of four cooperating modules:
+
+- `PatchwrightApp` is the native SwiftUI operator console.
+- `patchwright-core` owns typed state, policy, approvals, queue decisions, and
+ evidence contracts.
+- `patchwright-engine` owns SQLite persistence, repositories, worktrees,
+ command execution, Codex sessions, cancellation, and recovery.
+- `patchwright-relay` verifies GitHub webhooks and performs typed GitHub App
+ mutations after the engine presents a valid approval.
+
+The SwiftUI process does not perform GitHub writes. Codex does not receive
+GitHub App credentials or Patchwright approval tokens. Repository text, issue
+content, comments, and model output are untrusted context rather than authority.
+
+## Durable state and recovery
+
+SQLite stores tasks, append-only events, approval records, evidence metadata,
+webhook delivery identities, remote cursors, and safe lifecycle checkpoints.
+Credentials, raw repository content, prompts, command output, and diffs are not
+general telemetry.
+
+A task progresses through explicit states:
+
+`discovered → assessing → planned → awaitingPreparationApproval → preparing → implementing → verifying → reviewing → awaitingDeliveryApproval → delivering → monitoring → awaitingMergeApproval → merging → completed`
+
+Tasks may also be paused, blocked, failed, or cancelled with their evidence and
+worktree retained. Restart recovery resumes only from a durable checkpoint and
+never skips an approval state or blindly repeats an ambiguous remote write.
+
+## Repository execution
+
+Each mutating task receives an isolated Git worktree and branch. Commands are
+represented as an executable plus argument vector, working directory, timeout,
+and network policy; shell strings are not accepted at the engine boundary.
+Repository-controlled verification commands are not OS-sandboxed, so the app
+shows the exact commands and requires a separate confirmation immediately
+before running them.
+
+Instruction sources retain their path, content hash, scope, precedence, and
+enforcement status. Project and directory instructions may constrain a task but
+cannot grant new capabilities.
+
+## Codex integration
+
+Each active coding task owns a supervised Codex App Server process, thread, and
+turn identity. The engine performs protocol initialization, starts or resumes
+the recorded thread, streams typed events, surfaces runtime approvals, supports
+steering and interruption, and terminates the owned process group only after a
+graceful cancellation timeout.
+
+Protocol input has per-line and request-wide duration, event-count, and byte
+budgets. Responses and completion events must match the exact active request,
+thread, and turn. Credential-shaped event or approval content is redacted before
+durable storage. Codex authentication remains owned by Codex; Patchwright does
+not copy or persist its access tokens.
+
+## GitHub integration
+
+Read-only ingestion can use the GitHub CLI credential already present on the
+operator's Mac. Snapshots cover repositories, issues, pull requests, comments,
+reviews, review threads, checks, and Actions runs. Each repository refresh is
+atomic: a failed refresh preserves its previous complete snapshot. One global
+budget bounds nested pull-request fan-out.
+
+GitHub writes use a bring-your-own GitHub App. The private key is referenced
+through macOS Keychain or an owner-only file, and installation tokens remain in
+memory. Every mutation has:
+
+- a typed action preview;
+- repository, pull-request, branch, and relevant SHA identities;
+- a policy capability and short-lived approval;
+- a fresh precondition check;
+- an idempotency key and remote result identity;
+- an explicit retry or ambiguous-result reconciliation class.
+
+Drafting, readying, closing, reviewing, resolving threads, pushing, and merging
+must consume the exact approved identities supported by the corresponding
+GitHub operation. Merge never uses administrator bypass and always requires a
+separate merge-class approval.
+
+## Native interface
+
+The app uses native macOS navigation, tables, inspectors, menus, keyboard
+commands, settings, and approval sheets. The primary surfaces are Queue,
+Repositories, Active Tasks, Awaiting Approval, Monitoring, and Completed.
+
+Approval sheets show the exact target, capability, changed files, commit range,
+remote action, expiry, and invalidation conditions. There is no global
+"approve everything" action. Loading, empty, partial, cancelled, credential,
+blocked, expired-approval, and unknown-delivery states remain explicit.
+
+## Distribution lanes
+
+The official direct-download lane requires a clean tagged commit, Developer ID
+Application signing, Hardened Runtime, Apple notarization and stapling,
+Gatekeeper verification, digest-bound release evidence, independent promotion,
+and clean-machine validation. The signed Sparkle feed belongs only to this lane.
+
+A separate community-prerelease lane may package an exact-tag ad-hoc-signed app
+for source review and evaluation. Its manifest explicitly records
+`notarized: false`; it is never published through Sparkle or represented as an
+official trusted binary.
+
+## Readiness labels
+
+- `repo-ready`: source checks, tests, and builds pass.
+- `integration-ready`: real Codex and disposable GitHub App workflows pass.
+- `package-ready`: the intended packaging and signing path is validated.
+- `notarized candidate`: Developer ID, notarization, stapling, and Gatekeeper
+ verification pass for one frozen artifact.
+- `release-candidate ready`: the exact candidate passes clean-machine install,
+ update, integration, cancellation, and recovery checks.
+- `community prerelease`: a checksum-bound ad-hoc build is downloadable but is
+ not Developer ID signed or Apple notarized.
+- `blocked:external`: an owner credential, account action, or independent
+ distribution proof is still required.
+
+See [production operations](production-plan.md), [security operations](security.md),
+and [release procedures](RELEASING.md) for the maintained operating contracts.
diff --git a/docs/audits/2026-07-13-github-app-delivery-queue.md b/docs/audits/2026-07-13-github-app-delivery-queue.md
deleted file mode 100644
index 00fa6e7..0000000
--- a/docs/audits/2026-07-13-github-app-delivery-queue.md
+++ /dev/null
@@ -1,34 +0,0 @@
-# GitHub App delivery and queue audit
-
-Audit refreshed: 2026-07-14.
-
-## Result
-
-**Integration-ready.** The local implementation, mock/restart boundaries, production App identity, exact-repository installation-token ingestion, and authorized disposable-repository delivery/merge lifecycle all pass.
-
-## Verified locally
-
-- GitHub ingestion discovers repositories, issues, pull requests, discussions, checks, and workflow runs through the authenticated `gh` read-only development fallback. Synchronization is a durable single-flight job with cancellation during discovery and fan-out; completed repository snapshots survive cancellation. Installed repositories can also be synchronized exactly through a repository-scoped GitHub App installation token with read-only permissions and no account-wide discovery.
-- Issue and pull-request snapshots convert idempotently into typed task contracts bound to repository identity and exact source SHAs.
-- The relay mints scoped, cached, short-lived installation tokens from an RSA GitHub App key stored in Keychain or a protected file. Secret material is redacted and tokens are never persisted.
-- Branch, comment, review, check, draft-PR, update, enqueue, and exact-SHA merge payloads have typed previews and stable idempotency identities.
-- Delivery and merge require preview, a separate matching approval, a fresh precondition check, a single-use claim, and explicit execution. Merge uses its own approval class.
-- Twelve deterministic workflow presets persist their ordering, reasons, dependencies, overlap findings, and input hashes.
-- Durable monitoring covers pending/success/failure, requested changes, dismissed approval, new head/base SHA, conflicts, inaccessible forks, rate limits, network loss, bounded exponential backoff with jitter, repair-budget exhaustion, webhook wakeup, cancellation, restart, and approval invalidation.
-- The native queue and detail pane were exercised in the running release build. Sorting includes latest commit and latest update. The workflow menu exposed all twelve presets, and CI Rescue was applied successfully.
-
-## Live production-App qualification
-
-- `Patchwright s1korrrr` is installed only on the private disposable repository `s1korrrr/patchwright-e2e-sandbox`. The production `s1korrrr/patchwright` repository remained outside the installation and was rejected by the qualification guard.
-- `~/.patchwright/github-app.json` has owner-only mode `600`, references App ID `4294269`, and resolves to an owner-only protected private-key file. `patchwright-relay github-app-health` authenticated to GitHub and returned the expected `patchwright-s1korrrr` identity without printing key or JWT material.
-- `script/smoke_github_app.sh` rejects the production repository, requires an exact disposable-repository allowlist and one-shot confirmation, validates metadata plus Keychain or protected-file boundaries, authenticates the configured App identity, verifies repository identity through the installation token, and runs the local suites before mutation. It supports either an authenticated `gh` fixture or a narrowly manual UI fixture when the developer credential is unavailable; all Patchwright ingestion and mutation steps still use the App token.
-- Issue [#3](https://github.com/s1korrrr/patchwright-e2e-sandbox/issues/3) was ingested through the read-only installation token and converted to typed task `13a09acc-115e-42e7-bf05-e3d9f41e675a`.
-- Patchwright created branch `patchwright/e2e-20260714T104059Z`, a successful check run, an App-authored comment, and draft PR [#4](https://github.com/s1korrrr/patchwright-e2e-sandbox/pull/4) through distinct preview, approval, and execute calls.
-- PR #4 was re-ingested and converted to typed task `2d501038-9741-4ae5-ac16-3b13fe485bcc`. Patchwright posted an App-authored review and performed a separately approved squash merge bound to head `8205a0cc63801525c2202d8101b2136a2d057ffe`; GitHub produced merge commit `e0c4157ea9d616053d6c3cd26f2ce2b2f8d8b231`.
-- App-token reconciliation observed the comment, review, check, and closed PR. The durable database and engine log scan found no private key or installation token. The owner-only evidence is `/Users/s1kor/.patchwright/evidence/github-app-e2e-20260714T104059Z.json` (directory `700`, file `600`).
-- Delivery preview now rejects any GitHub action whose capability is absent from the typed task contract. Issue and pull-request conversion declare their lifecycle capabilities explicitly.
-- Delivery action JSON now uses the Swift-facing camelCase field contract while continuing to decode legacy snake_case records.
-
-## Remaining boundary
-
-Account-wide discovery remains an explicitly labeled local-development `gh` fallback because GitHub App installations are repository-scoped rather than user-account enumerators. Production installed-repository ingestion and all writes use the App broker. Developer ID signing, notarization, Gatekeeper, and clean-machine distribution remain independent Apple-controlled release gates.
diff --git a/docs/audits/2026-07-13-github-ingestion-e2e.md b/docs/audits/2026-07-13-github-ingestion-e2e.md
deleted file mode 100644
index f9c72db..0000000
--- a/docs/audits/2026-07-13-github-ingestion-e2e.md
+++ /dev/null
@@ -1,119 +0,0 @@
-# Patchwright GitHub Ingestion and SwiftUI Audit
-
-## Scope
-
-- Date: 2026-07-13
-- Platform: macOS 26, Apple silicon
-- App entry point: SwiftPM executable `Patchwright`
-- Runtime: signed Release app in `~/.patchwright/staged`, exposed at `dist/Patchwright.app`, with bundled Rust engine
-- Primary workflow: authenticated GitHub CLI account → read-only API ingestion → atomic SQLite snapshot → repository/issue/PR navigation in SwiftUI
-- Readiness target: repo-ready read-only GitHub workspace ingestion
-
-This was a targeted implementation and audit of the new GitHub ingestion diff. It was not an exhaustive Codex Security scan: the required scan workspace and delegated scan-worker capabilities were unavailable in this task.
-
-## Commands and evidence
-
-| Check | Command or tool | Result | Evidence |
-| --- | --- | --- | --- |
-| Account | `gh auth status` and authenticated REST calls | verified | Active account `s1korrrr`; token never printed by Patchwright |
-| Full account ingestion | `github.sync` with repository limit 100 and resource limit 1,000 | verified | 51/51 repositories in 40 seconds, zero failures |
-| Persistence parity | Decode every row in disposable and normal SQLite stores | verified | API summary and persisted totals matched exactly |
-| Rust formatting/lint/tests | `./script/verify.sh` | verified | fmt, Clippy `-D warnings`, workspace tests and doc tests passed |
-| Swift tests/build | `./script/verify.sh` | verified | 4 tests passed; Release build passed with warnings as errors |
-| Engine smoke | `./script/smoke.sh` | verified | Unix-socket health response and non-empty SQLite store |
-| Packaged launch | `./script/build_and_run.sh --verify` | verified | Two consecutive rebuild/launch cycles passed strict deep signature checks; app and exact bundled helper both running; zero new crash reports |
-| UI smoke | Computer Use accessibility tree | verified | Account repositories, repository snapshot, PR selection, detail, search and sync exercised |
-| Runtime logs | macOS unified log after controlled non-automation workflow | verified | No crash, layout recursion, geometry fault, or app error entries; Computer Use-only geometry faults are recorded below |
-| Local permissions | `stat` on `~/.patchwright` and database | verified | directory `0700`, SQLite `0600` |
-| Secret scan | repository pattern scan | verified | no credential or private-key material found |
-
-## Full-ingestion result
-
-| Record type | API summary | Persisted |
-| --- | ---: | ---: |
-| Repositories | 51 | 51 |
-| Issues and pull requests | 344 | 344 |
-| Discussion comments and reviews | 521 | 521 |
-| Check runs | 1,092 | 1,092 |
-| Workflow runs | 1,298 | 1,298 |
-
-The normal app database at `~/.patchwright/patchwright.sqlite3` contains the same 51-repository workspace. Repository snapshots are replaced only after a complete repository fetch; a failed refresh retains the prior complete snapshot.
-
-## Feature matrix
-
-| Workflow or state | Status | Notes |
-| --- | --- | --- |
-| Use existing GitHub CLI login | verified | Credential is requested at sync time and retained only in engine memory |
-| Discover all currently accessible repositories | verified | 51 found; default raised from 25 to 100 |
-| Paginate repository resources | verified | Standard arrays plus check-run and workflow-run wrapper pages |
-| Separate issues from PRs | verified | GitHub issue endpoints include PRs; `pull_request` entries are filtered before explicit PR ingestion |
-| Ingest issue/PR metadata | verified | Body, author, state, draft, head SHA, labels, assignees and milestone |
-| Ingest discussion and review data | verified | Issue comments, review comments and submitted reviews |
-| Ingest CI state | verified | PR-head check runs and Actions workflow runs |
-| Restart and reload | verified | SQLite restart test and real app relaunch both retained data |
-| Search issues and PRs | verified | Non-match removed the PR; matching text restored it |
-| Open PR detail | verified | Title, body, GitHub link, discussion state and checks state visible |
-| Partial repository failure | verified by integration contract | Failure is reported; previous snapshot is not overwritten |
-| Unauthenticated GitHub CLI | verified by error path | Sync returns a typed authentication error; existing snapshots remain readable |
-| GitHub mutations | not applicable | This ingestion surface is intentionally read-only |
-
-## Interaction sweep
-
-| Surface | Action | Result | Status |
-| --- | --- | --- | --- |
-| Toolbar | Sync GitHub | Honest busy state; repositories persisted incrementally; control disabled during sync | verified |
-| Sidebar | Select `s1korrrr/patchwright` | Repository counts and work-item list appeared | verified |
-| Work-item list | Select PR #1 | Full detail appeared without accessibility bridge failure | verified |
-| Search | Enter impossible query | Work-item result disappeared | verified |
-| Search | Enter `Build Patchwright` | PR result returned | verified |
-| Repository link | Hover/accessibility description | Described as opening the repository on GitHub | verified |
-| Comment link | Hover description | Described as opening the comment on GitHub | verified by code and build |
-| Inspector toolbar item | Help text | Describes evidence and ingestion details | verified by accessibility tree/build |
-| New Task | Existing local-repository sheet | Outside the ingestion diff; covered by prior Stage 1–3 MVP checks | not re-audited |
-
-## Issues found and fixed
-
-| Severity | Area | Finding | Fix and proof |
-| --- | --- | --- | --- |
-| High | Credential boundary | An untrusted pagination `Link` could redirect the bearer token to another origin | Pagination now accepts only the configured API origin; dedicated cross-origin token test passes |
-| High | RPC framing | Swift assumed a complete JSON response arrived in one socket receive, breaking large snapshots | Added bounded 64 MiB newline framing with repeated 64 KiB receives; fragmented-response test passes |
-| Medium | Filesystem safety | A stale-socket cleanup could remove a non-socket file at a caller-provided path | Engine now rejects non-socket paths; preservation regression test passes |
-| Medium | Data completeness | Labels, assignees and milestones were discarded | Added backward-compatible Rust/Swift fields, fixture assertions and native detail rendering |
-| Informational | UI automation | Computer Use clicks emitted paired AppKit negative-geometry faults | The same Release app auto-selected the large repository without Computer Use and emitted zero geometry faults; the evidence identifies this as an automation-bridge artifact, not an ordinary runtime defect |
-| Medium | Packaging smoke | The build script could leave its bundled helper alive and report a Launch Services false negative | Script terminates only the exact bundle-owned helper, waits, and verifies both processes |
-| Blocker | Code signing | Copying helpers and rewriting `Info.plist` invalidated the linker signature; a bundle staged inside the Documents workspace could also regain File Provider/Finder metadata immediately after cleanup, and macOS killed some launches with `Taskgated Invalid Signature` | Stage and sign in the user-only `~/.patchwright` directory, expose a stable `dist/Patchwright.app` symlink, and run strict verification before and after launch; two rebuild/launch cycles and zero new crash reports prove the fix |
-| Medium | Availability | GitHub requests had no explicit deadline | Added 10-second connect and 30-second request timeouts |
-| Medium | Sync latency | Per-PR review/check requests created a several-minute sequential tail that outlived the native RPC connection | Added bounded eight-way per-PR fetching; full 51-repository replay fell to 40 seconds |
-| Polish | Toolbar clarity | Icon-only actions lacked explicit hover descriptions | Added outcome-oriented help for create, inspector and sync actions |
-
-## Security boundary review
-
-- `gh auth token` is obtained through an argv-safe `Command`, redacted from `Debug`, never serialized, and never stored in SQLite.
-- Pagination is same-origin and bounded. Repository fan-out is capped at 100, per-resource ingestion at 1,000, and repository concurrency at four.
-- GitHub text is decoded as data and rendered as SwiftUI `Text`; it is not treated as policy or executable markup.
-- Snapshot writes use parameterized SQLite queries and transactionally replace one complete repository snapshot at a time.
-- The app-owned state directory is `0700`; the database is forced to `0600` on open.
-- The local RPC socket has no separate application-layer authentication. Its current control is the user-only parent directory; it must not be exposed or moved to a shared directory.
-- No GitHub write operation is reachable from this ingestion UI. Merge remains disabled by policy.
-
-## Visual and performance review
-
-- Native `NavigationSplitView`, sidebar, toolbar, searchable work-item column and semantic system icons are used.
-- Repository and work-item panes have adjustable min/ideal/max widths; the detail remains readable at the staged default size.
-- The busy overlay reports the number of locally available repositories and disables duplicate sync requests.
-- Four-repository engine concurrency keeps the 51-repository sync bounded without unbounded request fan-out.
-- The selected repository refreshes after sync, so visible detail does not silently remain stale.
-- No custom animation or global implicit animation was introduced; Reduce Motion behavior is therefore native.
-
-## Remaining risks and boundaries
-
-- A long sync is not yet cancellable from the UI. The engine remains fail-safe and snapshots are committed per completed repository, but a user must wait or stop the local engine.
-- The read-only CLI credential bridge is suitable for the local operator workflow. GitHub App installation-token brokering is still required before write-capable Stage 3 automation.
-- The staged app is ad-hoc signed and not notarized. Packaging, signing and clean-machine validation remain separate release gates.
-- The ingestion cap is deliberately 1,000 records per resource per repository. Repositories exceeding that cap report a bounded snapshot rather than attempting unbounded local ingestion.
-
-## Final readiness label
-
-- Label: **repo-ready for read-only GitHub ingestion**
-- Not claimed: package-ready, notarized release-candidate, or write-capable GitHub lifecycle
-- Next product slice: turn a selected ingested issue or PR into a typed Patchwright task while preserving the existing approval and no-merge boundaries
diff --git a/docs/audits/2026-07-13-orchestrator-foundation.md b/docs/audits/2026-07-13-orchestrator-foundation.md
deleted file mode 100644
index ffd725a..0000000
--- a/docs/audits/2026-07-13-orchestrator-foundation.md
+++ /dev/null
@@ -1,64 +0,0 @@
-# Orchestrator foundation audit — 2026-07-13
-
-## Readiness
-
-**Label: repo-ready orchestrator foundation.** The durable task model, persisted GitHub snapshot, issue/PR conversion boundary, deterministic sorting/filtering, and native macOS workbench are implemented and locally verified.
-
-This gate does **not** claim embedded Codex readiness, approval-bound GitHub write or merge readiness, production GitHub App readiness, or signed/notarized distribution readiness. Those remain separate plans and gates.
-
-## Verified scope
-
-| Surface | Evidence | Result |
-| --- | --- | --- |
-| Engine and staged app | `./script/build_and_run.sh --verify`; staged `Patchwright.app` and bundled engine remained running over the Unix socket | Pass |
-| Persisted ingestion | Relaunched app restored 51 repositories and 26 open pull requests from `~/.patchwright/patchwright.sqlite3` | Pass |
-| Pull request ordering | Applied Recently Updated; `s1korrrr/patchwright#1` moved ahead of older PRs after the table refresh | Pass |
-| Repository ordering | Applied Recently Updated; `s1korrrr/patchwright` and `s1korrrr/clip_vault` moved to the top | Pass |
-| Search | Searching `patchwright` reduced the PR table to `s1korrrr/patchwright#1` | Pass |
-| PR inspection | Rendered title, author, exact/relative time, long Markdown body, discussion, and checks from the local snapshot | Pass |
-| Conversion boundary | Previewing `s1korrrr/patchwright#1` failed closed with `Install the Patchwright GitHub App for this repository before creating tasks.` | Pass, expected external blocker |
-| Inspector | Opened repository snapshot, ingested-record, and credential-handling evidence | Pass |
-| Empty navigation | Issues shows an explicit empty state and clears the prior PR detail rather than presenting stale selection | Pass |
-| Window behavior | AppKit zoom/resize retained the three-column workbench without losing navigation or table content | Pass |
-| Appearance and motion | Current Dark appearance inspected; Light appearance and Reduce Motion were not changed during this run | Manual follow-up |
-
-The current local snapshot contains no open issues, so the Issues table correctly presents `No Issues — Sync GitHub to ingest open issues.` The engine and Swift store paths for issue ingestion and typed conversion are covered by fixtures; a production GitHub App installation is still required before converting a live repository item into a locally bound task.
-
-## Defects found and retained fixes
-
-1. Nested SwiftUI `GroupBox` detail cards caused accessibility inspection to terminate when a table selection revealed a long PR. Minimization proved the outer split view, scroll view, header, and long body were healthy. Replacing the cards with bounded vertical detail cards retained all content and made the full detail tree inspectable.
-2. Changing to an empty workspace section left the previously selected PR in the detail column. A store regression test now requires section changes to clear incompatible task, repository, work-item, preview, and error selection.
-3. Computer Use row selection emits AppKit `Invalid view geometry` diagnostics even when the selected detail is reduced to a single `Text`. It does not crash or hang the app, and full accessibility inspection succeeds after the detail-card fix. Classification remains a Computer Use/native-Table interaction artifact pending a human click comparison; it is not counted as clean runtime-log proof.
-
-No correct unit-test seam exists for the SwiftUI/AppKit geometry diagnostic itself. The original staged-app interaction is therefore the regression loop; store navigation behavior is locked down with a focused unit test.
-
-## Automated evidence
-
-Commands run during this gate:
-
-```text
-cargo fmt --all -- --check
-cargo clippy --workspace --all-targets -- -D warnings
-cargo test --workspace
-swift test
-swift build -c release -Xswiftc -warnings-as-errors
-./script/build_and_run.sh --verify
-/usr/bin/codesign --verify --deep --strict ~/.patchwright/staged/Patchwright.app
-```
-
-The final verification script completed with 47 Rust tests and 23 Swift tests, plus the focused sorting, conversion, presentation, and RPC suites.
-
-The local database is `0600` (`-rw-------`). No live GitHub mutation, review, check, PR delivery, or merge was attempted in this foundation gate.
-
-## Rollback and open gates
-
-The retained rollback point before this workbench slice is commit `b500285` (`Convert GitHub work items into durable tasks`). The workbench commit can be reverted independently without deleting the SQLite snapshot.
-
-Open gates:
-
-- Production GitHub App registration, installation-token brokering, and repository installation.
-- Embedded, supervised Codex thread lifecycle and restart recovery.
-- Approval-bound branch, comment, review, check, draft-PR, and exact-SHA merge operations.
-- Long-running sync cancellation.
-- Developer ID identity, notarization credentials, clean-machine validation, and distribution packaging.
-- Manual Light appearance and Reduce Motion interaction pass.
diff --git a/docs/audits/2026-07-13-patchwright-final-e2e.md b/docs/audits/2026-07-13-patchwright-final-e2e.md
deleted file mode 100644
index c133450..0000000
--- a/docs/audits/2026-07-13-patchwright-final-e2e.md
+++ /dev/null
@@ -1,35 +0,0 @@
-# Patchwright final end-to-end audit
-
-Audit refreshed: 2026-07-14 on the current `feat/andrzej_agent_sota_lab` source.
-
-## Gate summary
-
-| Gate | State | Current evidence |
-| --- | --- | --- |
-| Repo | **repo-ready** | `./script/verify.sh` passed, including full Rust workspace, Swift tests, migration/restart/cancellation suites, release contract, Clippy warnings-as-errors, and Swift release warnings-as-errors. |
-| Local smoke | **ready** | `./script/smoke.sh` passed. |
-| Codex | **integration-ready** | `./script/smoke_codex.sh` passed against signed-in `codex-cli 0.144.2`; the latest disposable lifecycle persisted 40 events with zero outstanding approvals. |
-| Native UI | **runtime-verified** | Release build launched. Queue selection, structured right panel, twelve workflow presets, CI Rescue selection, and GitHub App Settings were exercised through accessibility. |
-| GitHub App authentication | **integration-ready** | Production App ID `4294269` (`patchwright-s1korrrr`) has the audited permissions, owner-only metadata and protected-key files, and passed a live authenticated `/app` identity check. |
-| GitHub delivery/merge | **integration-ready** | Private sandbox issue [#3](https://github.com/s1korrrr/patchwright-e2e-sandbox/issues/3) completed App-token ingestion and typed conversion; Patchwright then created, checked, commented on, reviewed, and separately approval-gated the exact-SHA squash merge of PR [#4](https://github.com/s1korrrr/patchwright-e2e-sandbox/pull/4). Owner-only evidence: `/Users/s1kor/.patchwright/evidence/github-app-e2e-20260714T104059Z.json`. |
-| Bundle | **bundle-valid** | Implementation commit `c09bb1a` assembled `/Users/s1kor/.patchwright/release-work/Patchwright-0.1.0-1.rpqG08/Patchwright.app`, which passed structural validation. |
-| Developer ID / Hardened Runtime | **blocked:external** | No `Developer ID Application` identity is installed; the local bundle is not a distribution signature. |
-| Notarization / Gatekeeper | **blocked:external** | No Keychain notary profile or accepted/stapled DMG exists. |
-| Clean machine | **blocked:external** | A final notarized DMG has not been installed, updated, and recovered on the documented clean macOS 26 environment. |
-| Final release | **not release-candidate ready** | Current readiness JSON records repo, Codex, GitHub delivery/merge, and bundle gates as true while keeping every Apple distribution gate false: `/Users/s1kor/.patchwright/release-work/Patchwright-0.1.0-1.rpqG08/evidence/readiness.json`. |
-
-## Product behavior now present
-
-- GitHub repository, issue, pull-request, discussion, check, and workflow ingestion with sorting, filters, durable cancellation, and partial-snapshot safety.
-- Full typed task contracts from ingested issues and pull requests.
-- Embedded Codex app-server threads with streaming events, steering, exact runtime approvals, interruption, cancellation, process-group cleanup, and restart recovery.
-- Approval-bound GitHub action previews and execution, with an installation-token broker and exact-SHA merge boundary.
-- Explainable PR ordering across Quick Wins, CI Rescue, Review Closure, Conflict Recovery, Dependency Chain, Security First, Release Train, Stale PR Triage, Draft Completion, Post-Merge Watch, Review Load Balancing, and Duplicate/Overlap Detection.
-- Durable remote monitoring with bounded repair iterations and fail-closed lane blocking.
-- Reproducible direct-distribution assembly, signing/notary drivers, bundle and distribution verification, readiness reporting, and a clean-machine probe contract.
-
-## Remaining owner-controlled actions
-
-The GitHub App is installed only on the disposable private sandbox, and the full authorized delivery/merge gate is complete. The production `s1korrrr/patchwright` repository remains explicitly forbidden by the remote smoke gate.
-
-Developer ID completion requires the owner to obtain/install the certificate, create a `notarytool` Keychain profile, and provide a clean macOS 26 machine or VM. The repository scripts can then perform signing, notarization, stapling, Gatekeeper verification, DMG verification, and the clean-machine probe without receiving raw Apple credentials.
diff --git a/docs/audits/2026-07-14-embedded-codex.md b/docs/audits/2026-07-14-embedded-codex.md
deleted file mode 100644
index 4dbde32..0000000
--- a/docs/audits/2026-07-14-embedded-codex.md
+++ /dev/null
@@ -1,67 +0,0 @@
-# Embedded Codex End-to-End Audit
-
-Date: 2026-07-14
-
-Branch: `feat/andrzej_agent_sota_lab`
-
-Readiness: `integration-ready: Codex`
-
-## Decision
-
-The embedded Codex boundary is integration-ready on this Mac with `codex-cli 0.144.2` and the current signed-in ChatGPT account. Patchwright can supervise a task-owned app-server process, persist and resume its thread, stream durable events, bind one-time runtime approvals, pause or cancel safely, and recover after reopening SQLite.
-
-This is not a release-candidate or distribution-readiness claim. Production GitHub App installation access and Developer ID signing/notarization remain separate owner-controlled gates.
-
-## Real disposable smoke
-
-`./script/smoke_codex.sh` verifies the generated 0.144.2 app-server schema and signed-in account, runs the complete fake-server boundary suite, then invokes an ignored real integration test. The real test:
-
-- creates a temporary Git repository outside Patchwright's worktree;
-- starts a task-owned Codex app-server with the temporary repository as its working directory;
-- starts a new thread and asks for exactly one deterministic `result.txt` file;
-- polls and resolves only exact pending Codex runtime approvals, if Codex requests them;
-- waits for a persisted terminal turn event and verifies the exact file contents;
-- pauses the task, closes the service and database, reopens SQLite, and resumes the same thread under a new process generation;
-- cancels the resumed task and verifies the durable terminal task state.
-
-The final run reported `codex-cli 0.144.2`, zero requested runtime approvals, and 69 persisted events. The test prints only the pinned version and aggregate approval/event counts. Thread, turn, process-generation, task, and approval identifiers remain ephemeral and are not committed.
-
-## Live protocol findings retained
-
-The first real runs exposed three differences that the sanitized fixtures did not exercise:
-
-1. Codex 0.144 incoming notifications may omit the JSON-RPC `jsonrpc` member. The decoder now accepts an omitted member while still rejecting any present value other than `2.0`.
-2. Status notifications may arrive while a handshake request is awaiting its response. Session request handling now tolerates bounded interleaved events and continues waiting for the matching response, while still refusing server approval requests in handshake-only paths.
-3. A terminated app-server descendant can retain the inherited stderr pipe. Process-group termination now performs a final group kill sweep before awaiting stderr capture, with focused repeated process isolation coverage.
-
-Each behavior has a deterministic regression test in addition to the real smoke.
-
-## Inspector interface review
-
-| Before | After | Reason |
-| --- | --- | --- |
-| Repository and work-item links both looked generic | Repository context and work-item `Open on GitHub` actions are distinct | Makes the navigation target unambiguous |
-| Pull-request body appeared as raw Markdown and GitHub HTML | Native heading, list, paragraph, and code-block presentation with GitHub HTML normalization | Restores readable hierarchy and removes raw tags |
-| PR state and metadata formed one dense line | State/draft pills, author/time, branches, diff metrics, review, and CI are grouped | Supports rapid queue inspection |
-| Disabled preview remained visually prominent without an installation | Preview is absent until available; an explicit GitHub App requirement card explains the blocker | Avoids a false affordance and names the actual gate |
-| Discussion and checks were heavy nested cards | Lightweight native sections with counts and rendered comment bodies | Improves scanning in the narrow inspector |
-
-The staged app was relaunched and inspected through macOS accessibility at the supplied three-column window size. The Patchwright PR showed the new hierarchy without raw Markdown headings. A Dependabot PR containing `` markup rendered without raw HTML, and discussion Markdown used the same native renderer. The missing-installation state showed no `Preview Task` action and retained the `Manage GitHub Apps` recovery path.
-
-## Verification matrix
-
-| Gate | Command | Result |
-| --- | --- | --- |
-| Protocol schema | `./script/verify_codex_schema.sh` | Generated schema and required methods/fields match `codex-cli 0.144.2` |
-| Full static/test/build gate | `./script/verify.sh` | Rust fmt/Clippy/workspace tests, focused Codex tests, Swift tests, and macOS build passed |
-| Fake + real Codex lifecycle | `./script/smoke_codex.sh` | Disposable real turn, persistence, restart/resume, and cancellation passed |
-| Engine smoke | `./script/smoke.sh` | Unix-socket engine smoke passed |
-| Staged runtime | `./script/build_and_run.sh --verify` | Staged app launched with its engine and passed the verification probe |
-| Secret scan | repository credential-pattern scan | No committed production credential found; fixture-shaped test strings are synthetic |
-| Runtime log scan | unified log error/fault/panic/crash filter | No Patchwright crash or panic found during the final staged interaction |
-
-## Remaining external gates
-
-- The selected repositories do not yet expose a production Patchwright GitHub App installation to the app, so repository-bound task creation and approval-gated GitHub delivery remain `blocked: external installation`.
-- Developer ID identity, notarization credentials, clean-machine installation proof, and final distribution packaging remain `blocked: external Apple credentials and release operation`.
-- Approval-gated merge remains intentionally disabled until its dedicated policy and production-installation gates are completed.
diff --git a/docs/audits/2026-07-14-live-lifecycle-closure.md b/docs/audits/2026-07-14-live-lifecycle-closure.md
deleted file mode 100644
index 4c60610..0000000
--- a/docs/audits/2026-07-14-live-lifecycle-closure.md
+++ /dev/null
@@ -1,85 +0,0 @@
-# Patchwright live lifecycle closure audit
-
-Audit date: 2026-07-14
-
-Branch: `feat/andrzej_agent_sota_lab`
-
-## Outcome
-
-**Readiness: integration-ready for approval-gated GitHub issue and pull-request work on an installed repository.** The native app, durable Rust orchestrator, production GitHub App token broker, embedded Codex app-server, exact delivery previews, and exact-SHA merge boundary completed a live private-sandbox workflow. The staged app is bundle-valid and usable for local testing. Developer ID signing, notarization, Gatekeeper distribution acceptance, and clean-machine installation remain independent external Apple gates.
-
-Patchwright PR #1 was read-only throughout this audit and remains open.
-
-## Scope and authority boundary
-
-- App: `/Users/s1kor/.patchwright/staged/Patchwright.app`
-- Bundle ID: `ai.patchwright.app`
-- Workspace: `/Users/s1kor/dev/apps/patchwright`
-- Live mutation target: private repository `s1korrrr/patchwright-e2e-sandbox` only
-- Production GitHub App: `patchwright-s1korrrr`, App ID `4294269`
-- Forbidden during the audit: mutation or merge of `s1korrrr/patchwright#1`, admin bypass, default-branch push, force-push, secret logging, and unrelated repository mutation
-
-## Live end-to-end evidence
-
-| Surface | Result | Evidence |
-| --- | --- | --- |
-| Issue ingestion | Verified | Sandbox issue [#3](https://github.com/s1korrrr/patchwright-e2e-sandbox/issues/3) was ingested with the installation token and converted to typed task `44bc6755-9412-4d58-89a8-6aa7189ea092`. |
-| Isolated worktree | Verified | `/Users/s1kor/.patchwright/repositories/1300326259/worktrees/44bc6755-9412-4d58-89a8-6aa7189ea092`, branch `patchwright/44bc6755-9412-4d58-89a8-6aa7189ea092`. |
-| Exact branch push | Verified | Commit `078ee96c9c5c53b962188b9554136ef3bcc65537` was previewed, approved, pushed through the ephemeral App-token Git transport, and read back from GitHub. |
-| Draft PR | Verified | Patchwright created draft PR [#5](https://github.com/s1korrrr/patchwright-e2e-sandbox/pull/5); the observed head remained unchanged through ready-for-review. GitHub does not expose an atomic SHA condition for either operation, so current approvals bind these actions to branch and PR identity instead of claiming commit atomicity. |
-| PR ingestion | Verified | PR #5 was re-ingested and converted to typed task `593a577a-7cd8-4b1f-8d0f-1b3dfcdb2f43`, capturing base `e0c4157ea9d616053d6c3cd26f2ce2b2f8d8b231` and head `078ee96c9c5c53b962188b9554136ef3bcc65537`. |
-| Embedded Codex | Verified | The signed-in `codex-cli 0.144.2` reviewed the exact worktree without network or file mutation. SQLite persisted 430 ordered events and a terminal turn. The native Codex tab renders the prompt, command evidence, state, and signed-in status. |
-| Review delivery | Verified | The GitHub App posted review `PRR_kwDOTYFnc88AAAABGAr3ag` against exact commit `078ee96c9c5c53b962188b9554136ef3bcc65537`. |
-| Review-thread resolution | Verified | Sandbox PR [#6](https://github.com/s1korrrr/patchwright-e2e-sandbox/pull/6) ingested opaque thread `PRRT_kwDOTYFnc86Q50_7`; approval `976057bb61b5…` resolved only that repository/PR/thread identity, and the next App-token snapshot reported `threadResolved: true`. The unrelated thread remained unresolved. |
-| Exact-SHA merge | Verified | A separate Merge-class approval produced merge commit [`0dd94eecab8f72ae258fda4e971b71e53c324591`](https://github.com/s1korrrr/patchwright-e2e-sandbox/commit/0dd94eecab8f72ae258fda4e971b71e53c324591). PR #5 is `MERGED`, issue #3 is `CLOSED`, and sandbox `main` points to that commit. |
-| Historical task recovery | Verified | Read-only `task.reconcileGitHub` refreshed exact issue #3 and PR #5 through installation tokens, required the PR's captured head SHA and merged state, and atomically moved tasks `44bc6755…` and `593a577a…` to Completed. No direct SQLite repair was used. |
-| Sync cancellation | Verified | Durable job `afcd09b9-aed5-4ee5-8ad4-dfd8ed4dce04` ended `cancelled` with cancellation `acknowledged` and summary `GitHub sync cancelled after 15 repositories`. |
-| Patchwright PR safety | Verified | `s1korrrr/patchwright#1` remained `OPEN` on `feat/andrzej_agent_sota_lab`; no merge was attempted. |
-
-## Product behavior retained
-
-- Ingested issues and pull requests become immutable typed task contracts bound to repository installation, source URL, source SHAs, instruction digests, acceptance criteria, and declared capabilities.
-- Preparation creates a task-owned worktree at the captured source SHA. Git push uses an ephemeral installation-token credential helper and pushes only the inspected task branch head.
-- Embedded Codex has visible thread state, streamed durable events, steering, one-time runtime approvals, cancellation, process-group cleanup, and restart recovery.
-- GitHub writes cover branch creation/push, comments, reviews, review-thread resolution, checks, draft PRs, update branch, ready-for-review, issue/PR closure, merge-queue handoff, and exact-SHA merge. Every write requires a fresh typed preview, matching approval, supported precondition validation, and idempotency claim. Reviews, update-branch, branch creation, and merge carry the commit condition in the mutation GitHub processes. Draft creation, ready-for-review, closure, comments, and thread resolution bind to repository/branch/PR/thread identity because GitHub exposes no atomic SHA condition for those endpoints. Thread resolution uses installation identity first, then a non-persisted signed-in user token only when GitHub reports that the App viewer cannot resolve the author-owned thread.
-- Successful merge persistence and task lifecycle completion now occur in one local transaction. The task advances through delivery, monitoring, merge, and completion while recording visible timeline events.
-- A definitive failed delivery can be retried with a fresh approval. Ambiguous and successful outcomes remain claimed. Legacy non-JSON delivery results remain safely non-retryable instead of breaking database recovery.
-- Queue controls include Latest Commit and Updated sorting plus explainable workflow presets for Quick Wins, CI Rescue, Review Closure, Conflict Recovery, Dependency Chain, Security First, Release Train, Stale PR Triage, Draft Completion, Post-Merge Watch, Review Load Balancing, and Duplicate/Overlap Detection.
-
-## Verification matrix
-
-| Gate | Command or surface | Result |
-| --- | --- | --- |
-| Full static/test/build gate | `./script/verify.sh` | Passed: Rust fmt/Clippy, all Rust workspace tests and doc tests, 28 Swift tests, release contract, and production Swift build. |
-| Engine smoke | `./script/smoke.sh` | Passed with clean engine shutdown. |
-| Real Codex smoke | `./script/smoke_codex.sh` | Passed against signed-in `codex-cli 0.144.2`; disposable lifecycle persisted 42 events. |
-| Staged app | `./script/build_and_run.sh --verify` | Passed; app and bundled engine are running from the staged bundle. |
-| Bundle structure/signature | `validate_bundle.sh --require-signed` and strict deep `codesign` verification | Passed with marketing version `0.1.0`, build `1`, arm64 executables, and an ad-hoc local signature. |
-| Native interaction | Computer Use accessibility and screenshot inspection | Passed: queue sorting headers, selected PR detail, Active Tasks workbench, Merge gate, and embedded Codex transcript rendered in the rebuilt app. |
-| Review-thread interaction | Native Delivery workbench plus GraphQL readback | Passed: one unresolved thread exposes Preview Resolve with user-authority copy; the exact completed thread renders Resolved with file and line. |
-| Remote reconciliation | `gh pr view`, `gh issue view`, and `gh api .../commits/main` | Passed: PR merged, issue closed, review bound to exact head, and main bound to exact merge SHA. |
-| Release readiness | `script/release_readiness.sh` | Repo, Codex, GitHub integration, and bundle-valid gates are true; external Apple distribution gates are false. Evidence: `/Users/s1kor/.patchwright/evidence/release-readiness-20260714.json`. |
-
-## Defects found and fixed in this pass
-
-| Severity | Finding | Retained fix and re-verification |
-| --- | --- | --- |
-| High | A completed Codex turn moved the engine task to Verifying but the visible task header did not refresh. | The store refreshes tasks when a new terminal turn event arrives; focused Swift regression and full suite pass. |
-| High | Draft PRs could not be marked ready through Patchwright, so GitHub correctly rejected merge. | Added approval-bound `readyPullRequest`, GraphQL ready-for-review mutation, PR-identity validation, UI preview, and request-capture tests. The endpoint has no atomic head-SHA condition, so the action does not claim one. |
-| High | A definitive failed delivery remained permanently claimed. | Failed JSON results can be reclaimed; successful, ambiguous, and legacy results cannot. Restart and delivery regressions pass. |
-| High | Successful GitHub merge did not atomically advance the durable task to Completed. | Delivery result plus all remaining lifecycle events now commit in one SQLite transaction; focused lifecycle regression passes. |
-| High | REST review ingestion lacked the opaque thread identity required to resolve an individual discussion. | Added paginated GraphQL thread ingestion, typed `ResolveReviewThread`, exact repository/PR/thread identity validation, approval UI, and request-capture regressions. Live PR #6 resolution passed. |
-| High | GitHub installation identities report `viewerCanResolve: false`, even for an App-authored thread. | Resolution remains App-first but narrowly falls back to the already signed-in user's brokered token after the App attempt fails. The token is never persisted; the same exact approval and relay validations apply. |
-| High | Pre-fix remotely completed tasks remained stuck in Awaiting Delivery Approval. | Added read-only App-token reconciliation that rejects unmerged PRs and changed heads, persists the fresh snapshot, and commits remaining legal task events atomically. Both historical tasks now render under Completed. |
-| Medium | The retry predicate called `json_extract` on legacy non-JSON results and broke restart recovery. | JSON is inspected only after `json_valid`; the original restart failure is green. |
-| Medium | `build_and_run.sh` generated a launchable but release-invalid plist without marketing/build versions. | The staged build now uses canonical `Packaging/Info.plist` and validates the bundle before signing. Rebuilt bundle validation passes. |
-
-## Remaining boundaries
-
-- GitHub requires user-context authority to resolve author-owned review threads. The current local product brokers that authority from an authenticated `gh` installation after the App attempt fails; a clean-machine distribution needs either authenticated `gh` or a future in-app GitHub App user-authorization flow for this one action.
-- The staged test app is locally ad-hoc signed. A valid `Developer ID Application: Rafal Sikora (2NY8A789TN)` identity is installed, but live signing paused at the macOS Keychain private-key access prompt and was cancelled without producing a partially qualified artifact. `notarytool history --keychain-profile Patchwright` also reports that no Keychain password item exists. Developer ID signing needs one local Keychain approval; notarization/stapling, Gatekeeper distribution acceptance, final DMG qualification, and clean-machine validation additionally need a stored notary profile.
-- The GitHub App is intentionally installed only on the disposable sandbox. Installing it on another repository is an owner-controlled authorization decision.
-
-## Rollback
-
-All remote writes are confined to `patchwright-e2e-sandbox`. Source changes are isolated on `feat/andrzej_agent_sota_lab`. Patchwright PR #1 remains the review boundary; no production merge or force-push was used.
diff --git a/docs/audits/2026-07-17-product-quality-hardening.md b/docs/audits/2026-07-17-product-quality-hardening.md
deleted file mode 100644
index 59e0d13..0000000
--- a/docs/audits/2026-07-17-product-quality-hardening.md
+++ /dev/null
@@ -1,101 +0,0 @@
-# Patchwright Product Quality Hardening
-
-Date: 2026-07-17
-
-## Scope and authority
-
-This pass remediated the four findings from the end-to-end native product audit:
-
-1. Historical version-1 task contracts failed to decode after evidence fields became mandatory.
-2. Completed tasks still exposed delivery and merge workbench controls.
-3. The populated nine-column pull-request queue emitted negative AppKit geometry faults during accessibility enumeration.
-4. Task-preview copy implied that local contract review required GitHub App installation.
-
-The pass was authorized to change local product code and tests. It did not create credentials, mutate GitHub work items, or rewrite historical SQLite rows.
-
-## Official-documentation alignment
-
-- Apple documents `Table` as the native SwiftUI container for tabular data. The implementation keeps that semantic control and changes only the column set at a tested content-width boundary: .
-- Apple documents custom decoding as the compatibility boundary for external serialized representations. Swift independently validates supported versions, required content, and integrity evidence instead of accepting a structurally decodable payload: .
-- Serde documents that untagged variants are attempted in order and that `deny_unknown_fields` rejects fields not declared by a wire shape. The Rust snapshot decoder uses an explicit strict-first/read-only-second flow, with a denied-field legacy shape so malformed or partially upgraded payloads cannot silently downgrade: and .
-- GitHub documents that installation permissions govern GitHub API capabilities and recommends minimum required permissions. The UI now describes GitHub App access only at the remote-mutation boundary, while local contract review remains available: .
-
-## Findings and remediation
-
-### Historical contract compatibility
-
-- Category: objective defect
-- Severity: high
-- Evidence before: `task.contract` returned RPC error `-32000 persistence failure` with `decode task contract` for both completed local records.
-- Root cause: evidence-bound fields were added while both the prior and current serialized shapes remained version `1`.
-- Remediation:
- - New evidence-bound contracts serialize as version `2`.
- - Evidence-bound version-1 records remain executable for compatibility.
- - Pre-evidence version-1 records decode through a validated `TaskContractSnapshot` as read-only audit evidence.
- - Execution, preparation, verification, and delivery continue using the strict `TaskContract` decoder; no hashes or verification commands are fabricated.
- - Swift models independently reject malformed partial integrity evidence.
-- Runtime verification: direct RPC calls for the two existing completed records now return their original version, goal, criteria, and empty historical command list without an error. The running UI labels them `Version 1 · Read only` and explains that they cannot prepare, deliver, or merge changes.
-- Status: fixed and verified.
-
-### Terminal task immutability
-
-- Category: objective defect
-- Severity: medium
-- Evidence before: a completed pull-request task still displayed the workbench and an enabled `Preview Exact Merge` button.
-- Root cause: presentation policy handled cancelled and blocked tasks but treated completed tasks as generally interactive.
-- Remediation: `TaskSurfaceState` now resolves completed tasks to a dedicated read-only surface. The workbench picker and all preparation, delivery, and merge controls are absent while overview, lifecycle, source, and contract evidence remain visible.
-- Runtime verification: accessibility inspection of the completed task showed the full audit trail and historical contract, with no workbench tabs or mutation controls.
-- Status: fixed and verified.
-
-### Pull-request table accessibility geometry
-
-- Category: objective defect
-- Severity: high
-- Evidence before: accessibility enumeration of the populated queue emitted `Invalid view geometry: width is negative` and `height is negative`. Empty, filtered-small, Issues, and Repositories tables did not reproduce the fault.
-- Root cause: the normal 870.5-point content split attempted to expose nine columns whose aggregate mandatory width exceeded the available layout while both axes scrolled.
-- Remediation: the queue now selects a three-column compact table below 1,050 points and retains the expanded nine-column table for genuinely wide content panes. Compact rows preserve priority, PR identity, repository, author, CI, review, and update time.
-- Runtime verification: the populated 32-row queue exposed three semantic columns at 870.5 points. Repeated accessibility captures completed successfully, and the final Patchwright process emitted no negative-geometry messages, engine failures, or product-owned errors/faults. Unified logging still contains macOS-owned App Intents, Spotlight, and network-metadata diagnostics when their host services are unavailable; these are not emitted by Patchwright code and did not affect health or interaction.
-- Status: fixed and verified.
-
-### GitHub App boundary copy
-
-- Category: refinement opportunity
-- Severity: polish
-- Evidence before: `Preview Task` succeeded locally while its tooltip said it would verify GitHub App access, alongside an installation warning.
-- Remediation: the tooltip now says `Preview the local task contract`. The warning explicitly distinguishes available local/read-only behavior from GitHub App access required for remote mutation previews.
-- Runtime verification: the corrected tooltip and explanatory warning were present together in the running issue detail.
-- Status: fixed and verified.
-
-## Regression coverage
-
-- Rust core fixture for legacy read-only snapshot decoding and version-2 contract creation.
-- Engine Unix-socket RPC fixture proving a real legacy payload is returned for audit.
-- Existing strict persistence test proving evidence-free contracts remain rejected by execution paths.
-- Swift decoding fixtures for legacy records and malformed partial integrity evidence.
-- Workspace-store fixture proving legacy contract refresh no longer creates a lifecycle error.
-- Presentation-policy coverage for completed tasks and compact/expanded queue density.
-- Source contract coverage for the local-preview versus remote-mutation copy boundary.
-
-## Runtime interaction evidence
-
-- Populated Pull Request Queue: verified.
-- Completed historical task evidence: verified.
-- Terminal mutation-control removal: verified.
-- Issue detail and task-preview copy: verified.
-- Engine health after rebuild: `ok`, version `0.1.0`.
-- Existing SQLite records: preserved; no in-place migration or rewrite performed.
-- External GitHub writes: not performed.
-
-## Verification evidence
-
-- `SDKROOT="$(xcrun --sdk macosx --show-sdk-path)" ./script/verify.sh`: passed after the final code change.
-- Rust workspace tests, clippy/format gates, Swift tests (64 tests, 0 failures), production builds, release/security/compliance checks, and the 29-category promotion matrix: passed.
-- `./script/build_and_run.sh --verify`: passed for the final staged bundle.
-- `codesign --verify --deep --strict`: passed for the staged app and bundled helpers.
-- Direct `system.health` RPC: `ok`, version `0.1.0`.
-- Direct `task.contract` RPC: all three persisted records returned successfully, including historical version-1 records.
-- One real Codex disposable lifecycle test remains intentionally ignored because it requires a signed-in Codex account and available external quota; all offline and deterministic coverage passed.
-
-## Readiness
-
-The changed surfaces are interaction-clean and runtime-proven for the reproduced findings. Repository-wide local verification and the final diff review passed. Hosted PR/CI evidence remains the final merge gate and is recorded by GitHub rather than this local report.
diff --git a/docs/direct-download.md b/docs/direct-download.md
index e835f1a..68d3679 100644
--- a/docs/direct-download.md
+++ b/docs/direct-download.md
@@ -1,7 +1,7 @@
# Direct download and installation
Patchwright is distributed outside any app marketplace. Official binaries are
-published only through [GitHub Releases](https://github.com/s1korrrr/patchwright/releases).
+published only through [GitHub Releases](https://github.com/rsitech-ai/patchwright/releases).
Each release must be signed with an Apple **Developer ID Application** identity,
accepted by **Apple notarization**, and stapled before publication.
@@ -35,6 +35,27 @@ spctl --assess --type open --context context:primary-signature --verbose=4 Patch
The release page also publishes `appcast.xml` for signed Sparkle updates. The
feed and archive signatures are checked by Patchwright before extraction.
+## Community prerelease
+
+The repository may publish a ZIP labeled `community` for source review and
+evaluation when Developer ID or notarization credentials are unavailable. A
+community prerelease is ad-hoc signed and is **not Developer ID signed or Apple notarized**.
+It is not included in the signed Sparkle update feed and is not an
+official trusted binary distribution.
+
+Download the ZIP, its `.sha256` file, and its JSON manifest into the same
+directory, then verify the archive before expanding it:
+
+```sh
+shasum -a 256 -c Patchwright--community.-macos-.zip.sha256
+```
+
+The manifest binds the archive digest to the exact Git commit and tag and
+states the signing and notarization status. Gatekeeper may block an unnotarized
+archive. Do not disable Gatekeeper or strip quarantine metadata to work around
+that warning; build the tagged source locally if a community prerelease does
+not meet your trust requirements.
+
## Source builds
Source builds are supported for development and review, but they are not
diff --git a/docs/github-publication-plan.md b/docs/github-publication-plan.md
deleted file mode 100644
index f438fe6..0000000
--- a/docs/github-publication-plan.md
+++ /dev/null
@@ -1,69 +0,0 @@
-# GitHub publication plan
-
-This file records proposed external repository and profile changes. It does not
-authorize or apply them. Export the current settings immediately before any
-change and apply the items only after explicit approval.
-
-## Repository identity
-
-- Description: `Local-first macOS control plane for auditable GitHub engineering workflows, approval-gated mutations, and embedded Codex sessions.`
-- Homepage: leave unset until a maintained public documentation site exists.
-- Topics: `macos`, `swiftui`, `rust`, `github`, `developer-tools`,
- `code-review`, `local-first`, `automation`.
-- Default branch: keep `main`.
-- Issues: keep enabled. Discussions, Wiki, Projects, and Pages: keep disabled
- until a maintainer commits to operating them.
-- Merge policy: keep merge, squash, and rebase available initially; keep
- automatic deletion of merged branches enabled.
-
-## Default-branch ruleset
-
-Apply only after the readiness pull request proves the CI check name is stable.
-
-- Require a pull request before merging.
-- Require the `verify` CI job and require the branch to be current before merge.
-- Require conversation resolution.
-- Block force pushes and branch deletion.
-- Do not require signed commits initially; Patchwright already requires DCO
- sign-off and mandatory signatures would add contributor friction.
-- Keep bypass actors explicit and minimal. Record any owner emergency bypass in
- the repository settings export.
-
-Protect release tags matching `v*` from deletion or update after the first
-ruleset-backed release.
-
-## Security and Actions settings
-
-- Enable the dependency graph, vulnerability alerts, and Dependabot security
- updates.
-- Enable secret scanning and push protection if GitHub offers them for the
- repository.
-- Enable private vulnerability reporting and verify that the link in
- `SECURITY.md` works while signed out.
-- Keep the default Actions token read-only. Do not allow fork workflows to
- receive secrets or approve pull requests.
-- Retain the repository-local CI secret scan and `cargo audit`; consider CodeQL
- default setup only after confirming its Swift build is stable on this
- repository.
-
-## Labels
-
-Keep a small taxonomy: `bug`, `enhancement`, `documentation`, `security`,
-`dependencies`, `good first issue`, `help wanted`, `breaking change`, and
-`needs reproduction`. Do not delete existing labels without reviewing open
-issues and pull requests that use them.
-
-## Personal profile
-
-After release approval, pin `s1korrrr/patchwright`. A profile README entry can
-describe Patchwright as a local-first macOS engineering control plane and link
-to the repository and latest verified release. Do not change the account bio,
-location, company, email visibility, social links, or other pinned repositories
-without a separate review of the exact profile patch.
-
-## Post-change verification
-
-Inspect the repository signed out. Confirm the README, licenses, security form,
-issue forms, pull-request template, release assets, checksums, topics,
-description, rulesets, Actions permissions, and security settings. Recheck
-rulesets and security features after any visibility change.
diff --git a/docs/reflections/2026-07-13-durable-local-orchestrator.md b/docs/reflections/2026-07-13-durable-local-orchestrator.md
deleted file mode 100644
index 2f62a14..0000000
--- a/docs/reflections/2026-07-13-durable-local-orchestrator.md
+++ /dev/null
@@ -1,42 +0,0 @@
-# Durable Local Orchestrator Design Reflection
-
-## Task
-
-- **ID/Title:** Patchwright durable local orchestrator expansion
-- **Date:** 2026-07-13
-- **Scope:** repo-wide design
-
-## Plan and Risks
-
-- **Planned approach:** Extend the existing local-first engine through dependency-ordered vertical slices. Keep SwiftUI as the operator console, make the Rust engine the lifecycle authority, isolate one Codex app-server process per active task, centralize GitHub writes behind a production GitHub App broker, and retain independently verifiable release gates.
-- **Top failure hypotheses:** A stale or overly broad approval could merge changed code; Codex or Git commands could outlive cancellation and mutate the wrong worktree; installation-token or signing credentials could leak through argv, logs, persistence, or model context.
-- **Success criteria:** One ingested issue and one existing PR complete the typed lifecycle in a disposable repository; every remote mutation is previewed, scoped, idempotent, and recoverable; a merge requires a fresh exact-SHA approval; cancellation and restart fault tests pass; the final Developer ID artifact passes notarization, Gatekeeper, and clean-machine validation when external credentials are present.
-
-## Candidate Attempts
-
-| Candidate | Summary | Outcome | Signals | Why selected / rejected |
-|---|---|---|---|---|
-| A | Durable local Rust orchestrator with native SwiftUI control plane | Selected | Matches existing boundaries, supports restart recovery and fail-closed approvals | Best balance of local privacy, auditability, and incremental delivery |
-| B | SwiftUI invokes `git`, `gh`, and `codex` directly | Rejected | Fewer components initially | Approval enforcement, cancellation, idempotency, and recovery would fragment across UI code |
-| C | Hosted orchestration service first | Deferred | Strong future team/remote potential | Adds infrastructure and credential scope before the single-operator workflow is complete |
-
-## Reflection
-
-- **Failure modes observed:** The baseline presents a Stage 1–3 architecture but currently exposes only task creation/timeline and read-only GitHub ingestion. The Codex setting is not connected. Merge is hard-denied. The package is ad-hoc signed, and the current Keychain has no Developer ID Application identity.
-- **Root cause:** The baseline implemented domain and integration scaffolding before wiring the complete user-visible lifecycle and external release credentials.
-- **Fix that resolved it:** Not applicable yet; this reflection establishes the retained design and rollback boundaries before implementation.
-- **What improved score/quality:** Separating Codex approvals, local capabilities, GitHub delivery, and merge approval; binding merge to exact remote state; using a task-owned app-server process; and splitting repository readiness from external Apple/GitHub gates.
-- **Useful command-level evidence:** `git status --short`; `codex --version`; `codex app-server --help`; `security find-identity -p codesigning -v`; source inspection of RPC, policy, relay, SwiftUI, release, and security files.
-- **Branch comparison insight:** The working branch contains authenticated read-only GitHub ingestion and package hardening beyond `origin/main`, but the complete task/Codex/write/merge lifecycle remains unimplemented.
-
-## Reusable Lesson
-
-- **Pattern that worked:** Bind every irreversible remote action to a typed preview, fresh preconditions, short-lived approval, idempotency identity, and reconciliation path.
-- **Pattern to avoid:** Treating a model/runtime approval or a broad delivery approval as authority for later remote state.
-- **Where to apply next:** Task preparation, GitHub pushes, review replies, check publication, merge, signing, and notarization.
-
-## Decision
-
-- **Final chosen approach:** Durable local orchestrator with task-owned embedded Codex, production GitHub App broker, explainable bounded PR queue, exact-SHA approval-gated merge, and Developer ID direct distribution.
-- **Commit/rollback decision:** Commit the approved design only. Implementation will land in independently revertible vertical slices; the global kill switch and read-only ingestion remain the retained rollback path.
-- **Next step / follow-up:** User reviews the committed specification, then a dependency-ordered ExecPlan is written before code changes.
diff --git a/docs/reflections/2026-07-13-stages-1-3.md b/docs/reflections/2026-07-13-stages-1-3.md
deleted file mode 100644
index fa629af..0000000
--- a/docs/reflections/2026-07-13-stages-1-3.md
+++ /dev/null
@@ -1,25 +0,0 @@
-# Reflection: Patchwright Stages 1–3
-
-## Task
-
-- **ID/Title:** PATCHWRIGHT-001 / Stage 1–3 greenfield product
-- **Date:** 2026-07-13
-- **Scope:** repo-wide
-
-## Plan and risks
-
-- **Planned approach:** Build three deep modules with a typed JSON-RPC boundary, one vertical lifecycle tracer, then expand review, delivery, and webhook behavior through public-interface tests.
-- **Top failure hypotheses:** Policy can be bypassed by untrusted repository text; restart recovery can repeat GitHub mutations; a polished client can hide a non-functional engine boundary.
-- **Success criteria:** A disposable repository travels from discovery through durable monitoring evidence; all network and remote mutations are approval-gated; fresh Rust and Swift suites plus a real `.app` launch pass.
-
-## Candidate attempts
-
-| Candidate | Summary | Outcome | Signals | Why selected / rejected |
-| --- | --- | --- | --- | --- |
-| A | Swift-only prototype with direct GitHub calls | Rejected | Fast UI delivery, weak headless/recovery boundary | Conflicts with approved architecture and future runner reuse |
-| B | Swift client, shared Rust domain/engine, separate Rust relay | Selected | Small typed protocol, testable policy and persistence | Preserves local privacy and supports all three stages |
-
-## Retained rollback
-
-The feature branch is independent of an empty remote repository. Each subsystem remains buildable separately. No merge, automatic delivery, production GitHub App installation, or App Store action is authorized by this task.
-
diff --git a/docs/reflections/2026-07-14-review-thread-reconciliation.md b/docs/reflections/2026-07-14-review-thread-reconciliation.md
deleted file mode 100644
index 819b58c..0000000
--- a/docs/reflections/2026-07-14-review-thread-reconciliation.md
+++ /dev/null
@@ -1,42 +0,0 @@
-# Review Thread and Remote Reconciliation Reflection
-
-## Task
-
-- **ID/Title:** Patchwright final review-thread and historical-task closure
-- **Date:** 2026-07-14
-- **Scope:** multi-file GitHub integration and durable lifecycle
-
-## Plan and Risks
-
-- **Planned approach:** Add GraphQL review-thread ingestion and a separately approved typed resolution action, then add a read-only remote reconciliation RPC that validates immutable task identity before advancing local state.
-- **Top failure hypotheses:** A thread node ID could belong to another repository or PR; a stale task head could resolve a thread after new commits; local reconciliation could mark a closed-but-unmerged PR or unrelated issue complete.
-- **Success criteria:** Resolution is rejected for mismatched repository, PR, head, resolved state, or viewer authority; exact resolution succeeds once and survives re-ingestion; current pre-fix tasks become Completed only after remote identity/state verification; full and live sandbox gates pass.
-
-## Candidate Attempts
-
-| Candidate | Summary | Outcome | Signals | Why selected / rejected |
-|---|---|---|---|---|
-| A | GraphQL thread ingestion plus typed resolution and read-only reconciliation | Selected | GitHub exposes thread IDs and resolution state only through the GraphQL thread connection | Preserves exact identity and the existing approval architecture |
-| B | Infer threads from REST review comment IDs | Rejected | REST comments have database IDs but not their owning review-thread node IDs | Could resolve the wrong object or require unsafe guessing |
-| C | Directly patch the two historical SQLite task states | Rejected | Would make the current UI look correct without proving remote identity | Bypasses the production recovery path and leaves the real defect unfixed |
-
-## Reflection
-
-- **Failure modes observed:** The live PR and issue were remotely complete while their pre-fix local tasks remained at Awaiting Delivery Approval; review comments were ingested but thread node IDs were absent; live GitHub installation tokens reported `viewerCanResolve: false` even for an App-authored thread.
-- **Root cause:** The first live delivery path persisted remote results separately from task state, the read model used REST comments/reviews without GraphQL thread identity, and GitHub reserves thread resolution for user-context authority rather than installation identity.
-- **Fix that resolved it:** Paginated GraphQL ingestion, exact typed resolution, App-first then signed-in-user credential brokering for only the rejected resolution action, and read-only exact-identity task reconciliation.
-- **What improved score/quality:** Server-side ownership/head validation, explicit viewer authority, non-persisted user-token fallback, no direct database repair, and using the same recovery interface for historical and future ambiguous outcomes.
-- **Useful command-level evidence:** `gh pr view`, `gh issue view`, GraphQL thread query, focused action/relay/RPC tests, SQLite task timeline readback, `./script/verify.sh`, and `./script/smoke_codex.sh`.
-- **Branch comparison insight:** Commit `7f92449` completed the normal merge transaction; this slice closes recovery and review-thread gaps without broadening repository authorization.
-
-## Reusable Lesson
-
-- **Pattern that worked:** Treat opaque provider node identity as first-class data and revalidate ownership immediately before mutation.
-- **Pattern to avoid:** Conflating a review comment database ID with a review-thread node ID or repairing durable state outside the orchestrator.
-- **Where to apply next:** Any future GraphQL-only GitHub actions and ambiguous external-write reconciliation.
-
-## Decision
-
-- **Final chosen approach:** GraphQL-native review threads, exact approval with a narrow user-context fallback required by GitHub, installation-token readback, and local atomic reconciliation.
-- **Commit/rollback decision:** Keep the work in one independently revertible closure commit; retain the existing sandbox-only live mutation guard and do not merge PR #1.
-- **Next step / follow-up:** Preserve the live sandbox evidence and replace the local `gh` user broker with an in-app GitHub App user-authorization flow before clean-machine distribution if review-thread resolution must work without `gh`.
diff --git a/docs/release-checklist.md b/docs/release-checklist.md
index 8963ec1..632d543 100644
--- a/docs/release-checklist.md
+++ b/docs/release-checklist.md
@@ -22,3 +22,12 @@
- [ ] `promotion-manifest.json` binds the candidate manifest, every gate, `release-evidence.json`, and `release-assets.json`; `promotion-readiness.json` binds the promotion manifest digest.
- [ ] The promoted release is uploaded to GitHub Releases with the DMG, `.sha256`, and `appcast.xml`; the public URLs and updater feed are rechecked.
- [ ] The release report lists any remaining external gate independently and never upgrades a partial result to ready.
+
+## Community prerelease gate
+
+- [ ] Use this lane only when the Developer ID/notarization path is unavailable; do not alter `script/release.sh` or official evidence gates.
+- [ ] The exact source commit is merged through a reviewed pull request, clean, and tagged `v-community.`.
+- [ ] `./script/verify.sh`, `./script/smoke.sh`, and `./script/build_and_run.sh --verify` pass on that exact commit.
+- [ ] `script/package_community_release.sh` emits the ZIP, portable SHA-256 sidecar, and manifest with `signing: ad-hoc` and `notarized: false`.
+- [ ] The downloaded ZIP checksum and expanded app signature are reverified independently before the superseded GitHub release is removed.
+- [ ] The GitHub entry is a prerelease, does not publish `appcast.xml`, and states that Gatekeeper may block the unnotarized app.
diff --git a/docs/release-readiness.md b/docs/release-readiness.md
index b1ed736..ceb1946 100644
--- a/docs/release-readiness.md
+++ b/docs/release-readiness.md
@@ -28,7 +28,7 @@ Then run:
export PATCHWRIGHT_DEVELOPER_ID='Developer ID Application: Exact Name (TEAMID)'
export PATCHWRIGHT_SIGNING_KEYCHAIN='/absolute/path/to/Release.keychain-db'
export PATCHWRIGHT_NOTARY_PROFILE=Patchwright
-PATCHWRIGHT_VERSION=0.1.1 PATCHWRIGHT_BUILD=2 ./script/release.sh
+PATCHWRIGHT_VERSION=0.2.0 PATCHWRIGHT_BUILD=3 ./script/release.sh
```
The output remains under `~/.patchwright/release-work` until every active gate
diff --git a/docs/releases/v0.1.1.md b/docs/releases/v0.1.1.md
deleted file mode 100644
index 82ccc9d..0000000
--- a/docs/releases/v0.1.1.md
+++ /dev/null
@@ -1,46 +0,0 @@
-# Patchwright 0.1.1 release notes (draft)
-
-Patchwright is a local-first macOS engineering control plane that keeps coding
-sessions, verification, GitHub delivery, and approvals auditable. Version 0.1.1
-is a hardening release for the public technical beta.
-
-## Highlights
-
-- Preserves historical task contracts as read-only audit records while keeping
- execution fail closed without complete integrity evidence.
-- Revalidates exact approved commit identities immediately before draft,
- ready-for-review, close, and review-thread mutations.
-- Bounds GitHub snapshot fan-out and Codex protocol resources.
-- Matches Codex responses and completion events to the active request, thread,
- and turn, and redacts credential-shaped durable content.
-- Makes unsandboxed repository verification authority explicit at the moment of
- execution.
-
-## Install
-
-Download the DMG and matching checksum from the GitHub Release and follow the
-[direct-download guide](../direct-download.md). Do not use a source-built or
-ad-hoc-signed app as evidence for the official release.
-
-## Compatibility and limitations
-
-- Requires macOS 26 or newer on Apple silicon.
-- GitHub CLI and Codex are optional, separately installed integrations.
-- Repository-controlled verification commands are not OS-sandboxed and run as
- the current macOS user after an explicit warning and confirmation.
-- This beta provides best-effort support without a service-level agreement.
-
-## Upgrade notes
-
-No data migration or public API migration is required from 0.1.0. Back up
-important repositories and review the release checksum before installation.
-
-## Security
-
-Report suspected vulnerabilities through the private process in
-[SECURITY.md](../../SECURITY.md). Do not include credentials, private source, or
-personal data in public issues.
-
-The final GitHub Release must include the notarized DMG, checksum sidecar,
-signed appcast, SBOM, third-party notices, and complete promoted-release
-evidence generated from the same frozen candidate.
diff --git a/docs/releases/v0.2.0-community.1.md b/docs/releases/v0.2.0-community.1.md
new file mode 100644
index 0000000..ab78d9b
--- /dev/null
+++ b/docs/releases/v0.2.0-community.1.md
@@ -0,0 +1,48 @@
+# Patchwright 0.2.0 community prerelease 1
+
+Patchwright 0.2.0 moves the public project to the RSI Tech GitHub organization
+and packages the latest source-ready app for community evaluation.
+
+## Highlights
+
+- Revalidates exact approved commit identities immediately before supported
+ pull-request mutations.
+- Bounds GitHub snapshot fan-out and Codex protocol resources.
+- Matches Codex responses and completion events to the active request, thread,
+ and turn, and redacts credential-shaped durable content.
+- Makes unsandboxed repository verification authority explicit immediately
+ before execution.
+- Uses `rsitech-ai/patchwright` as the canonical source and release location.
+
+## Download integrity
+
+The release assets include:
+
+- `Patchwright-0.2.0-community.1-macos-arm64.zip`
+- `Patchwright-0.2.0-community.1-macos-arm64.zip.sha256`
+- `Patchwright-0.2.0-community.1-manifest.json`
+
+Download all three files into the same directory and run:
+
+```sh
+shasum -a 256 -c Patchwright-0.2.0-community.1-macos-arm64.zip.sha256
+```
+
+The manifest binds the archive to the exact Git commit and records the bundle
+version, build, architecture, signing class, and notarization status.
+
+## Trust boundary
+
+This community prerelease is ad-hoc signed and is **not Developer ID signed or
+Apple notarized**. Gatekeeper may block it. Do not disable Gatekeeper or remove
+quarantine metadata to bypass that decision; build the tagged source locally if
+you require a locally trusted copy. This ZIP is not served through the signed
+Sparkle update feed.
+
+## Compatibility
+
+- Requires macOS 26 or newer on Apple silicon.
+- GitHub CLI and Codex are optional, separately installed integrations.
+- Repository-controlled verification commands are not OS-sandboxed and run as
+ the current macOS user after an explicit warning and confirmation.
+- This beta provides best-effort support without a service-level agreement.
diff --git a/docs/superpowers/plans/2026-07-13-developer-id-release.md b/docs/superpowers/plans/2026-07-13-developer-id-release.md
deleted file mode 100644
index 4d3e796..0000000
--- a/docs/superpowers/plans/2026-07-13-developer-id-release.md
+++ /dev/null
@@ -1,134 +0,0 @@
-# Developer ID Release Implementation Plan
-
-> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
-
-**Goal:** Produce a reproducible, credential-free Patchwright release bundle and close Developer ID signing, notarization, Gatekeeper, install/update, and clean-machine validation without overstating external readiness.
-
-**Architecture:** Shell scripts assemble immutable Release outputs outside File Provider storage, validate metadata/entitlements, sign nested helpers inside-out, create a DMG, submit/staple through a named Keychain notary profile, and emit machine-readable evidence. All credentials stay in Keychain; unsigned/ad-hoc and Developer ID paths are explicit and cannot be confused.
-
-**Tech Stack:** SwiftPM, Cargo, `/usr/bin/codesign`, `/usr/bin/security`, `xcrun notarytool`, `xcrun stapler`, `spctl`, `hdiutil`, shellcheck-compatible zsh/bash, SHA-256 tooling.
-
-## Global Constraints
-
-- Depend on completed source/integration plans; packaging never substitutes for behavioral verification.
-- Direct distribution outside the Mac App Store; macOS 26+ Apple silicon; no App Sandbox if it breaks approved orchestration.
-- Release identity must be `Developer ID Application`. Apple Development, Apple Distribution, or ad-hoc signatures cannot produce a notarized-candidate label.
-- No Hardened Runtime exception entitlement without a proven failing behavior and documented review.
-- Never place certificate exports, passwords, App Store Connect keys, notary credentials, GitHub keys/tokens, or user state in the repository or reproducibility bundle.
-- Existing `dist` artifacts are replaced only after the new candidate passes its current gate; use `trash`, not permanent deletion.
-
----
-
-## Task 1: Define bundle metadata and minimal entitlements
-
-**Files:**
-- Add: `Packaging/Info.plist`
-- Add: `Packaging/Patchwright.entitlements`
-- Add: `Packaging/patchwright-engine.entitlements`
-- Add: `Packaging/patchwright-relay.entitlements`
-- Add: `script/validate_bundle.sh`
-- Add: `Tests/PackagingTests/validate_bundle.bats`
-- Modify: `Package.swift`
-
-- [ ] Add fixture tests rejecting missing/mismatched bundle ID/version/build/minimum system, writable/executable anomalies, symlinks escaping bundle, forbidden quarantine/FinderInfo/File Provider xattrs, unsigned helpers, resource-envelope drift, and unreviewed entitlement keys.
-- [ ] Observe RED.
-- [ ] Move generated Info.plist values into a versioned template with `ai.patchwright.app`, macOS 26 minimum, semantic marketing version, monotonic build, copyright, and document/privacy declarations actually used.
-- [ ] Define minimal app/helper entitlements and a checked allowlist; enable Hardened Runtime at signing time, not through an exception blanket.
-- [ ] Implement structural validation before and after signing, including nested helper architecture and executable paths.
-- [ ] Run fixture matrix and commit: `Define Patchwright release bundle metadata`.
-
-## Task 2: Build immutable Release components and reproducibility metadata
-
-**Files:**
-- Add: `script/build_release_components.sh`
-- Add: `script/generate_release_metadata.sh`
-- Add: `script/verify_reproducibility_bundle.sh`
-- Modify: `script/build_and_run.sh`
-- Add: `Packaging/THIRD_PARTY_NOTICES.md`
-- Modify: `docs/release-checklist.md`
-
-- [ ] Add shell tests proving clean output root, Release configuration, warnings-as-errors, pinned Cargo lock use, arm64 architectures, helper placement, deterministic manifest ordering, credential exclusion, and failure before replacing a prior candidate.
-- [ ] Observe RED.
-- [ ] Build Swift and Rust Release outputs into a fresh temporary root outside synced/File Provider locations; copy only declared artifacts.
-- [ ] Emit version/build/git commit/dirty-state/toolchain/dependency/license metadata and SHA-256 manifests. Dirty release builds are rejected unless an explicit local-debug mode labels them non-candidate.
-- [ ] Package source/lockfiles/scripts/manifests needed to reproduce without including `.git`, databases, logs, worktrees, Keychain exports, environment dumps, or credentials.
-- [ ] Keep `build_and_run.sh` as an ad-hoc developer path and label it clearly; route distribution through new scripts.
-- [ ] Run release-component tests and commit: `Build reproducible Patchwright release components`.
-
-## Task 3: Sign nested code inside-out with Developer ID
-
-**Files:**
-- Add: `script/sign_release.sh`
-- Add: `script/verify_signing.sh`
-- Add: `Tests/PackagingTests/signing.bats`
-- Modify: `docs/release-checklist.md`
-
-- [ ] Add tests that reject missing identity, ambiguous identities, wrong identity class, absent secure timestamp, missing Hardened Runtime, helper/app Team ID mismatch, forbidden entitlements, ad-hoc residue, and altered post-sign content.
-- [ ] Observe RED using the current machine's absence of `Developer ID Application` as the expected external-blocker case.
-- [ ] Resolve exactly one identity from `PATCHWRIGHT_DEVELOPER_ID` or an exact `Developer ID Application:` match; never fall back to Apple Development/Distribution/ad-hoc.
-- [ ] Strip xattrs, sign `patchwright-engine` and `patchwright-relay` with their entitlements, then app executable/bundle with secure timestamp and runtime options.
-- [ ] Verify `codesign --verify --deep --strict --verbose=4`, designated requirement, Team ID, entitlements, runtime flags, timestamp, nested identities, and `spctl --assess --type execute` with truthful pre-notarization handling.
-- [ ] Commit scripts/tests even when real signing remains `blocked:external`; record that no Developer ID candidate exists yet.
-- [ ] Commit: `Automate Developer ID signing verification`.
-
-## Task 4: Create, sign, notarize, staple, and verify the DMG
-
-**Files:**
-- Add: `script/create_dmg.sh`
-- Add: `script/notarize_release.sh`
-- Add: `script/verify_distribution.sh`
-- Add: `Tests/PackagingTests/distribution.bats`
-- Modify: `docs/release-checklist.md`
-
-- [ ] Add tests for DMG layout, Applications alias, volume name/version, read-only conversion, checksum, signed container, missing/wrong notary profile, rejected/in-progress/accepted submissions, log retention, stapling failure, offline ticket validation, and Gatekeeper rejection.
-- [ ] Observe RED.
-- [ ] Create the DMG from the already verified signed app, sign the DMG with the same Developer ID identity, and generate checksum metadata only after final stapling.
-- [ ] Accept only a named Keychain profile via `PATCHWRIGHT_NOTARY_PROFILE`; never accept raw Apple credentials in arguments/environment files.
-- [ ] Submit with `xcrun notarytool submit "$DMG_PATH" --keychain-profile "$PATCHWRIGHT_NOTARY_PROFILE" --wait --output-format json`, retain JSON and notarization log, require `Accepted`, staple app and DMG, then validate both tickets.
-- [ ] Verify final mounted payload, signature, Gatekeeper source, checksum, metadata manifest, and absence of credentials/quarantine.
-- [ ] Commit: `Automate notarized DMG distribution`.
-
-## Task 5: Add a truthful release driver and readiness report
-
-**Files:**
-- Add: `script/release.sh`
-- Add: `script/release_readiness.sh`
-- Add: `docs/release-readiness.md`
-- Modify: `script/verify.sh`
-- Modify: `README.md`
-
-- [ ] Add matrix tests for local unsigned validation, ad-hoc developer app, package-ready Developer ID app, notary blocked, notarized candidate, clean-machine blocked, and release-candidate ready.
-- [ ] Observe RED.
-- [ ] Compose gates without weakening them: verify source → build components → validate → Developer ID sign → verify → DMG → notarize → staple → final verify → report.
-- [ ] Emit machine-readable JSON and concise Markdown with independent booleans/evidence paths for repo, integration, package, Developer ID, Hardened Runtime, notarization, Gatekeeper, clean-machine, and external prerequisites.
-- [ ] Ensure a blocked external gate exits distinctly and never leaves a misleading final artifact named as a release candidate.
-- [ ] Document owner steps for obtaining the Developer ID Application certificate and creating a Keychain notary profile, without collecting credentials.
-- [ ] Commit: `Report truthful Patchwright release readiness`.
-
-## Task 6: Validate install, first launch, relaunch, update, and uninstall in a clean environment
-
-**Files:**
-- Add: `script/clean_machine_probe.sh`
-- Add: `docs/clean-machine-test-plan.md`
-- Add: `docs/audits/2026-07-13-clean-machine-validation.md`
-
-- [ ] Define a macOS 26+ clean-machine/VM image with no source checkout, developer toolchain, Patchwright state, `gh`, cached GitHub token, Codex, or engine process. Record OS/build/hardware/VM identity.
-- [ ] Add a signed probe that checks DMG checksum/mount, drag-install, Gatekeeper launch, bundled helper health, engine socket permissions, missing-Codex recovery, Codex install/sign-in/app-server connection, GitHub App discovery without `gh`, disposable ingestion, relaunch queue/task/thread recovery, offline/expired/revoked/missing-permission states, and clean quit.
-- [ ] Install the prior released schema fixture, ingest data, upgrade in place, and prove task/queue/thread/database preservation and migration idempotency.
-- [ ] Verify documented uninstall removes app separately from retained local data and that optional data deletion is explicit and scoped.
-- [ ] Capture screenshots/logs with private repository content and credentials redacted; retain exact failures and rollback.
-- [ ] Do not mark this task complete until the final notarized DMG, not a source-built app, passes.
-- [ ] Commit the plan/probe/evidence only after review: `Validate Patchwright on a clean Mac`.
-
-## Task 7: Final cross-system E2E audit
-
-**Files:**
-- Add: `docs/audits/2026-07-13-patchwright-final-e2e.md`
-- Modify: `docs/release-checklist.md`
-
-- [ ] From final source, run strict Rust/Swift tests, migration/restart/cancellation fault matrix, native UI interaction/accessibility/resize/theme/log audit, real disposable Codex smoke, and the separately authorized disposable GitHub App delivery/merge workflow.
-- [ ] Build the immutable candidate, run signature/Hardened Runtime/entitlement/secret/license/checksum/reproducibility audits, notarize/staple, and run clean-machine install/update workflow.
-- [ ] Review final branch diff and draft PR for scope, security, unresolved comments, CI, and accidental credentials/artifacts.
-- [ ] Record each gate independently: `repo-ready`, `integration-ready`, `package-ready`, `notarized candidate`, `release-candidate ready`, or exact `blocked:external`.
-- [ ] A current expected blocker is the missing `Developer ID Application` identity and notary profile; keep it explicit until live evidence changes.
-- [ ] Commit: `Audit Patchwright release end to end`.
diff --git a/docs/superpowers/plans/2026-07-13-embedded-codex.md b/docs/superpowers/plans/2026-07-13-embedded-codex.md
deleted file mode 100644
index ddf887b..0000000
--- a/docs/superpowers/plans/2026-07-13-embedded-codex.md
+++ /dev/null
@@ -1,136 +0,0 @@
-# Embedded Codex Implementation Plan
-
-> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
-
-**Goal:** Give every active Patchwright task a supervised, persistent, cancellable Codex app-server process and a fully native thread experience.
-
-**Architecture:** A Rust `CodexSupervisor` owns one process group per active task, speaks newline-delimited app-server JSON-RPC, normalizes notifications into durable task events, and exposes typed Patchwright RPC methods. Swift consumes normalized events and sends operator input/approvals; it never owns the Codex subprocess or authentication.
-
-**Tech Stack:** Rust/Tokio subprocess and async I/O, Codex app-server 0.144.x protocol schemas, SQLite, Unix process groups, Swift concurrency, SwiftUI.
-
-## Global Constraints
-
-- Depend on the foundation plan's task contracts, checkpoints, approvals, and jobs.
-- Generate or validate protocol fixtures against the installed Codex app-server schema; never infer message shapes from UI text.
-- A task process starts with its isolated worktree as `cwd`; Codex receives no GitHub, Apple, or Patchwright approval credential.
-- Persist thread/turn/item/approval identities and bounded summaries, not raw secrets or unbounded terminal output.
-- Graceful interrupt precedes process-group termination; task cancellation retains worktree and evidence.
-
----
-
-## Task 1: Pin and validate the app-server protocol boundary
-
-**Files:**
-- Add: `crates/patchwright-engine/src/codex/protocol.rs`
-- Add: `crates/patchwright-engine/src/codex/mod.rs`
-- Modify: `crates/patchwright-engine/src/lib.rs`
-- Add: `crates/patchwright-engine/tests/codex_protocol.rs`
-- Add: `crates/patchwright-engine/tests/fixtures/codex/*.jsonl`
-
-- [x] Capture sanitized fixtures for initialize/result, initialized, account/read, thread/start, thread/resume, turn/start, turn/steer, turn/interrupt, streamed item notifications, approval requests, completion, and error.
-- [x] Write decode/encode tests that reject unknown required enum values, missing IDs, oversized lines, malformed JSON, duplicate completion, and a response ID that does not match a pending request.
-- [x] Run `cargo test -p patchwright-engine --test codex_protocol` and observe missing-module RED.
-- [x] Implement typed request/response/notification envelopes with serde tagging only at the exact discriminator fields emitted by the validated official schema; retain an explicit `Unsupported` event for forward-compatible notifications.
-- [x] Add a 4 MiB per-line bound and redact credential-shaped fields from debug output.
-- [x] Add `script/verify_codex_schema.sh` that resolves the exact `codex` executable/version and compares required methods/fields with generated app-server schema output.
-- [x] Run fixtures and schema validation, then commit: `Define the Codex app-server protocol boundary`.
-
-## Task 2: Supervise one task-owned process group
-
-**Files:**
-- Add: `crates/patchwright-engine/src/codex/process.rs`
-- Add: `crates/patchwright-engine/tests/codex_process.rs`
-- Add: `crates/patchwright-engine/tests/support/fake_codex_app_server.rs`
-- Modify: `crates/patchwright-engine/Cargo.toml`
-
-- [x] Write fake-server tests for exact executable discovery, missing executable, version mismatch warning, worktree `cwd`, independent task processes, stderr capture bounds, early exit, hung initialization, and process-group cleanup.
-- [x] Observe RED.
-- [x] Implement `CodexExecutable`, `CodexProcess`, and `CodexProcessFactory`; launch with piped stdio/stderr and a distinct Unix process group.
-- [x] Add initialization and request timeouts, bounded stderr ring buffer, child-exit watcher, and explicit process states `starting/ready/stopping/exited/failed`.
-- [x] Never pass access tokens or GitHub environment variables into the child; construct an allowlisted environment plus required user/Codex paths.
-- [x] Run focused tests including two simultaneous fake tasks and commit: `Supervise task-owned Codex processes`.
-
-## Task 3: Initialize account state and persist thread identity
-
-**Files:**
-- Add: `crates/patchwright-engine/src/codex/session.rs`
-- Modify: `crates/patchwright-engine/src/store.rs`
-- Add: `crates/patchwright-engine/tests/codex_session.rs`
-
-- [x] Write tests for initialize→initialized order, account signed-in/signed-out/unavailable states, new thread start, saved thread resume after engine restart, stale thread fallback requiring operator confirmation, and no task transition before ready.
-- [x] Observe RED.
-- [x] Add `codex_sessions` and `codex_events` tables keyed by task and process generation; persist protocol version, executable version, account state, thread ID, last turn ID, last sequence, and bounded status.
-- [x] Implement `CodexSession` handshake and thread start/resume using task contract instructions and isolated worktree `cwd`.
-- [x] Atomically checkpoint thread identity with the task event that enters implementing.
-- [x] Run restart tests twice against the same database and commit: `Persist Codex task sessions`.
-
-## Task 4: Stream turns and render a native thread
-
-**Files:**
-- Modify: `crates/patchwright-engine/src/rpc.rs`
-- Add: `crates/patchwright-engine/src/codex/service.rs`
-- Add: `crates/patchwright-engine/tests/codex_rpc.rs`
-- Add: `Sources/PatchwrightCore/CodexModels.swift`
-- Modify: `Sources/PatchwrightCore/EngineClient.swift`
-- Modify: `Sources/PatchwrightCore/WorkspaceStore.swift`
-- Add: `Sources/PatchwrightApp/Views/CodexThreadView.swift`
-- Modify: `Sources/PatchwrightApp/Views/TaskDetailView.swift`
-- Add: `Tests/PatchwrightCoreTests/CodexPresentationTests.swift`
-
-- [x] Add engine tests for `codex.status`, `codex.start`, `codex.events`, `codex.turn.start`, and `codex.turn.steer`, including pagination cursor, duplicate client message ID, invalid task state, and input bounds.
-- [x] Add Swift tests for ordered text/reasoning/command/file-change/status events, streaming deltas, reconnect cursor, long content, unknown event, and send/steer disabled states.
-- [x] Observe RED in Rust and Swift.
-- [x] Implement a task-scoped event fan-in that normalizes app-server events and persists sequence numbers; Swift polls/cursors through the existing Unix socket until a later streaming transport is justified.
-- [x] Build `CodexThreadView` with native selectable transcript, operator composer, streaming status, command/file-change cards, interruption/failure/recovery states, and exact task/thread/turn details in inspector.
-- [x] Keep the task workbench mode stable across refresh with scene storage.
-- [x] Run focused tests, strict Swift Release build, staged app launch, and commit: `Embed the Codex task thread`.
-
-## Task 5: Bridge Codex runtime approvals without conflating authority
-
-**Files:**
-- Modify: `crates/patchwright-engine/src/codex/service.rs`
-- Modify: `crates/patchwright-engine/src/rpc.rs`
-- Add: `crates/patchwright-engine/tests/codex_approvals.rs`
-- Modify: `Sources/PatchwrightCore/CodexModels.swift`
-- Add: `Sources/PatchwrightApp/Views/CodexApprovalSheet.swift`
-- Modify: `Sources/PatchwrightCore/WorkspaceStore.swift`
-
-- [x] Add tests that a Codex command/file request creates only a `CodexRuntime` approval request; it cannot authorize network, GitHub delivery, workflow, or merge capability.
-- [x] Test exact request ID/process generation/turn binding, expiration, duplicate response idempotency, restart recovery, and invalidation after a new turn/process generation.
-- [x] Observe RED.
-- [x] Normalize approval requests into typed previews with command argv/cwd or file diff summary and feed accept/decline back to the originating app-server request.
-- [x] Add `codex.approval.resolve` RPC with optimistic generation check and append-only decision event.
-- [x] Render an exact approval sheet with target, reason, expiration, invalidation, and Approve once/Decline. Do not add global approval.
-- [x] Run all approval tests and commit: `Bridge exact Codex runtime approvals`.
-
-## Task 6: Implement interruption, cancellation, and crash recovery
-
-**Files:**
-- Modify: `crates/patchwright-engine/src/codex/process.rs`
-- Modify: `crates/patchwright-engine/src/codex/service.rs`
-- Modify: `crates/patchwright-engine/src/jobs.rs`
-- Add: `crates/patchwright-engine/tests/codex_cancellation.rs`
-- Modify: `Sources/PatchwrightCore/WorkspaceStore.swift`
-- Modify: `Sources/PatchwrightApp/Views/CodexThreadView.swift`
-
-- [x] Write fault tests for cancel before turn, during stream, during command, after app-server completion but before checkpoint, ignored interrupt, child crash, engine crash, and relaunch resume.
-- [x] Assert `turn/interrupt` is sent once; new turns/commands/GitHub work are prevented; after timeout the owned process group is terminated; unrelated processes survive; worktree/evidence remain.
-- [x] Observe RED.
-- [x] Implement cancellation-token propagation, graceful timeout, TERM then KILL only for the recorded group, and compare-and-set terminal checkpoint.
-- [x] Reconcile a completion received during cancellation before marking the task cancelled.
-- [x] Add Pause/Cancel UI with explicit semantics and retained-worktree message.
-- [x] Run fault matrix repeatedly and commit: `Cancel and recover Codex task execution`.
-
-## Task 7: Real local Codex integration gate
-
-**Files:**
-- Add: `script/smoke_codex.sh`
-- Add: `docs/audits/2026-07-14-embedded-codex.md`
-- Modify: `script/verify.sh`
-
-- [x] Create a disposable local Git repository containing a deterministic one-file task and verification command; never use Patchwright's own worktree for the smoke mutation.
-- [x] Verify installed Codex version/schema, account state, process isolation, new thread, one turn, streamed event persistence, runtime approval path if requested, file result, task interrupt, engine restart, and thread resume.
-- [x] Run the fake-server suite, complete Rust/Swift verification, real smoke, staged app interaction, relaunch, and secret/log scan.
-- [x] Record exact process/thread/turn IDs only in local evidence if they are not secrets; sanitize command output and repository content.
-- [x] Assign `integration-ready: Codex` only if the real disposable smoke passes; otherwise name the exact local/account blocker.
-- [x] Commit: `Verify embedded Codex end to end`.
diff --git a/docs/superpowers/plans/2026-07-13-github-app-delivery-queue.md b/docs/superpowers/plans/2026-07-13-github-app-delivery-queue.md
deleted file mode 100644
index e14c5e3..0000000
--- a/docs/superpowers/plans/2026-07-13-github-app-delivery-queue.md
+++ /dev/null
@@ -1,178 +0,0 @@
-# GitHub App Delivery and PR Queue Implementation Plan
-
-> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
-
-**Goal:** Replace development-only GitHub credentials with a production GitHub App broker, make ingestion cancellable, deliver exact approved writes, organize PR work explainably, and perform approval-gated exact-SHA merges or merge-queue handoff.
-
-**Architecture:** `patchwright-relay` owns GitHub App JWT/token minting and typed remote mutations. `patchwright-engine` owns durable jobs, action previews, policy/approval checks, ephemeral Git push coordination, queue decisions, and reconciliation. The Swift app only requests previews, collects scoped approvals, and displays durable results.
-
-**Tech Stack:** Rust, Tokio, reqwest, jsonwebtoken/RS256, macOS Keychain via Security framework or `security` subprocess with stdin-safe boundaries, SQLite, GitHub REST API, SwiftUI.
-
-## Global Constraints
-
-- Depend on the foundation approval/job model and embedded-Codex cancellation model.
-- `gh` remains development/read-only fallback. Production reads/writes use installation tokens.
-- Private key material lives in Keychain or a protected relay secret mount; installation tokens live only in memory and never appear in debug output.
-- Every remote mutation requires a fresh typed preview, exact action fingerprint, unexpired matching approval, idempotency identity, and ambiguous-result reconciliation.
-- No qualification write targets a production repository. A disposable GitHub App/repository requires a separately confirmed external test setup.
-- Never use admin bypass or treat labels/comments/repository text as authority.
-
----
-
-## Task 1: Model GitHub App configuration and secret storage
-
-**Files:**
-- Add: `crates/patchwright-relay/src/app_auth.rs`
-- Add: `crates/patchwright-relay/tests/app_auth.rs`
-- Modify: `crates/patchwright-relay/src/lib.rs`
-- Modify: `crates/patchwright-relay/Cargo.toml`
-- Add: `Sources/PatchwrightCore/GitHubAppModels.swift`
-- Modify: `Sources/PatchwrightCore/WorkspaceStore.swift`
-- Modify: `Sources/PatchwrightApp/Views/SettingsView.swift`
-
-- [ ] Add tests for PEM import validation, wrong algorithm, encrypted/invalid/truncated key, world-readable secret mount rejection, Keychain item reference persistence, and redacted Debug/Display/error output.
-- [ ] Observe RED.
-- [ ] Add `GitHubAppConfiguration { app_id, client_id, key_reference, api_base_url }`; persist only metadata/reference.
-- [ ] Add a narrow `PrivateKeyProvider` trait with macOS Keychain and protected-file implementations. Raw environment-variable private keys are rejected; an environment variable may contain only a path/reference.
-- [ ] Add Settings import through a file panel, app/installation health, credential source, permission summary, test connection, and actionable missing/revoked states.
-- [ ] Run tests plus a tracked-file/database/log secret scan and commit: `Add the GitHub App secret boundary`.
-
-## Task 2: Mint and cache scoped installation tokens
-
-**Files:**
-- Modify: `crates/patchwright-relay/src/app_auth.rs`
-- Add: `crates/patchwright-relay/src/installation.rs`
-- Add: `crates/patchwright-relay/tests/installation_tokens.rs`
-
-- [ ] Add deterministic-clock tests for RS256 JWT `iat` skew, `exp` maximum, `iss`, signature, installation discovery, repository/permission scoping, token expiry refresh, concurrent cache collapse, revocation, rate limit, and GitHub error redaction.
-- [ ] Observe RED.
-- [ ] Implement short-lived app JWT signing and installation lookup; mint tokens limited to the selected repository IDs and minimum requested permissions.
-- [ ] Cache installation tokens only in memory until a safety margin before expiration; key cache by installation+repository set+permission set.
-- [ ] Expose typed health/provenance without returning JWT/token/key material.
-- [ ] Run the mock GitHub suite under leak-detecting assertions and commit: `Broker scoped GitHub installation tokens`.
-
-## Task 3: Migrate reads and make sync a cancellable durable job
-
-**Files:**
-- Modify: `crates/patchwright-engine/src/github.rs`
-- Modify: `crates/patchwright-engine/src/rpc.rs`
-- Modify: `crates/patchwright-engine/src/jobs.rs`
-- Modify: `crates/patchwright-engine/src/store.rs`
-- Add: `crates/patchwright-engine/tests/github_jobs.rs`
-- Modify: `Sources/PatchwrightCore/GitHubModels.swift`
-- Modify: `Sources/PatchwrightCore/WorkspaceStore.swift`
-
-- [ ] Add tests for `github.sync.start/status/cancel`, one active sync per workspace, job progress, cancel before discovery/during fan-out/during response, request abort, engine restart, expired token refresh, installation-token primary path, and `gh` read-only fallback labeling.
-- [ ] Assert cancellation stops new fan-out, preserves every prior complete repository snapshot, never stores a partial current snapshot, and yields a durable cancelled summary.
-- [ ] Observe RED.
-- [ ] Inject a `GitHubCredentialProvider` into `GitHubSource`; route production reads through relay-issued installation tokens.
-- [ ] Replace blocking `github.sync` RPC with start/status/cancel; keep a temporary deprecated wrapper only if existing Swift migration tests require it.
-- [ ] Add cancellation tokens to discovery, semaphore acquisition, pagination, enrichment, and snapshot commit boundaries.
-- [ ] Update UI progress/cancel/partial/cancelled/retry states and commit: `Make GitHub ingestion cancellable and app-authenticated`.
-
-## Task 4: Define typed mutation previews and relay adapters
-
-**Files:**
-- Add: `crates/patchwright-core/src/github_actions.rs`
-- Add: `crates/patchwright-core/tests/github_action_contract.rs`
-- Modify: `crates/patchwright-core/src/lib.rs`
-- Add: `crates/patchwright-relay/src/mutations.rs`
-- Add: `crates/patchwright-relay/tests/mutations.rs`
-
-- [ ] Add contract tests for branch create/update, push intent, comment, pending/submitted review, inline review comments, thread reply/resolve, check run, draft PR create/update, update branch, close/supersede PR, enqueue, and merge.
-- [ ] Test payload bounds, repository/ref validation, exact expected SHAs, Markdown preview hashing, duplicate inline-comment positions, permission mapping, stable idempotency digest, and redacted serialization.
-- [ ] Observe RED.
-- [ ] Add `GitHubAction`, `GitHubActionPreview`, `RemotePrecondition`, `RemoteIdentity`, `RetryClass`, and `ReconciliationQuery`.
-- [ ] Implement relay REST adapters with exact API version/Accept headers, typed status handling, primary rate-limit metadata, and no automatic retry for ambiguous writes.
-- [ ] Run mock response matrices and commit: `Define typed GitHub delivery actions`.
-
-## Task 5: Execute approval-bound branch, push, comment, review, check, and draft PR delivery
-
-**Files:**
-- Add: `crates/patchwright-engine/src/delivery.rs`
-- Modify: `crates/patchwright-engine/src/rpc.rs`
-- Modify: `crates/patchwright-engine/src/store.rs`
-- Add: `crates/patchwright-engine/tests/delivery_flow.rs`
-- Add: `Sources/PatchwrightCore/DeliveryModels.swift`
-- Add: `Sources/PatchwrightApp/Views/DeliveryApprovalSheet.swift`
-- Modify: `Sources/PatchwrightCore/WorkspaceStore.swift`
-
-- [ ] Add end-to-end mock tests for preview→approval→fresh precondition→claim idempotency key→execute→record identity→re-fetch, plus expired/mismatched approval, changed head/base, changed payload, denied permission, definite failure, ambiguous timeout, restart reconciliation, and cancellation.
-- [ ] Add a Git push harness proving installation tokens do not appear in argv, remote URL, local/global Git config, reflog, environment dump, or logs; use a temporary credential-helper script/socket with restrictive permissions and remove it after the process exits.
-- [ ] Observe RED.
-- [ ] Implement `DeliveryService` with one serialized mutation lane per task and transactionally claimed action digests.
-- [ ] Add `delivery.preview`, `delivery.approve`, `delivery.execute`, `delivery.status`, and `delivery.cancel` RPC methods. Approval never executes implicitly.
-- [ ] Render an exact approval sheet with target, branch/PR, SHA range, changed files, remote body/review/check content, expiry, invalidations, and discrete actions—no Approve Everything.
-- [ ] Run the full mock/restart/secret suite and commit: `Execute approved GitHub delivery actions`.
-
-## Task 6: Build the explainable PR queue and workflow presets
-
-**Files:**
-- Add: `crates/patchwright-core/src/queue.rs`
-- Add: `crates/patchwright-core/tests/queue_contract.rs`
-- Add: `crates/patchwright-engine/src/queue.rs`
-- Modify: `crates/patchwright-engine/src/store.rs`
-- Modify: `crates/patchwright-engine/src/rpc.rs`
-- Add: `crates/patchwright-engine/tests/queue_recovery.rs`
-- Add: `Sources/PatchwrightCore/QueueModels.swift`
-- Modify: `Sources/PatchwrightCore/WorkspaceStore.swift`
-- Modify: `Sources/PatchwrightApp/Views/WorkspaceTableView.swift`
-
-- [ ] Add table-driven tests for all tiers, reason strings, dependency ordering, manual pins/reorder persistence, workflow presets, stale/unknown states, and deterministic tie-breakers.
-- [ ] Add overlap tests for dependency edges and changed-path intersections; one mutating task per repository; read-only assessment may coexist; a completed mutation cannot advance the next item until remote monitoring is fresh.
-- [ ] Observe RED.
-- [ ] Implement `QueueState`, `QueueTier`, `QueueReason`, `WorkflowPreset`, `DependencyEdge`, and pure assessment functions for Quick Wins, CI Rescue, Review Closure, Conflict Recovery, Dependency Chain, Security First, Release Train, Stale PR Triage, Draft Completion, Post-Merge Watch, Review Load Balancing, and Duplicate/Overlap Detection.
-- [ ] Persist queue items/decisions/manual order/decision input hash; recompute when source snapshot changes and retain the prior explanation in events.
-- [ ] Add queue start/pause/advance RPC and native table/toolbars/saved workflow selection.
-- [ ] Run queue/restart/Swift presentation tests and commit: `Organize pull requests into explainable workflows`.
-
-## Task 7: Monitor delivery and create bounded repair iterations
-
-**Files:**
-- Add: `crates/patchwright-engine/src/monitoring.rs`
-- Add: `crates/patchwright-engine/tests/monitoring_flow.rs`
-- Modify: `crates/patchwright-engine/src/rpc.rs`
-- Modify: `Sources/PatchwrightCore/WorkspaceStore.swift`
-
-- [ ] Add tests for CI pending/success/failure, requested changes, dismissed approval, new head SHA, base movement, conflict, inaccessible fork, rate limit, network loss, repair budget exhaustion, and post-push cancellation.
-- [ ] Observe RED.
-- [ ] Implement bounded polling with webhook wakeups, backoff/jitter, durable next-attempt time, fresh installation token, and repair iteration limits.
-- [ ] Re-enter assessing/planned for actionable repair; invalidate prior delivery/merge approvals; never let monitor text grant authority.
-- [ ] Stop the repository lane on unknown remote state or exhausted repair budget and show the exact blocker.
-- [ ] Run time-controlled tests and commit: `Monitor and repair delivered pull requests`.
-
-## Task 8: Add exact-SHA approval-gated merge and native merge-queue handoff
-
-**Files:**
-- Modify: `crates/patchwright-core/src/github_actions.rs`
-- Add: `crates/patchwright-core/tests/merge_approval.rs`
-- Modify: `crates/patchwright-relay/src/mutations.rs`
-- Add: `crates/patchwright-relay/tests/merge.rs`
-- Add: `crates/patchwright-engine/src/merge.rs`
-- Add: `crates/patchwright-engine/tests/merge_flow.rs`
-- Add: `Sources/PatchwrightCore/MergeModels.swift`
-- Add: `Sources/PatchwrightApp/Views/MergeApprovalSheet.swift`
-
-- [ ] Add tests binding approval to repository/installation/PR/exact head+base/method/check snapshot/review snapshot/expiry/idempotency key.
-- [ ] Add invalidation tests for any SHA/check/review/mergeability/branch-rule/permission change, new commit, conflict, stale snapshot, expired approval, automation kill switch, and admin bypass request.
-- [ ] Add direct merge tests that send expected head SHA and record merge SHA; add required merge-queue tests that enqueue, monitor merge group, and record final merge identity.
-- [ ] Add ambiguous timeout/restart reconciliation and post-merge regression tests that stop the repository queue.
-- [ ] Observe RED.
-- [ ] Implement fresh preflight immediately before execution and separate `merge.preview/approve/execute/status/cancel` RPC methods.
-- [ ] Render checks/reviews/method/SHAs/expiry/invalidation exactly; never combine merge approval with delivery approval.
-- [ ] Run the complete merge matrix and commit: `Gate merges on fresh exact pull request state`.
-
-## Task 9: Authorized disposable GitHub App E2E gate
-
-**Files:**
-- Add: `script/smoke_github_app.sh`
-- Add: `docs/audits/2026-07-13-github-app-delivery-queue.md`
-- Modify: `script/verify.sh`
-
-- [ ] Fail closed unless environment identifies an allowlisted disposable owner/repository and GitHub App installation. Print targets and require a one-shot explicit confirmation variable; reject the Patchwright production repository.
-- [ ] Exercise installation discovery, read sync, cancellation, task branch push, comment, check, pending/submitted review where supported, draft PR create/update, CI/review monitoring, approval invalidation on a changed SHA, approved merge or native merge-queue handoff, and post-merge queue advancement.
-- [ ] Revoke/expire credentials in the disposable setup and verify recovery without token persistence.
-- [ ] Audit database, process table, environment captures, Git config, logs, bundle, and evidence for secrets.
-- [ ] Run full local gates before and after E2E; record exact remote IDs/URLs and cleanup actions without deleting evidence needed for reconciliation.
-- [ ] Assign `integration-ready: GitHub delivery/merge` only if this authorized disposable workflow passes. Otherwise report `blocked:external` with the missing App/repository/permission.
-- [ ] Commit: `Verify GitHub App delivery and queue workflows`.
diff --git a/docs/superpowers/plans/2026-07-13-github-ingestion.md b/docs/superpowers/plans/2026-07-13-github-ingestion.md
deleted file mode 100644
index f2e0a00..0000000
--- a/docs/superpowers/plans/2026-07-13-github-ingestion.md
+++ /dev/null
@@ -1,64 +0,0 @@
-# GitHub Ingestion Implementation Plan
-
-**Goal:** Let an authenticated local user ingest and browse their accessible GitHub repositories, issues, pull requests, discussion, reviews, checks, and Actions runs without persisting credentials.
-
-**Architecture:** `gh auth token` is a local credential broker; the token exists only in process memory. A paginated Rust GitHub source maps REST payloads into stable domain records, SQLite atomically replaces each repository snapshot with sync provenance, JSON-RPC exposes sync/query methods, and the SwiftUI client presents account/repository/work-item navigation.
-
-**Tech Stack:** Rust 2024, Reqwest, Rusqlite, Tokio, GitHub REST API version `2026-03-10`, Swift 6.3, SwiftUI.
-
-## Global constraints
-
-- Initial live proof is read-only; no comments, labels, branches, reviews, checks, or pull requests are mutated.
-- Never persist or log bearer tokens, authorization headers, private repository bodies, or raw webhook secrets.
-- Pagination is mandatory and bounded by an explicit repository limit and per-resource page limit.
-- Issues returned with a `pull_request` key are not duplicated as issues.
-- A failed repository sync preserves its previous complete snapshot and records a sanitized failure.
-- UI shows exact connection, syncing, partial, empty, and failure states.
-
-### Task 1: GitHub source tracer
-
-- Add a mock-server integration test for authenticated user discovery, paginated repository discovery, issue/PR separation, and authorization-header presence.
-- Implement validated GitHub records, `GhCliCredentialBroker`, Link-header pagination, and `GitHubSource::snapshot`.
-- Run the focused test RED then GREEN.
-
-### Task 2: Atomic snapshot store
-
-- Add a restart test that writes account/repository/work-item/review/check/run records, replaces one repository snapshot, and proves failed replacement retains prior data.
-- Add schema-v2 tables and one-transaction `replace_github_snapshot` plus typed queries.
-- Run the focused test RED then GREEN.
-
-### Task 3: Engine ingestion surface
-
-- Add RPC/CLI tests for `github.status`, `github.sync`, `github.repositories`, and `github.repository`.
-- Add bounded orchestration, progress summaries, sanitized errors, and live `ingest-github` CLI output.
-- Run socket and CLI integration tests.
-
-### Task 4: Native GitHub workspace
-
-- Add Swift decoding/store tests for account, repository, issue/PR, review/check/run, empty, syncing, partial, and failure states.
-- Add GitHub sidebar, repository dashboard, work-item detail, sync toolbar/menu, and read-only provenance inspector.
-- Run Swift tests and warnings-as-errors release build.
-
-### Task 5: Live read-only proof and audit
-
-- Sync the authenticated `s1korrrr` account with a bounded repository limit into a disposable database and compare representative repository/PR counts with direct `gh api` reads.
-- Build/launch the app against that database, exercise sync/navigation/relaunch/error recovery, and inspect logs.
-- Run security/diff audit, full verification, smoke, exact app launch, commit, push, and update draft PR #1.
-
-## Progress
-
-- [x] Authenticated, same-origin, paginated GitHub source with redacted credentials.
-- [x] Atomic SQLite snapshots with account, repository, issue/PR, discussion, check, and Actions records.
-- [x] JSON-RPC sync/query surface with bounded four-way repository fan-out and partial-failure preservation.
-- [x] Native sidebar, repository/work-item browser, search, sync state, failure state, and provenance inspector.
-- [x] Live disposable sync: 51/51 repositories, 344 work items, 521 discussion records, 1,092 checks, and 1,298 workflow runs with no failures.
-- [x] Direct API parity for `s1korrrr/patchwright` and `s1korrrr/devscope`.
-- [x] Security regressions cover cross-origin pagination credential forwarding and database file permissions.
-- [x] Final packaged-app interaction sweep, full verification, commit, push, and PR update.
-
-## Decisions and outcomes
-
-- GitHub CLI remains the local credential broker for this stage; GitHub App installation credentials remain an external deployment concern.
-- The initial account snapshot is intentionally read-only and bounded to 100 repositories and 1,000 records per resource class per repository.
-- Computer Use clicks emitted paired negative-geometry AppKit faults, while the same Release app auto-selected the large repository without Computer Use and emitted no such faults. The audit therefore records them as an automation-bridge artifact rather than an ordinary app-runtime defect.
-- A second engine process now refuses to replace a healthy Unix socket, so app relaunches cannot disconnect the existing owner.
diff --git a/docs/superpowers/plans/2026-07-13-orchestrator-foundation.md b/docs/superpowers/plans/2026-07-13-orchestrator-foundation.md
deleted file mode 100644
index 6063787..0000000
--- a/docs/superpowers/plans/2026-07-13-orchestrator-foundation.md
+++ /dev/null
@@ -1,173 +0,0 @@
-# Orchestrator Foundation Implementation Plan
-
-> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
-
-**Goal:** Establish Patchwright's restart-safe task, approval, job, repository-binding, sorting, conversion, and native workbench foundation.
-
-**Architecture:** `patchwright-core` owns pure typed lifecycle, source, approval, queue-sort, and contract rules. `patchwright-engine` commits state changes and append-only events atomically in SQLite and exposes bounded JSON-RPC. `PatchwrightCore` mirrors wire types and deterministic presentation logic; `PatchwrightApp` renders a native split/table/inspector interface without executing mutations.
-
-**Tech Stack:** Rust 1.91, serde, chrono, rusqlite, Tokio, Swift 6.3, SwiftUI on macOS 26, Swift Testing/XCTest.
-
-## Global Constraints
-
-- Work only on `feat/andrzej_agent_sota_lab`; preserve unrelated changes and commit only intentional files.
-- Use RED/GREEN/REFACTOR for every behavior change. A focused failing assertion must be observed before production edits.
-- Treat GitHub/repository text as untrusted context. It may populate a contract but never grant capabilities or approvals.
-- Persist state plus append-only event in one transaction. Migrations are additive and restart-safe.
-- Keep all sort/filter results deterministic with explicit final tie-breakers.
-- Do not perform a live GitHub write in this plan.
-
----
-
-## Task 1: Migrate the typed lifecycle
-
-**Files:**
-- Modify: `crates/patchwright-core/src/domain.rs`
-- Modify: `crates/patchwright-core/tests/domain_contract.rs`
-- Modify: `Sources/PatchwrightCore/Models.swift`
-- Modify: `Tests/PatchwrightCoreTests/ModelsTests.swift`
-
-- [x] Add a Rust contract test for the approved happy path: `discovered → assessing → planned → awaitingPreparationApproval → preparing → implementing → verifying → reviewing → awaitingDeliveryApproval → delivering → monitoring → awaitingMergeApproval → merging → completed`.
-- [x] Add tests proving skipped approvals fail; any nonterminal state may enter `paused`, `blocked`, `failed`, or `cancelled`; terminal states cannot leave; `paused` and `blocked` resume only to their recorded `resume_state`.
-- [x] Run `cargo test -p patchwright-core --test domain_contract task_` and capture the missing-variant/transition RED.
-- [x] Replace `AwaitingApproval` with `AwaitingPreparationApproval`; add `Assessing`, `Paused`, `Blocked`, `AwaitingMergeApproval`, and `Merging` in Rust and Swift.
-- [x] Add `TaskInterruption { state, resume_state, reason }` and require a nonempty reason for paused/blocked/failed/cancelled transitions.
-- [x] Mirror attention rules in Swift: preparation, delivery, merge, blocked, and failed require attention.
-- [x] Run the focused Rust and Swift model tests and confirm GREEN.
-- [x] Commit: `Model the durable task lifecycle`.
-
-## Task 2: Add typed sources, repository bindings, and contracts
-
-**Files:**
-- Modify: `crates/patchwright-core/src/domain.rs`
-- Modify: `crates/patchwright-core/src/lib.rs`
-- Add: `crates/patchwright-core/src/contract.rs`
-- Add: `crates/patchwright-core/tests/task_contract.rs`
-
-- [x] Write tests for `TaskSource::LocalRequest`, `GitHubIssue`, and `GitHubPullRequest`, including immutable repository/item URL, snapshot time, and PR base/head refs and SHAs.
-- [x] Write boundary tests rejecting an empty repository name, non-HTTPS GitHub URLs, zero installation/repository IDs, missing PR SHAs, relative local roots, empty acceptance criteria, and duplicate dependency IDs.
-- [x] Run `cargo test -p patchwright-core --test task_contract` and observe RED.
-- [x] Add `RepositoryBinding`, `TaskSource`, `TaskContract`, `InstructionDigest`, `VerificationCommand`, `RiskClass`, and `SensitivePath` with private fields plus validating constructors.
-- [x] Keep `Task` summary-compatible while adding `source`, `repository_binding_id`, `contract_version`, and optional interruption/checkpoint references with serde defaults for old rows.
-- [x] Export the new public types and run focused tests, then `cargo test -p patchwright-core`.
-- [x] Commit: `Add typed task contracts and repository bindings`.
-
-## Task 3: Replace capability-only approvals with exact action fingerprints
-
-**Files:**
-- Modify: `crates/patchwright-core/src/policy.rs`
-- Add: `crates/patchwright-core/tests/approval_contract.rs`
-- Modify: `crates/patchwright-core/src/lib.rs`
-
-- [x] Add tests for four `ApprovalClass` values: `CodexRuntime`, `LocalCapability`, `GitHubDelivery`, and `Merge`.
-- [x] Add tests proving an approval is rejected for a different task, repository, capability, action digest, head/base SHA, policy hash, instruction hash, expiration, or invalidation generation.
-- [x] Add a test proving `MergePullRequest` is approval-required—not globally denied—and only a `Merge` approval with exact PR state authorizes it.
-- [x] Run `cargo test -p patchwright-core --test approval_contract` and observe RED.
-- [x] Add `ActionFingerprint` containing task ID, repository ID/name, optional PR/branch/head/base, typed payload SHA-256, policy/instruction hashes, and invalidation generation.
-- [x] Replace `Approval::for_capability` with `Approval::new(class, capability, fingerprint, approver, now, expires_at)` and `Policy::authorize(capability, fingerprint, approval, now)`.
-- [x] Preserve the automation kill switch and deny admin bypass as a separate non-approvable capability.
-- [x] Update existing tests/callers, run all core tests, and commit: `Bind approvals to exact actions`.
-
-## Task 4: Persist schema versions, checkpoints, jobs, approvals, and bindings
-
-**Files:**
-- Modify: `crates/patchwright-engine/src/store.rs`
-- Add: `crates/patchwright-engine/src/jobs.rs`
-- Modify: `crates/patchwright-engine/src/lib.rs`
-- Add: `crates/patchwright-engine/tests/durable_jobs.rs`
-- Modify: `crates/patchwright-engine/tests/recovery.rs`
-
-- [x] Write migration tests that open a Stage 1–3 database fixture, retain existing task/GitHub payloads, and add `schema_migrations`, `repository_bindings`, `task_contracts`, `approvals`, `jobs`, `job_events`, and `task_checkpoints`.
-- [x] Write atomicity tests proving task state/event/checkpoint commit together and a simulated failure leaves all three unchanged.
-- [x] Write restart tests for queued/running/cancelling/cancelled/succeeded/failed jobs and recovery of a running job to `interrupted`, never silently `running`.
-- [x] Run `cargo test -p patchwright-engine --test durable_jobs --test recovery` and observe RED.
-- [x] Add monotonic integer schema migrations inside one `BEGIN IMMEDIATE` transaction.
-- [x] Implement `JobId`, `JobKind`, `JobState`, `CancellationState`, `JobCheckpoint`, and store methods for compare-and-set transitions and append-only job events.
-- [x] Store approval payloads and action digests, but never source bodies, command output, or credentials in job summary columns.
-- [x] Run focused tests, restart them against the same temporary database, then run all engine tests.
-- [x] Commit: `Persist durable jobs and checkpoints`.
-
-## Task 5: Enrich GitHub snapshots for sorting and queue assessment
-
-**Files:**
-- Modify: `crates/patchwright-engine/src/github.rs`
-- Modify: `crates/patchwright-engine/tests/github_source.rs`
-- Modify: `Sources/PatchwrightCore/GitHubModels.swift`
-- Modify: `Tests/PatchwrightCoreTests/ModelsTests.swift`
-
-- [x] Add mock-server tests for repository `pushed_at`, default-branch commit SHA/date, open PR count, failing-check count, permissions, and installation ID.
-- [x] Add PR fixture tests for created time, head commit time, review activity time, review decision, mergeability/conflict state, additions/deletions/files, base/head refs/SHAs, fork identity, and update time.
-- [x] Run the focused source tests and capture decoding RED.
-- [x] Extend `GitHubRepository` and `GitHubWorkItem` with serde aliases/defaults that retain backward readability.
-- [x] Fetch missing default-branch commit and detailed PR fields with bounded concurrency; preserve a complete prior snapshot when enrichment fails.
-- [x] Mirror the wire model in Swift using `Date` values decoded by the shared ISO-8601 decoder.
-- [x] Run Rust and Swift focused tests and commit: `Ingest sortable repository and pull request metadata`.
-
-## Task 6: Implement deterministic sort and filter policies
-
-**Files:**
-- Add: `crates/patchwright-core/src/sorting.rs`
-- Add: `crates/patchwright-core/tests/sorting_contract.rs`
-- Modify: `crates/patchwright-core/src/lib.rs`
-- Add: `Sources/PatchwrightCore/WorkspaceSorting.swift`
-- Add: `Tests/PatchwrightCoreTests/WorkspaceSortingTests.swift`
-
-- [x] Add table-driven Rust and Swift tests for all approved repository and PR sort modes, ascending/descending behavior, nil timestamps, unknown CI/review state, and exact final tie-breakers (`full_name`, then repository ID; PR number, then item ID).
-- [x] Add filter tests for draft/open, author, assignee, label, review, CI, conflicts, age, queue state, and active Codex work; multiple active filters combine with AND semantics.
-- [x] Observe RED in both languages.
-- [x] Implement pure `RepositorySort`, `PullRequestSort`, `WorkspaceFilter`, and comparator functions. Define nil/unknown as last in either presentation direction rather than using epoch sentinels.
-- [x] Add Codable Swift preferences for per-workspace sort/filter state; do not bind them to global process state in tests.
-- [x] Run the focused parity fixtures in Rust and Swift and commit: `Add deterministic workspace sorting and filtering`.
-
-## Task 7: Convert an issue or PR into a persisted task
-
-**Files:**
-- Add: `crates/patchwright-engine/src/conversion.rs`
-- Modify: `crates/patchwright-engine/src/rpc.rs`
-- Modify: `crates/patchwright-engine/src/store.rs`
-- Add: `crates/patchwright-engine/tests/task_conversion.rs`
-- Modify: `Sources/PatchwrightCore/EngineClient.swift`
-- Modify: `Sources/PatchwrightCore/WorkspaceStore.swift`
-
-- [x] Add tests for `task.createFromGitHub` using issue and PR snapshots, duplicate conversion idempotency, missing/stale snapshot, missing repository binding, inaccessible fork, and exact source SHA retention.
-- [x] Observe JSON-RPC method-not-found RED.
-- [x] Implement `TaskConversionService` that reads a complete snapshot, builds the contract, records source snapshot identity, proposes repository binding/managed clone, and atomically inserts task+contract+event.
-- [x] Return a typed `ConversionPreview` before worktree creation. No capability is granted by conversion.
-- [x] Add `repository.bind` and `task.createFromGitHub` RPC methods with bounded string/ID validation and stable error codes.
-- [x] Add Swift client/store commands that refresh the created task and select it.
-- [x] Run RPC/store/Swift tests and commit: `Convert GitHub work items into durable tasks`.
-
-## Task 8: Build the native queue/workbench shell
-
-**Files:**
-- Modify: `Sources/PatchwrightApp/Views/ContentView.swift`
-- Modify: `Sources/PatchwrightApp/Views/SidebarView.swift`
-- Add: `Sources/PatchwrightApp/Views/WorkspaceTableView.swift`
-- Modify: `Sources/PatchwrightApp/Views/TaskDetailView.swift`
-- Modify: `Sources/PatchwrightApp/Views/GitHubRepositoryView.swift`
-- Modify: `Sources/PatchwrightApp/Views/GitHubInspector.swift`
-- Modify: `Sources/PatchwrightCore/WorkspaceStore.swift`
-- Add: `Tests/PatchwrightCoreTests/WorkspacePresentationTests.swift`
-
-- [x] Add store tests for primary navigation, table selection, sort persistence, conversion preview/success/failure, attention counts, relative/exact timestamps, and empty/loading/partial/cancelled/blocked states.
-- [x] Observe RED before view changes.
-- [x] Use adjustable `NavigationSplitView`; add Queue, Repositories, Active Tasks, Awaiting Approval, Monitoring, and Completed sources.
-- [x] Use native sortable `Table` columns for priority, repository, PR, queue state, CI, review, conflict/base, latest commit, updated time, and assigned task. Remove fixed-width manual columns.
-- [x] Add task workbench tabs Overview, Codex, Changes, Verification, Delivery, Merge and an optional inspector for evidence/approvals/instructions/credentials.
-- [x] Add outcome-oriented help and accessibility labels to icon-only actions. Display relative localized dates with exact values in details/help.
-- [x] Run Swift tests, `swift build -c release -Xswiftc -warnings-as-errors`, and `./script/build_and_run.sh --verify`.
-- [ ] Manually verify keyboard navigation, resize, Light/Dark, Reduce Motion, long titles/bodies, and explicit error/empty states; record evidence in `docs/audits/2026-07-13-orchestrator-foundation.md`. Dark appearance, resize, long body, search, and empty/error states passed; Light appearance and Reduce Motion remain a manual follow-up.
-- [x] Commit: `Build the native orchestration workbench`.
-
-## Task 9: Foundation verification gate
-
-**Files:**
-- Modify: `script/verify.sh`
-- Add: `docs/audits/2026-07-13-orchestrator-foundation.md`
-
-- [x] Add exact foundation focused suites to the verification script without weakening existing gates.
-- [x] Run `cargo fmt --all -- --check`, strict Clippy, all Rust tests, all Swift tests, and warnings-as-errors Release build.
-- [x] Run disposable migration/restart, issue conversion, PR conversion, sort/filter parity, staged-app launch, relaunch persistence, and log checks. The audit records the Computer Use/native-Table geometry diagnostic separately from app crash/hang evidence.
-- [x] Scan tracked files and built artifacts for tokens/private keys and confirm database mode `0600`.
-- [x] Record exact commands, counts, failures, retained rollback, and readiness label; do not claim Codex/GitHub-write/release readiness from this gate.
-- [x] Commit: `Verify the orchestrator foundation`.
diff --git a/docs/superpowers/plans/2026-07-13-patchwright-stages-1-3.md b/docs/superpowers/plans/2026-07-13-patchwright-stages-1-3.md
deleted file mode 100644
index 27158bf..0000000
--- a/docs/superpowers/plans/2026-07-13-patchwright-stages-1-3.md
+++ /dev/null
@@ -1,119 +0,0 @@
-# Patchwright Stages 1–3 Implementation Plan
-
-> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
-
-**Goal:** Build a native macOS control plane, durable local execution engine, and verified GitHub lifecycle relay that complete one issue-to-draft-PR workflow with explicit approvals and evidence.
-
-**Architecture:** A SwiftUI client consumes a narrow JSON-RPC 2.0 protocol over a Unix socket. A shared Rust library owns validated domain state and policy, while separate engine and relay binaries own local execution and GitHub HTTP/webhook I/O.
-
-**Tech Stack:** Swift 6.3/SwiftUI/Foundation Models, Rust 2024/Tokio/Axum/Serde/Rusqlite, SQLite, Git CLI, Codex App Server, GitHub REST API.
-
-## Global Constraints
-
-- Target macOS 26 or newer on Apple silicon; use semantic SwiftUI materials and native desktop navigation.
-- Rust packages use edition 2024, rust-version 1.85, `unsafe_code = "warn"`, and strict Clippy lints.
-- No merge capability, long-lived personal token, shell-string RPC, credential logging, or automatic workflow modification.
-- All tasks use isolated Git worktrees; all GitHub mutations require action-specific approval and idempotency evidence.
-- Repository text and GitHub comments are untrusted context, not policy authority.
-
----
-
-### Task 1: Shared domain and policy
-
-**Files:** `Cargo.toml`, `crates/patchwright-core/Cargo.toml`, `crates/patchwright-core/src/{lib,domain,policy,instructions}.rs`, `crates/patchwright-core/tests/domain_contract.rs`
-
-**Interfaces:** Produce `Task`, `TaskState`, `TaskEvent`, `Capability`, `Approval`, `Finding`, `Evidence`, `InstructionSource`, `EffectiveInstructions`, and `Policy::authorize`.
-
-- [ ] Write a failing public-interface test proving invalid task transitions and merge authorization are rejected.
-- [ ] Run `cargo test -p patchwright-core --test domain_contract`; expect failing imports.
-- [ ] Add validated domain values, transition rules, and fail-closed capability policy.
-- [ ] Run the focused test; expect all assertions to pass.
-
-### Task 2: Durable event store
-
-**Files:** `crates/patchwright-engine/src/store.rs`, `crates/patchwright-engine/tests/recovery.rs`
-
-**Interfaces:** Produce `EventStore::open`, `append`, `load_task`, `record_approval`, `claim_delivery`, and `complete_delivery`.
-
-- [ ] Write a restart test that appends task events, reopens SQLite, and rejects a duplicate delivery key.
-- [ ] Run `cargo test -p patchwright-engine --test recovery`; expect a missing `EventStore` failure.
-- [ ] Add schema migration in a transaction and append-only event persistence.
-- [ ] Re-run the focused test; expect restart state and idempotency assertions to pass.
-
-### Task 3: Repository, instruction, and worktree services
-
-**Files:** `crates/patchwright-engine/src/{repository,worktree,command}.rs`, `crates/patchwright-engine/tests/worktree_flow.rs`
-
-**Interfaces:** Produce `RepositoryService::inspect`, `InstructionResolver::resolve_for_paths`, `WorktreeService::prepare`, and `CommandRunner::run(CommandSpec)`.
-
-- [ ] Write a temporary-Git-repository test proving nested instruction precedence, branch isolation, argv-safe execution, timeout capture, and base-checkout preservation.
-- [ ] Run the focused integration test and confirm it fails before implementation.
-- [ ] Implement Git subprocesses with explicit argv, canonical writable roots, sanitized environment, timeouts, and process-group cancellation.
-- [ ] Re-run and confirm every observable behavior passes.
-
-### Task 4: JSON-RPC and Codex adapters
-
-**Files:** `crates/patchwright-engine/src/{rpc,codex}.rs`, `crates/patchwright-engine/src/main.rs`, `crates/patchwright-engine/tests/rpc_socket.rs`
-
-**Interfaces:** Produce RPC methods `system.health`, `repository.inspect`, `instructions.resolve`, `task.create`, `task.approve`, `task.prepare`, `task.verify`, `task.review`, `task.deliver`, `task.cancel`, and `task.timeline`.
-
-- [ ] Write a Unix-socket test proving health, invalid-parameter, create, approve, and timeline responses.
-- [ ] Run the focused test and capture the connection/method failure.
-- [ ] Add newline-delimited JSON-RPC framing, typed error mapping, connection limits, and Codex App Server process supervision.
-- [ ] Re-run the test and then `codex app-server generate-json-schema --out /tmp/patchwright-codex-schema` to validate local availability.
-
-### Task 5: GitHub App lifecycle
-
-**Files:** `crates/patchwright-relay/src/{main,webhook,github,state}.rs`, `crates/patchwright-relay/tests/webhook_flow.rs`
-
-**Interfaces:** Produce `verify_signature`, `WebhookEvent::parse`, `DeliveryStore::accept_once`, and `GitHubClient` operations for installation token, draft PR, check run, pending review, reply, and workflow status.
-
-- [ ] Write a router test with signed and tampered payloads plus duplicate delivery IDs.
-- [ ] Run the focused test and confirm the route is absent.
-- [ ] Add constant-time HMAC verification before JSON parsing, bounded bodies, sanitized event mapping, idempotency, and typed GitHub API errors.
-- [ ] Re-run and confirm invalid signatures cause no state write.
-
-### Task 6: Native client domain and engine transport
-
-**Files:** `Package.swift`, `Sources/PatchwrightCore/{Models,EngineClient,WorkspaceStore,FoundationReviewProvider}.swift`, `Tests/PatchwrightCoreTests/{ModelsTests,WorkspaceStoreTests}.swift`
-
-**Interfaces:** Produce `EngineServing`, `UnixEngineClient`, `WorkspaceStore`, `ReviewProviding`, and Codable mirrors of the public RPC domain.
-
-- [ ] Write Swift tests for RPC decoding, task presentation, store recovery/error state, and explicit Foundation Models unavailability.
-- [ ] Run `swift test`; expect missing module/type failures.
-- [ ] Add the public protocols, actor-safe transport, observable store, and availability-checked review provider.
-- [ ] Re-run `swift test`; expect all tests to pass.
-
-### Task 7: Native macOS workflow
-
-**Files:** `Sources/PatchwrightApp/App/PatchwrightApp.swift`, `Sources/PatchwrightApp/Views/{ContentView,SidebarView,TaskDetailView,EvidenceInspector,SettingsView}.swift`, `Sources/PatchwrightApp/Support/AppCommands.swift`
-
-**Interfaces:** Consume `WorkspaceStore`; produce a `WindowGroup`, `Settings` scene, sidebar/task selection, toolbar actions, approval sheets, searchable timelines, inspector evidence, menus, and keyboard shortcuts.
-
-- [ ] Add deterministic preview fixtures for empty, approval, running, failed, and completed states.
-- [ ] Build with `swift build -c release -Xswiftc -warnings-as-errors`; capture the first missing view failure.
-- [ ] Add native adaptive views with accessibility labels, Reduce Motion-aware progress, explicit errors, and disabled-action reasons.
-- [ ] Rebuild and confirm warnings-as-errors passes.
-
-### Task 8: Product scripts, configuration, and smoke
-
-**Files:** `script/{build_and_run,verify,smoke}.sh`, `.codex/environments/environment.toml`, `.engineering-agent/project.yml`, `README.md`, `docs/{operations,github-app,security,release-checklist}.md`
-
-**Interfaces:** Produce `./script/verify.sh` for all checks, `./script/build_and_run.sh --verify` for the real bundle, and `./script/smoke.sh` for a disposable end-to-end local lifecycle.
-
-- [ ] Add the scripts and run shell syntax checks.
-- [ ] Run `./script/verify.sh`; fix only concrete failures until Rust tests, Clippy, Swift tests, and Release build pass.
-- [ ] Run `./script/smoke.sh`; verify durable task/worktree/evidence state survives an engine restart.
-- [ ] Run `./script/build_and_run.sh --verify`; confirm the exact staged `.app` process is alive.
-
-### Task 9: Final hardening and publication
-
-**Files:** All intentional repository files; no credentials, local databases, sockets, worktrees, or build products.
-
-**Interfaces:** Produce one coherent commit and a draft pull request targeting the remote default branch.
-
-- [ ] Run secret, tracked-artifact, dependency, and full-diff inspection.
-- [ ] Re-run `./script/verify.sh`, smoke, and app process verification from final source.
-- [ ] Stage explicit paths, commit `build Patchwright stages 1-3`, and inspect the exact staged diff.
-- [ ] Push `feat/andrzej_agent_sota_lab` and open a draft PR with scope, safety boundary, checks, and external GitHub App/App Store blockers.
-
diff --git a/docs/superpowers/plans/2026-07-14-live-workflow-e2e-closure.md b/docs/superpowers/plans/2026-07-14-live-workflow-e2e-closure.md
deleted file mode 100644
index 5937759..0000000
--- a/docs/superpowers/plans/2026-07-14-live-workflow-e2e-closure.md
+++ /dev/null
@@ -1,66 +0,0 @@
-# Patchwright live workflow end-to-end closure
-
-## Goal
-
-- Prove that an ingested issue or pull request can become a durable Patchwright task, visibly run through an embedded Codex thread, create and push a branch, publish progress/checks/comments/reviews, resolve review work, deliver a draft pull request, and complete an exact-SHA approval-gated merge into the configured base branch.
-- Make failures and in-progress work visible in the native app with durable recovery evidence instead of relying on terminal-only status.
-
-## Audit Contract
-
-- App: `/Users/s1kor/.patchwright/staged/Patchwright.app`; SwiftPM workspace `/Users/s1kor/dev/apps/patchwright`; bundle ID `ai.patchwright.app`; launch through `./script/build_and_run.sh --verify`.
-- Platform: native macOS app backed by the local Rust engine, SQLite state, Codex app-server, GitHub App installation-token broker, and GitHub REST/git delivery adapters.
-- Live mutation target: private disposable repository `s1korrrr/patchwright-e2e-sandbox` only. Patchwright PR `s1korrrr/patchwright#1`, its branch, and production repositories are read-only during this audit.
-- Allowed live actions in the sandbox: create disposable issues, task branches, commits, checks, comments, review threads/reviews, draft PRs, exact-SHA approvals, and merges into the sandbox default branch; reconcile and close test-only artifacts when the workflow owns them.
-- Forbidden: bypass branch protection, use admin merge, expose credentials, log tokens/private keys, mutate unrelated repositories, or merge Patchwright PR #1.
-- Evidence: exact commands, GitHub object URLs/SHAs, SQLite/job events, Codex thread/turn state, app screenshots/accessibility trees, engine/app logs, restart/cancellation proof, and a committed audit report.
-- Readiness target: interaction-clean for the complete sandbox workflow; release-candidate signing/notarization remains an independent gate.
-
-## Failure Hypotheses
-
-- The UI exposes previews but does not drive the real typed lifecycle or lacks actionable progress after task creation.
-- Codex supervision can start locally while thread/turn streaming, recovery, cancellation, or task ownership is not visible or durable.
-- GitHub branch, push, check, comment, review, draft-PR, or merge adapters pass mocks but fail with production installation tokens or stale SHA preconditions.
-- Review resolution or merge approval can be applied to a stale head SHA, repeated after restart, or confused with native GitHub merge-queue handoff.
-- The queue can advance overlapping mutations or report completion before remote GitHub state reconciles.
-
-## Scenario Matrix
-
-1. Build, launch, sync, relaunch, and confirm production GitHub App health in the native UI.
-2. Ingest a disposable sandbox issue and existing PR; inspect source content, task preview, and acceptance criteria.
-3. Create a typed task and verify visible queued/running/Codex progress, persisted thread and turn identifiers, streamed output, and cancellation/restart semantics.
-4. Run branch creation, safe commit, push, progress check, issue/PR comment, draft-PR delivery, review submission, review-thread resolution, and remote reconciliation.
-5. Verify stale-head rejection, exact-SHA merge approval, branch-protection/no-admin-bypass behavior, merge execution, and recorded merge SHA.
-6. Exercise queue sorting/WIP gates, failure/retry states, app relaunch recovery, and final completed state.
-7. Re-run focused/full tests, real Codex smoke, disposable GitHub E2E, native interaction/log checks, and security/secret scans; update the audit with the weakest truthful readiness label.
-
-## Final Closure Slice
-
-1. Ingest GraphQL pull-request review threads with their opaque node IDs, exact PR identity, resolved/outdated state, and viewer resolution authority. Keep thread IDs as untrusted opaque values and never infer them from REST comment IDs.
-2. Add a typed `resolveReviewThread` action with exact PR/head preconditions, delivery approval, stable idempotency, scoped `pull_requests:write` permission, server-side ownership revalidation, and GraphQL mutation result verification.
-3. Render unresolved threads in the task Delivery workbench and expose only a preview action; reuse the existing approval sheet and execute boundary.
-4. Add a read-only `task.reconcileGitHub` RPC. Re-fetch the task's exact issue or PR through the installation token, require matching repository/number/head identity, and atomically advance only remotely closed/merged tasks through the remaining legal lifecycle states.
-5. Reconcile the two pre-fix sandbox tasks, relaunch the app, and verify they move from Active Tasks to Completed with durable timeline evidence.
-6. Create one disposable open sandbox PR with an unresolved inline thread, ingest it, resolve it through Patchwright's preview/approval/execute path, and re-ingest to prove `isResolved=true`.
-7. Repeat full verification, real Codex smoke, staged runtime/UI inspection, remote GitHub readback, release readiness, secret scan, commit, and branch push. Do not merge Patchwright PR #1.
-
-## Final Closure Decisions
-
-- Review-thread discovery uses GitHub GraphQL because REST review comments do not expose the `PullRequestReviewThread` node ID required by `resolveReviewThread`.
-- Reconciliation is a read-only remote verification followed by a local durable transition. It never performs a GitHub write and cannot accept an operator-supplied final state.
-- A merged PR must retain the task's captured head SHA; a closed-but-unmerged PR is not treated as completed unless the task explicitly executed an approved close action.
-- Historical records are reconciled by the same production RPC used after ambiguous outcomes, not by direct SQLite edits.
-
-## Rollback
-
-- Keep all live mutations confined to test objects in `patchwright-e2e-sandbox`. Preserve local task/evidence state for diagnosis. Revert cohesive source/test commits in reverse order; never guess at remote rollback or force-push a shared branch.
-
-## Progress Log
-
-- 2026-07-14: User requested a real end-to-end audit of issue/PR resolution, Codex progress visibility, GitHub delivery/review/merge, and recovery. Baseline audit started from clean branch `feat/andrzej_agent_sota_lab` with the local test app building and launching.
-- 2026-07-14: Live sandbox issue #3 became a typed task and exact worktree commit `078ee96c`; Patchwright pushed the task branch and created PR #5 through App-token delivery.
-- 2026-07-14: PR #5 became a second typed task. Embedded Codex persisted 430 review events, Patchwright posted an exact-head review, and separately approved merge delivery produced sandbox main commit `0dd94eec` while closing issue #3.
-- 2026-07-14: Global sync cancellation reached durable `cancelled/acknowledged` state after 15 repositories. Failed-delivery retry, ready-for-review, visible turn-completion refresh, and atomic merge-to-Completed reconciliation were added with regressions.
-- 2026-07-14: Full verify, engine smoke, real Codex smoke, staged runtime, canonical bundle metadata validation, strict code-sign verification, native workbench inspection, and remote GitHub reconciliation passed. A Developer ID identity is installed; Apple distribution remains blocked by the missing `notarytool` Keychain profile and clean-machine evidence.
-- 2026-07-14: GraphQL review-thread ingestion and exact typed resolution passed on sandbox PR #6. GitHub rejected installation identity for resolution, so the approved action now narrowly falls back to the non-persisted signed-in user token; a second App-token snapshot proved only the intended thread resolved.
-- 2026-07-14: Read-only `task.reconcileGitHub` verified issue #3 closed-completed and PR #5 merged at the captured head, then moved both pre-fix task records to Completed through atomic lifecycle events rather than direct database edits.
-- 2026-07-14: Clean-commit release assembly found a valid Developer ID identity, then reached the macOS Keychain private-key approval prompt. The attempt was cancelled safely. The `Patchwright` notary profile is absent, so signing needs one local Keychain approval and notarization remains externally blocked until `notarytool store-credentials Patchwright` is completed.
diff --git a/docs/superpowers/plans/2026-07-15-direct-open-source-release.md b/docs/superpowers/plans/2026-07-15-direct-open-source-release.md
deleted file mode 100644
index ffa55fb..0000000
--- a/docs/superpowers/plans/2026-07-15-direct-open-source-release.md
+++ /dev/null
@@ -1,349 +0,0 @@
-# Patchwright Direct Open-Source Release Implementation Plan
-
-> **For agentic workers:** REQUIRED SUB-SKILL: Use superpowers:subagent-driven-development (recommended) or superpowers:executing-plans to implement this plan task-by-task. Steps use checkbox (`- [ ]`) syntax for tracking.
-
-**Goal:** Publish Patchwright 0.1.0 as a fully open-source, Developer ID-signed, Apple-notarized, self-updating macOS technical beta through an immutable GitHub Release.
-
-**Architecture:** Keep source verification, candidate packaging, and public promotion as separate fail-closed boundaries. The app integrates pinned Sparkle 2.9.2 for signed updates; release scripts assemble and sign all nested code, generate license/SBOM evidence, and produce a digest-bound candidate manifest; promotion consumes exact-digest clean-machine and integration evidence without rebuilding.
-
-**Tech Stack:** Swift 6.2+/SwiftPM, SwiftUI/AppKit, Sparkle 2.9.2, Rust 1.85+/Cargo, Bash, Python 3 standard library, Developer ID Application, Hardened Runtime, `notarytool`, `stapler`, `spctl`, GitHub CLI and Releases.
-
-## Global Constraints
-
-- Distribution is direct Developer ID only; do not add StoreKit, App Sandbox, App Store Connect, or a privileged installer package.
-- Patchwright 0.1.0 supports macOS 26.0+ on Apple silicon only.
-- License the full repository as `MIT OR Apache-2.0`; never publish private keys, tokens, Keychain exports, certificate exports, or raw notary credentials.
-- The publisher GitHub App private key is never bundled. Read-only `gh` sync remains available; mutations require a user-owned GitHub App.
-- Sparkle uses `https://github.com/s1korrrr/patchwright/releases/latest/download/appcast.xml`, an embedded public Ed25519 key, HTTPS, pre-extraction verification, and signed feeds.
-- Official artifacts must map to public tag `v0.1.0` and one commit. Promotion consumes the notarized candidate rather than rebuilding it.
-- Preserve unrelated user files and never stage the pre-existing untracked monetization documents.
-- Use test-first red-green-refactor for behavior changes and keep release actions fail-closed.
-
----
-
-### Task 1: Establish the open-source repository contract
-
-**Files:**
-- Create: `LICENSE-MIT`
-- Create: `LICENSE-APACHE`
-- Create: `CONTRIBUTING.md`
-- Create: `SECURITY.md`
-- Create: `CODE_OF_CONDUCT.md`
-- Create: `PRIVACY.md`
-- Create: `SUPPORT.md`
-- Modify: `Cargo.toml`
-- Modify: `Packaging/Info.plist`
-- Modify: `README.md`
-- Test: `Tests/PackagingTests/release_contract.sh`
-
-**Interfaces:**
-- Produces: consistent `MIT OR Apache-2.0` repository metadata and public contribution/security/privacy boundaries consumed by release validation.
-
-- [ ] **Step 1: Add failing release-contract assertions**
-
-Require both license files, required public documents, Cargo `license = "MIT OR Apache-2.0"`, non-`All rights reserved` bundle copy, and README links. Run `Tests/PackagingTests/release_contract.sh`; expect failure on missing files and old metadata.
-
-- [ ] **Step 2: Add the minimal legal and community files**
-
-Use the canonical MIT and Apache-2.0 texts, a Developer Certificate of Origin contribution rule, private vulnerability-reporting guidance, Contributor Covenant 2.1, a local-first privacy disclosure, and best-effort beta support boundaries. Do not promise warranties, response times, or services.
-
-- [ ] **Step 3: Align metadata and documentation**
-
-Set Cargo to `MIT OR Apache-2.0`, update bundle copyright, and add build/download/license/security/privacy links to README.
-
-- [ ] **Step 4: Verify and commit**
-
-Run `Tests/PackagingTests/release_contract.sh`, `cargo metadata --locked --format-version 1`, and `git diff --check`. Expected: all pass. Commit only Task 1 paths.
-
-### Task 2: Generate SBOM, third-party notices, and publication secret evidence
-
-**Files:**
-- Create: `script/generate_release_compliance.py`
-- Create: `script/scan_publication_secrets.sh`
-- Create: `Tests/PackagingTests/compliance_contract.sh`
-- Modify: `script/build_release_components.sh`
-- Modify: `script/verify_reproducibility_bundle.sh`
-- Modify: `Packaging/THIRD_PARTY_NOTICES.md`
-- Modify: `script/verify.sh`
-
-**Interfaces:**
-- Produces: `evidence/sbom.spdx.json`, `evidence/third-party-notices.md`, and `evidence/secret-scan.json` for a release root.
-- Consumes: `cargo metadata --locked --format-version 1`, `swift package show-dependencies --format json`, and a Git repository path.
-
-- [ ] **Step 1: Write failing compliance fixtures**
-
-Create a temporary Cargo/Swift metadata fixture and assert SPDX 2.3 identity, package names/versions/licenses, deterministic ordering, dependency-derived notices, clean scan JSON, and rejection of token/private-key fixtures. Run `Tests/PackagingTests/compliance_contract.sh`; expect missing-command failure.
-
-- [ ] **Step 2: Implement deterministic compliance generation**
-
-Use Python 3 standard-library JSON parsing and hashing. Fail when a dependency lacks a declared license or the metadata is malformed. Include Patchwright, Rust packages, Swift packages, Sparkle, the app, engine, and relay as SPDX packages or files.
-
-- [ ] **Step 3: Implement complete-history and artifact scanning**
-
-Scan tracked files, all reachable Git blobs across `git rev-list --objects --all`, and the candidate release directory. Detect common GitHub, Apple/private-key, generic PEM, Codex/OpenAI, and webhook-secret patterns; record only redacted path/object identifiers and rule names. Exit nonzero on findings.
-
-- [ ] **Step 4: Wire compliance artifacts into assembly**
-
-Generate compliance evidence before final checksums; require nonempty valid JSON/Markdown and include their hashes in candidate metadata.
-
-- [ ] **Step 5: Verify and commit**
-
-Run the compliance contract, release contract, and secret scan against the current repository. Inspect every candidate finding rather than suppressing broadly. Commit only Task 2 paths.
-
-### Task 3: Integrate signed Sparkle updates
-
-**Files:**
-- Create: `Sources/PatchwrightApp/Services/UpdateController.swift`
-- Create: `Tests/PatchwrightCoreTests/UpdateConfigurationTests.swift`
-- Modify: `Package.swift`
-- Create/Modify: `Package.resolved`
-- Modify: `Sources/PatchwrightApp/App/PatchwrightApp.swift`
-- Modify: `Sources/PatchwrightApp/Support/AppCommands.swift`
-- Modify: `Packaging/Info.plist`
-- Modify: `Tests/PackagingTests/release_contract.sh`
-
-**Interfaces:**
-- Produces: `@MainActor UpdateController.checkForUpdates()` backed by `SPUStandardUpdaterController` and a user-visible `Check for Updates...` command.
-- Consumes: Sparkle product pinned exactly to `2.9.2` and a Keychain-generated Ed25519 public key.
-
-- [ ] **Step 1: Add failing update-configuration tests**
-
-Assert exact dependency pin, feed URL, 32-byte base64 public key, `SUVerifyUpdateBeforeExtraction=true`, `SURequireSignedFeed=true`, and command visibility. Run focused Swift and packaging tests; expect failure because Sparkle and keys are absent.
-
-- [ ] **Step 2: Resolve Sparkle and create the Keychain update key**
-
-Fetch Sparkle 2.9.2 from its official repository. Create the signing item in an owner-only dedicated release Keychain with access restricted to the pinned Sparkle tools; capture only the printed public key. Never export the private key into the workspace.
-
-- [ ] **Step 3: Implement the updater lifecycle**
-
-Own one `SPUStandardUpdaterController` for the app lifetime, expose a main-actor update action, and inject it into app commands without duplicating controllers or starting updates in tests.
-
-- [ ] **Step 4: Configure the signed feed**
-
-Add exact feed/public-key and signed-feed keys to the packaged Info.plist. Preserve monotonically increasing `CFBundleVersion` behavior.
-
-- [ ] **Step 5: Verify and commit**
-
-Run focused Swift tests, `swift build -c release -Xswiftc -warnings-as-errors`, and the release contract. Expected: all pass with Sparkle resolved at 2.9.2.
-
-### Task 4: Package and sign Sparkle nested code safely
-
-**Files:**
-- Modify: `script/build_release_components.sh`
-- Modify: `script/sign_release.sh`
-- Modify: `script/validate_bundle.sh`
-- Modify: `script/verify_signing.sh`
-- Modify: `Tests/PackagingTests/release_contract.sh`
-
-**Interfaces:**
-- Produces: a complete `Contents/Frameworks/Sparkle.framework` bundle with all nested code signed inside-out by the same Team ID.
-
-- [ ] **Step 1: Add failing nested-bundle fixtures**
-
-Assert the framework is copied, missing nested helpers fail validation, escaping symlinks fail, declared internal framework symlinks pass, signing order is deepest-first, and every nested code object has Developer ID/Hardened Runtime/timestamp/Team ID verification.
-
-- [ ] **Step 2: Copy the resolved Sparkle framework**
-
-Discover the framework from SwiftPM build metadata rather than a user-specific absolute path. Copy it with `ditto` into `Contents/Frameworks` and preserve required internal structure.
-
-- [ ] **Step 3: Sign nested code inside-out**
-
-Explicitly enumerate Sparkle XPC services, applications, frameworks, dylibs, and executable helpers in depth order; sign each before the Patchwright engine, relay, and app. Do not use `codesign --deep` for signing.
-
-- [ ] **Step 4: Tighten validation**
-
-Allow only nonescaping symlinks within the declared Sparkle framework. Verify every nested signature, secure timestamp where applicable, Team ID, Hardened Runtime, and absence of unreviewed entitlements.
-
-- [ ] **Step 5: Verify and commit**
-
-Run fixture contracts, build an unsigned bundle, inspect framework layout, and run `codesign --verify` against a local signed fixture when available.
-
-### Task 5: Add release-quality app identity and safe GitHub setup copy
-
-**Files:**
-- Create: `Assets/PatchwrightIcon-source.png`
-- Create: `Packaging/Patchwright.icns`
-- Modify: `Packaging/Info.plist`
-- Modify: `Sources/PatchwrightApp/Views/SettingsView.swift`
-- Modify: `README.md`
-- Modify: `Tests/PackagingTests/release_contract.sh`
-- Modify: `Tests/PatchwrightCoreTests/ModelsTests.swift` or a new focused copy test
-
-**Interfaces:**
-- Produces: packaged `Patchwright.icns`, explicit BYO GitHub App language, and separate read-only/Codex/mutation prerequisites.
-
-- [ ] **Step 1: Add failing icon and copy assertions**
-
-Require `CFBundleIconFile`, packaged `.icns`, nonempty icon representations, and copy that says the GitHub App/private key is user-owned and required only for mutations.
-
-- [ ] **Step 2: Produce the icon source and `.icns`**
-
-Create one original Patchwright identity optimized for Apple app-icon masks, retain a 1024x1024 editable source, generate the full iconset with `sips`, and compile with `iconutil`.
-
-- [ ] **Step 3: Revise setup copy**
-
-Keep read-only `gh` sync useful, make publisher-key absence explicit, and fail closed without suggesting broad or shared credentials.
-
-- [ ] **Step 4: Verify and commit**
-
-Run icon inspection, focused tests, release contract, and a local app launch to confirm the icon and settings render.
-
-### Task 6: Split notarized packaging from digest-bound promotion
-
-**Files:**
-- Create: `script/package_release.sh`
-- Create: `script/promote_release.sh`
-- Create: `script/verify_release_evidence.py`
-- Modify: `script/release.sh`
-- Modify: `script/release_readiness.sh`
-- Modify: `script/generate_release_metadata.sh`
-- Modify: `script/notarize_release.sh`
-- Modify: `Tests/PackagingTests/release_contract.sh`
-- Create: `Tests/PackagingTests/promotion_contract.sh`
-
-**Interfaces:**
-- Produces: `evidence/notarized-candidate.json` and promotion readiness JSON bound to `artifact_sha256`, `git_commit`, `tag`, `version`, and `build`.
-- Consumes: regular JSON evidence documents for repository, Codex, GitHub, clean-machine, secret-scan, and compliance gates, each naming the same artifact digest.
-
-- [ ] **Step 1: Add failing package/promotion matrix tests**
-
-Cover missing evidence, malformed JSON, digest mismatch, commit/tag mismatch, stale files, symlinks, nonregular files, unsigned candidate, notary rejection, Gatekeeper rejection, and a complete fixture promotion.
-
-- [ ] **Step 2: Implement candidate packaging**
-
-Move current build/sign/notarize/DMG/appcast/compliance logic into `package_release.sh`. Always print candidate and release-root paths even when later promotion gates remain pending.
-
-- [ ] **Step 3: Generate and sign the appcast**
-
-Use Sparkle's pinned `generate_appcast` tool with its Keychain key, point the enclosure at the immutable versioned GitHub asset URL, require the Ed25519 signature and signed feed, and include `appcast.xml` in candidate checksums.
-
-- [ ] **Step 4: Implement evidence validation and promotion preparation**
-
-Validate exact digest and commit bindings without accepting environment booleans. Produce a machine-readable release-asset manifest ready for GitHub upload but do not perform a public write in unit tests.
-
-- [ ] **Step 5: Keep a compatibility wrapper**
-
-Make `release.sh` run package mode and report `notarized candidate` with the exact follow-up promotion command; never label it release-ready before external evidence.
-
-- [ ] **Step 6: Verify and commit**
-
-Run the full fixture matrix, shell syntax checks, and release contracts.
-
-### Task 7: Add credential-free CI and public release documentation
-
-**Files:**
-- Create: `.github/workflows/ci.yml`
-- Create: `.github/release.yml`
-- Create: `docs/direct-download.md`
-- Modify: `docs/release-checklist.md`
-- Modify: `docs/release-readiness.md`
-- Modify: `docs/production-plan.md`
-- Modify: `README.md`
-- Test: `Tests/PackagingTests/release_contract.sh`
-
-**Interfaces:**
-- Produces: fork-safe source CI and a public download/verification contract. Signing and notarization remain local protected release actions.
-
-- [ ] **Step 1: Add failing workflow/docs checks**
-
-Require pinned third-party actions, read-only default permissions, no pull-request secrets, exact source checks, direct-download platform disclosure, checksum verification, and no Gatekeeper-bypass commands.
-
-- [ ] **Step 2: Add CI**
-
-Use the current official GitHub macOS runner/Xcode combination that supports Swift 6.2/macOS 26, pin action revisions, cache only dependency/build inputs without credentials, and run `./script/verify.sh` plus smoke where supported.
-
-- [ ] **Step 3: Rewrite direct-release documentation**
-
-Remove App Store Connect readiness vocabulary for this version. Document DMG verification, drag installation, BYO dependencies, update behavior, source build, official signature verification, support scope, and uninstall/data retention.
-
-- [ ] **Step 4: Verify and commit**
-
-Run workflow syntax validation, release contracts, link checks, and `git diff --check`.
-
-### Task 8: Whole-branch verification and security/publication audit
-
-**Files:**
-- Modify only when verification exposes an in-scope defect.
-- Create locally ignored evidence under `.release-audit/` or the candidate release root.
-
-**Interfaces:**
-- Produces: fresh source, security, license, runtime, and package evidence for the exact release commit.
-
-- [ ] **Step 1: Run full source verification**
-
-Run `./script/verify.sh`, `./script/smoke.sh`, `./script/smoke_codex.sh`, strict Swift Release build, locked Rust tests, formatter/lint checks, and the real app launch smoke.
-
-- [ ] **Step 2: Audit the whole branch**
-
-Review the full merge-base diff for scope, secrets, dependency changes, update security, path traversal/symlink handling, release command injection, evidence spoofing, permissions, and accidental publication of user data.
-
-- [ ] **Step 3: Scan complete history and candidate inputs**
-
-Run the repository scanner across every reachable object and local ref. Independently inspect GitHub's current secret-scanning state. Rotate any exposed credential before proceeding.
-
-- [ ] **Step 4: Obtain a clean review**
-
-Use an independent whole-branch reviewer. Fix Critical/Important findings, rerun covering tests, and repeat review until clean.
-
-### Task 9: Package, notarize, and validate the exact 0.1.0 candidate
-
-**Files:**
-- Release outputs only under `~/.patchwright/release-work`.
-- Evidence updates under `docs/audits/` only after redaction.
-
-**Interfaces:**
-- Produces: final `Patchwright-0.1.0.dmg`, checksum, signed appcast, SBOM, notices, candidate manifest, and notarization evidence.
-
-- [ ] **Step 1: Prepare the release commit and tag**
-
-Merge the reviewed branch, verify clean `main`, create annotated `v0.1.0`, and verify the tag resolves to the release commit.
-
-- [ ] **Step 2: Verify protected credentials without exposing them**
-
-Require exactly one selected Developer ID Application identity, a working named `notarytool` Keychain profile, and the Sparkle Keychain key. Print only identity class/team and profile/key availability.
-
-- [ ] **Step 3: Run package mode**
-
-Run `PATCHWRIGHT_VERSION=0.1.0 PATCHWRIGHT_BUILD=1 ./script/package_release.sh`. Require accepted/stapled app and DMG, passing Gatekeeper, valid appcast signature, and complete candidate evidence.
-
-- [ ] **Step 4: Validate from a disposable clean machine**
-
-Run the documented exact-DMG probe on a pristine Apple-silicon macOS 26+ VM and complete the missing-dependency, Codex, BYO GitHub App, lifecycle, update, offline/revocation, migration, relaunch, uninstall, and data-retention matrix. Bind the resulting JSON to the DMG digest.
-
-- [ ] **Step 5: Final promotion preflight**
-
-Run `promote_release.sh` in verify-only mode with exact digest-bound repository, Codex, GitHub, clean-machine, compliance, and secret evidence.
-
-### Task 10: Publish the source and immutable GitHub Release
-
-**Files/Systems:**
-- GitHub repository `s1korrrr/patchwright`
-- Tag `v0.1.0`
-- Release assets from the verified candidate manifest
-
-**Interfaces:**
-- Produces: public source repository and downloadable immutable 0.1.0 release.
-
-- [ ] **Step 1: Push reviewed source and tag**
-
-Push the reviewed main commit and `v0.1.0`. Confirm the remote commit and tag match the candidate manifest.
-
-- [ ] **Step 2: Create a complete draft release**
-
-Upload the DMG, checksum, appcast, SBOM, notices, and redacted evidence from the manifest. Verify asset sizes and downloaded hashes before publishing.
-
-- [ ] **Step 3: Perform the final visibility preflight**
-
-Re-run complete-history secret scanning against remote refs, inspect repository rules/settings, verify no private issues/discussions/actions artifacts would be unintentionally exposed, and confirm public README/support/privacy content.
-
-- [ ] **Step 4: Make the repository public and publish atomically**
-
-Change visibility with GitHub's explicit consequence acknowledgement, publish the complete release, enable release immutability for future releases, and verify anonymous source and asset access.
-
-- [ ] **Step 5: Verify the public install/update path**
-
-Download the public DMG without authentication, verify checksum/signature/notarization/Gatekeeper, install and launch, fetch the public signed appcast, and confirm `Check for Updates...` reaches the expected feed.
-
-- [ ] **Step 6: Record final truth**
-
-Update the audit with public URLs, tag/commit/digest, notarization status, clean-machine evidence, remaining external limitations, and rollback/incident procedure. Do not claim support beyond the documented beta boundary.
diff --git a/docs/superpowers/plans/2026-07-17-release-security-audit-remediation.md b/docs/superpowers/plans/2026-07-17-release-security-audit-remediation.md
deleted file mode 100644
index 4dcb350..0000000
--- a/docs/superpowers/plans/2026-07-17-release-security-audit-remediation.md
+++ /dev/null
@@ -1,89 +0,0 @@
-# Release and security audit remediation
-
-## Goal
-
-- User-visible outcome: Patchwright release verification is read-only, candidate bytes are bound to an exact clean Git state and source archive, notarization logs fail closed, live-smoke evidence is created safely, promotion evidence is reviewer/digest bound, CI scans history and Rust advisories, and service smoke shutdown is exact and bounded.
-- How to see it working: every packaging contract passes, targeted tamper cases fail for the intended reason, shell/Python syntax checks pass, and only the assigned release/docs paths are committed with DCO sign-offs.
-
-## Current State
-
-- Relevant paths: `script/`, `Tests/PackagingTests/`, `README.md`, `docs/`, and `.github/`.
-- Existing behavior: `verify_distribution.sh` overwrites the checksum sidecar; packaging checks Git state only before a long build; notarization accepts an `Accepted` submission without parsing its log; live-smoke evidence uses permissive path creation and a shell redirection; clean-machine gates contain booleans without reviewer or per-check evidence provenance; CI does not run the repository secret scanner or an advisory audit; `smoke.sh` does not wait for the exact engine PID to exit.
-- Constraints: no Rust or Swift changes, no writes outside the isolated `audit-release` worktree, no live Apple/GitHub mutations, strict red-green contract tests, and DCO-signed commits.
-
-## Target State
-
-- Desired behavior: release and promotion evidence fail closed on symlink, digest, dirty-state, identity, reviewer, and tamper mismatches; scripts do not overwrite verification inputs; operator docs match the actual relay CLI and GitHub redelivery semantics.
-- Non-goals: no network signing service, no live notarization, no GitHub release upload, and no changes to application/runtime source.
-
-## Risks and Failure Modes
-
-- Shell portability or macOS-specific tool assumptions could make contract fixtures misleading.
-- Stronger promotion schemas could reject older evidence; the schema change must be explicit and tested.
-- Evidence digest circularity could make manifests unverifiable; manifests must bind leaf evidence, while the promotion envelope separately binds the gate and candidate.
-- CI advisory tooling can drift; use a pinned local tool/version and document that advisory data is fetched at CI runtime.
-
-## Milestones
-
-### M1. Read-only distribution and exact release source binding
-
-- Goal: verify an explicit existing sidecar without mutation and reject source/tag/index/worktree/archive tampering.
-- Files / systems: release/candidate scripts and packaging contracts.
-- Changes: add no-follow checksum verification, final Git-state verification, source-archive digest provenance, and `dirty == false` enforcement.
-- Verification: targeted release and candidate/promotion contract cases, first RED then GREEN.
-- Expected result: every sidecar/source/repository tamper is explicitly rejected.
-
-### M2. Notary and evidence-file hardening
-
-- Goal: reject problematic accepted notary logs and publish live-smoke evidence without path races or overwrite.
-- Files / systems: notarization and GitHub smoke scripts plus contracts.
-- Changes: sanitized log summary parser; canonical owner-only evidence directory and exclusive atomic writer; move `fail` before use.
-- Verification: offline JSON fixtures and filesystem adversarial tests, first RED then GREEN.
-- Expected result: errors/default-policy warnings fail and evidence paths cannot be symlinked or overwritten.
-
-### M3. Clean-machine and promotion provenance
-
-- Goal: require independent reviewer identity and digest/path evidence for every documented clean-machine check.
-- Files / systems: promotion verifier/generator, clean-machine docs, promotion contract.
-- Changes: schema-v2 clean-machine checks, evidence manifest binding, promotion manifest output, expanded matrix tests.
-- Verification: happy path plus reviewer/path/digest/tamper rejection cases.
-- Expected result: promotion succeeds only with a complete reviewer-owned evidence set.
-
-### M4. CI, runtime shutdown, and operator docs
-
-- Goal: scan full Git history/advisories, stop the exact smoke process, and correct relay/redelivery instructions.
-- Files / systems: CI, smoke scripts/contracts, README and docs.
-- Changes: full-depth checkout, existing secret scanner, pinned local cargo advisory tool, bounded TERM-to-KILL helper with socket cleanup, accurate `serve --webhook-secret-file` examples and manual-redelivery truth.
-- Verification: contract tests, shell syntax, Python compile, workflow/doc assertions.
-- Expected result: CI and operator instructions enforce the same release/security boundaries as local scripts.
-
-## Verification
-
-- `Tests/PackagingTests/release_contract.sh`
-- `Tests/PackagingTests/candidate_evidence_contract.sh`
-- `Tests/PackagingTests/promotion_contract.sh`
-- `Tests/PackagingTests/compliance_contract.sh`
-- `Tests/PackagingTests/github_app_smoke_contract.sh`
-- `bash -n script/*.sh Tests/PackagingTests/*.sh`
-- `PYTHONDONTWRITEBYTECODE=1 python3 -m py_compile script/*.py`
-- `git diff --check`
-- `git status --short --branch`
-
-## Decision Log
-
-- 2026-07-17: Keep public provenance local and SHA-256 based; do not invent remote signing infrastructure.
-- 2026-07-17: Bind the archived committed source plus final repository state instead of changing the compiler/build checkout in this bounded remediation; final HEAD/index/worktree/tag checks preserve current local release ergonomics while making the remaining build-time mutation window explicit in evidence.
-- 2026-07-17: Treat all notarization warnings as release-blocking by default, with an explicit operator policy switch for accepted warnings.
-- 2026-07-17: Root coordination narrowed this commit to the already-green M1–M3 work and required docs. CI history/advisory scanning and exact `smoke.sh` shutdown remain deferred rather than being rushed into the signed handoff.
-
-## Progress Log
-
-- 2026-07-17: Completed repository/contract inventory and confirmed a clean isolated branch.
-- 2026-07-17: Completed M1–M3 with recorded RED signals and GREEN targeted contracts: release security, candidate evidence, and the 29-category promotion matrix.
-- 2026-07-17: Corrected relay `serve`/secret-file instructions and GitHub's operator-driven redelivery truth.
-- 2026-07-17: Deferred M4 CI and exact smoke-process shutdown changes by root direction; they remain explicit follow-up work.
-
-## Rollback / Recovery
-
-- If this fails: stop at the failing contract, preserve its exact signal, and revert only the coherent branch-local commit that introduced the regression.
-- Safe fallback: retain the prior release flow as blocked rather than weakening digest, identity, notarization, or clean-machine checks.
diff --git a/docs/superpowers/specs/2026-07-13-durable-local-orchestrator-design.md b/docs/superpowers/specs/2026-07-13-durable-local-orchestrator-design.md
deleted file mode 100644
index 8e14ee4..0000000
--- a/docs/superpowers/specs/2026-07-13-durable-local-orchestrator-design.md
+++ /dev/null
@@ -1,422 +0,0 @@
-# Patchwright Durable Local Orchestrator Design
-
-## Status
-
-- Date: 2026-07-13
-- Status: approved design
-- Target: macOS 26 or newer on Apple silicon
-- Distribution: Developer ID, notarized direct download
-- Product boundary: local-first, single operator, multiple repositories
-
-This specification supersedes the earlier Stage 1–3 design where the two conflict. In particular, `mergePullRequest` is no longer permanently disabled. Merge is permitted only through the separate, exact-SHA approval contract defined below.
-
-## Outcome
-
-Patchwright turns ingested GitHub issues and pull requests into durable engineering tasks, runs each task in an isolated worktree with a fully embedded Codex thread, verifies and reviews the result, performs explicitly approved GitHub writes through a production GitHub App, organizes open pull requests into an explainable queue, and eventually performs a separately approved merge.
-
-The finished product must remain recoverable, inspectable, and fail-closed across app restarts, engine crashes, network ambiguity, credential expiry, cancellation, and changing GitHub state.
-
-## Non-goals
-
-- Unattended merges without a fresh human approval.
-- Administrator or branch-protection bypass.
-- Giving Codex direct access to GitHub, Apple, signing, or approval credentials.
-- Treating issue text, comments, labels, or repository files as authority.
-- Hosted multi-user orchestration, organization SSO, billing, or arbitrary agent swarms.
-- Mac App Store distribution in this release.
-- App Sandbox when it would prevent the approved local process and repository workflow.
-
-## Architecture choice
-
-Patchwright uses a durable local orchestrator.
-
-- `PatchwrightApp` is the native operator console.
-- `patchwright-core` owns typed state, policy, approvals, queue decisions, findings, and evidence.
-- `patchwright-engine` owns persistence, repositories, worktrees, commands, Codex app-server processes, cancellation, and lifecycle orchestration.
-- `patchwright-relay` owns GitHub App authentication, typed GitHub API mutations, webhook verification, and remote reconciliation.
-- SQLite stores durable state and append-only events. Credentials, source bodies, command output, and private repository content do not become general telemetry.
-
-SwiftUI never executes GitHub mutations. Codex never receives GitHub credentials or Patchwright approval tokens.
-
-## Core data model
-
-### Repository binding
-
-A `RepositoryBinding` contains:
-
-- GitHub repository ID and full name
-- GitHub App installation ID
-- clone and HTML URLs
-- default branch
-- optional user-selected checkout
-- optional Patchwright-managed clone
-- local state and worktree roots
-- current default-branch SHA and commit timestamp
-- permission and credential-health snapshot
-
-If no local checkout is bound, Patchwright proposes a managed clone under `~/.patchwright/repositories`. Network access is explicit and the clone remains separate from task worktrees.
-
-### Task source
-
-A `TaskSource` is one of:
-
-- local request
-- GitHub issue
-- GitHub pull request
-
-GitHub sources retain repository identity, item number, immutable source URL, base/head refs and SHAs where applicable, and the snapshot timestamp used to create the contract.
-
-### Task contract
-
-A `TaskContract` contains:
-
-- source and repository binding
-- goal and acceptance criteria
-- base and optional head identities
-- relevant comments, reviews, checks, and changed paths
-- effective instruction sources with hashes and precedence
-- repository verification commands
-- required capabilities
-- risk and sensitive-path classification
-- queue identity and dependency edges
-- Codex process/thread/turn identities
-- worktree and branch identities
-- evidence, findings, approvals, and remote delivery identities
-
-GitHub and repository content is untrusted context. It cannot modify policy, grant capabilities, change an approval, or enable a tool.
-
-## Task lifecycle
-
-The lifecycle is:
-
-`discovered → assessing → planned → awaitingPreparationApproval → preparing → implementing → verifying → reviewing → awaitingDeliveryApproval → delivering → monitoring → awaitingMergeApproval → merging → completed`
-
-Any nonterminal task may enter:
-
-- `paused`: recoverable operator stop
-- `blocked`: needs clarification, credentials, dependency, or external action
-- `failed`: operation failed with retained evidence
-- `cancelled`: explicitly terminated with retained worktree and evidence
-
-Each transition appends an event and a safe checkpoint. Restart recovery may resume only from a recorded checkpoint and may never skip an approval state.
-
-## Issue-to-task workflow
-
-1. Convert the issue snapshot into a typed contract.
-2. Bind or materialize the repository.
-3. Resolve instructions, policy, verification commands, and sensitive paths.
-4. Present the plan, required capabilities, branch proposal, and intended GitHub actions.
-5. After preparation approval, create an isolated worktree and task branch.
-6. Start the task-owned Codex app-server process and thread.
-7. Run verification and an independent read-only review.
-8. Preview commit, push, check, comment, and draft-PR actions.
-9. Execute only the approved delivery actions.
-10. Monitor CI and reviews and create bounded repair iterations.
-11. Request a distinct merge approval only after all readiness gates pass.
-
-## Existing-PR workflow
-
-1. Materialize the exact base and head SHAs.
-2. Import requested changes, unresolved review threads, failing checks, conflicts, and changed paths into the contract.
-3. Determine whether the GitHub App can update the head repository and branch.
-4. If permitted, prepare an isolated worktree from the PR head and push repairs only after approval.
-5. If the head is an inaccessible fork, fail safely and offer a local patch, suggested review, or separate repair branch/PR when policy permits.
-6. Re-fetch CI, review, and head/base state after every push.
-7. Treat review-thread resolution as a separately previewed GitHub write.
-
-## Embedded Codex integration
-
-Each active task owns one supervised `codex app-server` process and process group. Bounded WIP limits keep this isolation affordable.
-
-The engine must:
-
-- discover the exact Codex CLI and version;
-- validate the matching generated app-server schema during verification;
-- communicate over newline-delimited JSON on stdio;
-- perform `initialize` followed by `initialized`;
-- read account state and expose signed-out/unavailable conditions;
-- start or resume the persisted thread;
-- start turns with the isolated worktree as `cwd`;
-- persist relevant thread, turn, item, approval, and completion events;
-- support user input and `turn/steer`;
-- surface command and file-change approval requests in the native UI;
-- use `turn/interrupt` for graceful cancellation;
-- terminate the owned process group only after an interrupt timeout;
-- restart the process and resume the thread after a recoverable crash.
-
-Codex authentication remains owned by Codex. Patchwright does not copy or persist Codex access tokens.
-
-## Approval model
-
-Approval classes remain separate:
-
-1. Codex runtime approval for a command or file change.
-2. Local capability approval for network, dependency, or exceptional command access.
-3. GitHub delivery approval for exact push, comment, review, check, thread-resolution, branch, or draft-PR actions.
-4. Merge approval for one exact PR state.
-
-Approval of one class never authorizes another.
-
-Every Patchwright approval records:
-
-- capability and typed action preview
-- repository and task
-- relevant branch and PR identity, plus head/base SHAs only when the GitHub mutation atomically consumes them
-- approver and timestamp
-- short expiration
-- policy and instruction hashes
-- invalidation conditions
-
-## Approval-gated merge
-
-Merge approval binds to:
-
-- repository and installation
-- PR number
-- exact head SHA consumed atomically by GitHub's merge endpoint
-- configured base-branch identity (GitHub does not expose an atomic expected-base-SHA merge parameter)
-- merge method
-- required-check snapshot
-- review-decision snapshot
-- approval identity and expiration
-- idempotency key
-
-Before the merge approval gate, Patchwright refreshes the PR, checks, reviews, branch rules, and mergeability. It rejects stale monitored evidence if the head or base changed, required checks regressed, reviews changed, conflicts appeared, or policy no longer permits the merge. The merge mutation itself carries the exact approved head SHA; the base is branch-identity-bound because GitHub offers no atomic expected-base-SHA parameter.
-
-Patchwright never uses administrator bypass. If the repository requires GitHub's native merge queue, Patchwright enqueues the approved PR and monitors the merge-group result. Otherwise it uses the merge endpoint with the expected head SHA. A successful response is recorded with the remote merge SHA before the next queue item may advance.
-
-A post-merge regression stops that repository queue and records a blocker.
-
-## PR queue
-
-Each repository has a durable local queue with these states:
-
-`inbox → assessed → ready | needsWork | blocked → active → awaitingWriteApproval → monitoring → mergeReady → awaitingMergeApproval → merged | failed`
-
-Default deterministic tiers are:
-
-1. manually pinned security, release, or production blockers;
-2. PRs that block other queued PRs;
-3. green, approved, conflict-free PRs that can complete immediately;
-4. PRs with actionable requested changes;
-5. PRs with reproducible failing CI;
-6. conflicted or behind-base PRs;
-7. active drafts with recent commits;
-8. stale drafts or PRs needing product clarification.
-
-Within a tier, order by dependency, critical-path risk, latest review or CI activity, latest head commit, latest GitHub update, creation time, and PR number.
-
-Every queue item stores an explainable reason such as `ready and blocks two PRs` or `three required checks failing`. Labels and comments are signals, never authority.
-
-The initial WIP limit is one mutating task per repository. Read-only assessment may run concurrently. Patchwright does not start mutating tasks whose changed-path or dependency graph overlaps an active task.
-
-Supported workflow presets are:
-
-- Quick Wins
-- CI Rescue
-- Review Closure
-- Conflict Recovery
-- Dependency Chain
-- Security First
-- Release Train
-- Stale PR Triage
-- Draft Completion
-- Post-Merge Watch
-- Review Load Balancing
-- Duplicate/Overlap Detection
-
-Manual pinning and reorder persist locally and do not mutate GitHub.
-
-## Sorting and filtering
-
-Repository sorts are:
-
-- queue priority
-- recently updated
-- recently pushed
-- latest default-branch commit
-- open PR count
-- failing-check count
-- name
-
-PR sorts are:
-
-- queue priority
-- recently updated
-- latest head commit
-- latest review activity
-- CI health
-- review state
-- created newest/oldest
-- change size
-- PR number
-
-Repository `latest commit` means the latest commit on the default branch. PR `latest commit` means the current PR head commit. Repository `recently pushed` remains a separate GitHub timestamp.
-
-Filters include draft/open state, author, assignee, labels, review state, CI result, merge conflict, age, queue state, and active Codex work. Preferences persist locally per workspace.
-
-## Cancellation
-
-GitHub ingestion becomes a durable job with:
-
-- `github.sync.start`
-- `github.sync.status`
-- `github.sync.cancel`
-
-Cancellation stops new fan-out, aborts active requests, preserves previously complete snapshots, and never replaces a repository snapshot with partial data.
-
-Task cancellation interrupts the active Codex turn, cancels owned commands and Git processes, prevents new GitHub mutations, reconciles any already-sent idempotent mutation, records a final remote identity when GitHub completed the action, and retains the worktree and evidence.
-
-## Production GitHub App broker
-
-The preferred local credential path is:
-
-1. Import a GitHub App private key through a file panel.
-2. Validate the private key.
-3. Store the key in macOS Keychain, not SQLite.
-4. Allow only the Rust credential broker to request it.
-5. Sign a short-lived RS256 app JWT.
-6. Resolve the repository installation.
-7. Mint a repository- and permission-scoped installation token.
-8. Cache the installation token only in memory until before expiration.
-
-For a deployed relay, the private key comes from a protected secret-file mount or secret manager. An environment variable may reference the secret but must not contain raw private-key content.
-
-GitHub CLI remains a development/fallback read-only credential bridge. The production path does not require `gh`.
-
-Typed GitHub adapters cover:
-
-- create/update branches and push task commits;
-- create/update draft pull requests;
-- post issue/PR comments;
-- create pending reviews with batched inline comments;
-- submit reviews and reply to or resolve threads;
-- create/update check runs;
-- update PR branches;
-- enqueue or merge PRs;
-- close or supersede stale PRs after approval.
-
-Git pushes use an ephemeral credential helper so tokens do not appear in argv, remotes, Git configuration, or logs.
-
-Every mutation has a policy capability, typed preview, fresh precondition check, scoped approval, idempotency key, recorded remote identity, retry classification, and ambiguous-result reconciliation.
-
-## Native macOS interface
-
-The root is an adjustable `NavigationSplitView` with a native source-list sidebar, a queue/repository/task content column, a detail workbench, and an optional SwiftUI inspector.
-
-Primary navigation is:
-
-- Queue
-- Repositories
-- Active Tasks
-- Awaiting Approval
-- Monitoring
-- Completed
-
-Settings remains a separate macOS scene.
-
-The central PR queue uses a sortable `Table` with priority, repository, PR, queue state, CI, review state, conflict/base state, latest commit, update time, and assigned task. Toolbar actions expose sorting, filters, saved workflows, search, refresh, queue start/pause, and cancellation.
-
-The task workbench has stable modes:
-
-- Overview
-- Codex
-- Changes
-- Verification
-- Delivery
-- Merge
-
-Evidence, approvals, effective instructions, and credential provenance live in the optional inspector. Fixed-width manual columns are removed. Window-scoped state uses scene storage; durable preferences use app storage.
-
-Approval sheets show the exact target, capability, commit range, changed files, remote content, merge method, checks, reviews, expiration, invalidation conditions, and reason. There is no `Approve Everything` action.
-
-Settings includes real Codex and GitHub App health, versions, account/installation state, permissions, credential source, webhook status, test connection, and actionable recovery.
-
-All empty, loading, partial, cancelled, blocked, expired-approval, credential, and unknown-delivery states are explicit. Icon-only actions have outcome-oriented help and accessibility labels. Raw timestamps are presented as localized relative dates with exact values available in details.
-
-## Distribution
-
-The first release is distributed outside the Mac App Store using Developer ID and notarization.
-
-The release pipeline produces:
-
-- `Patchwright.app`
-- signed and notarized `Patchwright.dmg`
-- SHA-256 checksum manifest
-- version/build metadata
-- dependency and license manifest
-- verification report
-- credential-free reproducibility bundle
-
-The pipeline builds Release artifacts, assembles outside File Provider, validates bundle metadata, signs nested helpers inside-out, signs the app with `Developer ID Application`, Hardened Runtime, secure timestamp, and minimal entitlements, verifies signatures and Gatekeeper, creates and signs the DMG, submits with `notarytool`, retains the notarization log, staples tickets, and verifies the final artifact.
-
-No Hardened Runtime exception entitlement is added without a proven requirement. App Sandbox is not required for direct distribution and is excluded when it prevents the approved local orchestration model.
-
-The current machine lacks a `Developer ID Application` identity and configured notarization credentials. Repository-side packaging is in scope; real Developer ID signing and notarization remain `blocked:external` until the owner installs the certificate and configures a Keychain notary profile.
-
-## Clean-machine validation
-
-The release candidate is installed from the final DMG in a fresh macOS environment with no source checkout, developer toolchain, Patchwright state, cached GitHub token, or running engine.
-
-Proof must include:
-
-- Gatekeeper acceptance and normal installation;
-- bundled helper launch and health;
-- actionable missing-Codex state;
-- Codex install/sign-in followed by app-server connection;
-- GitHub App installation discovery without `gh`;
-- test-repository ingestion;
-- relaunch recovery of queue, task, and thread state;
-- update-over-prior-version data preservation;
-- offline, expired, revoked, and missing-permission states;
-- clear uninstall/data-retention behavior.
-
-## Verification
-
-Implementation uses behavior-first vertical slices.
-
-Required proof includes:
-
-- public domain tests for queue, lifecycle, policy, approvals, merge invalidation, and restart recovery;
-- mock GitHub tests for JWT claims, installation tokens, permission scoping, expiry, rate limits, typed writes, exact-SHA merge, merge-queue handoff, idempotency, and ambiguous-result reconciliation;
-- fake app-server tests for initialization, account state, thread start/resume, streaming, approvals, steering, interruption, process failure, and isolation;
-- a real local Codex smoke in a disposable repository;
-- cancellation and restart fault injection at every lifecycle boundary;
-- a disposable GitHub App and test repository for the live write/merge workflow;
-- Swift tests for store behavior, sorting, filtering, state presentation, and recovery;
-- native interaction, accessibility, resize, keyboard, menu, Light/Dark, Reduce Motion, long-content, log, and Release-performance evidence;
-- secret, tracked-artifact, signing, notarization, Gatekeeper, and clean-machine audits.
-
-No production repository mutation is used for release qualification.
-
-## Readiness labels
-
-- `repo-ready`: source and local tests/lints/builds pass.
-- `integration-ready`: real Codex and disposable GitHub App workflows pass.
-- `package-ready`: packaging is reproducible and the available signing path is validated.
-- `notarized candidate`: Developer ID, Hardened Runtime, notarization, stapling, and Gatekeeper pass.
-- `release-candidate ready`: clean-machine install, update, ingestion, Codex, delivery, cancellation, and approved test-repository merge pass.
-- `blocked:external`: an Apple certificate, notary credential, GitHub App registration/installation, or owner decision remains.
-
-## Implementation order
-
-1. Domain/lifecycle/approval migration and durable jobs.
-2. Sorting, filtering, timestamps, and native split/table interface.
-3. Issue/PR-to-task conversion and repository binding.
-4. Embedded task-owned Codex app-server integration.
-5. Cancellable ingestion and task cancellation.
-6. GitHub App credential broker and read migration.
-7. Approval-gated GitHub delivery writes.
-8. Explainable PR queue and remediation workflows.
-9. Exact-SHA approval-gated merge and native merge-queue handoff.
-10. Developer ID packaging, notarization automation, clean-machine proof, and final E2E audit.
-
-## Authoritative references
-
-- Codex App Server: https://developers.openai.com/codex/app-server/
-- GitHub App installation tokens: https://docs.github.com/en/apps/creating-github-apps/authenticating-with-a-github-app/generating-an-installation-access-token-for-a-github-app
-- GitHub pull-request merge API: https://docs.github.com/en/rest/pulls/pulls#merge-a-pull-request
-- GitHub merge queue: https://docs.github.com/en/repositories/configuring-branches-and-merges-in-your-repository/configuring-pull-request-merges/managing-a-merge-queue
-- Apple Design Resources: https://developer.apple.com/design/resources/
-- Developer ID certificates: https://developer.apple.com/help/account/certificates/create-developer-id-certificates/
-- Notarizing macOS software: https://developer.apple.com/documentation/security/notarizing-macos-software-before-distribution
diff --git a/docs/superpowers/specs/2026-07-13-patchwright-stages-1-3-design.md b/docs/superpowers/specs/2026-07-13-patchwright-stages-1-3-design.md
deleted file mode 100644
index 185893a..0000000
--- a/docs/superpowers/specs/2026-07-13-patchwright-stages-1-3-design.md
+++ /dev/null
@@ -1,98 +0,0 @@
-# Patchwright Stages 1–3 Design
-
-## Product contract
-
-Patchwright is a local-first engineering control plane for one developer operating one GitHub repository at a time. It turns a local repository or authorized GitHub issue into an auditable task that can be reviewed locally, prepared in an isolated worktree, verified, delivered as a draft pull request, and monitored through GitHub feedback and CI.
-
-The first release includes the complete product loop described as Stages 1–3 in the source brief. It does not include Stage 4 team administration, hosted runners, organization SSO, automatic merge, arbitrary agent swarms, or iOS execution.
-
-## Target and support
-
-- Native SwiftUI application for macOS 26 or newer on Apple silicon.
-- Local Rust 2024 engine for macOS and future headless portability.
-- Rust webhook relay suitable for a local tunnel or a separately operated HTTPS deployment.
-- GitHub App credentials supplied at runtime and never stored in the repository.
-- Codex App Server discovered from the local `codex` executable.
-- Apple Foundation Models used only when available; unavailability is explicit and recoverable.
-
-## Primary workflow
-
-1. The developer adds a local repository.
-2. Patchwright resolves repository policy and hierarchical `AGENTS.md` instructions.
-3. The developer selects a base/head comparison or enters a GitHub issue.
-4. Patchwright constructs a typed implementation contract and shows required capabilities.
-5. An approval creates an isolated worktree and starts the coding runtime.
-6. Configured format, lint, test, and build commands run under command policy.
-7. A separate read-only review pass produces structured, evidence-backed findings.
-8. An approval commits, pushes, and creates a draft pull request.
-9. GitHub webhook events update the durable task timeline; CI and review feedback can trigger bounded repair proposals.
-10. Patchwright returns control to the developer. Merge remains outside the product.
-
-## Architecture
-
-### `PatchwrightApp`
-
-The SwiftUI app uses a `WindowGroup` with a sidebar-detail-inspector layout and a separate `Settings` scene. App-wide state lives in `WorkspaceStore`; selection remains window-scoped. The app presents repositories and tasks in the sidebar, a task/evidence timeline in the detail pane, and effective instructions, approvals, and findings in the inspector. Primary actions have menu and keyboard equivalents.
-
-`EngineClient` talks JSON-RPC 2.0 over a Unix domain socket. `FoundationReviewProvider` uses Apple Foundation Models behind a `ReviewProviding` protocol and reports exact availability and recovery states. The UI never executes Git or GitHub mutations directly.
-
-### `patchwright-core`
-
-The shared Rust library owns domain types, validated identifiers, the task state machine, approval/action policy, instruction precedence, structured findings, evidence records, GitHub event envelopes, and typed error codes. Domain types are serializable and form the JSON-RPC contract.
-
-### `patchwright-engine`
-
-The local engine owns repository inspection, worktrees, command execution, Codex App Server sessions, durable SQLite state, and evidence capture. Mutating actions are possible only after an action-specific approval token. Every command has a configured executable, argument vector, working directory, timeout, and network policy. Shell strings are not accepted at the RPC boundary.
-
-### `patchwright-relay`
-
-The relay verifies GitHub webhook HMAC signatures before parsing events, deduplicates deliveries, records sanitized lifecycle events, and forwards typed events to the engine. Its GitHub client obtains installation tokens from a GitHub App JWT and supports draft PRs, check runs, pending reviews with batched comments, replies, and CI status reads. Private keys and installation tokens stay in memory and logs redact authentication headers.
-
-## Task states and approvals
-
-Task transitions are explicit:
-
-`discovered → planned → awaitingApproval → preparing → implementing → verifying → reviewing → awaitingDeliveryApproval → delivering → monitoring → completed`
-
-Any active state can transition to `failed` or `cancelled`. Recovery replays durable events and may continue only from a recorded safe checkpoint.
-
-Capabilities are `readRepository`, `modifyWorktree`, `runKnownCommand`, `accessNetwork`, `installDependency`, `pushBranch`, `createPullRequest`, `postReview`, `resolveThread`, `modifyWorkflow`, and `mergePullRequest`. The shipped defaults automatically allow the first three only inside an isolated worktree, require approval for network and all GitHub mutations, always require a distinct approval for workflow changes, and disable merge.
-
-## Instruction resolution
-
-Instruction sources use this precedence, from lowest to highest:
-
-1. organization policy
-2. user preferences
-3. `.engineering-agent/project.yml`
-4. root `AGENTS.md`
-5. nearest directory `AGENTS.md`
-6. branch or pull-request instructions
-7. current task instruction
-
-The resolver preserves source path, content hash, scope, precedence, advisory/enforced status, and conflicts. Repository text and GitHub comments are untrusted context, never authority.
-
-## Persistence and evidence
-
-SQLite stores tasks, append-only task events, approvals, evidence, webhook delivery IDs, and remote cursors. Repository contents, prompts, command output, and diffs remain local. Evidence entries contain a content hash, timestamp, producer, task/step relationship, and local artifact path. Sensitive environment variables are never persisted.
-
-## Error behavior
-
-- Invalid RPC input returns a stable typed code and does not mutate state.
-- A missing repository, dirty base checkout, policy denial, stale approval, timeout, failed verification, rejected webhook signature, and GitHub rate limit are distinct errors.
-- GitHub mutations carry idempotency keys derived from task, action, and head SHA.
-- Restart recovery never repeats a mutation whose successful remote identity was recorded.
-- Model unavailability is visible and allows deterministic/Codex alternatives when policy permits.
-
-## Verification contract
-
-- Rust unit tests cover state transitions, policy decisions, instruction ordering, signature verification, delivery deduplication, and command allowlisting.
-- Rust integration tests cover JSON-RPC over a real Unix socket, SQLite restart recovery, a real temporary Git worktree, and mocked GitHub HTTP responses.
-- Swift tests cover decoding, store state, Foundation Models availability mapping, and task presentation.
-- The repository provides one command for all tests and a project-local build/run script that stages and verifies the real `.app` bundle.
-- A smoke fixture initializes a disposable repository, creates a review task, prepares a worktree, runs a harmless verification command, restarts the engine, and verifies that evidence survives.
-
-## Privacy and release boundary
-
-Patchwright is local-first. The first release collects no product analytics. Unified logs contain identifiers and state changes, not source contents, prompts, tokens, or command output. The app uses the smallest feasible sandbox/entitlement set; repository access is user-selected. The local build can be release-candidate quality, but App Store upload readiness remains blocked on final bundle identity, signing profile, store metadata, privacy declarations, and owner authorization.
-
diff --git a/docs/superpowers/specs/2026-07-15-direct-open-source-release-design.md b/docs/superpowers/specs/2026-07-15-direct-open-source-release-design.md
deleted file mode 100644
index e9fd8f8..0000000
--- a/docs/superpowers/specs/2026-07-15-direct-open-source-release-design.md
+++ /dev/null
@@ -1,107 +0,0 @@
-# Patchwright Direct Open-Source Release Design
-
-## Outcome
-
-Patchwright 0.1.0 ships outside the Mac App Store as a free technical beta. The official Apple-silicon macOS 26+ build is assembled from the public `v0.1.0` source tag, signed with Developer ID Application, notarized and stapled by Apple, distributed in an immutable GitHub Release, and updateable through Sparkle 2.
-
-The complete Patchwright source needed to build the desktop app, engine, relay, packaging scripts, and release metadata is public under `MIT OR Apache-2.0`. Publisher credentials, private signing keys, notary credentials, update-signing keys, and GitHub App private keys are operational secrets and are never published.
-
-## Product and Distribution Boundary
-
-- The release lane is direct Developer ID distribution. Mac App Store, App Sandbox, App Store Connect, and StoreKit are out of scope for this version.
-- The official artifact is `Patchwright-0.1.0.dmg`. A privileged installer package is not added.
-- The supported matrix is macOS 26.0 or newer on Apple silicon. Intel and older macOS releases are explicit non-goals for 0.1.0.
-- The application remains local-first. It stores state under `~/.patchwright`, launches the bundled engine, and discovers a separately installed Codex CLI.
-- Read-only GitHub sync may use the user's existing `gh` authentication. GitHub mutations remain disabled until the user configures a bring-your-own GitHub App. The publisher's GitHub App private key is never distributed.
-- The repository and binary release become public only after complete-history secret scanning, source verification, notarized-artifact verification, and exact-digest promotion gates pass.
-
-## Open-Source Contract
-
-- Add `LICENSE-MIT` and `LICENSE-APACHE` and declare `MIT OR Apache-2.0` consistently in Cargo and public documentation.
-- Add contribution, security-reporting, code-of-conduct, privacy, support, and build-from-source documentation.
-- Replace misleading `All rights reserved` bundle copy with clear copyright and license wording.
-- Generate a machine-readable SPDX 2.3 SBOM and a dependency-derived third-party notice for every release candidate. The generated documents cover Rust, Swift, bundled binaries, and Sparkle.
-- Scan the complete Git object graph, all local refs, and the release directory for credential-shaped content. Publication fails closed on a finding.
-- Public documentation states that Patchwright is open source while macOS, Apple Foundation Models, GitHub, and Codex are external platforms or services with their own terms.
-
-## Update Architecture
-
-- Pin Sparkle 2.9.2 through Swift Package Manager and link the `Sparkle` product into `PatchwrightApp`.
-- Add a single updater controller owned by the application lifecycle and a `Check for Updates...` command.
-- Configure `SUFeedURL` as `https://github.com/s1korrrr/patchwright/releases/latest/download/appcast.xml`.
-- Embed only the Sparkle Ed25519 public key in `Info.plist`. Keep the private key in the release operator's protected Keychain and never accept it through command-line arguments, environment files, repository files, or release assets.
-- Require HTTPS, Ed25519-signed update archives, pre-extraction verification, and a signed feed.
-- Sign and verify all Sparkle frameworks, XPC services, applications, and helper executables inside-out before signing Patchwright.app.
-- Allow only the known Sparkle framework symlinks required by the pinned dependency; continue rejecting escaping or undeclared bundle symlinks.
-
-## GitHub Credential Model
-
-- The technical beta keeps the existing bring-your-own GitHub App model for mutation workflows.
-- Setup copy must say that the user creates and owns the GitHub App and private key.
-- Read-only sync remains usable without a GitHub App when `gh` authentication is available.
-- The app must never imply that a publisher credential is bundled, and mutation controls remain fail-closed until repository access is verified.
-- A hosted official relay, OAuth/device authorization, team administration, billing, and managed execution are future service work and are not part of 0.1.0.
-
-## Release Architecture
-
-The release workflow is split into two digest-bound phases.
-
-### Package
-
-1. Require a clean, tagged source commit.
-2. Run source tests, strict builds, packaging contracts, secret checks, and dependency/license checks.
-3. Assemble the app outside File Provider storage.
-4. Sign all nested code and the app with one Developer ID Application identity, Hardened Runtime, and secure timestamps.
-5. Create and sign the DMG.
-6. Submit the app and DMG with a named `notarytool` Keychain profile, retain the notarization results, and staple both artifacts.
-7. Verify code signatures, Team ID consistency, entitlements, notarization tickets, mounted DMG layout, Gatekeeper, appcast signature, SBOM, notices, and checksums.
-8. Emit a notarized-candidate manifest containing the source commit, tag, version, build number, artifact path, artifact SHA-256, and evidence paths.
-
-### Promote
-
-1. Consume the notarized-candidate manifest rather than rebuilding.
-2. Require clean-machine and integration evidence bound to the candidate DMG SHA-256.
-3. Verify that the public tag resolves to the candidate source commit.
-4. Create a draft GitHub Release and attach the DMG, checksum, appcast, SBOM, third-party notices, and redacted release evidence.
-5. Publish the complete release atomically and enable repository release immutability.
-6. Change repository visibility to public only after the publication preflight remains green.
-
-Environment booleans are not sufficient evidence. Every external proof consumed during promotion must name the candidate digest and be represented by a regular JSON evidence file.
-
-## Release Security
-
-- Pull-request and fork CI never receives Developer ID, notary, GitHub App, or Sparkle private credentials.
-- The first official release is produced on the trusted local release Mac. Later automation may use a protected, dedicated macOS runner, but importing a `.p12` into ordinary hosted CI is not part of this release.
-- The release process uses a named Keychain notary profile and a Keychain-backed Sparkle key. Raw secrets are never accepted as script arguments.
-- Complete-history scanning runs before changing repository visibility. Any historical secret requires revocation or rotation before publication; unresolved findings block publication.
-- Release evidence may expose the public Team ID, bundle ID, notarization request ID, commit, version, and artifact hash. Local paths, usernames, repository content, tokens, keys, and private GitHub identifiers are redacted.
-
-## User Experience
-
-- Add a production-quality Patchwright app icon and include its editable source asset plus generated `.icns` in the repository.
-- The first-launch and settings experience identifies missing Codex, missing `gh` authentication, and missing bring-your-own GitHub App configuration separately.
-- The download documentation says macOS 26+ and Apple silicon before the download action, explains drag installation, and never asks users to bypass Gatekeeper.
-- The About surface exposes version, build, source URL, licenses, privacy document, and update check.
-
-## Testing and Evidence
-
-- Every behavior change follows red-green-refactor with focused Swift or shell contract tests.
-- `./script/verify.sh` remains the source gate and gains updater, license, SBOM, secret-scan, package-manifest, and promotion-contract coverage.
-- A release build must pass `codesign`, `stapler`, `spctl`, mounted-DMG validation, and a launch smoke from `/Applications` or an equivalent clean install location.
-- The exact notarized DMG must pass the disposable clean-machine matrix covering first launch, missing dependencies, Codex setup, GitHub setup, one disposable approval-gated lifecycle, relaunch, update, offline/revoked states, migration, and uninstall/data-retention behavior.
-- Publication is blocked when any required evidence is absent, stale, references a different digest, or contains credential-shaped content.
-
-## Publication and Commercial Position
-
-- Patchwright 0.1.0 is free and has no StoreKit, local license lock, subscription, or paywall.
-- Future revenue may come from a managed open-source relay, team controls, hosted execution, stable/LTS support, and deployment assistance. These future services do not narrow the 0.1.0 source license.
-- The public release page identifies official signed binaries as maintainer builds and explains that community builds do not carry the maintainer's Developer ID signature.
-
-## Acceptance Criteria
-
-- The public repository contains complete buildable source, explicit dual licenses, contribution/security/privacy documentation, and no unresolved secret-scan findings.
-- `Patchwright-0.1.0.dmg` is signed with Developer ID Application, Hardened Runtime, and secure timestamps; the app and DMG have valid notarization tickets and pass Gatekeeper.
-- Sparkle can parse the published signed appcast and verifies the release archive with the embedded public key.
-- The release assets are traceable to public tag `v0.1.0` and one commit through checksums, SBOM, build metadata, and immutable release attestation.
-- Clean-machine and integration evidence is bound to the released DMG digest.
-- The repository is public and the immutable GitHub Release is downloadable without Mac App Store access.
diff --git a/plans/active/2026-07-20-open-source-release-readiness.md b/plans/active/2026-07-20-open-source-release-readiness.md
deleted file mode 100644
index b8c1bf2..0000000
--- a/plans/active/2026-07-20-open-source-release-readiness.md
+++ /dev/null
@@ -1,101 +0,0 @@
-# Patchwright open-source release readiness
-
-## Goal
-
-- User-visible outcome: prepare Patchwright's current source tree for a professional public GitHub release, remediate safe repository-side blockers, and finish with an evidence-backed publication decision.
-- How to see it working: a clean clone can follow the documented build path, required checks and release rehearsal pass, security and provenance evidence is recorded, public community files are usable, and remaining owner/external gates are stated exactly.
-
-## Current State
-
-- Relevant paths: Swift package in `Package.swift`, Rust workspace in `Cargo.toml`, runtime crates in `crates/`, Swift sources in `Sources/`, tests in `Tests/` and crate test directories, release tooling in `script/`, packaging inputs in `Packaging/`, public documentation in the repository root and `docs/`, and GitHub configuration in `.github/`.
-- Existing behavior: Patchwright is a macOS 26+ local-first GitHub engineering control plane with a SwiftUI app, Rust engine, Rust relay, direct-download packaging, GitHub Actions, tags `v0.1.0` and `v0.1.1`, and an existing dual `MIT OR Apache-2.0` license choice.
-- Baseline: `main` at `8e9a08111ed721d80a7059a89bf9326ee3b0540d`, tracking `origin/main`; release work is isolated on `chore/oss-release-readiness`.
-- Constraints: preserve three pre-existing untracked monetization-document paths; do not publish a GitHub Release, change visibility/settings/profiles, choose new legal identity, rewrite history, or expose secrets. On 2026-07-20 the user explicitly authorized merging this release-readiness work to `main`, pushing `main`, and cleaning up task-owned temporary artifacts and the merged branch.
-
-## Target State
-
-- Desired behavior: public-source blockers are removed or fail-closed; build, lint, test, package, security, documentation, and clean-clone evidence is reproducible; community and release configuration match actual support boundaries; the final report distinguishes repository readiness from GitHub, signing, notarization, and owner approval gates.
-- Non-goals: no repository settings/profile mutation, no profile pinning, no binary/package publication, no license or copyright change, no history rewrite, and no unrelated product redesign.
-
-## Risks and Failure Modes
-
-- Existing untracked user work could be accidentally staged or committed.
-- Release claims could exceed current signing, notarization, GitHub settings, or clean-machine evidence.
-- A broad cleanup could break exact approval, credential, or release-evidence contracts.
-- Security scanners can produce false positives or leak secret material if raw output is handled carelessly.
-- Public CI can become unsafe if fork-controlled inputs reach privileged tokens or publishing jobs.
-- The local 6.2 GB checkout includes ignored build caches and a release worktree; these must not be mistaken for tracked release contents.
-
-## Milestones
-
-### M1. Baseline and public-surface inventory
-
-- Goal: establish the exact Git, toolchain, tracked-file, build, test, documentation, release, and GitHub baseline before edits.
-- Files / systems: repository tree, Git metadata, manifests, workflows, scripts, docs, local GitHub metadata where read-only authenticated access is available.
-- Changes: record evidence only; update this plan as facts replace assumptions.
-- Verification: `git status --short --branch`, `git ls-files`, tool-version checks, repository-provided verification commands, and read-only GitHub inspection.
-- Expected result: pre-existing failures and external limitations are separated from regressions.
-
-### M2. Privacy, history, and provenance closure
-
-- Goal: scan the checkout and reachable history for publication secrets, inventory third-party rights, and close dependency/provenance blockers.
-- Files / systems: all tracked source/config/docs/assets plus reachable Git history.
-- Changes: apply focused, tested runtime and release-control hardening; do not rewrite history or make legal decisions.
-- Verification: repository secret-scan scripts, dependency advisories, license inventory, focused regression tests, and redacted history checks. The user explicitly removed the Codex Security scan from scope on 2026-07-20.
-- Expected result: the publication corpus is secret-clean, locked dependencies have no known advisory blocker, focused hardening tests pass, and any historical or IP blocker is explicit.
-
-### M3. Correctness, hygiene, and public CI
-
-- Goal: fix validated release blockers and tighten repository hygiene, CI permissions, test coverage, and deterministic release behavior without scope creep.
-- Files / systems: implementation, tests, `.gitignore`, `.gitattributes`/`.editorconfig` where justified, `.github/`, package metadata, and release scripts.
-- Changes: small reviewable edits grouped by cause, with tests first for behavior fixes.
-- Verification: Swift and Rust formatting, linting, unit/integration tests, build, workflow-policy checks, `git diff --check`, and targeted regression smokes.
-- Expected result: required checks pass locally or have a precise accepted environmental blocker.
-
-### M4. Documentation, community, and release package
-
-- Goal: make installation, safety boundaries, support, contribution, security reporting, release steps, and GitHub intake accurate and executable.
-- Files / systems: `README.md`, `CONTRIBUTING.md`, `SECURITY.md`, `SUPPORT.md`, `CODE_OF_CONDUCT.md`, `CHANGELOG.md`, `docs/`, `.github/`, packaging metadata and notices.
-- Changes: correct unsupported claims and stale commands; add only community/release files that serve a real workflow.
-- Verification: execute every documented command where practical, validate links and metadata, inspect package contents, and compare release claims to evidence.
-- Expected result: a new public contributor can build and verify without private dependencies or unstated credentials.
-
-### M5. Fresh-clone rehearsal and final gate
-
-- Goal: prove the prepared tree from a fresh temporary clone and produce the required GO/NO-GO report plus exact approval request.
-- Files / systems: clean temporary clone, built artifacts, security bundle, release dossier, Git status and commit set.
-- Changes: finalize evidence, logical local commits containing only intentional release work, and no remote writes.
-- Verification: clean-clone setup/build/tests/quickstart/package/install smoke, secret rescan, documentation/link checks, package inspection, and final `git diff --check`/status review.
-- Expected result: `READY AFTER LISTED APPROVALS` only if repository-side evidence passes; otherwise `NOT READY FOR PUBLICATION` with blocking next actions.
-
-## Verification
-
-- `./script/verify.sh`
-- `./script/smoke.sh`
-- `./script/build_and_run.sh --verify`
-- `cargo fmt --all -- --check`
-- `cargo clippy --workspace --all-targets --all-features -- -D warnings`
-- `cargo test --workspace --all-targets --all-features`
-- `swift test`
-- `./script/scan_publication_secrets.sh`
-- Release/package commands discovered from `script/release_readiness.sh`, `script/package_release.sh`, and release documentation.
-- Fresh-clone manual smoke from a temporary path using only documented prerequisites.
-
-## Decision Log
-
-- 2026-07-20: Use the user-specified `chore/oss-release-readiness` branch even though the general HQ default is `feat/andrzej_*`; the task brief explicitly names this branch.
-- 2026-07-20: Treat the existing dual MIT/Apache-2.0 files and manifest declaration as an already-selected license, not authority to change license or copyright ownership.
-- 2026-07-20: Preserve and exclude the pre-existing untracked `docs/monetization/`, `docs/reflections/2026-07-15-patchwright-monetization-assessment.md`, and `docs/superpowers/plans/2026-07-15-patchwright-monetization-assessment.md` paths.
-- 2026-07-20: The user explicitly canceled the Codex Security scan deliverable after the code hardening and repository verification had completed; temporary scan artifacts are excluded from the release output and removed during cleanup.
-- 2026-07-20: The user explicitly authorized a local merge to `main`, push of `main`, and cleanup of task-owned temporary artifacts and the merged branch. Repository settings, profile changes, and binary release publication remain separate actions.
-
-## Progress Log
-
-- 2026-07-20: Completed session bootstrap, task/authority parsing, Git/manifest/community-file inventory, branch isolation, repository/publication hardening, community and release documentation, and focused regression coverage.
-- 2026-07-20: `./script/verify.sh`, `./script/smoke.sh`, `./script/build_and_run.sh --verify`, `cargo fmt --all -- --check`, refreshed `cargo audit --deny warnings`, local-link validation, and a clean temporary-copy `./script/verify.sh` all passed. The only intentionally ignored test requires a signed-in Codex installation and may consume model quota.
-- 2026-07-20: Final step: stage only task-owned files, rescan the exact staged publication set, commit, merge to `main`, verify the merged tree, push `main`, and clean task-owned temporary artifacts without touching the three preserved user paths.
-
-## Rollback / Recovery
-
-- If this fails: stop before any external or destructive action, record the exact failing command and affected file, and leave user-owned untracked paths untouched.
-- Safe fallback: revert only task-owned hunks with a reviewed patch or commit-level inverse after confirmation; never reset, clean, stash, or overwrite unrelated work.
diff --git a/script/build_release_components.sh b/script/build_release_components.sh
index 412bb89..fb93486 100755
--- a/script/build_release_components.sh
+++ b/script/build_release_components.sh
@@ -2,8 +2,8 @@
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
-VERSION="${PATCHWRIGHT_VERSION:-0.1.1}"
-BUILD="${PATCHWRIGHT_BUILD:-2}"
+VERSION="${PATCHWRIGHT_VERSION:-0.2.0}"
+BUILD="${PATCHWRIGHT_BUILD:-3}"
OUTPUT_PARENT="${PATCHWRIGHT_RELEASE_WORK_ROOT:-$HOME/.patchwright/release-work}"
ALLOW_DIRTY="${PATCHWRIGHT_ALLOW_DIRTY:-0}"
[[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+([.-][A-Za-z0-9]+)*$ ]] || { echo "invalid PATCHWRIGHT_VERSION" >&2; exit 64; }
diff --git a/script/generate_release_compliance.py b/script/generate_release_compliance.py
index 6fe5242..b80cd68 100755
--- a/script/generate_release_compliance.py
+++ b/script/generate_release_compliance.py
@@ -370,7 +370,7 @@ def build_documents(
"dataLicense": "CC0-1.0",
"SPDXID": "SPDXRef-DOCUMENT",
"name": "Patchwright release SBOM",
- "documentNamespace": f"https://github.com/s1korrrr/patchwright/spdx/{namespace_digest}",
+ "documentNamespace": f"https://github.com/rsitech-ai/patchwright/spdx/{namespace_digest}",
"creationInfo": {"created": created_timestamp(), "creators": ["Tool: Patchwright compliance generator"]},
"packages": package_rows,
"files": files,
diff --git a/script/package_community_release.sh b/script/package_community_release.sh
new file mode 100755
index 0000000..b88a315
--- /dev/null
+++ b/script/package_community_release.sh
@@ -0,0 +1,128 @@
+#!/usr/bin/env bash
+set -euo pipefail
+umask 077
+
+ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
+APP_PATH=""
+OUTPUT_DIR=""
+VERSION=""
+BUILD=""
+TAG=""
+STAGE=""
+
+cleanup() {
+ if [[ -n "$STAGE" && -e "$STAGE" ]]; then
+ /usr/bin/trash "$STAGE" >/dev/null 2>&1 || true
+ fi
+}
+trap cleanup EXIT
+
+fail() {
+ echo "community release failed: $*" >&2
+ exit 65
+}
+
+usage() {
+ cat >&2 <<'EOF'
+usage: package_community_release.sh \
+ --app /absolute/path/Patchwright.app \
+ --output /absolute/path/output \
+ --version X.Y.Z \
+ --build N \
+ --tag vX.Y.Z-community.N
+EOF
+ exit 64
+}
+
+while [[ $# -gt 0 ]]; do
+ case "$1" in
+ --app) [[ $# -ge 2 ]] || usage; APP_PATH="$2"; shift 2 ;;
+ --output) [[ $# -ge 2 ]] || usage; OUTPUT_DIR="$2"; shift 2 ;;
+ --version) [[ $# -ge 2 ]] || usage; VERSION="$2"; shift 2 ;;
+ --build) [[ $# -ge 2 ]] || usage; BUILD="$2"; shift 2 ;;
+ --tag) [[ $# -ge 2 ]] || usage; TAG="$2"; shift 2 ;;
+ *) usage ;;
+ esac
+done
+
+[[ "$APP_PATH" == /* && -d "$APP_PATH" && ! -L "$APP_PATH" ]] \
+ || fail "--app must be an absolute, non-symlink app bundle"
+[[ "$OUTPUT_DIR" == /* ]] || fail "--output must be an absolute directory path"
+[[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || fail "invalid community release version"
+[[ "$BUILD" =~ ^[1-9][0-9]*$ ]] || fail "invalid community release build"
+ESCAPED_VERSION="${VERSION//./\\.}"
+[[ "$TAG" =~ ^v${ESCAPED_VERSION}-community\.[1-9][0-9]*$ ]] \
+ || fail "community release tag must match v$VERSION-community.N"
+
+COMMIT="$(git -C "$ROOT_DIR" rev-parse HEAD)"
+[[ -z "$(git -C "$ROOT_DIR" status --porcelain)" ]] \
+ || fail "community release worktree must be clean"
+TAG_COMMIT="$(git -C "$ROOT_DIR" rev-parse "refs/tags/$TAG^{commit}" 2>/dev/null || true)"
+[[ "$TAG_COMMIT" == "$COMMIT" ]] || fail "community release tag must resolve to HEAD"
+
+INFO_PLIST="$APP_PATH/Contents/Info.plist"
+EXECUTABLE_NAME="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleExecutable' "$INFO_PLIST" 2>/dev/null || true)"
+APP_VERSION="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' "$INFO_PLIST" 2>/dev/null || true)"
+APP_BUILD="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleVersion' "$INFO_PLIST" 2>/dev/null || true)"
+MINIMUM_MACOS="$(/usr/libexec/PlistBuddy -c 'Print :LSMinimumSystemVersion' "$INFO_PLIST" 2>/dev/null || true)"
+[[ -n "$EXECUTABLE_NAME" && -f "$APP_PATH/Contents/MacOS/$EXECUTABLE_NAME" ]] \
+ || fail "app bundle executable is missing"
+[[ "$APP_VERSION" == "$VERSION" ]] || fail "app version does not match --version"
+[[ "$APP_BUILD" == "$BUILD" ]] || fail "app build does not match --build"
+[[ -n "$MINIMUM_MACOS" ]] || fail "app minimum macOS version is missing"
+
+/usr/bin/codesign --verify --deep --strict "$APP_PATH"
+SIGNING_DETAILS="$(/usr/bin/codesign -dv --verbose=4 "$APP_PATH" 2>&1)"
+grep -Fq 'Signature=adhoc' <<<"$SIGNING_DETAILS" \
+ || fail "community app must use an ad-hoc signature"
+TEAM_ID="$(sed -n 's/^TeamIdentifier=//p' <<<"$SIGNING_DETAILS")"
+[[ -z "$TEAM_ID" || "$TEAM_ID" == "not set" ]] \
+ || fail "community app must not carry a Developer ID team identifier"
+
+ARCHS="$(/usr/bin/lipo -archs "$APP_PATH/Contents/MacOS/$EXECUTABLE_NAME")"
+case "$ARCHS" in
+ arm64) ARCHITECTURE="arm64" ;;
+ x86_64) ARCHITECTURE="x86_64" ;;
+ 'x86_64 arm64'|'arm64 x86_64') ARCHITECTURE="universal2" ;;
+ *) fail "unsupported app architecture: $ARCHS" ;;
+esac
+
+RELEASE_SUFFIX="${TAG#v$VERSION-}"
+ARCHIVE_NAME="Patchwright-$VERSION-$RELEASE_SUFFIX-macos-$ARCHITECTURE.zip"
+MANIFEST_NAME="Patchwright-$VERSION-$RELEASE_SUFFIX-manifest.json"
+CHECKSUM_NAME="$ARCHIVE_NAME.sha256"
+mkdir -p "$OUTPUT_DIR"
+for path in "$OUTPUT_DIR/$ARCHIVE_NAME" "$OUTPUT_DIR/$CHECKSUM_NAME" "$OUTPUT_DIR/$MANIFEST_NAME"; do
+ [[ ! -e "$path" ]] || fail "refusing to overwrite existing release output: $path"
+done
+
+STAGE="$(mktemp -d "${TMPDIR:-/tmp}/patchwright-community-package.XXXXXX")"
+/usr/bin/ditto "$APP_PATH" "$STAGE/Patchwright.app"
+/usr/bin/ditto -c -k --keepParent --sequesterRsrc "$STAGE/Patchwright.app" "$STAGE/$ARCHIVE_NAME"
+ARCHIVE_SHA256="$(shasum -a 256 "$STAGE/$ARCHIVE_NAME" | awk '{print $1}')"
+printf '%s %s\n' "$ARCHIVE_SHA256" "$ARCHIVE_NAME" >"$STAGE/$CHECKSUM_NAME"
+CREATED_AT="$(git -C "$ROOT_DIR" show -s --format=%cI "$COMMIT")"
+jq -n \
+ --arg version "$VERSION" \
+ --arg build "$BUILD" \
+ --arg tag "$TAG" \
+ --arg git_commit "$COMMIT" \
+ --arg archive "$ARCHIVE_NAME" \
+ --arg archive_sha256 "$ARCHIVE_SHA256" \
+ --arg minimum_macos "$MINIMUM_MACOS" \
+ --arg architecture "$ARCHITECTURE" \
+ --arg created_at "$CREATED_AT" \
+ '{schema_version:1,kind:"patchwright.community-prerelease",version:$version,build:$build,
+ tag:$tag,git_commit:$git_commit,archive:$archive,archive_sha256:$archive_sha256,
+ platform:"macOS",minimum_macos:$minimum_macos,architecture:$architecture,
+ signing:"ad-hoc",notarized:false,created_at:$created_at,
+ install_warning:"This community build is not Developer ID signed or Apple notarized. macOS Gatekeeper may block it; build from source if you require a locally trusted copy."}' \
+ >"$STAGE/$MANIFEST_NAME"
+
+/bin/mv "$STAGE/$ARCHIVE_NAME" "$OUTPUT_DIR/$ARCHIVE_NAME"
+/bin/mv "$STAGE/$CHECKSUM_NAME" "$OUTPUT_DIR/$CHECKSUM_NAME"
+/bin/mv "$STAGE/$MANIFEST_NAME" "$OUTPUT_DIR/$MANIFEST_NAME"
+printf 'PATCHWRIGHT_COMMUNITY_ARCHIVE=%s\n' "$OUTPUT_DIR/$ARCHIVE_NAME"
+printf 'PATCHWRIGHT_COMMUNITY_CHECKSUM=%s\n' "$OUTPUT_DIR/$CHECKSUM_NAME"
+printf 'PATCHWRIGHT_COMMUNITY_MANIFEST=%s\n' "$OUTPUT_DIR/$MANIFEST_NAME"
+printf 'PATCHWRIGHT_STATUS=community-prerelease-not-notarized\n'
diff --git a/script/package_release.sh b/script/package_release.sh
index 4cdad9c..60db77c 100755
--- a/script/package_release.sh
+++ b/script/package_release.sh
@@ -3,8 +3,8 @@ set -euo pipefail
umask 077
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
-VERSION="${PATCHWRIGHT_VERSION:-0.1.1}"
-BUILD="${PATCHWRIGHT_BUILD:-2}"
+VERSION="${PATCHWRIGHT_VERSION:-0.2.0}"
+BUILD="${PATCHWRIGHT_BUILD:-3}"
SPARKLE_ACCOUNT="ai.patchwright.app.release-v1"
SIGNING_KEYCHAIN="${PATCHWRIGHT_SIGNING_KEYCHAIN:-}"
APPCAST_STAGE=""
@@ -80,8 +80,8 @@ SPARKLE_BIN="$ROOT_DIR/.build/artifacts/sparkle/Sparkle/bin"
APPCAST_STAGE="$(mktemp -d "${TMPDIR:-/tmp}/patchwright-appcast.XXXXXX")"
/usr/bin/ditto "$DMG_PATH" "$APPCAST_STAGE/$(basename "$DMG_PATH")"
"$SPARKLE_BIN/generate_appcast" --account "$SPARKLE_ACCOUNT" \
- --download-url-prefix "https://github.com/s1korrrr/patchwright/releases/download/v$VERSION/" \
- --link "https://github.com/s1korrrr/patchwright/releases/tag/v$VERSION" --versions "$BUILD" --maximum-deltas 0 \
+ --download-url-prefix "https://github.com/rsitech-ai/patchwright/releases/download/v$VERSION/" \
+ --link "https://github.com/rsitech-ai/patchwright/releases/tag/v$VERSION" --versions "$BUILD" --maximum-deltas 0 \
-o "$APPCAST_STAGE/appcast.xml" "$APPCAST_STAGE"
APPCAST_PATH="$RELEASE_ROOT/appcast.xml"
/usr/bin/ditto "$APPCAST_STAGE/appcast.xml" "$APPCAST_PATH"
diff --git a/script/smoke_github_app.sh b/script/smoke_github_app.sh
index ca2cee6..68dfbf0 100755
--- a/script/smoke_github_app.sh
+++ b/script/smoke_github_app.sh
@@ -30,7 +30,11 @@ if [[ -n "$EXISTING_ISSUE_NUMBER" ]]; then
fi
[[ -n "$TARGET_OWNER" && -n "$TARGET_REPOSITORY" ]] || fail "set the disposable owner and repository"
-[[ "$NORMALIZED_TARGET" != "s1korrrr/patchwright" ]] || fail "the Patchwright production repository is forbidden"
+case "$NORMALIZED_TARGET" in
+ rsitech-ai/patchwright|s1korrrr/patchwright)
+ fail "the Patchwright production repository is forbidden"
+ ;;
+esac
[[ "$TARGET" == "$ALLOWLIST" ]] || fail "PATCHWRIGHT_GITHUB_E2E_ALLOWLIST must exactly equal $TARGET"
[[ "$CONFIRMATION" == "authorize:$TARGET" ]] || fail "set PATCHWRIGHT_GITHUB_E2E_CONFIRM=authorize:$TARGET for this one run"
[[ "$TARGET_REPOSITORY_ID" =~ ^[1-9][0-9]*$ ]] || fail "set the numeric disposable repository ID"
diff --git a/script/verify.sh b/script/verify.sh
index 13f1a1f..8f03e73 100755
--- a/script/verify.sh
+++ b/script/verify.sh
@@ -8,6 +8,7 @@ bash -n script/smoke_github_app.sh
Tests/PackagingTests/github_app_smoke_contract.sh
Tests/PackagingTests/release_security_contract.sh
Tests/PackagingTests/release_contract.sh
+Tests/PackagingTests/community_release_contract.sh
Tests/PackagingTests/compliance_contract.sh
Tests/PackagingTests/candidate_evidence_contract.sh
Tests/PackagingTests/promotion_contract.sh
diff --git a/script/verify_release_evidence.py b/script/verify_release_evidence.py
index 76fc85a..d7aec57 100755
--- a/script/verify_release_evidence.py
+++ b/script/verify_release_evidence.py
@@ -401,7 +401,7 @@ def verify_candidate(candidate_path: Path, repo: Path, now: datetime) -> tuple[d
item = enclosure_items[0]
versions = item.findall(f"{sparkle}version")
short_versions = item.findall(f"{sparkle}shortVersionString")
- expected_url = f"https://github.com/s1korrrr/patchwright/releases/download/{identity['tag']}/{identity['artifact_filename']}"
+ expected_url = f"https://github.com/rsitech-ai/patchwright/releases/download/{identity['tag']}/{identity['artifact_filename']}"
if enclosure.get("url") != expected_url or enclosure.get("length") != str(artifact_stat.st_size) or enclosure.get("type") != "application/octet-stream" or len(versions) != 1 or versions[0].text != identity["build"] or len(short_versions) != 1 or short_versions[0].text != identity["version"]:
raise VerificationError("signed appcast enclosure does not match candidate")
appcast_bytes = read_bytes(appcast, "signed appcast", MAX_JSON_BYTES)
From ecbcba7d3552356c9967447bfe2b870225bb43bf Mon Sep 17 00:00:00 2001
From: Rafal Sikora <24563931+s1korrrr@users.noreply.github.com>
Date: Mon, 20 Jul 2026 21:58:36 +0200
Subject: [PATCH 2/3] Harden community release provenance
Signed-off-by: Rafal Sikora <24563931+s1korrrr@users.noreply.github.com>
---
CHANGELOG.md | 9 +-
CONTRIBUTING.md | 2 +-
Cargo.toml | 2 +-
LICENSE-APACHE => LICENSE | 0
LICENSE-MIT | 21 ---
NOTICE | 7 +
Packaging/Info.plist | 2 +-
README.md | 15 +-
SECURITY.md | 4 +-
SUPPORT.md | 5 +
.../community_release_contract.sh | 161 ++++++++++++------
Tests/PackagingTests/compliance_contract.sh | 5 +-
Tests/PackagingTests/release_contract.sh | 28 ++-
docs/RELEASING.md | 7 +-
docs/releases/v0.2.0-community.1.md | 9 +-
script/build_release_components.sh | 39 +++++
script/generate_release_compliance.py | 4 +-
script/package_community_release.sh | 105 +++++++++---
18 files changed, 295 insertions(+), 130 deletions(-)
rename LICENSE-APACHE => LICENSE (100%)
delete mode 100644 LICENSE-MIT
create mode 100644 NOTICE
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b5245b8..42ae56c 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -15,6 +15,8 @@ All notable user-facing and distribution changes are documented here. Patchwrigh
- Move the canonical public repository and release URLs to the RSI Tech
organization at `rsitech-ai/patchwright`.
+- Adopt Apache-2.0 as the sole project license and record Rafal Sikora as the
+ copyright owner, with RSI Tech as public maintainer.
- Require the live GitHub App qualification smoke to reject both the canonical
organization repository and the legacy founder-account redirect.
- Separate community prerelease downloads from the unchanged Developer ID,
@@ -37,17 +39,10 @@ All notable user-facing and distribution changes are documented here. Patchwrigh
- Remove preparation, delivery, and merge controls from completed task surfaces.
- Adapt the populated pull-request queue to constrained window widths without negative AppKit geometry faults.
- Clarify that local task preview and read-only GitHub data remain available without GitHub App mutation access.
-- Revalidate the approved head commit before resolving review threads, marking pull requests ready, or closing pull requests, and revalidate both approved refs before creating a draft pull request.
-- Bound GitHub snapshot fan-out across pull requests instead of applying the full resource limit independently to every nested endpoint.
### Security
- Reject malformed or partial task-contract integrity evidence consistently in the Rust engine and Swift client.
-- Reject malformed signing team identifiers in release evidence.
-- Bound Codex protocol-line allocation and aggregate request duration, event count, and event bytes.
-- Match Codex responses and completion events to their exact active request, thread, and turn identities.
-- Redact credential-shaped Codex event and approval content before durable SQLite persistence.
-- Require an explicit warning and confirmation before running unsandboxed repository-controlled verification commands.
### Distribution
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 39cbfa6..7da288c 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -38,7 +38,7 @@ sign-offs before merge.
Unless you explicitly state otherwise, contributions intentionally submitted
for inclusion in Patchwright are licensed under the repository's
-`MIT OR Apache-2.0` terms, without additional terms or conditions.
+Apache License 2.0 terms, without additional terms or conditions.
Community participation is governed by the [Code of Conduct](CODE_OF_CONDUCT.md).
Security vulnerabilities must follow the private process in
diff --git a/Cargo.toml b/Cargo.toml
index 4ab4399..b734729 100644
--- a/Cargo.toml
+++ b/Cargo.toml
@@ -9,7 +9,7 @@ resolver = "3"
[workspace.package]
edition = "2024"
rust-version = "1.85"
-license = "MIT OR Apache-2.0"
+license = "Apache-2.0"
[workspace.dependencies]
anyhow = "1.0"
diff --git a/LICENSE-APACHE b/LICENSE
similarity index 100%
rename from LICENSE-APACHE
rename to LICENSE
diff --git a/LICENSE-MIT b/LICENSE-MIT
deleted file mode 100644
index 6933e6d..0000000
--- a/LICENSE-MIT
+++ /dev/null
@@ -1,21 +0,0 @@
-MIT License
-
-Copyright (c) 2026 Patchwright contributors
-
-Permission is hereby granted, free of charge, to any person obtaining a copy
-of this software and associated documentation files (the "Software"), to deal
-in the Software without restriction, including without limitation the rights
-to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
-copies of the Software, and to permit persons to whom the Software is
-furnished to do so, subject to the following conditions:
-
-The above copyright notice and this permission notice shall be included in all
-copies or substantial portions of the Software.
-
-THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
-IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
-FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
-AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
-LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
-OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
-SOFTWARE.
diff --git a/NOTICE b/NOTICE
new file mode 100644
index 0000000..c6e71be
--- /dev/null
+++ b/NOTICE
@@ -0,0 +1,7 @@
+Patchwright
+Copyright 2026 Rafal Sikora
+
+Maintained publicly by RSI Tech (https://rsitech.ai).
+Project contact: info@rsitech.ai.
+
+Licensed under the Apache License, Version 2.0.
diff --git a/Packaging/Info.plist b/Packaging/Info.plist
index 9069884..34acb4c 100644
--- a/Packaging/Info.plist
+++ b/Packaging/Info.plist
@@ -29,7 +29,7 @@
NSHighResolutionCapable
NSHumanReadableCopyright
- Copyright © 2026 Patchwright contributors. Licensed under MIT OR Apache-2.0.
+ Copyright © 2026 Rafal Sikora. Licensed under Apache-2.0.
NSPrincipalClass
NSApplication
SUFeedURL
diff --git a/README.md b/README.md
index b1a9c77..7def771 100644
--- a/README.md
+++ b/README.md
@@ -16,8 +16,12 @@ Project policies: [Contributing](CONTRIBUTING.md) ·
[Security](SECURITY.md) · [Privacy](PRIVACY.md) · [Support](SUPPORT.md) ·
[Code of Conduct](CODE_OF_CONDUCT.md) · [Changelog](CHANGELOG.md)
-Patchwright is available under your choice of the
-[MIT License](LICENSE-MIT) or [Apache License 2.0](LICENSE-APACHE).
+Patchwright is maintained by [RSI Tech](https://rsitech.ai). Public and
+confidential project correspondence can be sent to
+[info@rsitech.ai](mailto:info@rsitech.ai).
+
+Copyright © 2026 Rafal Sikora. Patchwright is available under the
+[Apache License 2.0](LICENSE); see the accompanying [NOTICE](NOTICE).
This repository contains the Stage 1–3 MVP:
@@ -106,9 +110,10 @@ explicit promotion step. See the [direct-download guide](docs/direct-download.md
[clean-machine test plan](docs/clean-machine-test-plan.md).
When Developer ID and notarization credentials are unavailable,
-`script/package_community_release.sh` can package an already verified ad-hoc
-app from an exact clean tag. Its ZIP, checksum, and manifest are community
-prerelease artifacts only; they do not satisfy the official release gates.
+`script/package_community_release.sh` builds an ad-hoc-signed app from the
+exact clean tagged checkout and packages it with source, SBOM, and notice
+bindings. These community prerelease artifacts do not satisfy the official
+release gates.
## Safety
diff --git a/SECURITY.md b/SECURITY.md
index ba5216d..353530d 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -8,8 +8,8 @@ developer tooling and review action previews before approving them.
Do not open a public issue for a suspected vulnerability. Use GitHub's
[private vulnerability reporting form](https://github.com/rsitech-ai/patchwright/security/advisories/new).
-If that form is unavailable, contact a maintainer privately through the contact
-method on their GitHub profile.
+If that form is unavailable, email the RSI Tech maintainers privately at
+[info@rsitech.ai](mailto:info@rsitech.ai).
Include the affected version or commit, impact, reproduction steps, and any
suggested mitigation. Remove tokens, private source, personal data, and other
diff --git a/SUPPORT.md b/SUPPORT.md
index 1f59fff..4019758 100644
--- a/SUPPORT.md
+++ b/SUPPORT.md
@@ -6,6 +6,11 @@ agreement. Community support is offered on a best-effort basis through
promise of response time, resolution, compatibility, continued maintenance, or
individual support.
+General project correspondence can be sent to the RSI Tech maintainers at
+[info@rsitech.ai](mailto:info@rsitech.ai). Please do not send vulnerability
+details through public issues; use the confidential process in
+[SECURITY.md](SECURITY.md).
+
Before opening an issue:
1. Search existing issues and test the latest release or default branch.
diff --git a/Tests/PackagingTests/community_release_contract.sh b/Tests/PackagingTests/community_release_contract.sh
index 3901d96..abc7040 100755
--- a/Tests/PackagingTests/community_release_contract.sh
+++ b/Tests/PackagingTests/community_release_contract.sh
@@ -14,82 +14,139 @@ PACKAGER="$ROOT_DIR/script/package_community_release.sh"
[[ -x "$PACKAGER" ]] || fail "missing executable script/package_community_release.sh"
FIXTURE_REPO="$TMP_ROOT/repository"
-FIXTURE_APP="$TMP_ROOT/Patchwright.app"
OUTPUT_DIR="$TMP_ROOT/output"
-mkdir -p "$FIXTURE_REPO/script" "$FIXTURE_APP/Contents/MacOS"
+mkdir -p "$FIXTURE_REPO/script" "$TMP_ROOT/builds"
cp "$PACKAGER" "$FIXTURE_REPO/script/package_community_release.sh"
-xcrun clang -arch arm64 -x c -o "$FIXTURE_APP/Contents/MacOS/Patchwright" - <<'C'
+cat >"$FIXTURE_REPO/script/build_release_components.sh" <<'SH'
+#!/usr/bin/env bash
+set -euo pipefail
+[[ "${1:-}" == --community && $# == 1 ]] || { echo "community assembly mode required" >&2; exit 64; }
+ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
+VERSION="${PATCHWRIGHT_VERSION:?version required}"
+BUILD="${PATCHWRIGHT_BUILD:?build required}"
+OUTPUT_PARENT="${PATCHWRIGHT_RELEASE_WORK_ROOT:?work root required}"
+mkdir -p "$OUTPUT_PARENT"
+WORK_ROOT="$(mktemp -d "$OUTPUT_PARENT/Patchwright-$VERSION-$BUILD.XXXXXX")"
+APP_PATH="$WORK_ROOT/Patchwright.app"
+mkdir -p "$APP_PATH/Contents/MacOS" "$APP_PATH/Contents/Resources/third-party-licenses/Fake" \
+ "$WORK_ROOT/evidence" "$WORK_ROOT/reproducibility"
+xcrun clang -arch arm64 -x c -o "$APP_PATH/Contents/MacOS/Patchwright" - <<'C'
int main(void) { return 0; }
C
-chmod 755 "$FIXTURE_APP/Contents/MacOS/Patchwright"
-cat >"$FIXTURE_APP/Contents/Info.plist" <<'PLIST'
+chmod 755 "$APP_PATH/Contents/MacOS/Patchwright"
+cat >"$APP_PATH/Contents/Info.plist" <
-
-
- CFBundleExecutable
- Patchwright
- CFBundleIdentifier
- ai.patchwright.app
- CFBundlePackageType
- APPL
- CFBundleShortVersionString
- 0.2.0
- CFBundleVersion
- 3
- LSMinimumSystemVersion
- 26.0
-
-
+
+CFBundleExecutablePatchwright
+CFBundleIdentifierai.patchwright.app
+CFBundlePackageTypeAPPL
+CFBundleShortVersionString$VERSION
+CFBundleVersion$BUILD
+LSMinimumSystemVersion26.0
+
PLIST
-/usr/bin/codesign --force --sign - "$FIXTURE_APP"
+printf '\n' \
+ >"$APP_PATH/Contents/Resources/PrivacyInfo.xcprivacy"
+printf '# Third-Party Notices\n\nFake dependency.\n' \
+ >"$APP_PATH/Contents/Resources/THIRD_PARTY_NOTICES.md"
+printf 'Fake license\n' >"$APP_PATH/Contents/Resources/third-party-licenses/Fake/LICENSE"
+/usr/bin/codesign --force --sign - "$APP_PATH"
+git -C "$ROOT_DIR" archive --format=tar.gz --output="$WORK_ROOT/reproducibility/source.tar.gz" HEAD
+COMMIT="$(git -C "$ROOT_DIR" rev-parse HEAD)"
+SOURCE_SHA256="$(shasum -a 256 "$WORK_ROOT/reproducibility/source.tar.gz" | awk '{print $1}')"
+printf '{"spdxVersion":"SPDX-2.3","dataLicense":"CC0-1.0"}\n' >"$WORK_ROOT/evidence/sbom.spdx.json"
+cp "$APP_PATH/Contents/Resources/THIRD_PARTY_NOTICES.md" "$WORK_ROOT/evidence/third-party-notices.md"
+SBOM_SHA256="$(shasum -a 256 "$WORK_ROOT/evidence/sbom.spdx.json" | awk '{print $1}')"
+NOTICES_SHA256="$(shasum -a 256 "$WORK_ROOT/evidence/third-party-notices.md" | awk '{print $1}')"
+jq -n --arg app_path "$APP_PATH" --arg version "$VERSION" --arg build "$BUILD" \
+ --arg git_commit "$COMMIT" --arg source_archive_sha256 "$SOURCE_SHA256" \
+ --arg sbom_sha256 "$SBOM_SHA256" --arg notices_sha256 "$NOTICES_SHA256" \
+ '{schema_version:1,kind:"patchwright.community-assembly",app_path:$app_path,
+ version:$version,build:$build,git_commit:$git_commit,dirty:false,
+ signing:"ad-hoc",notarized:false,source_archive_sha256:$source_archive_sha256,
+ compliance:{sbom_sha256:$sbom_sha256,third_party_notices_sha256:$notices_sha256}}' \
+ >"$WORK_ROOT/evidence/community-assembly.json"
+(
+ cd "$WORK_ROOT"
+ find . -type f ! -path './evidence/SHA256SUMS' -print0 | LC_ALL=C sort -z \
+ | while IFS= read -r -d '' file; do
+ printf '%s %s\n' "$(shasum -a 256 "$file" | awk '{print $1}')" "${file#./}"
+ done
+) >"$WORK_ROOT/evidence/SHA256SUMS"
+if [[ "${PATCHWRIGHT_FIXTURE_TAMPER:-0}" == 1 ]]; then
+ printf 'tampered\n' >>"$APP_PATH/Contents/MacOS/Patchwright"
+fi
+printf 'PATCHWRIGHT_RELEASE_ROOT=%s\nPATCHWRIGHT_APP_PATH=%s\n' "$WORK_ROOT" "$APP_PATH"
+printf 'PATCHWRIGHT_COMMUNITY_ASSEMBLY=%s\n' "$WORK_ROOT/evidence/community-assembly.json"
+SH
+chmod +x "$FIXTURE_REPO/script/package_community_release.sh" "$FIXTURE_REPO/script/build_release_components.sh"
git -C "$FIXTURE_REPO" init -q
git -C "$FIXTURE_REPO" config user.name Fixture
git -C "$FIXTURE_REPO" config user.email fixture@example.invalid
-git -C "$FIXTURE_REPO" add script/package_community_release.sh
+git -C "$FIXTURE_REPO" add script
git -C "$FIXTURE_REPO" commit -qm fixture
git -C "$FIXTURE_REPO" tag v0.2.0-community.1
-"$FIXTURE_REPO/script/package_community_release.sh" \
- --app "$FIXTURE_APP" \
- --output "$OUTPUT_DIR" \
- --version 0.2.0 \
- --build 3 \
- --tag v0.2.0-community.1
+if "$FIXTURE_REPO/script/package_community_release.sh" \
+ --app "$TMP_ROOT/unrelated.app" --output "$OUTPUT_DIR/unrelated" \
+ --version 0.2.0 --build 3 --tag v0.2.0-community.1 \
+ >"$TMP_ROOT/unrelated.out" 2>&1; then
+ fail "packager still accepts an arbitrary app path"
+fi
+grep -Fq 'usage: package_community_release.sh' "$TMP_ROOT/unrelated.out" \
+ || fail "arbitrary app rejection did not use the strict interface"
+
+PATCHWRIGHT_RELEASE_WORK_ROOT="$TMP_ROOT/builds" \
+ "$FIXTURE_REPO/script/package_community_release.sh" \
+ --output "$OUTPUT_DIR" --version 0.2.0 --build 3 --tag v0.2.0-community.1
ARCHIVE="$OUTPUT_DIR/Patchwright-0.2.0-community.1-macos-arm64.zip"
CHECKSUM="$ARCHIVE.sha256"
MANIFEST="$OUTPUT_DIR/Patchwright-0.2.0-community.1-manifest.json"
-[[ -f "$ARCHIVE" && -f "$CHECKSUM" && -f "$MANIFEST" ]] \
- || fail "packager did not emit the archive, checksum, and manifest"
+SBOM="$OUTPUT_DIR/Patchwright-0.2.0-community.1-sbom.spdx.json"
+NOTICES="$OUTPUT_DIR/Patchwright-0.2.0-community.1-third-party-notices.md"
+for output in "$ARCHIVE" "$CHECKSUM" "$MANIFEST" "$SBOM" "$NOTICES"; do
+ [[ -f "$output" ]] || fail "packager did not emit $(basename "$output")"
+done
(cd "$OUTPUT_DIR" && shasum -a 256 -c "$(basename "$CHECKSUM")")
EXPANDED="$TMP_ROOT/expanded"
mkdir -p "$EXPANDED"
/usr/bin/ditto -x -k "$ARCHIVE" "$EXPANDED"
-[[ -d "$EXPANDED/Patchwright.app" ]] || fail "archive did not preserve the app bundle"
-/usr/bin/codesign --verify --deep --strict "$EXPANDED/Patchwright.app"
+EXPANDED_APP="$EXPANDED/Patchwright.app"
+[[ -f "$EXPANDED_APP/Contents/Resources/PrivacyInfo.xcprivacy" ]] \
+ || fail "community archive omitted the privacy manifest"
+[[ -f "$EXPANDED_APP/Contents/Resources/THIRD_PARTY_NOTICES.md" ]] \
+ || fail "community archive omitted third-party notices"
+[[ -f "$EXPANDED_APP/Contents/Resources/third-party-licenses/Fake/LICENSE" ]] \
+ || fail "community archive omitted the third-party license tree"
+/usr/bin/codesign --verify --deep --strict "$EXPANDED_APP"
COMMIT="$(git -C "$FIXTURE_REPO" rev-parse HEAD)"
-jq -e \
- --arg commit "$COMMIT" \
- '.schema_version == 1 and
- .kind == "patchwright.community-prerelease" and
- .version == "0.2.0" and
- .build == "3" and
- .tag == "v0.2.0-community.1" and
- .git_commit == $commit and
- .signing == "ad-hoc" and
- .notarized == false and
- .minimum_macos == "26.0" and
- .architecture == "arm64"' \
- "$MANIFEST" >/dev/null || fail "manifest did not preserve the community release boundary"
+jq -e --arg commit "$COMMIT" \
+ '.schema_version == 1 and .kind == "patchwright.community-prerelease" and
+ .version == "0.2.0" and .build == "3" and .tag == "v0.2.0-community.1" and
+ .git_commit == $commit and .signing == "ad-hoc" and .notarized == false and
+ .minimum_macos == "26.0" and .architecture == "arm64" and
+ (.source_archive_sha256 | length) == 64 and (.sbom_sha256 | length) == 64 and
+ (.third_party_notices_sha256 | length) == 64' \
+ "$MANIFEST" >/dev/null || fail "manifest did not preserve source and compliance bindings"
+
+if PATCHWRIGHT_RELEASE_WORK_ROOT="$TMP_ROOT/tampered-builds" PATCHWRIGHT_FIXTURE_TAMPER=1 \
+ "$FIXTURE_REPO/script/package_community_release.sh" \
+ --output "$OUTPUT_DIR/tampered" --version 0.2.0 --build 3 --tag v0.2.0-community.1 \
+ >"$TMP_ROOT/tampered.out" 2>&1; then
+ fail "packager accepted component bytes changed after assembly"
+fi
+grep -Fq 'community assembly checksums failed' "$TMP_ROOT/tampered.out" \
+ || fail "tampered assembly rejection was not explicit"
printf 'dirty\n' >"$FIXTURE_REPO/dirty.txt"
-if "$FIXTURE_REPO/script/package_community_release.sh" \
- --app "$FIXTURE_APP" --output "$OUTPUT_DIR/dirty" \
- --version 0.2.0 --build 3 --tag v0.2.0-community.1 \
+if PATCHWRIGHT_RELEASE_WORK_ROOT="$TMP_ROOT/dirty-builds" \
+ "$FIXTURE_REPO/script/package_community_release.sh" \
+ --output "$OUTPUT_DIR/dirty" --version 0.2.0 --build 3 --tag v0.2.0-community.1 \
>"$TMP_ROOT/dirty.out" 2>&1; then
fail "packager accepted a dirty release repository"
fi
@@ -98,9 +155,9 @@ grep -Fq 'community release worktree must be clean' "$TMP_ROOT/dirty.out" \
git -C "$FIXTURE_REPO" add dirty.txt
git -C "$FIXTURE_REPO" commit -qm newer
-if "$FIXTURE_REPO/script/package_community_release.sh" \
- --app "$FIXTURE_APP" --output "$OUTPUT_DIR/tag-mismatch" \
- --version 0.2.0 --build 3 --tag v0.2.0-community.1 \
+if PATCHWRIGHT_RELEASE_WORK_ROOT="$TMP_ROOT/tag-builds" \
+ "$FIXTURE_REPO/script/package_community_release.sh" \
+ --output "$OUTPUT_DIR/tag-mismatch" --version 0.2.0 --build 3 --tag v0.2.0-community.1 \
>"$TMP_ROOT/tag-mismatch.out" 2>&1; then
fail "packager accepted a release tag that did not resolve to HEAD"
fi
diff --git a/Tests/PackagingTests/compliance_contract.sh b/Tests/PackagingTests/compliance_contract.sh
index 21713cd..5f83e08 100755
--- a/Tests/PackagingTests/compliance_contract.sh
+++ b/Tests/PackagingTests/compliance_contract.sh
@@ -37,7 +37,7 @@ jq -n \
'{
packages: [
{id:"zeta@2.0.0",name:"zeta",version:"2.0.0",license:"Apache-2.0",source:"registry+https://example.invalid/index",manifest_path:$zeta_manifest},
- {id:"patchwright-core@0.1.0",name:"patchwright-core",version:"0.1.0",license:"MIT OR Apache-2.0",source:null,manifest_path:"/fixture/patchwright-core/Cargo.toml"},
+ {id:"patchwright-core@0.1.0",name:"patchwright-core",version:"0.1.0",license:"Apache-2.0",source:null,manifest_path:"/fixture/patchwright-core/Cargo.toml"},
{id:"alpha@1.0.0",name:"alpha",version:"1.0.0",license:"MIT",source:"registry+https://example.invalid/index",manifest_path:$alpha_manifest}
],
resolve: {nodes:[{id:"zeta@2.0.0"},{id:"patchwright-core@0.1.0"},{id:"alpha@1.0.0"}]}
@@ -83,6 +83,9 @@ jq -e '
([.packages[].name] == ([.packages[].name] | sort)) and
([.packages[] | select(.name == "alpha" and .versionInfo == "1.0.0" and .licenseDeclared == "MIT")] | length == 1) and
([.packages[] | select(.name == "Sparkle" and .versionInfo == "2.9.2" and .licenseDeclared == "MIT")] | length == 1) and
+ ([.packages[] | select(.name == "Patchwright" and .licenseDeclared == "Apache-2.0")] | length == 1) and
+ ([.packages[] | select(.name == "patchwright-core" and .licenseDeclared == "Apache-2.0")] | length == 1) and
+ ([.files[] | select(.licenseConcluded == "Apache-2.0")] | length == 3) and
([.files[].fileName] == ["Patchwright.app", "patchwright-engine", "patchwright-relay"])
' "$TMP_ROOT/out-a/sbom.spdx.json" >/dev/null || fail "SPDX identity, ordering, package, or component contract failed"
diff --git a/Tests/PackagingTests/release_contract.sh b/Tests/PackagingTests/release_contract.sh
index 37fb95e..3962bab 100755
--- a/Tests/PackagingTests/release_contract.sh
+++ b/Tests/PackagingTests/release_contract.sh
@@ -22,8 +22,8 @@ require_text() {
}
for required in \
- LICENSE-MIT \
- LICENSE-APACHE \
+ LICENSE \
+ NOTICE \
CONTRIBUTING.md \
SECURITY.md \
CODE_OF_CONDUCT.md \
@@ -74,15 +74,23 @@ require_text script/package_release.sh 'VERSION="${PATCHWRIGHT_VERSION:-0.2.0}"'
require_text script/package_release.sh 'BUILD="${PATCHWRIGHT_BUILD:-3}"'
require_text script/build_release_components.sh 'VERSION="${PATCHWRIGHT_VERSION:-0.2.0}"'
require_text script/build_release_components.sh 'BUILD="${PATCHWRIGHT_BUILD:-3}"'
+require_text script/build_release_components.sh 'MODE="community"'
+require_text script/build_release_components.sh 'Contents/Resources/PrivacyInfo.xcprivacy'
+require_text script/package_community_release.sh 'community assembly checksums failed'
+if grep -Fq -- '--app' "$ROOT_DIR/script/package_community_release.sh" "$ROOT_DIR/docs/RELEASING.md"; then
+ fail "community packager must build from the exact checkout instead of accepting --app"
+fi
if grep -En 'App Store|App Store Connect|Mac App Store' README.md docs/release-checklist.md docs/release-readiness.md docs/production-plan.md; then
fail "direct-distribution documentation must not claim an App Store release lane"
fi
[[ -x "$ROOT_DIR/script/generate_app_icon.sh" ]] || fail "script/generate_app_icon.sh must be executable"
require_text Assets/PatchwrightIcon-source.svg 'viewBox="0 0 1024 1024"'
-require_text LICENSE-MIT "Permission is hereby granted, free of charge"
-require_text LICENSE-APACHE "Apache License"
-require_text LICENSE-APACHE "Version 2.0, January 2004"
+require_text LICENSE "Apache License"
+require_text LICENSE "Version 2.0, January 2004"
+require_text NOTICE "Copyright 2026 Rafal Sikora"
+require_text NOTICE "RSI Tech"
+require_text NOTICE "info@rsitech.ai"
require_text CONTRIBUTING.md "Developer Certificate of Origin"
require_text CONTRIBUTING.md "Signed-off-by:"
require_text SECURITY.md "security/advisories/new"
@@ -135,12 +143,14 @@ EOF
[[ "$(find "$ICONSET" -type f -name '*.png' | wc -l | tr -d ' ')" == 10 ]] \
|| fail "iconset must contain exactly ten PNG representations"
-grep -Eq '^license = "MIT OR Apache-2\.0"$' "$ROOT_DIR/Cargo.toml" \
- || fail 'Cargo.toml must declare license = "MIT OR Apache-2.0"'
+grep -Eq '^license = "Apache-2\.0"$' "$ROOT_DIR/Cargo.toml" \
+ || fail 'Cargo.toml must declare license = "Apache-2.0"'
BUNDLE_COPYRIGHT="$(/usr/libexec/PlistBuddy -c 'Print :NSHumanReadableCopyright' "$ROOT_DIR/Packaging/Info.plist")"
[[ "$BUNDLE_COPYRIGHT" != *"All rights reserved"* ]] \
|| fail "bundle copyright must not claim All rights reserved"
+[[ "$BUNDLE_COPYRIGHT" == 'Copyright © 2026 Rafal Sikora. Licensed under Apache-2.0.' ]] \
+ || fail "bundle copyright must name Rafal Sikora and Apache-2.0"
[[ "$(/usr/libexec/PlistBuddy -c 'Print :CFBundleIconFile' "$ROOT_DIR/Packaging/Info.plist" 2>/dev/null || true)" == Patchwright.icns ]] \
|| fail "CFBundleIconFile must be Patchwright.icns"
@@ -163,8 +173,8 @@ KEY_BYTES="$(printf '%s' "$SPARKLE_PUBLIC_KEY" | /usr/bin/base64 -D 2>/dev/null
for target in \
'#build-and-verify' \
'https://github.com/rsitech-ai/patchwright/releases' \
- 'LICENSE-MIT' \
- 'LICENSE-APACHE' \
+ 'LICENSE' \
+ 'NOTICE' \
'CONTRIBUTING.md' \
'SECURITY.md' \
'PRIVACY.md' \
diff --git a/docs/RELEASING.md b/docs/RELEASING.md
index 70f525f..a5dc05f 100644
--- a/docs/RELEASING.md
+++ b/docs/RELEASING.md
@@ -45,11 +45,10 @@ It never replaces or relaxes the Developer ID path above.
2. Create a versioned community tag on that exact commit.
3. Run `./script/verify.sh`, `./script/smoke.sh`, and
`./script/build_and_run.sh --verify` from the clean tagged checkout.
-4. Package the staged app with:
+4. Build and package the app from that exact checkout with:
```sh
./script/package_community_release.sh \
- --app "$HOME/.patchwright/staged/Patchwright.app" \
--output "$PWD/dist/community" \
--version 0.2.0 \
--build 3 \
@@ -57,8 +56,8 @@ It never replaces or relaxes the Developer ID path above.
```
5. Verify the ZIP checksum and expanded app signature from a separate temporary
- directory, then publish it only as a GitHub prerelease with the manifest and
- an explicit not-notarized warning.
+ directory, then publish it only as a GitHub prerelease with the manifest,
+ SBOM, third-party notices, and an explicit not-notarized warning.
Community artifacts must not include `appcast.xml`, use the GitHub `latest`
release designation, or claim Gatekeeper, Developer ID, notarization,
diff --git a/docs/releases/v0.2.0-community.1.md b/docs/releases/v0.2.0-community.1.md
index ab78d9b..b51e2a5 100644
--- a/docs/releases/v0.2.0-community.1.md
+++ b/docs/releases/v0.2.0-community.1.md
@@ -21,15 +21,18 @@ The release assets include:
- `Patchwright-0.2.0-community.1-macos-arm64.zip`
- `Patchwright-0.2.0-community.1-macos-arm64.zip.sha256`
- `Patchwright-0.2.0-community.1-manifest.json`
+- `Patchwright-0.2.0-community.1-sbom.spdx.json`
+- `Patchwright-0.2.0-community.1-third-party-notices.md`
-Download all three files into the same directory and run:
+Download the assets into the same directory and run:
```sh
shasum -a 256 -c Patchwright-0.2.0-community.1-macos-arm64.zip.sha256
```
-The manifest binds the archive to the exact Git commit and records the bundle
-version, build, architecture, signing class, and notarization status.
+The manifest binds the archive, source archive, SBOM, notices, and assembly
+evidence to the exact Git commit and records the bundle version, build,
+architecture, signing class, and notarization status.
## Trust boundary
diff --git a/script/build_release_components.sh b/script/build_release_components.sh
index fb93486..a014945 100755
--- a/script/build_release_components.sh
+++ b/script/build_release_components.sh
@@ -2,6 +2,12 @@
set -euo pipefail
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
+MODE="official"
+if [[ "${1:-}" == --community ]]; then
+ MODE="community"
+ shift
+fi
+[[ $# == 0 ]] || { echo "usage: build_release_components.sh [--community]" >&2; exit 64; }
VERSION="${PATCHWRIGHT_VERSION:-0.2.0}"
BUILD="${PATCHWRIGHT_BUILD:-3}"
OUTPUT_PARENT="${PATCHWRIGHT_RELEASE_WORK_ROOT:-$HOME/.patchwright/release-work}"
@@ -72,6 +78,39 @@ generate_compliance
SBOM_SHA256="$(shasum -a 256 "$WORK_ROOT/evidence/sbom.spdx.json" | awk '{print $1}')"
NOTICES_SHA256="$(shasum -a 256 "$WORK_ROOT/evidence/third-party-notices.md" | awk '{print $1}')"
+if [[ "$MODE" == community ]]; then
+ SPARKLE="$APP_PATH/Contents/Frameworks/Sparkle.framework"
+ /usr/bin/codesign --force --sign - "$SPARKLE/Versions/B/XPCServices/Installer.xpc"
+ /usr/bin/codesign --force --sign - --preserve-metadata=entitlements \
+ "$SPARKLE/Versions/B/XPCServices/Downloader.xpc"
+ /usr/bin/codesign --force --sign - "$SPARKLE/Versions/B/Autoupdate"
+ /usr/bin/codesign --force --sign - "$SPARKLE/Versions/B/Updater.app"
+ /usr/bin/codesign --force --sign - "$SPARKLE"
+ /usr/bin/codesign --force --sign - "$APP_PATH/Contents/Helpers/patchwright-engine"
+ /usr/bin/codesign --force --sign - "$APP_PATH/Contents/Helpers/patchwright-relay"
+ /usr/bin/codesign --force --sign - "$APP_PATH"
+ /usr/bin/codesign --verify --deep --strict "$APP_PATH"
+
+ COMMIT="$(git -C "$ROOT_DIR" rev-parse HEAD)"
+ SOURCE_SHA256="$(shasum -a 256 "$WORK_ROOT/reproducibility/source.tar.gz" | awk '{print $1}')"
+ jq -n \
+ --arg app_path "$APP_PATH" --arg version "$VERSION" --arg build "$BUILD" \
+ --arg git_commit "$COMMIT" --arg source_archive_sha256 "$SOURCE_SHA256" \
+ --arg sbom_sha256 "$SBOM_SHA256" --arg notices_sha256 "$NOTICES_SHA256" \
+ '{schema_version:1,kind:"patchwright.community-assembly",app_path:$app_path,
+ version:$version,build:$build,git_commit:$git_commit,dirty:false,
+ signing:"ad-hoc",notarized:false,source_archive_sha256:$source_archive_sha256,
+ compliance:{sbom_sha256:$sbom_sha256,third_party_notices_sha256:$notices_sha256}}' \
+ >"$WORK_ROOT/evidence/community-assembly.json"
+ "$ROOT_DIR/script/generate_symlink_manifest.py" \
+ --root "$WORK_ROOT" --output "$WORK_ROOT/evidence/SYMLINKS.json"
+ "$ROOT_DIR/script/generate_release_metadata.sh" \
+ --phase checksums --output-root "$WORK_ROOT"
+ printf 'PATCHWRIGHT_RELEASE_ROOT=%s\nPATCHWRIGHT_APP_PATH=%s\n' "$WORK_ROOT" "$APP_PATH"
+ printf 'PATCHWRIGHT_COMMUNITY_ASSEMBLY=%s\n' "$WORK_ROOT/evidence/community-assembly.json"
+ exit 0
+fi
+
jq -n \
--arg app "$APP_PATH" \
--arg root "$WORK_ROOT" \
diff --git a/script/generate_release_compliance.py b/script/generate_release_compliance.py
index b80cd68..a7bfbbc 100755
--- a/script/generate_release_compliance.py
+++ b/script/generate_release_compliance.py
@@ -120,7 +120,7 @@ def swift_packages(metadata: dict[str, Any]) -> list[dict[str, str]]:
{
"name": root_name,
"version": root_version,
- "license": "MIT OR Apache-2.0",
+ "license": "Apache-2.0",
"source": "workspace",
"ecosystem": "Swift",
"first_party": "true",
@@ -353,7 +353,7 @@ def build_documents(
"SPDXID": spdx_id("File", name, checksum),
"fileName": name,
"checksums": [{"algorithm": "SHA256", "checksumValue": checksum}],
- "licenseConcluded": "MIT OR Apache-2.0",
+ "licenseConcluded": "Apache-2.0",
"licenseInfoInFiles": ["NOASSERTION"],
"copyrightText": "NOASSERTION",
}
diff --git a/script/package_community_release.sh b/script/package_community_release.sh
index b88a315..5eb6781 100755
--- a/script/package_community_release.sh
+++ b/script/package_community_release.sh
@@ -3,7 +3,6 @@ set -euo pipefail
umask 077
ROOT_DIR="$(cd "$(dirname "${BASH_SOURCE[0]}")/.." && pwd)"
-APP_PATH=""
OUTPUT_DIR=""
VERSION=""
BUILD=""
@@ -25,7 +24,6 @@ fail() {
usage() {
cat >&2 <<'EOF'
usage: package_community_release.sh \
- --app /absolute/path/Patchwright.app \
--output /absolute/path/output \
--version X.Y.Z \
--build N \
@@ -36,7 +34,6 @@ EOF
while [[ $# -gt 0 ]]; do
case "$1" in
- --app) [[ $# -ge 2 ]] || usage; APP_PATH="$2"; shift 2 ;;
--output) [[ $# -ge 2 ]] || usage; OUTPUT_DIR="$2"; shift 2 ;;
--version) [[ $# -ge 2 ]] || usage; VERSION="$2"; shift 2 ;;
--build) [[ $# -ge 2 ]] || usage; BUILD="$2"; shift 2 ;;
@@ -45,8 +42,6 @@ while [[ $# -gt 0 ]]; do
esac
done
-[[ "$APP_PATH" == /* && -d "$APP_PATH" && ! -L "$APP_PATH" ]] \
- || fail "--app must be an absolute, non-symlink app bundle"
[[ "$OUTPUT_DIR" == /* ]] || fail "--output must be an absolute directory path"
[[ "$VERSION" =~ ^[0-9]+\.[0-9]+\.[0-9]+$ ]] || fail "invalid community release version"
[[ "$BUILD" =~ ^[1-9][0-9]*$ ]] || fail "invalid community release build"
@@ -60,6 +55,52 @@ COMMIT="$(git -C "$ROOT_DIR" rev-parse HEAD)"
TAG_COMMIT="$(git -C "$ROOT_DIR" rev-parse "refs/tags/$TAG^{commit}" 2>/dev/null || true)"
[[ "$TAG_COMMIT" == "$COMMIT" ]] || fail "community release tag must resolve to HEAD"
+STAGE="$(mktemp -d "${TMPDIR:-/tmp}/patchwright-community-package.XXXXXX")"
+ASSEMBLY_LOG="$STAGE/community-assembly.log"
+BUILD_WORK_ROOT="${PATCHWRIGHT_RELEASE_WORK_ROOT:-$STAGE/builds}"
+mkdir -p "$BUILD_WORK_ROOT"
+PATCHWRIGHT_VERSION="$VERSION" PATCHWRIGHT_BUILD="$BUILD" \
+ PATCHWRIGHT_RELEASE_WORK_ROOT="$BUILD_WORK_ROOT" \
+ "$ROOT_DIR/script/build_release_components.sh" --community | tee "$ASSEMBLY_LOG"
+
+RELEASE_ROOT="$(sed -n 's/^PATCHWRIGHT_RELEASE_ROOT=//p' "$ASSEMBLY_LOG" | tail -1)"
+APP_PATH="$(sed -n 's/^PATCHWRIGHT_APP_PATH=//p' "$ASSEMBLY_LOG" | tail -1)"
+ASSEMBLY="$(sed -n 's/^PATCHWRIGHT_COMMUNITY_ASSEMBLY=//p' "$ASSEMBLY_LOG" | tail -1)"
+[[ -d "$RELEASE_ROOT" && ! -L "$RELEASE_ROOT" ]] || fail "community assembly root is invalid"
+[[ -d "$APP_PATH" && ! -L "$APP_PATH" ]] || fail "community assembly app is invalid"
+[[ -f "$ASSEMBLY" && ! -L "$ASSEMBLY" ]] || fail "community assembly evidence is missing"
+RELEASE_REAL="$(cd "$RELEASE_ROOT" && pwd -P)"
+APP_REAL="$(cd "$APP_PATH" && pwd -P)"
+ASSEMBLY_REAL="$(cd "$(dirname "$ASSEMBLY")" && pwd -P)/$(basename "$ASSEMBLY")"
+[[ "$APP_REAL" == "$RELEASE_REAL/"* && "$ASSEMBLY_REAL" == "$RELEASE_REAL/"* ]] \
+ || fail "community assembly paths escape the release root"
+
+# Recheck source identity after the build, then bind every assembled byte before
+# making the public archive. This closes both source drift and post-build swaps.
+[[ "$(git -C "$ROOT_DIR" rev-parse HEAD)" == "$COMMIT" ]] \
+ || fail "community release source changed during assembly"
+[[ -z "$(git -C "$ROOT_DIR" status --porcelain)" ]] \
+ || fail "community release worktree changed during assembly"
+[[ "$(git -C "$ROOT_DIR" rev-parse "refs/tags/$TAG^{commit}" 2>/dev/null || true)" == "$COMMIT" ]] \
+ || fail "community release tag changed during assembly"
+[[ -f "$RELEASE_ROOT/evidence/SHA256SUMS" ]] || fail "community assembly checksums are missing"
+if ! (cd "$RELEASE_ROOT" && shasum -a 256 -c evidence/SHA256SUMS >/dev/null); then
+ fail "community assembly checksums failed"
+fi
+
+SOURCE_ARCHIVE="$RELEASE_ROOT/reproducibility/source.tar.gz"
+SBOM_SOURCE="$RELEASE_ROOT/evidence/sbom.spdx.json"
+NOTICES_SOURCE="$RELEASE_ROOT/evidence/third-party-notices.md"
+for required in "$SOURCE_ARCHIVE" "$SBOM_SOURCE" "$NOTICES_SOURCE" \
+ "$APP_PATH/Contents/Resources/PrivacyInfo.xcprivacy" \
+ "$APP_PATH/Contents/Resources/THIRD_PARTY_NOTICES.md"; do
+ [[ -f "$required" && ! -L "$required" ]] || fail "required assembled file is missing: $required"
+done
+[[ -d "$APP_PATH/Contents/Resources/third-party-licenses" ]] \
+ || fail "third-party license tree is missing"
+find "$APP_PATH/Contents/Resources/third-party-licenses" -type f -print -quit | grep -q . \
+ || fail "third-party license tree is empty"
+
INFO_PLIST="$APP_PATH/Contents/Info.plist"
EXECUTABLE_NAME="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleExecutable' "$INFO_PLIST" 2>/dev/null || true)"
APP_VERSION="$(/usr/libexec/PlistBuddy -c 'Print :CFBundleShortVersionString' "$INFO_PLIST" 2>/dev/null || true)"
@@ -87,42 +128,64 @@ case "$ARCHS" in
*) fail "unsupported app architecture: $ARCHS" ;;
esac
+SOURCE_SHA256="$(shasum -a 256 "$SOURCE_ARCHIVE" | awk '{print $1}')"
+SBOM_SHA256="$(shasum -a 256 "$SBOM_SOURCE" | awk '{print $1}')"
+NOTICES_SHA256="$(shasum -a 256 "$NOTICES_SOURCE" | awk '{print $1}')"
+ASSEMBLY_SHA256="$(shasum -a 256 "$ASSEMBLY" | awk '{print $1}')"
+jq -e --arg app_path "$APP_PATH" --arg version "$VERSION" --arg build "$BUILD" \
+ --arg git_commit "$COMMIT" --arg source_sha256 "$SOURCE_SHA256" \
+ --arg sbom_sha256 "$SBOM_SHA256" --arg notices_sha256 "$NOTICES_SHA256" \
+ '.schema_version == 1 and .kind == "patchwright.community-assembly" and
+ .app_path == $app_path and .version == $version and .build == $build and
+ .git_commit == $git_commit and .dirty == false and .signing == "ad-hoc" and
+ .notarized == false and .source_archive_sha256 == $source_sha256 and
+ .compliance.sbom_sha256 == $sbom_sha256 and
+ .compliance.third_party_notices_sha256 == $notices_sha256' \
+ "$ASSEMBLY" >/dev/null || fail "community assembly evidence does not match assembled bytes"
+
RELEASE_SUFFIX="${TAG#v$VERSION-}"
ARCHIVE_NAME="Patchwright-$VERSION-$RELEASE_SUFFIX-macos-$ARCHITECTURE.zip"
MANIFEST_NAME="Patchwright-$VERSION-$RELEASE_SUFFIX-manifest.json"
CHECKSUM_NAME="$ARCHIVE_NAME.sha256"
+SBOM_NAME="Patchwright-$VERSION-$RELEASE_SUFFIX-sbom.spdx.json"
+NOTICES_NAME="Patchwright-$VERSION-$RELEASE_SUFFIX-third-party-notices.md"
mkdir -p "$OUTPUT_DIR"
-for path in "$OUTPUT_DIR/$ARCHIVE_NAME" "$OUTPUT_DIR/$CHECKSUM_NAME" "$OUTPUT_DIR/$MANIFEST_NAME"; do
+for path in "$OUTPUT_DIR/$ARCHIVE_NAME" "$OUTPUT_DIR/$CHECKSUM_NAME" \
+ "$OUTPUT_DIR/$MANIFEST_NAME" "$OUTPUT_DIR/$SBOM_NAME" "$OUTPUT_DIR/$NOTICES_NAME"; do
[[ ! -e "$path" ]] || fail "refusing to overwrite existing release output: $path"
done
-STAGE="$(mktemp -d "${TMPDIR:-/tmp}/patchwright-community-package.XXXXXX")"
-/usr/bin/ditto "$APP_PATH" "$STAGE/Patchwright.app"
-/usr/bin/ditto -c -k --keepParent --sequesterRsrc "$STAGE/Patchwright.app" "$STAGE/$ARCHIVE_NAME"
+/usr/bin/ditto -c -k --keepParent --sequesterRsrc "$APP_PATH" "$STAGE/$ARCHIVE_NAME"
ARCHIVE_SHA256="$(shasum -a 256 "$STAGE/$ARCHIVE_NAME" | awk '{print $1}')"
printf '%s %s\n' "$ARCHIVE_SHA256" "$ARCHIVE_NAME" >"$STAGE/$CHECKSUM_NAME"
+cp "$SBOM_SOURCE" "$STAGE/$SBOM_NAME"
+cp "$NOTICES_SOURCE" "$STAGE/$NOTICES_NAME"
CREATED_AT="$(git -C "$ROOT_DIR" show -s --format=%cI "$COMMIT")"
jq -n \
- --arg version "$VERSION" \
- --arg build "$BUILD" \
- --arg tag "$TAG" \
- --arg git_commit "$COMMIT" \
- --arg archive "$ARCHIVE_NAME" \
- --arg archive_sha256 "$ARCHIVE_SHA256" \
- --arg minimum_macos "$MINIMUM_MACOS" \
- --arg architecture "$ARCHITECTURE" \
- --arg created_at "$CREATED_AT" \
+ --arg version "$VERSION" --arg build "$BUILD" --arg tag "$TAG" \
+ --arg git_commit "$COMMIT" --arg archive "$ARCHIVE_NAME" \
+ --arg archive_sha256 "$ARCHIVE_SHA256" --arg minimum_macos "$MINIMUM_MACOS" \
+ --arg architecture "$ARCHITECTURE" --arg created_at "$CREATED_AT" \
+ --arg source_archive_sha256 "$SOURCE_SHA256" --arg sbom "$SBOM_NAME" \
+ --arg sbom_sha256 "$SBOM_SHA256" --arg notices "$NOTICES_NAME" \
+ --arg third_party_notices_sha256 "$NOTICES_SHA256" \
+ --arg community_assembly_sha256 "$ASSEMBLY_SHA256" \
'{schema_version:1,kind:"patchwright.community-prerelease",version:$version,build:$build,
tag:$tag,git_commit:$git_commit,archive:$archive,archive_sha256:$archive_sha256,
platform:"macOS",minimum_macos:$minimum_macos,architecture:$architecture,
signing:"ad-hoc",notarized:false,created_at:$created_at,
+ source_archive_sha256:$source_archive_sha256,sbom:$sbom,sbom_sha256:$sbom_sha256,
+ third_party_notices:$notices,third_party_notices_sha256:$third_party_notices_sha256,
+ community_assembly_sha256:$community_assembly_sha256,
install_warning:"This community build is not Developer ID signed or Apple notarized. macOS Gatekeeper may block it; build from source if you require a locally trusted copy."}' \
>"$STAGE/$MANIFEST_NAME"
-/bin/mv "$STAGE/$ARCHIVE_NAME" "$OUTPUT_DIR/$ARCHIVE_NAME"
-/bin/mv "$STAGE/$CHECKSUM_NAME" "$OUTPUT_DIR/$CHECKSUM_NAME"
-/bin/mv "$STAGE/$MANIFEST_NAME" "$OUTPUT_DIR/$MANIFEST_NAME"
+for asset in "$ARCHIVE_NAME" "$CHECKSUM_NAME" "$MANIFEST_NAME" "$SBOM_NAME" "$NOTICES_NAME"; do
+ /bin/mv "$STAGE/$asset" "$OUTPUT_DIR/$asset"
+done
printf 'PATCHWRIGHT_COMMUNITY_ARCHIVE=%s\n' "$OUTPUT_DIR/$ARCHIVE_NAME"
printf 'PATCHWRIGHT_COMMUNITY_CHECKSUM=%s\n' "$OUTPUT_DIR/$CHECKSUM_NAME"
printf 'PATCHWRIGHT_COMMUNITY_MANIFEST=%s\n' "$OUTPUT_DIR/$MANIFEST_NAME"
+printf 'PATCHWRIGHT_COMMUNITY_SBOM=%s\n' "$OUTPUT_DIR/$SBOM_NAME"
+printf 'PATCHWRIGHT_COMMUNITY_NOTICES=%s\n' "$OUTPUT_DIR/$NOTICES_NAME"
printf 'PATCHWRIGHT_STATUS=community-prerelease-not-notarized\n'
From 17c0348e4b158b39b74f9cd04162bf3bd175c973 Mon Sep 17 00:00:00 2001
From: Rafal Sikora <24563931+s1korrrr@users.noreply.github.com>
Date: Mon, 20 Jul 2026 22:24:56 +0200
Subject: [PATCH 3/3] Ship project license with community builds
Signed-off-by: Rafal Sikora <24563931+s1korrrr@users.noreply.github.com>
---
CHANGELOG.md | 2 ++
.../community_release_contract.sh | 31 ++++++++++++++++---
Tests/PackagingTests/release_contract.sh | 4 +++
docs/RELEASING.md | 3 +-
docs/releases/v0.2.0-community.1.md | 9 ++++--
script/build_release_components.sh | 11 +++++--
script/package_community_release.sh | 31 ++++++++++++++++---
7 files changed, 77 insertions(+), 14 deletions(-)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 42ae56c..2cda63f 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -10,6 +10,8 @@ All notable user-facing and distribution changes are documented here. Patchwrigh
app archive and checksum to the exact clean Git commit and release tag.
- Publish machine-readable community release metadata that states the app
architecture, minimum macOS version, signing class, and notarization status.
+- Embed and publish the Apache project license and RSI Tech project notice with
+ the community app alongside third-party attribution evidence.
### Changed
diff --git a/Tests/PackagingTests/community_release_contract.sh b/Tests/PackagingTests/community_release_contract.sh
index abc7040..b26af5c 100755
--- a/Tests/PackagingTests/community_release_contract.sh
+++ b/Tests/PackagingTests/community_release_contract.sh
@@ -17,6 +17,8 @@ FIXTURE_REPO="$TMP_ROOT/repository"
OUTPUT_DIR="$TMP_ROOT/output"
mkdir -p "$FIXTURE_REPO/script" "$TMP_ROOT/builds"
cp "$PACKAGER" "$FIXTURE_REPO/script/package_community_release.sh"
+printf 'Apache License\nVersion 2.0, January 2004\n' >"$FIXTURE_REPO/LICENSE"
+printf 'Patchwright fixture notice\n' >"$FIXTURE_REPO/NOTICE"
cat >"$FIXTURE_REPO/script/build_release_components.sh" <<'SH'
#!/usr/bin/env bash
set -euo pipefail
@@ -51,6 +53,10 @@ printf '\n' \
printf '# Third-Party Notices\n\nFake dependency.\n' \
>"$APP_PATH/Contents/Resources/THIRD_PARTY_NOTICES.md"
printf 'Fake license\n' >"$APP_PATH/Contents/Resources/third-party-licenses/Fake/LICENSE"
+cp "$ROOT_DIR/LICENSE" "$APP_PATH/Contents/Resources/LICENSE.txt"
+cp "$ROOT_DIR/NOTICE" "$APP_PATH/Contents/Resources/NOTICE.txt"
+cp "$ROOT_DIR/LICENSE" "$WORK_ROOT/reproducibility/LICENSE"
+cp "$ROOT_DIR/NOTICE" "$WORK_ROOT/reproducibility/NOTICE"
/usr/bin/codesign --force --sign - "$APP_PATH"
git -C "$ROOT_DIR" archive --format=tar.gz --output="$WORK_ROOT/reproducibility/source.tar.gz" HEAD
COMMIT="$(git -C "$ROOT_DIR" rev-parse HEAD)"
@@ -59,13 +65,18 @@ printf '{"spdxVersion":"SPDX-2.3","dataLicense":"CC0-1.0"}\n' >"$WORK_ROOT/evide
cp "$APP_PATH/Contents/Resources/THIRD_PARTY_NOTICES.md" "$WORK_ROOT/evidence/third-party-notices.md"
SBOM_SHA256="$(shasum -a 256 "$WORK_ROOT/evidence/sbom.spdx.json" | awk '{print $1}')"
NOTICES_SHA256="$(shasum -a 256 "$WORK_ROOT/evidence/third-party-notices.md" | awk '{print $1}')"
+PROJECT_LICENSE_SHA256="$(shasum -a 256 "$WORK_ROOT/reproducibility/LICENSE" | awk '{print $1}')"
+PROJECT_NOTICE_SHA256="$(shasum -a 256 "$WORK_ROOT/reproducibility/NOTICE" | awk '{print $1}')"
jq -n --arg app_path "$APP_PATH" --arg version "$VERSION" --arg build "$BUILD" \
--arg git_commit "$COMMIT" --arg source_archive_sha256 "$SOURCE_SHA256" \
--arg sbom_sha256 "$SBOM_SHA256" --arg notices_sha256 "$NOTICES_SHA256" \
+ --arg project_license_sha256 "$PROJECT_LICENSE_SHA256" \
+ --arg project_notice_sha256 "$PROJECT_NOTICE_SHA256" \
'{schema_version:1,kind:"patchwright.community-assembly",app_path:$app_path,
version:$version,build:$build,git_commit:$git_commit,dirty:false,
signing:"ad-hoc",notarized:false,source_archive_sha256:$source_archive_sha256,
- compliance:{sbom_sha256:$sbom_sha256,third_party_notices_sha256:$notices_sha256}}' \
+ compliance:{sbom_sha256:$sbom_sha256,third_party_notices_sha256:$notices_sha256,
+ project_license_sha256:$project_license_sha256,project_notice_sha256:$project_notice_sha256}}' \
>"$WORK_ROOT/evidence/community-assembly.json"
(
cd "$WORK_ROOT"
@@ -85,7 +96,7 @@ chmod +x "$FIXTURE_REPO/script/package_community_release.sh" "$FIXTURE_REPO/scri
git -C "$FIXTURE_REPO" init -q
git -C "$FIXTURE_REPO" config user.name Fixture
git -C "$FIXTURE_REPO" config user.email fixture@example.invalid
-git -C "$FIXTURE_REPO" add script
+git -C "$FIXTURE_REPO" add script LICENSE NOTICE
git -C "$FIXTURE_REPO" commit -qm fixture
git -C "$FIXTURE_REPO" tag v0.2.0-community.1
@@ -107,7 +118,10 @@ CHECKSUM="$ARCHIVE.sha256"
MANIFEST="$OUTPUT_DIR/Patchwright-0.2.0-community.1-manifest.json"
SBOM="$OUTPUT_DIR/Patchwright-0.2.0-community.1-sbom.spdx.json"
NOTICES="$OUTPUT_DIR/Patchwright-0.2.0-community.1-third-party-notices.md"
-for output in "$ARCHIVE" "$CHECKSUM" "$MANIFEST" "$SBOM" "$NOTICES"; do
+PROJECT_LICENSE="$OUTPUT_DIR/Patchwright-0.2.0-community.1-LICENSE.txt"
+PROJECT_NOTICE="$OUTPUT_DIR/Patchwright-0.2.0-community.1-NOTICE.txt"
+for output in "$ARCHIVE" "$CHECKSUM" "$MANIFEST" "$SBOM" "$NOTICES" \
+ "$PROJECT_LICENSE" "$PROJECT_NOTICE"; do
[[ -f "$output" ]] || fail "packager did not emit $(basename "$output")"
done
(cd "$OUTPUT_DIR" && shasum -a 256 -c "$(basename "$CHECKSUM")")
@@ -122,6 +136,14 @@ EXPANDED_APP="$EXPANDED/Patchwright.app"
|| fail "community archive omitted third-party notices"
[[ -f "$EXPANDED_APP/Contents/Resources/third-party-licenses/Fake/LICENSE" ]] \
|| fail "community archive omitted the third-party license tree"
+cmp "$FIXTURE_REPO/LICENSE" "$EXPANDED_APP/Contents/Resources/LICENSE.txt" \
+ || fail "community archive omitted the exact Apache project license"
+cmp "$FIXTURE_REPO/NOTICE" "$EXPANDED_APP/Contents/Resources/NOTICE.txt" \
+ || fail "community archive omitted the exact project notice"
+cmp "$FIXTURE_REPO/LICENSE" "$PROJECT_LICENSE" \
+ || fail "community release asset omitted the exact Apache project license"
+cmp "$FIXTURE_REPO/NOTICE" "$PROJECT_NOTICE" \
+ || fail "community release asset omitted the exact project notice"
/usr/bin/codesign --verify --deep --strict "$EXPANDED_APP"
COMMIT="$(git -C "$FIXTURE_REPO" rev-parse HEAD)"
@@ -131,7 +153,8 @@ jq -e --arg commit "$COMMIT" \
.git_commit == $commit and .signing == "ad-hoc" and .notarized == false and
.minimum_macos == "26.0" and .architecture == "arm64" and
(.source_archive_sha256 | length) == 64 and (.sbom_sha256 | length) == 64 and
- (.third_party_notices_sha256 | length) == 64' \
+ (.third_party_notices_sha256 | length) == 64 and
+ (.project_license_sha256 | length) == 64 and (.project_notice_sha256 | length) == 64' \
"$MANIFEST" >/dev/null || fail "manifest did not preserve source and compliance bindings"
if PATCHWRIGHT_RELEASE_WORK_ROOT="$TMP_ROOT/tampered-builds" PATCHWRIGHT_FIXTURE_TAMPER=1 \
diff --git a/Tests/PackagingTests/release_contract.sh b/Tests/PackagingTests/release_contract.sh
index 3962bab..9a2bf15 100755
--- a/Tests/PackagingTests/release_contract.sh
+++ b/Tests/PackagingTests/release_contract.sh
@@ -76,7 +76,11 @@ require_text script/build_release_components.sh 'VERSION="${PATCHWRIGHT_VERSION:
require_text script/build_release_components.sh 'BUILD="${PATCHWRIGHT_BUILD:-3}"'
require_text script/build_release_components.sh 'MODE="community"'
require_text script/build_release_components.sh 'Contents/Resources/PrivacyInfo.xcprivacy'
+require_text script/build_release_components.sh 'Contents/Resources/LICENSE.txt'
+require_text script/build_release_components.sh 'Contents/Resources/NOTICE.txt'
require_text script/package_community_release.sh 'community assembly checksums failed'
+require_text script/package_community_release.sh 'project_license_sha256'
+require_text script/package_community_release.sh 'project_notice_sha256'
if grep -Fq -- '--app' "$ROOT_DIR/script/package_community_release.sh" "$ROOT_DIR/docs/RELEASING.md"; then
fail "community packager must build from the exact checkout instead of accepting --app"
fi
diff --git a/docs/RELEASING.md b/docs/RELEASING.md
index a5dc05f..f1e0e67 100644
--- a/docs/RELEASING.md
+++ b/docs/RELEASING.md
@@ -57,7 +57,8 @@ It never replaces or relaxes the Developer ID path above.
5. Verify the ZIP checksum and expanded app signature from a separate temporary
directory, then publish it only as a GitHub prerelease with the manifest,
- SBOM, third-party notices, and an explicit not-notarized warning.
+ SBOM, third-party notices, project license, project notice, and an explicit
+ not-notarized warning.
Community artifacts must not include `appcast.xml`, use the GitHub `latest`
release designation, or claim Gatekeeper, Developer ID, notarization,
diff --git a/docs/releases/v0.2.0-community.1.md b/docs/releases/v0.2.0-community.1.md
index b51e2a5..32fd1a6 100644
--- a/docs/releases/v0.2.0-community.1.md
+++ b/docs/releases/v0.2.0-community.1.md
@@ -23,6 +23,8 @@ The release assets include:
- `Patchwright-0.2.0-community.1-manifest.json`
- `Patchwright-0.2.0-community.1-sbom.spdx.json`
- `Patchwright-0.2.0-community.1-third-party-notices.md`
+- `Patchwright-0.2.0-community.1-LICENSE.txt`
+- `Patchwright-0.2.0-community.1-NOTICE.txt`
Download the assets into the same directory and run:
@@ -30,9 +32,10 @@ Download the assets into the same directory and run:
shasum -a 256 -c Patchwright-0.2.0-community.1-macos-arm64.zip.sha256
```
-The manifest binds the archive, source archive, SBOM, notices, and assembly
-evidence to the exact Git commit and records the bundle version, build,
-architecture, signing class, and notarization status.
+The manifest binds the archive, source archive, SBOM, third-party notices,
+Apache project license, project notice, and assembly evidence to the exact Git
+commit. It also records the bundle version, build, architecture, signing class,
+and notarization status.
## Trust boundary
diff --git a/script/build_release_components.sh b/script/build_release_components.sh
index a014945..42fe5b7 100755
--- a/script/build_release_components.sh
+++ b/script/build_release_components.sh
@@ -44,6 +44,8 @@ cp "$ROOT_DIR/Packaging/Info.plist" "$APP_PATH/Contents/Info.plist"
cp "$ROOT_DIR/Packaging/Patchwright.icns" "$APP_PATH/Contents/Resources/Patchwright.icns"
cp "$ROOT_DIR/Packaging/PrivacyInfo.xcprivacy" "$APP_PATH/Contents/Resources/PrivacyInfo.xcprivacy"
cp "$ROOT_DIR/Packaging/THIRD_PARTY_NOTICES.md" "$APP_PATH/Contents/Resources/THIRD_PARTY_NOTICES.md"
+cp "$ROOT_DIR/LICENSE" "$APP_PATH/Contents/Resources/LICENSE.txt"
+cp "$ROOT_DIR/NOTICE" "$APP_PATH/Contents/Resources/NOTICE.txt"
/usr/libexec/PlistBuddy -c "Set :CFBundleShortVersionString $VERSION" "$APP_PATH/Contents/Info.plist"
/usr/libexec/PlistBuddy -c "Set :CFBundleVersion $BUILD" "$APP_PATH/Contents/Info.plist"
chmod 755 "$APP_PATH/Contents/MacOS/Patchwright" "$APP_PATH/Contents/Helpers/patchwright-engine" "$APP_PATH/Contents/Helpers/patchwright-relay"
@@ -51,7 +53,7 @@ chmod 755 "$APP_PATH/Contents/MacOS/Patchwright" "$APP_PATH/Contents/Helpers/pat
cp "$ROOT_DIR/Cargo.lock" "$ROOT_DIR/Cargo.toml" "$ROOT_DIR/Package.swift" "$WORK_ROOT/reproducibility/"
cp -R "$ROOT_DIR/Packaging" "$ROOT_DIR/script" "$WORK_ROOT/reproducibility/"
-cp "$ROOT_DIR/README.md" "$ROOT_DIR/LICENSE" "$WORK_ROOT/reproducibility/" 2>/dev/null || true
+cp "$ROOT_DIR/README.md" "$ROOT_DIR/LICENSE" "$ROOT_DIR/NOTICE" "$WORK_ROOT/reproducibility/"
git -C "$ROOT_DIR" archive --format=tar.gz --output="$WORK_ROOT/reproducibility/source.tar.gz" HEAD
cargo metadata --locked --format-version 1 >"$WORK_ROOT/reproducibility/cargo-metadata.json"
swift package show-dependencies --format json >"$WORK_ROOT/reproducibility/swift-dependencies.json"
@@ -77,6 +79,8 @@ generate_compliance
"$ROOT_DIR/script/validate_bundle.sh" "$APP_PATH"
SBOM_SHA256="$(shasum -a 256 "$WORK_ROOT/evidence/sbom.spdx.json" | awk '{print $1}')"
NOTICES_SHA256="$(shasum -a 256 "$WORK_ROOT/evidence/third-party-notices.md" | awk '{print $1}')"
+PROJECT_LICENSE_SHA256="$(shasum -a 256 "$WORK_ROOT/reproducibility/LICENSE" | awk '{print $1}')"
+PROJECT_NOTICE_SHA256="$(shasum -a 256 "$WORK_ROOT/reproducibility/NOTICE" | awk '{print $1}')"
if [[ "$MODE" == community ]]; then
SPARKLE="$APP_PATH/Contents/Frameworks/Sparkle.framework"
@@ -97,10 +101,13 @@ if [[ "$MODE" == community ]]; then
--arg app_path "$APP_PATH" --arg version "$VERSION" --arg build "$BUILD" \
--arg git_commit "$COMMIT" --arg source_archive_sha256 "$SOURCE_SHA256" \
--arg sbom_sha256 "$SBOM_SHA256" --arg notices_sha256 "$NOTICES_SHA256" \
+ --arg project_license_sha256 "$PROJECT_LICENSE_SHA256" \
+ --arg project_notice_sha256 "$PROJECT_NOTICE_SHA256" \
'{schema_version:1,kind:"patchwright.community-assembly",app_path:$app_path,
version:$version,build:$build,git_commit:$git_commit,dirty:false,
signing:"ad-hoc",notarized:false,source_archive_sha256:$source_archive_sha256,
- compliance:{sbom_sha256:$sbom_sha256,third_party_notices_sha256:$notices_sha256}}' \
+ compliance:{sbom_sha256:$sbom_sha256,third_party_notices_sha256:$notices_sha256,
+ project_license_sha256:$project_license_sha256,project_notice_sha256:$project_notice_sha256}}' \
>"$WORK_ROOT/evidence/community-assembly.json"
"$ROOT_DIR/script/generate_symlink_manifest.py" \
--root "$WORK_ROOT" --output "$WORK_ROOT/evidence/SYMLINKS.json"
diff --git a/script/package_community_release.sh b/script/package_community_release.sh
index 5eb6781..ccaef9d 100755
--- a/script/package_community_release.sh
+++ b/script/package_community_release.sh
@@ -91,9 +91,14 @@ fi
SOURCE_ARCHIVE="$RELEASE_ROOT/reproducibility/source.tar.gz"
SBOM_SOURCE="$RELEASE_ROOT/evidence/sbom.spdx.json"
NOTICES_SOURCE="$RELEASE_ROOT/evidence/third-party-notices.md"
+PROJECT_LICENSE_SOURCE="$RELEASE_ROOT/reproducibility/LICENSE"
+PROJECT_NOTICE_SOURCE="$RELEASE_ROOT/reproducibility/NOTICE"
for required in "$SOURCE_ARCHIVE" "$SBOM_SOURCE" "$NOTICES_SOURCE" \
+ "$PROJECT_LICENSE_SOURCE" "$PROJECT_NOTICE_SOURCE" \
"$APP_PATH/Contents/Resources/PrivacyInfo.xcprivacy" \
- "$APP_PATH/Contents/Resources/THIRD_PARTY_NOTICES.md"; do
+ "$APP_PATH/Contents/Resources/THIRD_PARTY_NOTICES.md" \
+ "$APP_PATH/Contents/Resources/LICENSE.txt" \
+ "$APP_PATH/Contents/Resources/NOTICE.txt"; do
[[ -f "$required" && ! -L "$required" ]] || fail "required assembled file is missing: $required"
done
[[ -d "$APP_PATH/Contents/Resources/third-party-licenses" ]] \
@@ -131,16 +136,22 @@ esac
SOURCE_SHA256="$(shasum -a 256 "$SOURCE_ARCHIVE" | awk '{print $1}')"
SBOM_SHA256="$(shasum -a 256 "$SBOM_SOURCE" | awk '{print $1}')"
NOTICES_SHA256="$(shasum -a 256 "$NOTICES_SOURCE" | awk '{print $1}')"
+PROJECT_LICENSE_SHA256="$(shasum -a 256 "$PROJECT_LICENSE_SOURCE" | awk '{print $1}')"
+PROJECT_NOTICE_SHA256="$(shasum -a 256 "$PROJECT_NOTICE_SOURCE" | awk '{print $1}')"
ASSEMBLY_SHA256="$(shasum -a 256 "$ASSEMBLY" | awk '{print $1}')"
jq -e --arg app_path "$APP_PATH" --arg version "$VERSION" --arg build "$BUILD" \
--arg git_commit "$COMMIT" --arg source_sha256 "$SOURCE_SHA256" \
--arg sbom_sha256 "$SBOM_SHA256" --arg notices_sha256 "$NOTICES_SHA256" \
+ --arg project_license_sha256 "$PROJECT_LICENSE_SHA256" \
+ --arg project_notice_sha256 "$PROJECT_NOTICE_SHA256" \
'.schema_version == 1 and .kind == "patchwright.community-assembly" and
.app_path == $app_path and .version == $version and .build == $build and
.git_commit == $git_commit and .dirty == false and .signing == "ad-hoc" and
.notarized == false and .source_archive_sha256 == $source_sha256 and
.compliance.sbom_sha256 == $sbom_sha256 and
- .compliance.third_party_notices_sha256 == $notices_sha256' \
+ .compliance.third_party_notices_sha256 == $notices_sha256 and
+ .compliance.project_license_sha256 == $project_license_sha256 and
+ .compliance.project_notice_sha256 == $project_notice_sha256' \
"$ASSEMBLY" >/dev/null || fail "community assembly evidence does not match assembled bytes"
RELEASE_SUFFIX="${TAG#v$VERSION-}"
@@ -149,9 +160,12 @@ MANIFEST_NAME="Patchwright-$VERSION-$RELEASE_SUFFIX-manifest.json"
CHECKSUM_NAME="$ARCHIVE_NAME.sha256"
SBOM_NAME="Patchwright-$VERSION-$RELEASE_SUFFIX-sbom.spdx.json"
NOTICES_NAME="Patchwright-$VERSION-$RELEASE_SUFFIX-third-party-notices.md"
+PROJECT_LICENSE_NAME="Patchwright-$VERSION-$RELEASE_SUFFIX-LICENSE.txt"
+PROJECT_NOTICE_NAME="Patchwright-$VERSION-$RELEASE_SUFFIX-NOTICE.txt"
mkdir -p "$OUTPUT_DIR"
for path in "$OUTPUT_DIR/$ARCHIVE_NAME" "$OUTPUT_DIR/$CHECKSUM_NAME" \
- "$OUTPUT_DIR/$MANIFEST_NAME" "$OUTPUT_DIR/$SBOM_NAME" "$OUTPUT_DIR/$NOTICES_NAME"; do
+ "$OUTPUT_DIR/$MANIFEST_NAME" "$OUTPUT_DIR/$SBOM_NAME" "$OUTPUT_DIR/$NOTICES_NAME" \
+ "$OUTPUT_DIR/$PROJECT_LICENSE_NAME" "$OUTPUT_DIR/$PROJECT_NOTICE_NAME"; do
[[ ! -e "$path" ]] || fail "refusing to overwrite existing release output: $path"
done
@@ -160,6 +174,8 @@ ARCHIVE_SHA256="$(shasum -a 256 "$STAGE/$ARCHIVE_NAME" | awk '{print $1}')"
printf '%s %s\n' "$ARCHIVE_SHA256" "$ARCHIVE_NAME" >"$STAGE/$CHECKSUM_NAME"
cp "$SBOM_SOURCE" "$STAGE/$SBOM_NAME"
cp "$NOTICES_SOURCE" "$STAGE/$NOTICES_NAME"
+cp "$PROJECT_LICENSE_SOURCE" "$STAGE/$PROJECT_LICENSE_NAME"
+cp "$PROJECT_NOTICE_SOURCE" "$STAGE/$PROJECT_NOTICE_NAME"
CREATED_AT="$(git -C "$ROOT_DIR" show -s --format=%cI "$COMMIT")"
jq -n \
--arg version "$VERSION" --arg build "$BUILD" --arg tag "$TAG" \
@@ -169,6 +185,8 @@ jq -n \
--arg source_archive_sha256 "$SOURCE_SHA256" --arg sbom "$SBOM_NAME" \
--arg sbom_sha256 "$SBOM_SHA256" --arg notices "$NOTICES_NAME" \
--arg third_party_notices_sha256 "$NOTICES_SHA256" \
+ --arg project_license "$PROJECT_LICENSE_NAME" --arg project_license_sha256 "$PROJECT_LICENSE_SHA256" \
+ --arg project_notice "$PROJECT_NOTICE_NAME" --arg project_notice_sha256 "$PROJECT_NOTICE_SHA256" \
--arg community_assembly_sha256 "$ASSEMBLY_SHA256" \
'{schema_version:1,kind:"patchwright.community-prerelease",version:$version,build:$build,
tag:$tag,git_commit:$git_commit,archive:$archive,archive_sha256:$archive_sha256,
@@ -176,11 +194,14 @@ jq -n \
signing:"ad-hoc",notarized:false,created_at:$created_at,
source_archive_sha256:$source_archive_sha256,sbom:$sbom,sbom_sha256:$sbom_sha256,
third_party_notices:$notices,third_party_notices_sha256:$third_party_notices_sha256,
+ project_license:$project_license,project_license_sha256:$project_license_sha256,
+ project_notice:$project_notice,project_notice_sha256:$project_notice_sha256,
community_assembly_sha256:$community_assembly_sha256,
install_warning:"This community build is not Developer ID signed or Apple notarized. macOS Gatekeeper may block it; build from source if you require a locally trusted copy."}' \
>"$STAGE/$MANIFEST_NAME"
-for asset in "$ARCHIVE_NAME" "$CHECKSUM_NAME" "$MANIFEST_NAME" "$SBOM_NAME" "$NOTICES_NAME"; do
+for asset in "$ARCHIVE_NAME" "$CHECKSUM_NAME" "$MANIFEST_NAME" "$SBOM_NAME" "$NOTICES_NAME" \
+ "$PROJECT_LICENSE_NAME" "$PROJECT_NOTICE_NAME"; do
/bin/mv "$STAGE/$asset" "$OUTPUT_DIR/$asset"
done
printf 'PATCHWRIGHT_COMMUNITY_ARCHIVE=%s\n' "$OUTPUT_DIR/$ARCHIVE_NAME"
@@ -188,4 +209,6 @@ printf 'PATCHWRIGHT_COMMUNITY_CHECKSUM=%s\n' "$OUTPUT_DIR/$CHECKSUM_NAME"
printf 'PATCHWRIGHT_COMMUNITY_MANIFEST=%s\n' "$OUTPUT_DIR/$MANIFEST_NAME"
printf 'PATCHWRIGHT_COMMUNITY_SBOM=%s\n' "$OUTPUT_DIR/$SBOM_NAME"
printf 'PATCHWRIGHT_COMMUNITY_NOTICES=%s\n' "$OUTPUT_DIR/$NOTICES_NAME"
+printf 'PATCHWRIGHT_COMMUNITY_LICENSE=%s\n' "$OUTPUT_DIR/$PROJECT_LICENSE_NAME"
+printf 'PATCHWRIGHT_COMMUNITY_PROJECT_NOTICE=%s\n' "$OUTPUT_DIR/$PROJECT_NOTICE_NAME"
printf 'PATCHWRIGHT_STATUS=community-prerelease-not-notarized\n'