From 992f1444e6720c720ea24f3a8b88748dfbe70ce4 Mon Sep 17 00:00:00 2001
From: Akshay Kolli
Date: Tue, 30 Jun 2026 00:18:59 -0700
Subject: [PATCH] Clean up repository structure and release docs
---
.../bug_report.md => ISSUE_TEMPLATE.md} | 28 +-
.github/ISSUE_TEMPLATE/feature_request.md | 27 --
.github/pull_request_template.md | 6 +
.gitignore | 2 +
CHANGELOG.md | 8 +
CONTRIBUTING.md | 19 +-
Package.swift | 14 +-
README.md | 40 +-
RELEASE_NOTES.md | 33 --
ROADMAP.md | 39 +-
SECURITY.md | 4 +-
SUPPORT.md | 19 -
.../app-icon.png | Bin
docs/APP_STORE.md | 60 ---
docs/APP_STORE_COPY.md | 97 ----
docs/DESIGN_REVIEW.md | 39 --
docs/ENGINEERING.md | 72 ---
docs/FUNCTIONALITY_AUDIT.md | 35 --
docs/QA.md | 26 +-
docs/RELEASE.md | 43 +-
docs/WORKFLOW_AUDIT.md | 53 ---
docs/screenshots/comments-sidebar.png | Bin 531586 -> 0 bytes
docs/screenshots/dark-mode-reading.png | Bin 816445 -> 0 bytes
.../screenshots/highlight-comment-popover.png | Bin 509914 -> 0 bytes
docs/screenshots/main-window.png | Bin 44898 -> 0 bytes
docs/screenshots/no-document.png | Bin 507702 -> 0 bytes
docs/screenshots/preview-interoperability.png | Bin 773610 -> 0 bytes
.../screenshots/preview-visible-signature.png | Bin 534610 -> 0 bytes
goal.md | 446 ------------------
ihatepdf.png | Bin 8939 -> 0 bytes
scripts/build-app.sh | 4 +-
scripts/make-app-store-pkg.sh | 2 +-
scripts/make-tiny-archives.sh | 25 +-
scripts/verify-pdf-annotations.swift | 175 ++++++-
scripts/verify-release-size.sh | 40 --
scripts/verify-sample-pdf.swift | 167 -------
.../IHatePDFs-AppStore.entitlements | 0
.../app}/AppSettings.swift | 0
.../IHatePDFs => sources/app}/AppState.swift | 0
.../app}/CommentEditorView.swift | 0
.../app}/CommitTextView.swift | 0
.../app}/IHatePDFsApp.swift | 0
.../app}/InterfacePalette.swift | 0
.../IHatePDFs => sources/app}/MainView.swift | 0
.../app}/PDFKitRepresentedView.swift | 0
.../app}/ReaderAdaptiveLayout.swift | 0
.../app}/ReviewState.swift | 0
.../app}/SidebarViews.swift | 0
.../core}/AnnotationColorPreference.swift | 0
.../core}/AnnotationFactory.swift | 0
.../core}/AnnotationHitTesting.swift | 0
.../core}/AnnotationModels.swift | 0
.../core}/PDFDocumentBookmarks.swift | 0
.../core}/PDFFileSelection.swift | 0
.../core}/PDFRecentDocuments.swift | 0
.../core}/ReturnKeyCommitPolicy.swift | 0
.../app}/AppStateWorkflowTests.swift | 0
.../app}/ReaderAdaptiveLayoutTests.swift | 0
.../AnnotationColorPreferenceTests.swift | 0
.../core}/AnnotationFactoryTests.swift | 0
.../core}/AnnotationHitTestingTests.swift | 0
.../core}/PDFDocumentBookmarksTests.swift | 0
.../core}/PDFFileSelectionTests.swift | 0
.../core}/PDFRecentDocumentsTests.swift | 0
.../core}/PerformanceBudgetTests.swift | 0
.../core}/ReturnKeyCommitPolicyTests.swift | 0
66 files changed, 330 insertions(+), 1193 deletions(-)
rename .github/{ISSUE_TEMPLATE/bug_report.md => ISSUE_TEMPLATE.md} (50%)
delete mode 100644 .github/ISSUE_TEMPLATE/feature_request.md
delete mode 100644 RELEASE_NOTES.md
delete mode 100644 SUPPORT.md
rename ihatepdf-profile-transparent.png => assets/app-icon.png (100%)
delete mode 100644 docs/APP_STORE.md
delete mode 100644 docs/APP_STORE_COPY.md
delete mode 100644 docs/DESIGN_REVIEW.md
delete mode 100644 docs/ENGINEERING.md
delete mode 100644 docs/FUNCTIONALITY_AUDIT.md
delete mode 100644 docs/WORKFLOW_AUDIT.md
delete mode 100644 docs/screenshots/comments-sidebar.png
delete mode 100644 docs/screenshots/dark-mode-reading.png
delete mode 100644 docs/screenshots/highlight-comment-popover.png
delete mode 100644 docs/screenshots/main-window.png
delete mode 100644 docs/screenshots/no-document.png
delete mode 100644 docs/screenshots/preview-interoperability.png
delete mode 100644 docs/screenshots/preview-visible-signature.png
delete mode 100644 goal.md
delete mode 100644 ihatepdf.png
delete mode 100755 scripts/verify-release-size.sh
delete mode 100644 scripts/verify-sample-pdf.swift
rename {Signing => signing}/IHatePDFs-AppStore.entitlements (100%)
rename {Sources/IHatePDFs => sources/app}/AppSettings.swift (100%)
rename {Sources/IHatePDFs => sources/app}/AppState.swift (100%)
rename {Sources/IHatePDFs => sources/app}/CommentEditorView.swift (100%)
rename {Sources/IHatePDFs => sources/app}/CommitTextView.swift (100%)
rename {Sources/IHatePDFs => sources/app}/IHatePDFsApp.swift (100%)
rename {Sources/IHatePDFs => sources/app}/InterfacePalette.swift (100%)
rename {Sources/IHatePDFs => sources/app}/MainView.swift (100%)
rename {Sources/IHatePDFs => sources/app}/PDFKitRepresentedView.swift (100%)
rename {Sources/IHatePDFs => sources/app}/ReaderAdaptiveLayout.swift (100%)
rename {Sources/IHatePDFs => sources/app}/ReviewState.swift (100%)
rename {Sources/IHatePDFs => sources/app}/SidebarViews.swift (100%)
rename {Sources/IHatePDFsCore => sources/core}/AnnotationColorPreference.swift (100%)
rename {Sources/IHatePDFsCore => sources/core}/AnnotationFactory.swift (100%)
rename {Sources/IHatePDFsCore => sources/core}/AnnotationHitTesting.swift (100%)
rename {Sources/IHatePDFsCore => sources/core}/AnnotationModels.swift (100%)
rename {Sources/IHatePDFsCore => sources/core}/PDFDocumentBookmarks.swift (100%)
rename {Sources/IHatePDFsCore => sources/core}/PDFFileSelection.swift (100%)
rename {Sources/IHatePDFsCore => sources/core}/PDFRecentDocuments.swift (100%)
rename {Sources/IHatePDFsCore => sources/core}/ReturnKeyCommitPolicy.swift (100%)
rename {Tests/IHatePDFsTests => tests/app}/AppStateWorkflowTests.swift (100%)
rename {Tests/IHatePDFsTests => tests/app}/ReaderAdaptiveLayoutTests.swift (100%)
rename {Tests/IHatePDFsCoreTests => tests/core}/AnnotationColorPreferenceTests.swift (100%)
rename {Tests/IHatePDFsCoreTests => tests/core}/AnnotationFactoryTests.swift (100%)
rename {Tests/IHatePDFsCoreTests => tests/core}/AnnotationHitTestingTests.swift (100%)
rename {Tests/IHatePDFsCoreTests => tests/core}/PDFDocumentBookmarksTests.swift (100%)
rename {Tests/IHatePDFsCoreTests => tests/core}/PDFFileSelectionTests.swift (100%)
rename {Tests/IHatePDFsCoreTests => tests/core}/PDFRecentDocumentsTests.swift (100%)
rename {Tests/IHatePDFsCoreTests => tests/core}/PerformanceBudgetTests.swift (100%)
rename {Tests/IHatePDFsCoreTests => tests/core}/ReturnKeyCommitPolicyTests.swift (100%)
diff --git a/.github/ISSUE_TEMPLATE/bug_report.md b/.github/ISSUE_TEMPLATE.md
similarity index 50%
rename from .github/ISSUE_TEMPLATE/bug_report.md
rename to .github/ISSUE_TEMPLATE.md
index be1342f..d0a3e54 100644
--- a/.github/ISSUE_TEMPLATE/bug_report.md
+++ b/.github/ISSUE_TEMPLATE.md
@@ -1,25 +1,23 @@
----
-name: Bug report
-about: Report a reproducible problem in I Hate PDFs
-title: ""
-labels: bug
-assignees: ""
----
+## Type
+
+Bug report, feature request, documentation issue, or support question?
## Summary
-What happened?
-
-## Expected Behavior
-
-What did you expect to happen?
+What should maintainers know first?
## Steps To Reproduce
+For bugs, list the shortest reproducible path:
+
1.
2.
3.
+## Expected Behavior
+
+What did you expect to happen?
+
## Environment
- I Hate PDFs version/build:
@@ -27,10 +25,10 @@ What did you expect to happen?
- Install source: GitHub release or Mac App Store
- Mac architecture: Apple Silicon or Intel
-## Screenshots Or Recordings
+## UI Evidence
Attach screenshots or recordings for UI problems. Each file must be under 1 MB.
-## Additional Context
+## Size And Privacy Impact
-Add any relevant PDF workflow details. Do not attach private PDFs publicly.
+For feature requests, note whether this requires new assets, dependencies, network behavior, bundled PDFs, or release-size increases.
diff --git a/.github/ISSUE_TEMPLATE/feature_request.md b/.github/ISSUE_TEMPLATE/feature_request.md
deleted file mode 100644
index ec3c88c..0000000
--- a/.github/ISSUE_TEMPLATE/feature_request.md
+++ /dev/null
@@ -1,27 +0,0 @@
----
-name: Feature request
-about: Suggest an improvement for I Hate PDFs
-title: ""
-labels: enhancement
-assignees: ""
----
-
-## Problem
-
-What workflow problem should this solve?
-
-## Proposed Solution
-
-What should I Hate PDFs do?
-
-## Alternatives Considered
-
-What workaround or other app behavior have you tried?
-
-## UI Impact
-
-Will this change visible UI? If yes, describe the screen, toolbar, menu, sidebar, popover, or dialog affected.
-
-## Size And Privacy Impact
-
-Does this require new assets, dependencies, network behavior, bundled PDFs, or release-size increases?
diff --git a/.github/pull_request_template.md b/.github/pull_request_template.md
index 92e2ae1..fe4f830 100644
--- a/.github/pull_request_template.md
+++ b/.github/pull_request_template.md
@@ -2,6 +2,10 @@
Describe what changed and why.
+## Vibe Coding Disclosure
+
+Was this pull request vibe coded or assisted by generated code? If yes, describe what you manually reviewed before opening it.
+
## Screenshots Or Recordings
Required for UI changes. Include before and after screenshots for changed UI, or at least one screenshot/recording for new UI.
@@ -14,6 +18,7 @@ List the checks you ran:
- [ ] `swift test`
- [ ] `swift build -c release`
+- [ ] `swift scripts/verify-pdf-annotations.swift`
- [ ] `scripts/verify-release-artifacts.sh`
- [ ] Manual UI check
- [ ] Not run, because:
@@ -23,6 +28,7 @@ List the checks you ran:
- [ ] I read `CONTRIBUTING.md`.
- [ ] This pull request is focused on one behavior, fix, or documentation change.
- [ ] I updated `CHANGELOG.md` for user-visible changes, or this change is not user-visible.
+- [ ] I documented the before/after behavior and QA performed.
- [ ] UI changes include screenshots or recordings, or this pull request does not change UI.
- [ ] Every screenshot, recording, and committed media file in this pull request is under 1 MB.
- [ ] I explained any app-size impact from new assets, dependencies, or release packaging changes.
diff --git a/.gitignore b/.gitignore
index a6daaea..1b35d4e 100644
--- a/.gitignore
+++ b/.gitignore
@@ -5,12 +5,14 @@ DerivedData/
dist/
release/
plans/
+$tmpdir/
*.dmg
*.pkg
*.tar.gz
*.tar.xz
*.zip
*.xcuserstate
+*.swp
*.xcworkspace/xcuserdata/
*.xcodeproj/xcuserdata/
*.mobileprovision
diff --git a/CHANGELOG.md b/CHANGELOG.md
index b0829a1..b6834f8 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -7,6 +7,14 @@
- Added README badges for release, license, platform, Swift, contributions, and media-size policy.
- Added contribution, support, security, issue, and pull request policies for open-source contributors.
- Added a pull request media-size policy requiring UI screenshots or recordings and limiting each screenshot, recording, or committed media file to less than 1 MB.
+- Renamed source, test, and signing directories to lowercase paths.
+- Removed duplicate release/planning docs, stale screenshot targets, and the unused duplicate icon image.
+- Removed redundant support/App Store copy docs and trimmed repository screenshots to one representative image.
+- Consolidated release helper scripts by folding size checks into tiny archive creation and sample PDF generation into PDF annotation verification.
+- Consolidated workflow audit guidance into the manual QA document.
+- Consolidated engineering guidance into contributing docs and App Store packaging into release docs.
+- Documented that vibe coded pull requests are welcome when they include clear change documentation, strict QA, and UI screenshots or recordings when relevant.
+- Documented `https://www.akkolli.net/ihatepdfs` as the project website and `akshaykolli@hotmail.com` as the support contact.
## Version 0.4.0 (build 6) - 2026-06-25
diff --git a/CONTRIBUTING.md b/CONTRIBUTING.md
index 962c196..0c82285 100644
--- a/CONTRIBUTING.md
+++ b/CONTRIBUTING.md
@@ -4,12 +4,13 @@ I Hate PDFs is a native macOS app for local PDF reading and annotation. Contribu
By contributing, you agree that your contribution is licensed under GNU General Public License version 2 only.
+Vibe coded pull requests are welcome. This is a vibe coded repo, but vibe coded does not mean unreviewed: every change must be understandable, documented, tested at the right level, and held to the same strict QA bar as hand-written code.
+
## Before You Start
- Check existing issues and pull requests before starting duplicate work.
- Open an issue first for large UI changes, new dependencies, release-process changes, or features that affect PDF saving/export behavior.
-- Read `docs/ENGINEERING.md` before adding dependencies, bundled assets, PDF engines, runtimes, or broad architectural changes.
-- Read `docs/WORKFLOW_AUDIT.md` before changing a user workflow.
+- Read `docs/QA.md` before changing a user workflow.
- Read `docs/RELEASE.md` before preparing a release.
## Development
@@ -33,15 +34,29 @@ scripts/verify-release-artifacts.sh
Run the checks that match your change and list them in the pull request. If you skip a relevant check, say why.
+## Engineering Policy
+
+- Build with Swift, SwiftUI, AppKit, PDFKit, and system frameworks that ship with macOS.
+- Do not replace the app with Electron, Chromium, a web runtime, a bundled JavaScript shell, or a cross-platform UI toolkit.
+- Do not bundle a PDF renderer, OCR engine, database, scripting runtime, or large framework when a macOS system API can satisfy the requirement.
+- Keep third-party dependencies at or near zero. Any new package must justify shipped size, runtime cost, maintenance cost, and why system APIs are insufficient.
+- Keep assets minimal. Avoid large raster images, fonts, sample PDFs, videos, model files, or generated resources in the app bundle.
+- Keep expensive work page-scoped or lazy when possible.
+- Treat release-size growth as a product regression. Each direct-download per-architecture installer must stay under 400,000 bytes.
+- Run `scripts/make-tiny-archives.sh` before release-impacting changes; it builds and checks the per-architecture archives.
+
## Pull Request Policy
- Keep each pull request focused on one behavior, bug fix, or documentation change.
- Explain the user-visible behavior change, not only the implementation detail.
+- For vibe coded changes, say so in the pull request and describe what you reviewed manually before opening it.
- Link the issue when one exists.
- Update `CHANGELOG.md` for user-visible changes.
- Avoid unrelated formatting churn.
- Do not add a new dependency, bundled asset, PDF engine, runtime, or release artifact without explaining the size and maintenance impact.
- Preserve the app's local-first privacy model.
+- Document the before/after behavior clearly enough that a maintainer can review the intent without reverse-engineering the diff.
+- Include the QA commands and manual checks that prove the change works.
## UI Screenshot Policy
diff --git a/Package.swift b/Package.swift
index ceeb930..b5d8031 100644
--- a/Package.swift
+++ b/Package.swift
@@ -11,18 +11,24 @@ let package = Package(
.library(name: "IHatePDFsCore", targets: ["IHatePDFsCore"])
],
targets: [
- .target(name: "IHatePDFsCore"),
+ .target(
+ name: "IHatePDFsCore",
+ path: "sources/core"
+ ),
.executableTarget(
name: "IHatePDFs",
- dependencies: ["IHatePDFsCore"]
+ dependencies: ["IHatePDFsCore"],
+ path: "sources/app"
),
.testTarget(
name: "IHatePDFsCoreTests",
- dependencies: ["IHatePDFsCore"]
+ dependencies: ["IHatePDFsCore"],
+ path: "tests/core"
),
.testTarget(
name: "IHatePDFsTests",
- dependencies: ["IHatePDFs", "IHatePDFsCore"]
+ dependencies: ["IHatePDFs", "IHatePDFsCore"],
+ path: "tests/app"
)
]
)
diff --git a/README.md b/README.md
index a4c5ecf..98020ea 100644
--- a/README.md
+++ b/README.md
@@ -1,5 +1,5 @@
-
+
I Hate PDFs
@@ -15,15 +15,18 @@
+
Download
·
- Report a bug
+ Report a bug
·
Contribute
·
+ Support
+ ·
Privacy
@@ -45,7 +48,7 @@ Download the v0.4 macOS DMG from the GitHub release page:
Use `IHatePDFs-v0.4-macos.dmg` for direct installation. Open the DMG, then move `I Hate PDFs.app` into `/Applications`.
-The direct-download DMG is separate from the Mac App Store build. The App Store package uses bundle ID `net.akkolli.ihatepdfs` and is built with the sandbox entitlements documented in `docs/APP_STORE.md`.
+The direct-download DMG is separate from the Mac App Store build. The App Store package uses bundle ID `net.akkolli.ihatepdfs` and is built with sandbox entitlements documented in `docs/RELEASE.md`.
## Features
@@ -70,9 +73,9 @@ The direct-download DMG is separate from the Mac App Store build. The App Store
## Privacy And Support
-- Product and support page:
+- Project website:
+- Support email:
- Privacy policy:
-- Support policy: [SUPPORT.md](SUPPORT.md)
- Security policy: [SECURITY.md](SECURITY.md)
I Hate PDFs works with user-selected local files. It does not require an account, collect analytics, or upload PDFs.
@@ -134,7 +137,7 @@ PROVISIONING_PROFILE="$HOME/Downloads/IHatePDFs_AppStore.provisionprofile" \
scripts/make-app-store-pkg.sh
```
-The App Store package is written to `dist/IHatePDFs-v0.4-macos-appstore.pkg`. More details are in `docs/APP_STORE.md`.
+The App Store package is written to `dist/IHatePDFs-v0.4-macos-appstore.pkg`. More details are in `docs/RELEASE.md`.
## Installation
@@ -149,13 +152,13 @@ The project is a Swift Package with two targets:
- `IHatePDFsCore`: PDF annotation models, annotation export helpers, hit testing, color preference logic, file selection, and keyboard policies.
- `IHatePDFs`: SwiftUI macOS app, PDFKit bridge, toolbar, menus, sidebars, anchored comment popovers, opening, saving, sharing, and search.
-Engineering rule: keep this a native macOS app with the smallest final bundle that still delivers the required fluidity and functionality. See `docs/ENGINEERING.md` before adding dependencies, bundled assets, PDF engines, runtimes, or broad architectural changes.
-Use `docs/WORKFLOW_AUDIT.md` when checking whether a feature matches the intended user workflow before changing or releasing it.
+Engineering rule: keep this a native macOS app with the smallest final bundle that still delivers the required fluidity and functionality. See `CONTRIBUTING.md` before adding dependencies, bundled assets, PDF engines, runtimes, or broad architectural changes.
Use `docs/RELEASE.md` when preparing a new version; it is the checklist for version bumps, release validation, size gates, and upload packaging.
Open source contribution policy:
- Contributions are accepted under GPL-2.0-only. See [LICENSE](LICENSE).
+- Vibe coded pull requests are welcome, but they must include clear change documentation, strict QA notes, and screenshots or recordings for UI changes.
- Start with [CONTRIBUTING.md](CONTRIBUTING.md) before opening a pull request.
- UI pull requests must include before/after screenshots or a short screen recording.
- Screenshots, recordings, and committed media files included with a pull request must each be under 1 MB.
@@ -165,36 +168,21 @@ Useful checks:
```sh
swift test
swift build -c release
-swift scripts/verify-sample-pdf.swift
swift scripts/verify-pdf-annotations.swift
scripts/verify-release-artifacts.sh
```
-The PDF verification scripts generate and inspect standard highlight, underline, selected-text comment, reply, free-text, contents, and annotation relationship dictionaries.
+The PDF verification script generates and inspects standard highlight, underline, selected-text comment, reply, free-text, contents, and annotation relationship dictionaries.
The release artifact verifier checks the current direct-download app and DMG by default. Run `REQUIRE_APP_STORE_PKG=1 scripts/verify-release-artifacts.sh` after creating an App Store package.
-Manual release QA for Preview, Acrobat Reader, and browser PDF viewers is documented in `docs/QA.md`. App Store packaging is documented in `docs/APP_STORE.md`, and paste-ready App Store metadata is in `docs/APP_STORE_COPY.md`.
+Manual release QA and workflow guardrails for Preview, Acrobat Reader, and browser PDF viewers are documented in `docs/QA.md`. Release and App Store packaging are documented in `docs/RELEASE.md`.
-## Screenshots
+## Screenshot
Screenshots live in `docs/screenshots`.
-Current repository screenshots that are useful for local review:
-
-- `docs/screenshots/default-reading.png`
-- `docs/screenshots/main-window.png`
-- `docs/screenshots/comments-sidebar.png`
-- `docs/screenshots/dark-mode-reading.png`
-- `docs/screenshots/preview-interoperability.png`
-
-`docs/screenshots/no-document.png` and `docs/screenshots/highlight-comment-popover.png` are capture targets that need to be retaken before public release docs use them.
-

-
-
-
-
## License
GNU General Public License version 2 only. See [LICENSE](LICENSE).
diff --git a/RELEASE_NOTES.md b/RELEASE_NOTES.md
deleted file mode 100644
index b2ec6aa..0000000
--- a/RELEASE_NOTES.md
+++ /dev/null
@@ -1,33 +0,0 @@
-# Release Notes
-
-## I Hate PDFs v0.4.0
-
-Version 0.4 is focused on keeping the app small, fast, and reader-first. The experimental Fill & Sign, form-field navigation, and PDF signing work has been removed from this release line and will be revisited later from scratch.
-
-### What's New
-
-- Focused document opening: PDFs open in the reader with sidebars hidden and the page fit to available width.
-- Smaller app surface area after removing the experimental Fill & Sign/signing implementation.
-- Recent PDFs in the empty window and File > Open Recent.
-- Settings for highlight and comment colors, including opacity.
-- Standalone highlights that do not open a comment editor.
-- Return saves a comment or reply; Shift-Return inserts a new line.
-- Mac App Store packaging for `net.akkolli.ihatepdfs`.
-
-### Reliability Fixes
-
-- Comment text survives when saved PDFs are opened in macOS Preview and Adobe Acrobat.
-- The comment editor focuses correctly when a new selected-text comment is created.
-- Comment popovers open from the actual annotated text instead of nearby whitespace.
-- The app warns before unsaved annotations or reply drafts are lost.
-- Search highlights clear correctly when search is closed or edited.
-- The comments sidebar keeps threads, filters, replies, and selected highlights in sync.
-- PDFKit page/selection observers are cleaned up when the reader view is reattached.
-- Sidebar toggles now close the active sidebar mode directly instead of switching modes first.
-
-### Version
-
-- App version: `0.4.0`
-- Build number: `6`
-- Direct-download DMG name: `IHatePDFs-v0.4-macos.dmg`
-- Mac App Store package name: `IHatePDFs-v0.4-macos-appstore.pkg`
diff --git a/ROADMAP.md b/ROADMAP.md
index ed9ed8a..4b657e5 100644
--- a/ROADMAP.md
+++ b/ROADMAP.md
@@ -1,37 +1,6 @@
# Roadmap
-## Version 0.1
-
-- Native macOS SwiftUI/PDFKit app.
-- Local PDF opening.
-- Reading controls: scrolling, zoom, fit width, fit page, page navigation, search.
-- Focused default reading mode with optional page thumbnail sidebar.
-- Highlight, underline, selection-bound comment, and free-text annotations.
-- Anchored comment popovers from newly created selected-text comments, underlines, free text, and clicked comment-capable annotations; plain highlights remain standalone.
-- Annotation list sidebar.
-- Optional comments review sidebar with grouping, collapsed filtering, replies, and navigation.
-- Save, Save As, and native macOS sharing with standard PDF annotation writing.
-- `.app` and `.dmg` build scripts.
-- Visual QA screenshots for empty, reading, popover, comments, and dark-mode states.
-
-## Shipped In Version 0.3
-
-- Settings for highlight and comment colors.
-- Higher-contrast default highlights and comments.
-- Standalone highlights that do not open a comment editor.
-- Drag-and-drop PDF opening from the empty app window.
-- Return-to-save and Shift-Return-for-newline comment behavior.
-- Preview-compatible exported comments for selected-text markup.
-- Safer close/open/quit prompts for unsaved annotations and reply drafts.
-- Mac App Store packaging path for `net.akkolli.ihatepdfs`.
-
-## Preparing Version 0.4
-
-- Keep the reader focused on open: sidebars are hidden and the PDF is fit to the available width.
-- Preserve the lightweight annotation workflow: highlight, underline, selected-text comments, free text, replies, search, bookmarks, and native sharing.
-- Remove the experimental Fill & Sign, form-field navigation, and PDF signing implementation from v0.4.
-- Keep the direct-download DMG and per-architecture archives under the release size budget.
-- Release metadata, docs, and packaging names prepared for `0.4.0` build `6`.
+I Hate PDFs is a small native macOS reader and annotation app. The roadmap should stay focused on local PDF review, standards-compatible annotations, and a small bundle.
## Next
@@ -51,3 +20,9 @@
- Optional AI summaries or question prompts.
- iPad companion app.
- LMS integrations.
+
+## Not Planned
+
+- Accounts, sync, analytics, or cloud PDF upload.
+- Bundled PDF engines or large runtimes when system frameworks are enough.
+- Broad document-management features that pull focus away from reading and annotation.
diff --git a/SECURITY.md b/SECURITY.md
index 59a2499..7d7bf3b 100644
--- a/SECURITY.md
+++ b/SECURITY.md
@@ -10,9 +10,7 @@ Security fixes target the latest public release and the `main` branch.
Do not report security vulnerabilities in public issues.
-Use GitHub private vulnerability reporting if it is enabled for this repository. If it is not enabled, contact the maintainer through the product support page:
-
-
+Use GitHub private vulnerability reporting if it is enabled for this repository. If it is not enabled, contact the maintainer at .
Include:
diff --git a/SUPPORT.md b/SUPPORT.md
deleted file mode 100644
index f75ced1..0000000
--- a/SUPPORT.md
+++ /dev/null
@@ -1,19 +0,0 @@
-# Support
-
-Use the public issue tracker for reproducible bugs, feature requests, and documentation problems:
-
-
-
-Use the product and support page for user support:
-
-
-
-Before opening an issue, include:
-
-- I Hate PDFs version and build number
-- macOS version
-- Whether the app came from GitHub releases or the Mac App Store
-- A short description of the PDF workflow involved
-- Screenshots or recordings for UI problems, each under 1 MB
-
-Do not open public issues for security vulnerabilities. Follow `SECURITY.md`.
diff --git a/ihatepdf-profile-transparent.png b/assets/app-icon.png
similarity index 100%
rename from ihatepdf-profile-transparent.png
rename to assets/app-icon.png
diff --git a/docs/APP_STORE.md b/docs/APP_STORE.md
deleted file mode 100644
index 85a3a0f..0000000
--- a/docs/APP_STORE.md
+++ /dev/null
@@ -1,60 +0,0 @@
-# Mac App Store Release
-
-Bundle ID: `net.akkolli.ihatepdfs`
-
-Current App Store build values:
-
-- `CFBundleShortVersionString`: `0.4.0`
-- `CFBundleVersion`: `6`
-- Privacy policy URL: `https://www.akkolli.net/ihatepdfs/privacy`
-- Marketing/support URL: `https://www.akkolli.net/ihatepdfs`
-
-Paste-ready metadata, review notes, privacy answers, and screenshot guidance live in `docs/APP_STORE_COPY.md`.
-The general release checklist is in `docs/RELEASE.md`.
-
-## Required Apple Developer Items
-
-- An explicit macOS App ID for `net.akkolli.ihatepdfs`.
-- An App Store provisioning profile for that App ID.
-- An application signing certificate installed in Keychain, usually named `Apple Distribution: ...` or `3rd Party Mac Developer Application: ...`.
-- An installer signing certificate installed in Keychain, usually named `3rd Party Mac Developer Installer: ...`. Apple may label this certificate type as Mac Installer Distribution in the developer portal or Xcode.
-
-The app only needs these sandbox entitlements right now:
-
-- `com.apple.security.app-sandbox`
-- `com.apple.security.files.user-selected.read-write`
-
-Do not add network, Apple Events, Downloads-folder, or bookmark entitlements unless the app gains a feature that requires them.
-
-## Build The Upload Package
-
-Download the App Store provisioning profile from Apple Developer, then run:
-
-```sh
-APP_SIGNING_IDENTITY="3rd Party Mac Developer Application: Your Name (TEAMID)" \
-INSTALLER_SIGNING_IDENTITY="3rd Party Mac Developer Installer: Your Name (TEAMID)" \
-PROVISIONING_PROFILE="$HOME/Downloads/IHatePDFs_AppStore.provisionprofile" \
-scripts/make-app-store-pkg.sh
-```
-
-The package is written to `dist/IHatePDFs-v0.4-macos-appstore.pkg`.
-
-The script derives the App Store application identifier and team identifier from the provisioning profile before signing. It builds the App Store app in a temporary staging directory, so the direct-download `dist/I Hate PDFs.app` remains a clean app bundle without an embedded provisioning profile. It also clears download quarantine metadata from the staged bundle before packaging, because App Store Connect rejects packages that contain quarantine extended attributes.
-
-If macOS opens a Keychain private-key access prompt during `codesign`, approve it, preferably with Always Allow for the selected signing certificate, and rerun the command. The build cannot finish unattended until the private key for the selected application signing certificate is allowed.
-
-Before uploading, verify that the package matches the current build number:
-
-```sh
-REQUIRE_APP_STORE_PKG=1 scripts/verify-release-artifacts.sh
-```
-
-This catches stale package files, bundle-ID mismatches, missing embedded provisioning profiles, missing sandbox/user-selected-file entitlements, and app/package version mismatches.
-
-Use `pkgutil --check-signature` and App Store Connect or Transporter validation for this App Store package. A local `spctl -t install` assessment is a Developer ID distribution check and may reject a package signed with the Mac App Store `3rd Party Mac Developer Installer` identity even when the package signature is valid for App Store upload.
-
-## Upload
-
-Upload the `.pkg` with Transporter. You can also set `VALIDATE_WITH_ALTOOL=1` when running `scripts/make-app-store-pkg.sh` if you want the script to perform an `altool` validation after packaging. After App Store Connect processes the build, select it in the app version, finish metadata, answer App Privacy, fill review notes, and submit for review.
-
-Keep `CFBundleShortVersionString` as `0.4.0` and `CFBundleVersion` as `6` for the next upload. Increment `BUILD_NUMBER` in `scripts/release-version.sh` before uploading another build for the same version.
diff --git a/docs/APP_STORE_COPY.md b/docs/APP_STORE_COPY.md
deleted file mode 100644
index b5126b3..0000000
--- a/docs/APP_STORE_COPY.md
+++ /dev/null
@@ -1,97 +0,0 @@
-# App Store Copy
-
-Use this as the source of truth when filling out App Store Connect for `net.akkolli.ihatepdfs`.
-
-## URLs
-
-- Marketing URL: `https://www.akkolli.net/ihatepdfs`
-- Support URL: `https://www.akkolli.net/ihatepdfs`
-- Privacy Policy URL: `https://www.akkolli.net/ihatepdfs/privacy`
-
-## Copyright
-
-`2026 Akshay Kolli`
-
-## App Information
-
-- Name: `I Hate PDFs`
-- Subtitle: `A small PDF review app`
-- Category: `Productivity`
-- Secondary category: `Education`
-
-## Promotional Text
-
-Read, highlight, comment, and review local PDFs without accounts, cloud upload, or heavyweight document management.
-
-## Description
-
-I Hate PDFs is a small native macOS app for reading and reviewing local PDF files.
-
-Open a PDF, highlight important text, add comments, write free-text notes, and review everything from a compact comments sidebar. The app writes standard PDF annotations so your saved files can be opened in common PDF readers like Preview and Adobe Acrobat.
-
-The app is intentionally lightweight. It uses native macOS document behavior, keeps your PDFs on your Mac, and does not require an account.
-
-Features:
-
-- Open local PDF files from disk, Finder, drag and drop, or recent documents.
-- Read with native PDFKit scrolling, zoom, fit-to-width, fit-to-page, page navigation, and search.
-- Highlight selected text without opening an unnecessary comment box.
-- Add selected-text comments, underline comments, and free-text notes.
-- Press Return to save comments and Shift-Return to insert a new line.
-- Review annotations in a comments sidebar with search, filters, replies, edit, delete, and click-to-navigate.
-- Customize highlight and comment colors from Settings.
-- Save annotations directly into a PDF after an overwrite warning, or use Save As for a separate annotated copy.
-- Share the saved PDF through the native macOS share sheet.
-
-Privacy:
-
-I Hate PDFs does not collect analytics, does not require sign-in, and does not upload your documents. Your PDFs stay on your Mac unless you choose to share them.
-
-## Keywords
-
-pdf,reader,annotate,highlight,comments,review,professor,academic,documents,notes
-
-## What's New
-
-Keeps the app focused on fast local PDF reading and annotation, with recent PDFs, focused open behavior, sidebar polish, bookmarks, highlight sorting, and Settings for annotation colors.
-
-## App Review Notes
-
-I Hate PDFs is a local macOS PDF reader and annotation utility.
-
-No account is required. The reviewer can test with any local `.pdf` file. The app asks for user-selected file access only when opening, saving, or sharing a PDF.
-
-Suggested review path:
-
-1. Launch the app.
-2. Open or drag in any PDF.
-3. Select text and add a highlight or comment.
-4. Open the comments sidebar to review annotations.
-5. Save As to create an annotated copy.
-6. Open Settings with Command-, or File > Settings... to change annotation colors.
-7. Open Bookmarks and Highlights from the sidebar controls to verify the review views.
-
-## App Privacy Answers
-
-Recommended App Privacy summary:
-
-- Data collection: no data collected.
-- Tracking: no tracking.
-- Third-party advertising: no.
-- User account required: no.
-
-The app works with user-selected local PDF files. It does not transmit documents to a server and does not include analytics.
-
-## Screenshot Checklist
-
-Use real bitmap screenshots, not drawn SVG mockups.
-
-Required minimum set:
-
-- Empty window with the Open PDF action and compact Recent PDFs area.
-- Main reading view with a PDF page dominant.
-- Highlight or comment editor popover on selected text.
-- Comments sidebar with several annotations and at least one reply.
-- Settings window showing color controls.
-
-Capture light-mode screenshots first. Add dark-mode screenshots if they make the product quality clearer.
diff --git a/docs/DESIGN_REVIEW.md b/docs/DESIGN_REVIEW.md
deleted file mode 100644
index 5064a05..0000000
--- a/docs/DESIGN_REVIEW.md
+++ /dev/null
@@ -1,39 +0,0 @@
-# macOS Design Review
-
-This review checks the current app against Apple's Human Interface Guidelines before a public release.
-
-References:
-
-- Apple HIG overview: https://developer.apple.com/design/human-interface-guidelines
-- Designing for macOS: https://developer.apple.com/design/human-interface-guidelines/designing-for-macos
-- Toolbars: https://developer.apple.com/design/human-interface-guidelines/toolbars
-- Sidebars: https://developer.apple.com/design/human-interface-guidelines/sidebars
-- Menus and the menu bar: https://developer.apple.com/design/human-interface-guidelines/menus and https://developer.apple.com/design/human-interface-guidelines/the-menu-bar
-- Color: https://developer.apple.com/design/human-interface-guidelines/color
-- Typography: https://developer.apple.com/design/human-interface-guidelines/typography
-
-## Result
-
-Status: Pass for the current version 1 implementation direction, with manual visual QA still required on physical Intel and Apple Silicon Macs before a tagged release.
-
-## Checks
-
-- Platform fit: The app is macOS-only, targets macOS 13 or newer, uses SwiftUI/AppKit/PDFKit, and ships as a normal `.app` bundle inside a `.dmg`.
-- Window and toolbar: Primary document controls live in the titlebar toolbar, grouped by opening/sharing, navigation, zoom, annotation, search, and saving.
-- Menus and shortcuts: File, View, and Annotate commands are available through native command menus with standard keyboard shortcuts where appropriate.
-- Sidebars: Page thumbnails, annotation list, and comments review are optional sidebars. The default open-PDF state is single-pane reading, and sidebars open only when requested.
-- Responsive layout: Compact windows use a compact toolbar/status treatment and keep sidebars mutually exclusive; regular and wide windows can show both sidebars while preserving a usable PDF reading width.
-- Comments review: The comments sidebar uses a compact review-stream layout with a visible total count, add-comment affordance, collapsible page groups, hidden search/filter controls, and connected reply threads.
-- Color and appearance: The UI uses system colors and materials, so light mode, dark mode, and automatic appearance inherit from macOS.
-- Typography: Text uses system fonts and native SwiftUI controls; no custom brand typography is used in the reading interface.
-- Reading focus: The PDF view remains the central, quiet surface; controls are compact and document-oriented.
-- Accessibility basics: Native controls supply focus states and keyboard access; colors use system palettes with restrained highlight/note colors.
-- Academic workflow: The open, select, highlight, comment, continue reading, save, and share path is available without accounts, sync, projects, or conversion.
-
-## Release QA Still Required
-
-- Run the app on both Apple Silicon and Intel hardware.
-- Verify contrast and focus states in light and dark mode.
-- Verify toolbar and sidebar behavior at compact, regular, and wide window sizes.
-- Verify keyboard-only operation for opening, searching, navigating, annotating, saving, and reviewing comments.
-- Verify VoiceOver labels for toolbar buttons and sidebar controls.
diff --git a/docs/ENGINEERING.md b/docs/ENGINEERING.md
deleted file mode 100644
index 3c6b92f..0000000
--- a/docs/ENGINEERING.md
+++ /dev/null
@@ -1,72 +0,0 @@
-# Engineering Principles
-
-I Hate PDFs is intentionally a small native macOS app. Future work should preserve that constraint unless there is a documented, user-visible reason to do otherwise.
-
-## Native First
-
-- Build features with Swift, SwiftUI, AppKit, PDFKit, and other system frameworks that ship with macOS.
-- Do not replace the app with Electron, Chromium, a web runtime, a bundled JavaScript app shell, or a cross-platform UI toolkit.
-- Do not bundle a PDF renderer, OCR engine, database, scripting runtime, or large framework when a macOS system API can satisfy the requirement.
-- Prefer native macOS controls and document behaviors over custom reimplementations when they meet the product need.
-
-## Small By Default
-
-Every change should aim for the smallest final app that still delivers the required fluidity, reliability, and functionality.
-
-- Keep third-party dependencies at or near zero. Any new package must justify its shipped size, runtime cost, maintenance cost, and why system APIs are insufficient.
-- Keep assets minimal. Avoid large raster images, fonts, sample PDFs, videos, model files, or generated resources in the app bundle.
-- Keep build outputs out of source and releases unless they are intentional release artifacts.
-- Prefer dynamic links to Apple system frameworks over vendored libraries.
-- Avoid storing duplicate PDF data, rendered page caches, or annotation indexes unless profiling shows they are required for fluid interaction.
-- Favor targeted updates over whole-document rescans for common interactions such as editing, replying, filtering, hovering, and sidebar refreshes.
-
-## Size Budget
-
-The release DMG should stay as small as practical. Treat size growth as a product regression, not just a packaging detail.
-
-Hard release-size budget: each direct-download per-architecture installer must be under 400 KB, measured as fewer than 400,000 bytes. Universal builds may be larger, but they do not satisfy the small-download budget. Run `scripts/make-tiny-archives.sh` before release; it builds and checks `IHatePDFs-v-macos-arm64.tar.xz` and `IHatePDFs-v-macos-x86_64.tar.xz` by default.
-
-Before merging release-impacting work, compare:
-
-```sh
-scripts/build-app.sh
-scripts/make-dmg.sh
-du -sh "dist/I Hate PDFs.app" \
- "dist/I Hate PDFs.app/Contents/MacOS/IHatePDFs" \
- "dist/I Hate PDFs.app/Contents/Resources/AppIcon.icns" \
- dist/IHatePDFs-v*-macos.dmg
-```
-
-If a change materially increases the app bundle or DMG size, document why in the PR or commit notes. A useful rule of thumb: any dependency addition, bundled asset addition, or release-size increase above roughly 10% needs explicit justification.
-
-## Performance Budget
-
-Small size should not come at the expense of reader fluidity.
-
-- Opening, scrolling, zooming, searching, annotating, saving, and sidebar navigation should remain responsive on long PDFs.
-- Optimize around measured user workflows instead of speculative micro-optimizations.
-- Keep expensive work page-scoped or lazy when possible.
-- Use `swift test` plus the PDF verification scripts after behavior changes:
-
-```sh
-swift test
-swift scripts/verify-sample-pdf.swift
-swift scripts/verify-pdf-annotations.swift
-```
-
-## Release Packaging
-
-Release builds should use the existing lightweight packaging path:
-
-```sh
-scripts/build-app.sh
-scripts/make-dmg.sh
-```
-
-`scripts/build-app.sh` strips release binaries by default to reduce shipped size. Use `STRIP_RELEASE=0 scripts/build-app.sh` only when a symbol-rich release build is needed for debugging.
-
-Universal `arm64` + `x86_64` builds are the default for public releases. Single-architecture builds are acceptable for local testing:
-
-```sh
-ARCHS="" scripts/build-app.sh
-```
diff --git a/docs/FUNCTIONALITY_AUDIT.md b/docs/FUNCTIONALITY_AUDIT.md
deleted file mode 100644
index 8949be6..0000000
--- a/docs/FUNCTIONALITY_AUDIT.md
+++ /dev/null
@@ -1,35 +0,0 @@
-# Functionality Audit
-
-Date: 2026-06-29
-
-## Current Build Scope
-
-I Hate PDFs v0.4 is a small native macOS PDF reader and annotation app. The shipping scope is:
-
-- Local PDF opening, recent documents, drag/drop, close-current-PDF, and focused reader startup.
-- PDFKit reading, page navigation, zoom, fit controls, search, and responsive sidebars.
-- Highlights, underline comments, selected-text comments, free text, replies, review state, filters, grouped comments, bookmarks, and highlight sorting.
-- Settings for highlight and comment colors.
-- Save, Save As, native Share, overwrite warnings, unsent reply-draft warnings, and empty temporary annotation cleanup.
-- Lightweight release packaging with `.app`, `.dmg`, tiny per-architecture archives, and App Store package scripts.
-
-## Removed Scope
-
-The experimental Fill & Sign and PDF signing work has been removed from source, tests, scripts, settings, menus, and release docs for v0.4. This includes custom flat fill marks, form-field scanning/navigation, form choice editing, Keychain-backed PDF signing, signature validation/inspection, and signed-document save branching.
-
-## Verification
-
-Run before release:
-
-```sh
-swift build
-swift test
-swift scripts/verify-sample-pdf.swift
-swift scripts/verify-pdf-annotations.swift
-scripts/build-app.sh
-scripts/make-dmg.sh
-scripts/make-tiny-archives.sh
-scripts/verify-release-artifacts.sh
-```
-
-Manual QA remains documented in `docs/QA.md`.
diff --git a/docs/QA.md b/docs/QA.md
index 85fb9be..9715cd1 100644
--- a/docs/QA.md
+++ b/docs/QA.md
@@ -2,6 +2,18 @@
Run this checklist before tagging a public release.
+## Workflow Contract
+
+Use this section as the source of truth when checking whether a feature matches the product workflow before changing or releasing it.
+
+- Opened PDFs intentionally reset to focused single-pane reading with sidebars hidden.
+- Plain Highlight is standalone.
+- Selected-text Comment and Underline open the anchored editor.
+- The visible Save toolbar icon is intentionally absent. Save remains available from the File menu and keyboard shortcut; Share remains visible.
+- Compact windows intentionally make left and right sidebars mutually exclusive to preserve usable PDF width.
+- Sidebar resize handles should be easy to grab through hover/cursor affordance without becoming large visual dividers.
+- Experimental Fill & Sign, custom form-field navigation, PDF signing, signature inspection, and related QA are outside v0.4 scope.
+
## Latest v0.4 Automated QA Run
Completed on 2026-06-29:
@@ -12,7 +24,6 @@ Completed on 2026-06-29:
Before release, also run:
```sh
-swift scripts/verify-sample-pdf.swift
swift scripts/verify-pdf-annotations.swift
swift build -c release --product IHatePDFs
scripts/build-app.sh
@@ -64,15 +75,24 @@ Use at least:
29. Start typing a sidebar reply without sending it, then close, replace, save, or share the PDF and verify the app warns before omitting or discarding the draft.
30. Create a new selected-text comment or free text, leave its popover empty, choose Save or Share, and verify the temporary empty annotation is discarded.
+## Regression Coverage
+
+- Focused reading layout after opening a PDF.
+- Returning to the empty-window workflow after closing a PDF.
+- Compact one-sidebar-at-a-time behavior.
+- Page sidebar toggle closing the active Marks sidebar instead of switching to Pages first.
+- Right-sidebar toolbar toggle closing and reopening the current right mode without switching tabs.
+- Regular-width ability to show navigation and review sidebars together.
+- Save availability for clean, dirty, and reply-draft-only states.
+
## External Readers
Before manual reader checks, run the automated PDF structure checks:
```sh
-swift scripts/verify-sample-pdf.swift
swift scripts/verify-pdf-annotations.swift
```
-These checks generate an annotated PDF, reopen it with PDFKit, and inspect raw PDF annotation dictionaries for standard `/Highlight`, `/Underline`, `/Text`, `/FreeText`, `/Contents`, `/QuadPoints`, `/IRT`, `/RT`, and `/Parent` entries.
+This check generates an annotated PDF, reopens it with PDFKit, and inspects raw PDF annotation dictionaries for standard `/Highlight`, `/Underline`, `/Text`, `/FreeText`, `/Contents`, `/QuadPoints`, `/IRT`, `/RT`, and `/Parent` entries.
For Preview, Acrobat Reader, and browser PDF viewers, verify exported markup comments keep their comment text on the parent annotation's standard `/Contents` key and do not depend on PDFKit-generated `/Popup` links for highlights or underlines.
diff --git a/docs/RELEASE.md b/docs/RELEASE.md
index 56216e8..2b8e777 100644
--- a/docs/RELEASE.md
+++ b/docs/RELEASE.md
@@ -23,7 +23,6 @@ Run these before tagging or uploading:
```sh
swift test
-swift scripts/verify-sample-pdf.swift
swift scripts/verify-pdf-annotations.swift
scripts/build-app.sh
BUILD_APP=0 scripts/make-dmg.sh
@@ -34,13 +33,6 @@ scripts/verify-release-artifacts.sh
`scripts/make-tiny-archives.sh` builds per-architecture direct-download archives and
fails if either archive is `>= 400,000` bytes.
-For signature changes, also run:
-
-```sh
-USE_TEMP_SIGNING_KEYCHAIN=1 scripts/verify-pdf-signatures.sh
-scripts/prepare-acrobat-qa.sh
-```
-
Finish the manual reader checks in `docs/QA.md` before public distribution.
## Direct Download
@@ -57,12 +49,39 @@ pollute source control.
## App Store
-Use `docs/APP_STORE.md` for signing identities, provisioning profile setup, and the
-upload package command. After building the App Store package, run:
+Bundle ID: `net.akkolli.ihatepdfs`
+
+Project website: `https://www.akkolli.net/ihatepdfs`
+
+Support email: `akshaykolli@hotmail.com`
+
+Required Apple Developer items:
+
+- Explicit macOS App ID for `net.akkolli.ihatepdfs`.
+- App Store provisioning profile for that App ID.
+- Application signing certificate installed in Keychain.
+- Installer signing certificate installed in Keychain.
+
+The app only needs these sandbox entitlements right now:
+
+- `com.apple.security.app-sandbox`
+- `com.apple.security.files.user-selected.read-write`
+
+Do not add network, Apple Events, Downloads-folder, or bookmark entitlements unless a shipped feature requires them.
+
+Build the upload package:
+
+```sh
+APP_SIGNING_IDENTITY="3rd Party Mac Developer Application: Your Name (TEAMID)" \
+INSTALLER_SIGNING_IDENTITY="3rd Party Mac Developer Installer: Your Name (TEAMID)" \
+PROVISIONING_PROFILE="$HOME/Downloads/IHatePDFs_AppStore.provisionprofile" \
+scripts/make-app-store-pkg.sh
+```
+
+After building the App Store package, run:
```sh
REQUIRE_APP_STORE_PKG=1 scripts/verify-release-artifacts.sh
```
-Do not change App Store entitlements unless a shipped feature requires the new
-capability.
+Upload the `.pkg` with Transporter or App Store Connect tooling. Keep `APP_VERSION` and `BUILD_NUMBER` in `scripts/release-version.sh` aligned with App Store Connect before submitting.
diff --git a/docs/WORKFLOW_AUDIT.md b/docs/WORKFLOW_AUDIT.md
deleted file mode 100644
index 325ea63..0000000
--- a/docs/WORKFLOW_AUDIT.md
+++ /dev/null
@@ -1,53 +0,0 @@
-# Workflow Audit
-
-Date: 2026-06-29
-
-This file records the intended v0.4 user flow. It is the source of truth when checking whether a feature matches the product workflow before changing or releasing it.
-
-## Current Capabilities
-
-1. Open local PDFs from an open panel, drag/drop, recent documents, and file URLs.
-2. Start each opened PDF in focused reading: sidebars hidden, PDF fit to available width, previous document sidebar state ignored.
-3. Read with PDFKit scrolling, page navigation, zoom, fit width, fit page, two-page continuous view, and search.
-4. Use a responsive layout across compact, regular, and wide Mac windows.
-5. Use the left sidebar for page thumbnails and annotation marks.
-6. Use the right sidebar for Comments, Highlights, and Bookmarks; the right-sidebar toolbar button is a visibility toggle for the active right mode.
-7. Highlight selected text, use highlighter mode, and choose highlight colors.
-8. Add selected-text comments, underline comments, and free-text annotations.
-9. Use PDF-view shortcuts `H`, `U`, and `C` without conflicting with Command-C.
-10. Edit/delete annotations and comment threads through anchored popovers and sidebar controls.
-11. Review comments with search, filters, page grouping, collapsed groups, review state, replies, hover highlighting, edit/delete, and navigation.
-12. Review highlights sorted by color or page.
-13. Add, remove, and navigate per-document bookmarks.
-14. Configure highlight and comment colors in Settings.
-15. Save, Save As, Share, warn for unsent reply drafts, discard empty temporary editors, and warn before overwriting originals.
-16. Package a small native app through the release scripts, DMG script, tiny archive script, and App Store package script.
-
-## Removed From v0.4
-
-The experimental Fill & Sign, custom form-field navigation, form choice popover, PDF signing, signature inspection, signed-document save safeguards, signature QA scripts, and related tests were removed from v0.4. Revisit that work later as a smaller design from scratch.
-
-## Workflow Decisions
-
-- Opened PDFs intentionally reset to focused single-pane reading with sidebars hidden. Opening a PDF should maximize the reading area and leave comments, highlights, bookmarks, page thumbnails, and annotation marks closed until the user asks for them.
-- Plain Highlight is standalone. Selected-text Comment and Underline open the anchored editor.
-- The visible Save toolbar icon is intentionally absent. Save remains available from the File menu and keyboard shortcut; Share remains visible.
-- Compact windows intentionally make left and right sidebars mutually exclusive to preserve usable PDF width.
-- Sidebar resize handles should be easy to grab through hover/cursor affordance without becoming large visual dividers.
-
-## Regression Coverage
-
-- Focused reading layout after opening a PDF.
-- Returning to the empty-window workflow after closing a PDF.
-- Compact one-sidebar-at-a-time behavior.
-- Page sidebar toggle closing the active Marks sidebar instead of switching to Pages first.
-- Right-sidebar toolbar toggle closing and reopening the current right mode without switching tabs.
-- Regular-width ability to show navigation and review sidebars together.
-- Save availability for clean, dirty, and reply-draft-only states.
-
-## Manual QA Gaps
-
-- Real Finder drag/drop, menu disabled states, visual Settings interaction, alert button flows, native share picker, popover text focus, and sidebar resize affordances need UI automation or manual QA.
-- Preview, Acrobat Reader, and browser PDF-viewer checks remain external interoperability gates even though raw PDF structure checks exist.
-- Cross-reader reply-thread display is not fully proven because PDFKit public APIs do not provide reliable object-valued `/IRT` writing. Primary annotation comments remain standard `/Contents`.
-- Screenshot docs still need recapture before public marketing or release use.
diff --git a/docs/screenshots/comments-sidebar.png b/docs/screenshots/comments-sidebar.png
deleted file mode 100644
index e1006cfb6dc59a2d9c717bb31b3dc4f4b9a0e3e5..0000000000000000000000000000000000000000
GIT binary patch
literal 0
HcmV?d00001
literal 531586
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