From 16a1c68a777d50d3e4d54ff95bf660f4479bd6cf Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Fri, 27 Feb 2026 23:58:10 +0000 Subject: [PATCH 1/3] Initial plan From 08ab479070488d66cefdbee6c0385f26964d3d7f Mon Sep 17 00:00:00 2001 From: "copilot-swe-agent[bot]" <198982749+Copilot@users.noreply.github.com> Date: Sat, 28 Feb 2026 00:02:54 +0000 Subject: [PATCH 2/3] =?UTF-8?q?=F0=9F=A7=AD=20Atlas:=20Fix=20CI/CD=20docs?= =?UTF-8?q?=20drift=20and=20add=20drift-prevention=20script?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Fix wrong UI test command in workflows README (pixel7Api34DebugAndroidTest -> pixel7Api34StagingDebugAndroidTest) - Fix wrong artifact output names (debug-artifact-name -> test-artifact-name, release-artifact-name -> prod-release-artifact-name) - Fix wrong package path (com/btreemap/letterbox -> org/joefang/letterbox) - Update test file listing from 3 to all 11 actual test files - Add missing rust/letterbox-proxy and docs/ to README repo layout - Fix Cargo.toml description to mention both workspace members - Add scripts/check-doc-drift.sh for drift prevention - Add .jules/atlas.md journal Co-authored-by: MinecraftFuns <25814618+MinecraftFuns@users.noreply.github.com> --- .github/workflows/README.md | 18 +++-- .jules/atlas.md | 9 +++ README.md | 4 +- scripts/check-doc-drift.sh | 139 ++++++++++++++++++++++++++++++++++++ 4 files changed, 164 insertions(+), 6 deletions(-) create mode 100644 .jules/atlas.md create mode 100755 scripts/check-doc-drift.sh diff --git a/.github/workflows/README.md b/.github/workflows/README.md index 1dbdf82..2848084 100644 --- a/.github/workflows/README.md +++ b/.github/workflows/README.md @@ -13,11 +13,11 @@ This directory contains the CI/CD workflows for the Letterbox project. The workf **Jobs:** - **lint-and-test**: Runs Rust format checks, Rust tests, Android lint, and Android unit tests -- **build**: Builds debug and release APKs with native libraries for all architectures +- **build**: Builds staging debug and prod release APKs with native libraries for all architectures **Outputs:** -- `debug-artifact-name`: Name of the uploaded debug APK artifact -- `release-artifact-name`: Name of the uploaded release APK artifact +- `test-artifact-name`: Name of the uploaded staging debug APK artifact +- `prod-release-artifact-name`: Name of the uploaded prod release (unsigned) APK artifact ### 2. `android-ui.yml` - Android UI Tests **Trigger:** On completion of the Build workflow (via `workflow_run`). @@ -120,13 +120,21 @@ The `android-ui.yml` workflow runs instrumented tests using Gradle Managed Devic ```bash # Run UI tests locally -./gradlew pixel7Api34DebugAndroidTest +./gradlew pixel7Api34StagingDebugAndroidTest ``` -Test files are located in `app/src/androidTest/java/com/btreemap/letterbox/`: +Test files are located in `app/src/androidTest/java/org/joefang/letterbox/`: - `HomeScreenTest.kt` - Core UI element tests - `NavigationTest.kt` - Navigation flow tests +- `BackNavigationTest.kt` - Back navigation behavior tests - `AccessibilityTest.kt` - Accessibility compliance tests +- `EmailDetailScreenTest.kt` - Email detail screen tests +- `EmailOpeningE2ETest.kt` - End-to-end email opening tests +- `AttachmentInteractionE2ETest.kt` - Attachment interaction tests +- `HistoryFeaturesE2ETest.kt` - History feature tests +- `LinkHandlingE2ETest.kt` - Link handling tests +- `CloudflareTermsConsentE2ETest.kt` - Cloudflare consent flow tests +- `ImageProxyIntegrationTest.kt` - Image proxy integration tests ## Artifact Retention Policies diff --git a/.jules/atlas.md b/.jules/atlas.md new file mode 100644 index 0000000..9da2001 --- /dev/null +++ b/.jules/atlas.md @@ -0,0 +1,9 @@ +# Atlas Journal — Critical Learnings + +## 2026-02-27 - Package path mismatch pattern +**Learning:** The Android package is `org.joefang.letterbox` (see `app/build.gradle.kts` applicationId), but the GitHub org is `BTreeMap`. Documentation that references file paths may use the wrong package path (e.g., `com/btreemap/letterbox` instead of `org/joefang/letterbox`). Always verify package paths against the actual `applicationId` in `build.gradle.kts`. +**Action:** When auditing docs that reference Java/Kotlin file paths, cross-check against `applicationId` in `app/build.gradle.kts` and the actual directory structure. + +## 2026-02-27 - Cargo workspace has two crates, not one +**Learning:** The Cargo workspace includes both `rust/letterbox-core` and `rust/letterbox-proxy`. Documentation and CI both build/test these independently. Any doc claiming to describe the Rust workspace should mention both crates. +**Action:** When auditing Rust-related docs, verify all workspace members from `Cargo.toml` are mentioned. diff --git a/README.md b/README.md index bd502be..d9999bb 100644 --- a/README.md +++ b/README.md @@ -24,8 +24,10 @@ Letterbox is an Android application built with Jetpack Compose that opens and in - `app/`: Android application module, Compose UI, Room data layer, UniFFI bindings, and Gradle tasks to build native artifacts. - `rust/letterbox-core/`: Rust library that parses emails with `mail-parser` and exposes UniFFI bindings for Kotlin/Android. +- `rust/letterbox-proxy/`: Rust library implementing a privacy-preserving image proxy using Cloudflare WARP. +- `docs/`: Project documentation (architecture, troubleshooting, versioning, signing, and more). - `gradle/`, `build.gradle.kts`, `settings.gradle.kts`: Gradle wrapper and version catalog configuration for the Android project. -- `Cargo.toml`: Rust workspace definition pointing to `rust/letterbox-core`. +- `Cargo.toml`: Rust workspace definition for `rust/letterbox-core` and `rust/letterbox-proxy`. - `LICENSE`: MIT license for the project. ## Quickstart diff --git a/scripts/check-doc-drift.sh b/scripts/check-doc-drift.sh new file mode 100755 index 0000000..620dc29 --- /dev/null +++ b/scripts/check-doc-drift.sh @@ -0,0 +1,139 @@ +#!/usr/bin/env bash +# check-doc-drift.sh — Detect documentation drift for key CI/workflow claims. +# +# Usage: ./scripts/check-doc-drift.sh +# +# Exits 0 if all checks pass, 1 if any drift is detected. +# Run this locally or in CI to prevent docs from silently going stale. + +set -euo pipefail + +REPO_ROOT="$(cd "$(dirname "$0")/.." && pwd)" +WORKFLOWS_README="$REPO_ROOT/.github/workflows/README.md" +ROOT_README="$REPO_ROOT/README.md" +BUILD_YML="$REPO_ROOT/.github/workflows/build.yml" +UI_YML="$REPO_ROOT/.github/workflows/android-ui.yml" +CARGO_TOML="$REPO_ROOT/Cargo.toml" +ANDROID_TEST_DIR="$REPO_ROOT/app/src/androidTest/java/org/joefang/letterbox" + +ERRORS=0 + +fail() { + echo "❌ DRIFT: $1" + ERRORS=$((ERRORS + 1)) +} + +pass() { + echo "✅ $1" +} + +echo "=== Documentation Drift Check ===" +echo "" + +# --- 1. Workflow output names in workflows README must match build.yml --- +echo "--- Checking build.yml output names in workflows README ---" + +# Extract output keys from build.yml (under workflow_call.outputs) +BUILD_OUTPUTS=$(grep -E '^\s{6}\w.*:$' "$BUILD_YML" | sed -n '/outputs:/,/^[^ ]/p' | grep -oP '^\s+\K\S+(?=:)' 2>/dev/null || true) +# Simpler: just check the two known output names exist +for output_name in "test-artifact-name" "prod-release-artifact-name"; do + if grep -qF "$output_name" "$BUILD_YML" && grep -qF "$output_name" "$WORKFLOWS_README"; then + pass "Workflow output '$output_name' found in both build.yml and workflows README" + elif ! grep -qF "$output_name" "$BUILD_YML"; then + fail "Workflow output '$output_name' referenced in README but not in build.yml" + else + fail "Workflow output '$output_name' exists in build.yml but missing from workflows README" + fi +done + +# Check for stale output names that no longer exist in build.yml +# Use word-boundary-aware matching to avoid false positives from substrings +for stale_name in "debug-artifact-name" "release-artifact-name"; do + # Match the stale name as a standalone backtick-delimited identifier (e.g. `debug-artifact-name`) + if grep -qP '(? Date: Sat, 28 Feb 2026 00:03:55 +0000 Subject: [PATCH 3/3] Address code review: remove unused variable, fix variable shadowing, clean up dead code Co-authored-by: MinecraftFuns <25814618+MinecraftFuns@users.noreply.github.com> --- scripts/check-doc-drift.sh | 13 ++++--------- 1 file changed, 4 insertions(+), 9 deletions(-) diff --git a/scripts/check-doc-drift.sh b/scripts/check-doc-drift.sh index 620dc29..235c20a 100755 --- a/scripts/check-doc-drift.sh +++ b/scripts/check-doc-drift.sh @@ -33,9 +33,6 @@ echo "" # --- 1. Workflow output names in workflows README must match build.yml --- echo "--- Checking build.yml output names in workflows README ---" -# Extract output keys from build.yml (under workflow_call.outputs) -BUILD_OUTPUTS=$(grep -E '^\s{6}\w.*:$' "$BUILD_YML" | sed -n '/outputs:/,/^[^ ]/p' | grep -oP '^\s+\K\S+(?=:)' 2>/dev/null || true) -# Simpler: just check the two known output names exist for output_name in "test-artifact-name" "prod-release-artifact-name"; do if grep -qF "$output_name" "$BUILD_YML" && grep -qF "$output_name" "$WORKFLOWS_README"; then pass "Workflow output '$output_name' found in both build.yml and workflows README" @@ -97,14 +94,12 @@ echo "" echo "--- Checking androidTest file listing ---" if [ -d "$ANDROID_TEST_DIR" ]; then - MISSING_FILES=0 for kt_file in "$ANDROID_TEST_DIR"/*.kt; do - basename=$(basename "$kt_file") - if grep -qF "$basename" "$WORKFLOWS_README"; then - pass "Test file '$basename' listed in workflows README" + kt_filename=$(basename "$kt_file") + if grep -qF "$kt_filename" "$WORKFLOWS_README"; then + pass "Test file '$kt_filename' listed in workflows README" else - fail "Test file '$basename' exists but is not listed in workflows README" - MISSING_FILES=$((MISSING_FILES + 1)) + fail "Test file '$kt_filename' exists but is not listed in workflows README" fi done fi