Files
Gotcha/AGENTS.md
2026-07-31 16:44:16 +02:00

6.5 KiB

Repository instructions

Gitea issue workflow

Use this repository's gotcha CLI to list, inspect, create, update, comment on, and close Gitea issues. Run it from the repository root so the configured Git remote selects the server and repository:

cargo run -q -p gotcha-cli -- issue list
cargo run -q -p gotcha-cli -- issue list --milestones "first feature complete release"
cargo run -q -p gotcha-cli -- issue show 7
cargo run -q -p gotcha-cli -- issue comment 7 < comment.txt
cargo run -q -p gotcha-cli -- issue close 7

Use gotcha issue list --help for state, kind, keyword, label, milestone, author, assignee, mention, date, and pagination filters. Grant network access before invoking commands that contact Gitea in a sandboxed runner.

Required pre-commit gates

Run every gate below from the repository root before committing. Every command must succeed; do not commit code that is unformatted, fails Clippy, or compiles with warnings.

cargo fmt --all -- --check
RUSTFLAGS="-D warnings" cargo check --workspace --all-targets
cargo clippy --workspace --all-targets -- -D warnings
cargo test --workspace

Do not weaken or skip these gates to make a commit pass. Fix the underlying warning, lint, formatting issue, or test failure.

Gitea, app, CLI, and Swift ownership boundary

gotcha_gitea owns Gitea networking and authentication plus the behavior of Gitea objects: validation, pagination, name-to-ID resolution, mutations, ownership checks, object relationships, activity targets, commit graphs, and diff parsing. The app and CLI must not import generated Gitea API modules or build generated-client configurations. Add a concrete Client operation to gotcha_gitea instead. Generated response models may cross the boundary when a frontend only needs to present their fields; the CLI's explicit api request command is the sole low-level escape hatch.

crates/app owns application state, persistence, preferences, favorites, content classification, navigation targets, and view-ready UniFFI records. The CLI owns argument and YAML parsing plus terminal formatting. Do not duplicate Gitea object transformations or relationship handling in either frontend.

Swift is the native iOS presentation layer. Limit ios/Sources to UIKit and SwiftUI lifecycle, view-controller navigation, native controls, layout, drawing, fonts, colors, symbols, accessibility, task cancellation tied to view lifetime, and Apple presentation integrations such as Quick Look. Swift may map Rust-provided states to visual treatments and maintain transient control state; it must not infer domain state from display strings, duplicate Rust transformations, classify content, or implement persistence and API behavior.

When changing iOS functionality:

  • Trace the complete flow before editing and implement Gitea behavior in gotcha_gitea and app behavior in crates/app first.
  • Prefer view-ready Rust records over exposing raw Gitea models or rebuilding titles, summaries, selections, progress, and categories in Swift.
  • Treat a pure Swift helper that does not require an Apple UI framework as a boundary warning; move it to Rust unless it only calculates view geometry.
  • Regenerate and commit the UniFFI Swift and C bindings whenever the exported Rust interface changes.
  • During review, inspect both sides of the bridge and reject new business logic added to Swift merely because its caller is a view controller.

UI verification conventions

TESTING.md is the source of truth for iOS visual verification and the release regression suite.

  • Update TESTING.md in the same commit whenever UI appearance, behavior, navigation, or interaction changes so its scenarios remain current.
  • For each ordinary commit, run every TESTING.md scenario relevant to the changed UI in addition to the required pre-commit gates. Report which visual scenarios were exercised.
  • When asked to perform a release test, run the complete TESTING.md checklist. Every scenario must succeed before reporting release sign-off; record failures and resolve release blockers instead of skipping them.

iOS simulator build and deployment

This Apple Silicon project builds the simulator app for arm64. Do not disable code signing: the Rust build script consumes Xcode's generated simulator entitlement paths. Do not request an x86_64 simulator build unless the x86_64-apple-ios Rust target has explicitly been installed.

Use this sequence from the repository root:

cd ios
xcodegen generate

xcodebuild \
  -project Gotcha.xcodeproj \
  -scheme Gotcha \
  -configuration Debug \
  -sdk iphonesimulator \
  -destination 'platform=iOS Simulator,name=iPhone 17 Pro' \
  ARCHS=arm64 \
  ONLY_ACTIVE_ARCH=YES \
  build

gotcha_build_dir="$(
  xcodebuild \
    -project Gotcha.xcodeproj \
    -scheme Gotcha \
    -configuration Debug \
    -sdk iphonesimulator \
    -destination 'platform=iOS Simulator,name=iPhone 17 Pro' \
    -showBuildSettings -json \
    ARCHS=arm64 \
    ONLY_ACTIVE_ARCH=YES |
  plutil -extract 0.buildSettings.TARGET_BUILD_DIR raw -o - -
)"
xcrun simctl install booted "$gotcha_build_dir/Gotcha.app"
xcrun simctl launch booted de.rfc1437.gotcha

Before deploying, check for a booted simulator with xcrun simctl list devices available. If none is booted, boot an available iPhone (currently xcrun simctl boot "iPhone 17 Pro") and open Simulator. CoreSimulator access may require running xcodebuild and simctl outside the workspace sandbox.

Post-issue release deployment

After an issue is verified, committed, pushed, commented on, and closed, deploy the completed version according to the code it changes:

  • For CLI changes, build gotcha-cli in release mode and install the resulting gotcha executable in ~/.local/bin/ so the command is available on PATH.
  • For iOS app changes, install the completed app on the currently paired iPhone.
  • The Gitea crate is shared by the CLI and iOS app, so changes to that crate also require installing the completed app on the paired iPhone.

A purely CLI change does not require an iPhone deployment. If an issue changes both release surfaces, perform both deployments.

Generated build data

Use Xcode's default DerivedData location; do not pass -derivedDataPath. Cargo's ignored target/ directory is a disposable build cache. Cargo does not bound or garbage-collect stale target artifacts, so check it with du -sh target and run cargo clean when disk space is worth a full rebuild. Do not add a custom cache-pruning tool or disable incremental compilation just to reduce routine cache usage.