Skip to content
Closed
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 2 additions & 2 deletions .github/ISSUE_TEMPLATE/config.yml
Original file line number Diff line number Diff line change
@@ -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.
32 changes: 30 additions & 2 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
2 changes: 1 addition & 1 deletion CODE_OF_CONDUCT.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
6 changes: 3 additions & 3 deletions Cargo.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

6 changes: 3 additions & 3 deletions Packaging/Info.plist
Original file line number Diff line number Diff line change
Expand Up @@ -19,9 +19,9 @@
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.1.1</string>
<string>0.2.0</string>
<key>CFBundleVersion</key>
<string>2</string>
<string>3</string>
<key>LSApplicationCategoryType</key>
<string>public.app-category.developer-tools</string>
<key>LSMinimumSystemVersion</key>
Expand All @@ -33,7 +33,7 @@
<key>NSPrincipalClass</key>
<string>NSApplication</string>
<key>SUFeedURL</key>
<string>https://github.com/s1korrrr/patchwright/releases/latest/download/appcast.xml</string>
<string>https://github.com/rsitech-ai/patchwright/releases/latest/download/appcast.xml</string>
<key>SUPublicEDKey</key>
<string>oMzk7aUjqsQFvrRBZDd5JsXaeTh8B4pQrJ7n6YHRWUA=</string>
<key>SURequireSignedFeed</key>
Expand Down
16 changes: 10 additions & 6 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down Expand Up @@ -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.
Expand All @@ -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).
2 changes: 1 addition & 1 deletion SECURITY.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
2 changes: 1 addition & 1 deletion SUPPORT.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.

Expand Down
110 changes: 110 additions & 0 deletions Tests/PackagingTests/community_release_contract.sh
Original file line number Diff line number Diff line change
@@ -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'
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
<key>CFBundleExecutable</key>
<string>Patchwright</string>
<key>CFBundleIdentifier</key>
<string>ai.patchwright.app</string>
<key>CFBundlePackageType</key>
<string>APPL</string>
<key>CFBundleShortVersionString</key>
<string>0.2.0</string>
<key>CFBundleVersion</key>
<string>3</string>
<key>LSMinimumSystemVersion</key>
<string>26.0</string>
</dict>
</plist>
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"
11 changes: 8 additions & 3 deletions Tests/PackagingTests/github_app_smoke_contract.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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" \
Expand Down
2 changes: 1 addition & 1 deletion Tests/PackagingTests/promotion_contract.sh
Original file line number Diff line number Diff line change
Expand Up @@ -124,7 +124,7 @@ def appcast_content(archive_signature: str) -> str:
'<channel><item><title>Patchwright 0.1.0</title>'
'<sparkle:version>1</sparkle:version>'
'<sparkle:shortVersionString>0.1.0</sparkle:shortVersionString>'
'<enclosure url="https://github.com/s1korrrr/patchwright/releases/download/v0.1.0/Patchwright-0.1.0.dmg" '
'<enclosure url="https://github.com/rsitech-ai/patchwright/releases/download/v0.1.0/Patchwright-0.1.0.dmg" '
f'length="{len(DMG_BYTES)}" type="application/octet-stream" '
f'sparkle:edSignature="{archive_signature}"/>'
'</item></channel></rss>\n'
Expand Down
30 changes: 16 additions & 14 deletions Tests/PackagingTests/release_contract.sh
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand All @@ -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' \
Expand Down Expand Up @@ -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' \
Expand Down
2 changes: 1 addition & 1 deletion Tests/PatchwrightCoreTests/UpdateConfigurationTests.swift
Original file line number Diff line number Diff line change
Expand Up @@ -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 {
Expand Down
3 changes: 1 addition & 2 deletions crates/patchwright-core/Cargo.toml
Original file line number Diff line number Diff line change
@@ -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
Expand All @@ -19,4 +19,3 @@ unsafe_code = "warn"
[lints.clippy]
all = "warn"
pedantic = "warn"

Loading
Loading