diff --git a/.github/PULL_REQUEST_TEMPLATE.md b/.github/PULL_REQUEST_TEMPLATE.md index 11d407a..9c66823 100644 --- a/.github/PULL_REQUEST_TEMPLATE.md +++ b/.github/PULL_REQUEST_TEMPLATE.md @@ -8,6 +8,11 @@ Describe what changed and why. - [ ] `swift build -c release` - [ ] Tested on a physical Busy Bar when the change affects device behavior +## AI assistance + +List any generative AI tools used and what they assisted with, or write +`None`: + ## Device details - BarKeep version or branch: @@ -20,6 +25,8 @@ Describe what changed and why. - [ ] The change is focused and does not include unrelated files. - [ ] Tests cover new or changed behavior. - [ ] Public documentation is updated when setup or behavior changed. +- [ ] I reviewed and understand all submitted code, including AI-assisted + changes. - [ ] No passwords, tokens, private messages, signing credentials, or personal data are included. - [ ] UI changes include a screenshot or short recording. diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md index ca512f3..a75fd14 100644 --- a/CONTRIBUTING.md +++ b/CONTRIBUTING.md @@ -65,6 +65,18 @@ Before opening a pull request: GitHub Actions runs the test suite and release build for every pull request. Maintainers may ask for changes before merging. +## AI-assisted contributions + +AI-assisted contributions are welcome. If you use a generative AI tool, +identify the tool and summarize what it assisted with in the pull-request +description. You remain responsible for understanding and reviewing every +submitted change, running the required tests, and confirming that the +contribution does not include private data or code with incompatible licensing. + +Treat generated output as untrusted until you have reviewed and tested it. Do +not paste credentials, private messages, proprietary source code, or other +sensitive material into an AI service. + ## Protect credentials and private data Never commit: diff --git a/README.md b/README.md index c93036c..a32a1d8 100644 --- a/README.md +++ b/README.md @@ -17,6 +17,19 @@ BarKeep is free and open-source software under the [MIT License](LICENSE). You are welcome to use it, fork it, modify it, redistribute it, or build your own project from it. Contributions are welcome. +## Development transparency + +BarKeep was built with substantial assistance from generative AI tools, +primarily OpenAI ChatGPT/Codex and Anthropic Claude. AI assisted with product +exploration, implementation, debugging, tests, documentation, and release +automation. + +Brian Phillips is the human maintainer and reviews, tests, signs, and takes +responsibility for every official release. This disclosure describes how the +software was developed: BarKeep does not require or contact an AI service +during normal operation. Its optional hooks and MCP server only connect to AI +tools when you explicitly configure them. + ## Features **Menu bar app** (tabbed popover: Device / Message / Timers / Arcade / Settings) @@ -244,6 +257,11 @@ swift build # debug build The icon is generated: `cd assets && swift gen_icon.swift 1024 icon.png` (see `gen_icon.swift` for the pixel grid). +Release packaging verifies the signed app before archiving and verifies a +freshly extracted copy with +[`scripts/verify-release-archive.sh`](scripts/verify-release-archive.sh), so a +damaged release archive fails before publication. + ## Contributing Bug reports, feature ideas, documentation improvements, code contributions, diff --git a/scripts/package-release.sh b/scripts/package-release.sh index 3b1e4a5..07a1d80 100755 --- a/scripts/package-release.sh +++ b/scripts/package-release.sh @@ -26,8 +26,17 @@ fi codesign --verify --deep --strict --verbose=2 "$APP" ZIP="dist/BarKeep-${VERSION}.zip" -rm -f "$ZIP" -ditto -c -k --keepParent "$APP" "$ZIP" + +package_and_verify() { + rm -f "$ZIP" + # Do not ship local resource-fork metadata as unnecessary AppleDouble (._*) + # entries. The signed files and notarization ticket remain in the archive. + ditto -c -k --norsrc --keepParent "$APP" "$ZIP" + codesign --verify --deep --strict --verbose=2 "$APP" + ./scripts/verify-release-archive.sh "$ZIP" +} + +package_and_verify if [ -n "${BARKEEP_NOTARY_PROFILE:-}" ]; then xcrun notarytool submit "$ZIP" \ @@ -35,8 +44,9 @@ if [ -n "${BARKEEP_NOTARY_PROFILE:-}" ]; then --wait xcrun stapler staple "$APP" xcrun stapler validate "$APP" - rm -f "$ZIP" - ditto -c -k --keepParent "$APP" "$ZIP" + codesign --verify --deep --strict --verbose=2 "$APP" + spctl --assess --type execute --verbose=2 "$APP" + package_and_verify fi echo "Packaged $ZIP" diff --git a/scripts/verify-release-archive.sh b/scripts/verify-release-archive.sh new file mode 100755 index 0000000..35cda5b --- /dev/null +++ b/scripts/verify-release-archive.sh @@ -0,0 +1,28 @@ +#!/bin/zsh +# Verifies the app exactly as users receive it after extracting a release ZIP. +set -euo pipefail + +if [ "$#" -ne 1 ]; then + echo "Usage: $0 " >&2 + exit 64 +fi + +ZIP="$1" +if [ ! -f "$ZIP" ]; then + echo "Release archive not found: $ZIP" >&2 + exit 66 +fi + +VERIFY_DIR="$(mktemp -d "${TMPDIR:-/tmp}/barkeep-release-verify.XXXXXX")" +trap 'rm -rf "$VERIFY_DIR"' EXIT + +ditto -x -k --norsrc "$ZIP" "$VERIFY_DIR" + +APP="$VERIFY_DIR/BarKeep.app" +if [ ! -d "$APP" ]; then + echo "Release archive does not contain BarKeep.app at its root" >&2 + exit 65 +fi + +codesign --verify --deep --strict --verbose=2 "$APP" +echo "Verified extracted release app: $APP"