Skip to content

Add native C ABI mobench backend#31

Closed
dcbuild3r wants to merge 69 commits into
mainfrom
codex/native-c-abi-backend
Closed

Add native C ABI mobench backend#31
dcbuild3r wants to merge 69 commits into
mainfrom
codex/native-c-abi-backend

Conversation

@dcbuild3r
Copy link
Copy Markdown
Collaborator

@dcbuild3r dcbuild3r commented May 14, 2026

Summary

  • add a backend-aware mobench config with ffi_backend = "native-c-abi"
  • add the mobench-sdk native JSON C ABI export macro and generated Android/iOS native runners
  • make Android/iOS builders skip UniFFI for native backend and package native headers
  • bump workspace crates to v0.1.41 for release prep

Verification

  • cargo clippy --all-targets -- -D warnings
  • cargo test --all --no-fail-fast
  • cargo test -p mobench-sdk native_backend_runner_template -- --nocapture
  • ProveKit PR430 local iOS release build, IPA package, XCUITest package, and Android release APK build via this branch

Crates.io publish is still blocked locally by missing CARGO_REGISTRY_TOKEN.

tfe-app Bot and others added 30 commits December 4, 2025 11:51
…fetch, Android logging, iOS UI tests, and docs (#2)

* initial commit

* Fix Android UniFFI integration and benchmark display

This commit resolves multiple issues preventing the Android app from
loading the Rust native library and correctly displaying benchmark results.

Changes implemented:

1. Added JNA dependency (android/app/build.gradle)
   - Added net.java.dev.jna:jna:5.14.0@aar dependency
   - Required for UniFFI's Kotlin bindings to interface with native code
   - Also added NDK version specification and benchmark spec asset directories

2. Fixed library naming mismatch (crates/sample-fns/Cargo.toml)
   - Set explicit lib name = "sample_fns" (not uniffi_sample_fns)
   - Changed crate-type to ["lib", "cdylib", "staticlib"] for UniFFI
   - Added UniFFI dependencies and build configuration
   - Migrated from JNI to UniFFI for cleaner FFI bindings

3. Updated sync script for library renaming (scripts/sync-android-libs.sh)
   - Added TARGET_LIB_NAME variable to rename .so during copy
   - Rust builds libsample_fns.so but JNA expects libuniffi_sample_fns.so
   - Script now copies and renames: libsample_fns.so -> libuniffi_sample_fns.so
   - Ensures FFI symbol prefixes match UniFFI expectations

4. Updated Android MainActivity (android/app/src/main/java/dev/world/bench/MainActivity.kt)
   - Changed System.loadLibrary("sample_fns") to System.loadLibrary("uniffi_sample_fns")
   - Migrated from JNI to UniFFI-generated Kotlin bindings
   - Updated benchmark display to show microseconds (μs) instead of milliseconds
   - Added raw nanosecond display alongside formatted values
   - Improved error handling with UniFFI's BenchException variants
   - Added support for loading benchmark specs from assets (bench_spec.json)

Root cause analysis:
- UniFFI generates Kotlin bindings that expect library name "uniffi_<namespace>"
- The namespace from sample_fns.udl is "sample_fns"
- JNA looks for libuniffi_sample_fns.so based on this naming convention
- Rust builds libsample_fns.so by default (from crate name)
- Solution: Keep Rust lib name simple, rename during Android integration

Benchmark display fix:
- Functions execute in 0-42 nanoseconds (extremely fast)
- Previous millisecond display showed "0.000 ms" for all samples
- Now displays in microseconds with raw nanosecond values for clarity
- Example: "0.042 μs (42 ns)" instead of "0.000 ms"

Testing:
- App builds successfully with ./gradlew :app:assembleDebug
- Native library loads without UnsatisfiedLinkError
- Benchmarks execute and display timing results correctly
- Fibonacci(24) averages ~17 nanoseconds per iteration on ARM64

* Android: log benchmark JSON and fix test matcher

* iOS: add UI test target and accessibility id

* bench-cli: add BrowserStack fetch and artifact download

* Commit remaining workspace changes

* Ignore generated build artifacts

* gitignore: exclude CLI-generated artifacts

- Add run-summary.json (benchmark run results)
- Add bench-config.toml (user configuration template)
- Add device-matrix.yaml (device matrix template)

These files are generated by bench-cli and should not be tracked in git.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* iOS: standardize time units to microseconds

Change benchmark result display from milliseconds (ms) to microseconds (μs)
to match Android's output format. This provides better granularity for
typical function benchmarks and makes cross-platform comparison easier.

Before: 0.045 ms
After:  45.320 μs (45320 ns)

Also add raw nanosecond values in parentheses to match Android formatting.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* bench-cli: add comprehensive BrowserStack client tests

Add 11 new tests covering:
- Client initialization and configuration
- URL construction and path handling
- Input validation for schedule/upload methods
- Error cases for missing artifacts
- Both Espresso (Android) and XCUITest (iOS) code paths

Also suppress dead_code warning for test-only with_base_url helper.

Test coverage increased from 1 to 12 tests for browserstack.rs module.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

---------

Co-authored-by: dcbuilder.eth <dcbuilder@protonmail.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>
….1.5) (#4)

* Initial commit

* Add .github/workflows/relyance-sci.yml

* initial commit

* Fix Android UniFFI integration and benchmark display

This commit resolves multiple issues preventing the Android app from
loading the Rust native library and correctly displaying benchmark results.

Changes implemented:

1. Added JNA dependency (android/app/build.gradle)
   - Added net.java.dev.jna:jna:5.14.0@aar dependency
   - Required for UniFFI's Kotlin bindings to interface with native code
   - Also added NDK version specification and benchmark spec asset directories

2. Fixed library naming mismatch (crates/sample-fns/Cargo.toml)
   - Set explicit lib name = "sample_fns" (not uniffi_sample_fns)
   - Changed crate-type to ["lib", "cdylib", "staticlib"] for UniFFI
   - Added UniFFI dependencies and build configuration
   - Migrated from JNI to UniFFI for cleaner FFI bindings

3. Updated sync script for library renaming (scripts/sync-android-libs.sh)
   - Added TARGET_LIB_NAME variable to rename .so during copy
   - Rust builds libsample_fns.so but JNA expects libuniffi_sample_fns.so
   - Script now copies and renames: libsample_fns.so -> libuniffi_sample_fns.so
   - Ensures FFI symbol prefixes match UniFFI expectations

4. Updated Android MainActivity (android/app/src/main/java/dev/world/bench/MainActivity.kt)
   - Changed System.loadLibrary("sample_fns") to System.loadLibrary("uniffi_sample_fns")
   - Migrated from JNI to UniFFI-generated Kotlin bindings
   - Updated benchmark display to show microseconds (μs) instead of milliseconds
   - Added raw nanosecond display alongside formatted values
   - Improved error handling with UniFFI's BenchException variants
   - Added support for loading benchmark specs from assets (bench_spec.json)

Root cause analysis:
- UniFFI generates Kotlin bindings that expect library name "uniffi_<namespace>"
- The namespace from sample_fns.udl is "sample_fns"
- JNA looks for libuniffi_sample_fns.so based on this naming convention
- Rust builds libsample_fns.so by default (from crate name)
- Solution: Keep Rust lib name simple, rename during Android integration

Benchmark display fix:
- Functions execute in 0-42 nanoseconds (extremely fast)
- Previous millisecond display showed "0.000 ms" for all samples
- Now displays in microseconds with raw nanosecond values for clarity
- Example: "0.042 μs (42 ns)" instead of "0.000 ms"

Testing:
- App builds successfully with ./gradlew :app:assembleDebug
- Native library loads without UnsatisfiedLinkError
- Benchmarks execute and display timing results correctly
- Fibonacci(24) averages ~17 nanoseconds per iteration on ARM64

* Android: log benchmark JSON and fix test matcher

* iOS: add UI test target and accessibility id

* bench-cli: add BrowserStack fetch and artifact download

* Commit remaining workspace changes

* Ignore generated build artifacts

* gitignore: exclude CLI-generated artifacts

- Add run-summary.json (benchmark run results)
- Add bench-config.toml (user configuration template)
- Add device-matrix.yaml (device matrix template)

These files are generated by bench-cli and should not be tracked in git.

* iOS: standardize time units to microseconds

Change benchmark result display from milliseconds (ms) to microseconds (μs)
to match Android's output format. This provides better granularity for
typical function benchmarks and makes cross-platform comparison easier.

Before: 0.045 ms
After:  45.320 μs (45320 ns)

Also add raw nanosecond values in parentheses to match Android formatting.

* bench-cli: add comprehensive BrowserStack client tests

Add 11 new tests covering:
- Client initialization and configuration
- URL construction and path handling
- Input validation for schedule/upload methods
- Error cases for missing artifacts
- Both Espresso (Android) and XCUITest (iOS) code paths

Also suppress dead_code warning for test-only with_base_url helper.

Test coverage increased from 1 to 12 tests for browserstack.rs module.

* Migrate from UniFFI UDL to proc macros

Replace manual UDL file with proc macro attributes for better developer
experience and single source of truth in Rust code.

## Changes

### sample-fns crate:
- Add `#[derive(uniffi::Record)]` to BenchSpec, BenchSample, BenchReport
- Add `#[derive(uniffi::Error)]` with `#[uniffi(flat_error)]` to BenchError
- Add `#[uniffi::export]` to run_benchmark function
- Add `uniffi::setup_scaffolding!()` macro to generate scaffolding
- Remove UDL file (sample_fns.udl)
- Update Cargo.toml: enable uniffi "cli" feature
- Update build.rs: remove UDL scaffolding generation (now proc macro-based)
- Update generate-bindings.rs: use library_mode instead of UDL-based generation

### Generated bindings:
- Kotlin bindings regenerated from proc macros
- Swift bindings regenerated from proc macros
- FFI interface remains identical (no breaking changes)

## Benefits

1. **Single source of truth**: Rust code is the only place to define types
2. **Better IDE support**: Type checking and autocomplete in Rust
3. **Automatic sync**: No manual UDL maintenance required
4. **Improved DevEx**: Attributes are inline with type definitions
5. **Type safety**: Compiler enforces FFI boundaries

## Migration notes

- UniFFI 0.28 supports both UDL and proc macros
- Generated bindings are functionally identical
- All tests pass (22 tests)
- CLI demo verified working
- Android/iOS apps use same generated bindings

* docs: update for proc macros and dual workflows

Update documentation to reflect:
1. UniFFI proc macros (no UDL file needed)
2. Two distinct workflows: Local Development vs BrowserStack

## README.md Changes

- Add "Testing Workflows" section with clear separation
- Update UniFFI section for proc macro mode with examples
- Add comprehensive BrowserStack workflow section:
  - Android + Espresso step-by-step
  - iOS + XCUITest step-by-step
  - Config file examples
  - BrowserStack features overview
- Reorganize into Local Development vs BrowserStack sections
- Remove outdated UDL references
- Add requirements for both workflows

## CLAUDE.md Changes

- Update Mobile Integration Flow to mention proc macros
- Rewrite FFI Boundary section with proc macro examples
- Update "Adding New Benchmark Functions" workflow
- Remove references to sample_fns.udl
- Add note that no UDL file is needed

These changes make it much clearer for users:
- How to test locally (fast iteration)
- How to test on BrowserStack (real devices)
- How to add new FFI types with proc macros

* initial procmacros

* feat: Phase 1 - Transform mobile-bench-rs into bench-sdk library crate

This commit implements the complete Phase 1 MVP, transforming mobile-bench-rs
from a standalone tool into a library crate (bench-sdk) that can be imported
into any Rust project for mobile benchmarking.

## Core Features

### 1. Proc Macro System (bench-macros)
- Implement #[benchmark] attribute macro for automatic function registration
- Use inventory crate for compile-time collection, runtime discovery
- Generate fully-qualified function names (e.g., my_crate::my_function)

### 2. Core SDK Library (bench-sdk)
- **types.rs**: Core types (BenchError, Target, BuildConfig, BuildProfile, etc.)
- **registry.rs**: Function discovery via inventory::collect!()
  - discover_benchmarks(), find_benchmark(), list_benchmark_names()
- **runner.rs**: Execution engine with BenchmarkBuilder fluent API
- **codegen.rs**: Template generation system
  - Generates bench-mobile FFI wrapper crate with UniFFI
  - Creates Android/iOS project structures
  - Generates config files and examples
- **builders/android.rs**: Complete Android build pipeline
  - cargo-ndk integration for multi-ABI builds
  - JNI library syncing
  - Gradle APK generation
- **builders/ios.rs**: Complete iOS build pipeline
  - Multi-architecture builds (device + simulator)
  - xcframework creation with proper structure
  - Automatic code signing
  - XcodeGen integration

### 3. CLI Integration (bench-cli)
- Refactor to use SDK API as thin wrapper
- Add new commands:
  - init-sdk: Initialize benchmark project with templates
  - build: Build mobile artifacts using SDK builders
  - list: Discover and list all registered benchmarks
- Maintain backward compatibility with existing commands

### 4. Templates (templates/)
- **Android**: Gradle project, MainActivity, Espresso tests, resources
  - Templatized with package name, library name, etc.
  - Complete build.gradle, settings.gradle, AndroidManifest.xml
- **iOS**: XcodeGen project, SwiftUI app, XCUITest tests
  - Templatized with project name, bundle ID, etc.
  - Complete project.yml, Swift files, bridging headers

### 5. Example Project (examples/basic-benchmark)
- Migrate sample-fns to example demonstrating SDK usage
- Use #[benchmark] attributes with registry-based execution
- Full test coverage (6 passing tests)

## Architecture Changes

### Workspace Structure
```
mobile-bench-rs/
├── crates/
│   ├── bench-sdk/        # Core library (NEW, for crates.io)
│   ├── bench-macros/     # Proc macro crate (NEW)
│   ├── bench-cli/        # CLI tool (REFACTORED)
│   ├── bench-runner/     # Timing harness (UNCHANGED)
│   └── sample-fns/       # Legacy (DEPRECATED)
├── examples/
│   └── basic-benchmark/  # SDK example (NEW)
└── templates/            # Mobile app templates (NEW)
    ├── android/
    └── ios/
```

### Public API Surface
```rust
// Proc macro
#[benchmark]
fn my_function() { /* ... */ }

// Discovery
bench_sdk::discover_benchmarks() -> Vec<&BenchFunction>
bench_sdk::find_benchmark(name) -> Option<&BenchFunction>

// Execution
bench_sdk::run_benchmark(spec) -> Result<BenchReport>
BenchmarkBuilder::new(name).iterations(100).run()

// Builders
AndroidBuilder::new(root, crate_name).build(&config)
IosBuilder::new(root, crate_name).build(&config)

// Codegen
generate_project(&InitConfig) -> Result<PathBuf>
```

## Testing

All tests passing (25 total):
- bench-sdk: 12 tests
- basic-benchmark: 6 tests
- sample-fns: 6 tests (legacy)
- bench-runner: 1 test

## Documentation

- Updated README.md with Phase 1 information
- Inline rustdoc comments throughout
- Working example in examples/basic-benchmark
- Updated references in BUILD.md, TESTING.md

## Migration Path

Users can now:
1. Add bench-sdk to Cargo.toml
2. Annotate functions with #[benchmark]
3. Run `cargo bench-sdk init-sdk` to generate project
4. Run `cargo bench-sdk build` to build mobile artifacts
5. Run `cargo bench-sdk list` to discover benchmarks

## Future Work

Phase 1 provides the foundation for:
- Phase 2: Adaptive iterations, warmup detection
- Phase 3: Statistical analysis, baselines
- Phase 4: Full BrowserStack integration
- Phase 5: cargo bench harness, DevEx improvements
- Phase 6: Caching, reproducibility, CI optimization

* feat: wire sdk scaffolding and bindings

- Render Android/iOS templates with project-specific names and link user crate in bench-mobile

- Run UniFFI binding generation in SDK builders and ensure headers are packaged

- Route CLI builds through SDK builders and detect bench-mobile crate name

- Align Android JNI library naming (sample_fns) and update templates/scripts

- Improve binding generation tooling for ABI-aware Android builds

* docs: align build and binding workflow

- Document ABI-aware Android builds with UNIFFI_ANDROID_ABI

- Update binding regeneration steps to use scripts/generate-bindings.sh

- Simplify Android local/testing steps to use build-android-app.sh

* docs: add bench-sdk integration guide

- Add step-by-step setup for dependencies and annotations

- Document local Android/iOS testing workflow

- Document BrowserStack Espresso/XCUITest runs

* docs: expand integration guide

- Add prerequisites and clarify script availability

- Document CLI build path when scripts are absent

- Link guide from README

* docs: link prerequisite downloads

- Add official download links for Rust, Android, JDK, Xcode, and xcodegen

* docs: clarify JDK requirement

- Use vendor-agnostic JDK 17+ wording and OpenJDK link

- Note AGP official support for Java 17

* feat: Rename bench-cli to mobench and add iOS IPA packaging

Major improvements to CLI tooling and iOS workflow:

1. Rename bench-cli → mobench
   - More memorable and concise name (7 chars)
   - Available on crates.io
   - Dual binaries: mobench + cargo-mobench
   - Updated all documentation and references

2. Add iOS IPA packaging with xcodebuild
   - New command: cargo mobench package-ipa
   - SigningMethod enum: AdHoc and Development
   - Ad-hoc signing (no Apple ID needed) for BrowserStack
   - Development signing for physical devices
   - Pure xcodebuild implementation (no fastlane dependency)
   - Automatic ExportOptions.plist generation

3. Eliminate script dependencies for SDK integrators
   - Added prominent warnings in README and integration docs
   - Deprecation notices in all shell scripts
   - CLI-first approach: cargo mobench build replaces ./scripts/
   - Templates embedded in binary, no repo checkout needed

4. Add package metadata
   - Author: Dominik Clemente - dcbuilder.eth <dc@world.org>
   - Added to mobench, bench-sdk, and bench-macros
   - Repository links and keywords for crates.io

All changes tested and verified:
- 25 tests passing
- cargo mobench --help shows all commands
- package-ipa supports both adhoc and development methods
- Documentation updated across all files

* refactor: Rename bench-sdk → mobench-sdk and bench-macros → mobench-macros

Complete branding consistency across all packages:

1. Crate renames:
   - bench-sdk → mobench-sdk
   - bench-macros → mobench-macros

2. Updated all references:
   - Package names in Cargo.toml files
   - Workspace member names
   - Dependency declarations
   - Import statements (bench_sdk → mobench_sdk)
   - Documentation and code examples
   - CLI help messages

3. All tests passing (25 tests)
   - mobench-sdk: 12 tests
   - sample-fns: 6 tests
   - basic-benchmark: 6 tests
   - mobench CLI verified

Now all three publishable packages have consistent branding:
- mobench (CLI)
- mobench-sdk (core library)
- mobench-macros (proc macros)

* feat: Add metadata to bench-runner for crates.io publication

* fix: Add version requirements to path dependencies in mobench-sdk

* fix: Update repository URLs to worldcoin org and include templates in mobench-sdk package

* fix: Include templates directory in mobench-sdk crate for crates.io packaging

* chore: prepare mobench for crates.io publication

- Update repository URL to worldcoin organization
- Add version requirements to published dependencies (mobench-sdk, bench-runner)

* chore: make sample-fns dependency optional for publishing

- Add 'demo' feature flag for sample-fns dependency
- Feature-gate Demo command to only work when demo feature is enabled
- Users can install with: cargo install mobench --features demo

This allows mobench to be published without requiring sample-fns
(which is not published to crates.io).

* chore: remove Demo command for crates.io publication

- Demo command was only useful for development/testing
- Requires unpublished sample-fns crate
- Move sample-fns to dev-dependencies only
- Published CLI focuses on core functionality

* docs: add BrowserStack test run results and manual test script

Completed test runs on BrowserStack:
- ✅ Android Espresso test PASSED on Pixel 7 (50s duration)
- ⚠️  iOS XCUITest encountered packaging/parsing issues

Build artifacts created:
- Android APK (9.5 MB) + test APK
- iOS IPA (284 KB) + test suite (5.6 MB)

The Android integration is fully functional. iOS XCUITest requires
additional work on test runner packaging to meet BrowserStack's
parsing requirements.

Added test_browserstack.sh for manual BrowserStack API testing,
bypassing CLI's benchmark registry validation.

* refactor: rename bench-runner to mobench-runner for consistency

- Renamed crates/bench-runner to crates/mobench-runner
- Updated package name from bench-runner to mobench-runner
- Updated all imports from bench_runner to mobench_runner
- Updated workspace and all dependent crates:
  - mobench-sdk
  - mobench CLI
  - sample-fns
  - examples/basic-benchmark

This aligns the runner crate naming with the mobench ecosystem
(mobench, mobench-sdk, mobench-macros, mobench-runner).

Preparing for republication to crates.io.

* chore: bump version to 0.1.1 for republication

Updated workspace version to 0.1.1 after:
- Publishing mobench-runner v0.1.0 (new package)
- Republishing mobench-sdk v0.1.1 (updated dependency)
- Republishing mobench v0.1.1 (updated dependency)

All packages now use mobench-runner instead of bench-runner.

* docs: add comprehensive READMEs to all packages for crates.io

Added detailed README files to all packages:

- mobench-runner: Explains timing harness, shows basic usage examples
- mobench-macros: Documents #[benchmark] attribute, macro expansion
- mobench-sdk: Comprehensive SDK guide with examples and architecture
- mobench: Complete CLI documentation with all commands and workflows

Each README includes:
- Feature overview
- Installation instructions
- Usage examples
- API documentation
- Best practices
- Integration with other packages
- Requirements and troubleshooting

Updated Cargo.toml files to include readme = "README.md" field
for proper display on crates.io package pages.

Bumped version to 0.1.2 for republication with documentation.

* chore: add MIT license and update all package licenses

- Added LICENSE.md with MIT license under World Foundation (2026)
- Updated all READMEs to reference MIT license only
- Changed workspace license from 'MIT OR Apache-2.0' to 'MIT'
- Updated license sections in all 4 package READMEs:
  - mobench-runner
  - mobench-macros
  - mobench-sdk
  - mobench
- Bumped version to 0.1.3 for republication

Copyright (c) 2026 World Foundation

* chore: reset version to 0.1.0 for fresh release

Yanked all previous versions (0.1.0-0.1.3) from crates.io.
Starting fresh with proper:
- MIT license under World Foundation (2026)
- Comprehensive READMEs for all packages
- Consistent naming (mobench-runner instead of bench-runner)

This is the canonical first release.

* chore: use version 0.1.4 as canonical first release

Cannot reuse version 0.1.0 even after yanking.
Version 0.1.4 will be the canonical first release with:
- MIT license under World Foundation (2026)
- Comprehensive READMEs
- Proper naming (mobench-runner)

Versions 0.1.0-0.1.3 are yanked.

* docs: update CLAUDE.md to reflect SDK-first architecture and crates.io publication

- Update project overview with published packages (v0.1.4)
- Document recommended cargo mobench build workflow
- Mark scripts/ as legacy for repository development only
- Add SDK integration examples and Quick Start
- Reorganize file structure documentation
- Add template system documentation

* fix: address GitHub Advanced Security and Codex review findings

1. Add explicit workflow permissions (contents: read)
   - Addresses GitHub Advanced Security CodeQL warnings
   - Limits GITHUB_TOKEN permissions to read-only for CI workflow
   - Reduces security risk by following principle of least privilege

2. Fix local smoke test for user benchmarks
   - Only run local smoke test for sample_fns::* functions
   - Skip gracefully for user-defined benchmarks
   - Prevents 'unknown benchmark function' errors
   - User benchmarks aren't linked into CLI binary (will run on device)
   - Addresses Codex P1 review finding

Note: Skipped iOS certificate pinning (Semgrep finding) as the app
does not make network requests. Can be revisited if needed later.

* mobench: support repository structure and fix iOS IPA packaging

Updates CLI and SDK to work seamlessly with both SDK projects (bench-mobile/)
and repository structure (crates/sample-fns/), enabling full end-to-end testing
using only mobench commands.

Changes:

- AndroidBuilder/IosBuilder: Add find_crate_dir() to detect benchmark crate
  in multiple locations (bench-mobile/ or crates/{crate_name}/)

- UniFFI binding generation: Make optional, use pre-existing bindings if
  available, only require uniffi-bindgen CLI for fresh generation

- iOS IPA packaging: Complete rewrite from xcodebuild archive to simpler
  xcodebuild build approach, with ad-hoc signing support for BrowserStack
  testing (no Apple Developer account needed)

- BrowserStack XCUITest: Add only-testing parameter support to specify
  test methods (required by BrowserStack API)

- iOS project: Add schemes configuration to project.yml for proper
  xcodebuild support

Verified working:
- cargo mobench build --target android
- cargo mobench build --target ios
- cargo mobench package-ipa --method adhoc
- cargo mobench run (both Android and iOS on BrowserStack)

* mobench: add --fetch flag for CI-ready result retrieval

Implements automatic polling and result fetching for BrowserStack runs,
making the CLI fully CI-ready with one-command benchmark execution.

BrowserStack Client API:
- poll_build_completion(): Wait for build to finish with configurable timeout
- get_espresso_build_status() / get_xcuitest_build_status(): Check build status
- get_device_logs(): Fetch logs from specific device sessions
- extract_benchmark_results(): Parse benchmark JSON from logs
- wait_and_fetch_results(): Complete workflow (poll + fetch + extract)

CLI Integration:
- --fetch flag on 'run' command triggers automatic result fetching
- Merges benchmark_results into output JSON (device -> results map)
- Configurable timeout (--fetch-timeout-secs, default: 1800)
- Configurable poll interval (--fetch-poll-interval-secs, default: 10)
- Graceful error handling with warnings (command succeeds even if fetch fails)

Output Format Enhancement:
- RunSummary now includes optional benchmark_results field
- Results organized by device name
- Each device has array of benchmark results with samples, mean, min, max

Testing:
- 8 new comprehensive tests for result extraction and parsing
- Tests for BuildStatus conversion and deserialization
- Tests for JSON extraction from logs (single, multiple, invalid, missing)
- All tests passing (21 total in browserstack module)

Documentation:
- FETCH_RESULTS_GUIDE.md: Complete guide for --fetch usage
- BROWSERSTACK_CI_INTEGRATION.md: Programmatic API reference
- GitHub Actions examples with step summaries
- Error handling patterns and best practices

Example Usage:
  cargo mobench run \
    --target android \
    --function sample_fns::fibonacci \
    --iterations 30 \
    --warmup 5 \
    --devices "Google Pixel 7-13.0" \
    --fetch \
    --output results.json

This release makes mobench fully CI-ready with automatic result retrieval,
eliminating the need for manual log parsing or separate fetch commands.

* gitignore: exclude BrowserStack run artifacts and temp files

* mobench: print dashboard URL and result summary with --fetch

Improves CLI output when using --fetch to show:
- Dashboard URL immediately after scheduling (not just on error)
- Summary of benchmark results for each device
- Mean time in both nanoseconds and milliseconds
- Number of samples collected
- Dashboard URL again after successful fetch for easy access

Example output:
  Waiting for build 88f8c5a... to complete...
  Dashboard: https://app-automate.browserstack.com/dashboard/v2/builds/88f8c5a...

  ✓ Successfully fetched results from 1 device(s)

    Device: Google Pixel 7-13.0
      Benchmark 1: sample_fns::fibonacci
        Mean: 1237000 ns (1.24 ms)
        Samples: 30

    View full results: https://app-automate.browserstack.com/...

Makes CI output more informative and actionable without requiring manual
JSON parsing or URL construction.

* docs: document BrowserStack metrics and performance monitoring

Adds comprehensive documentation on what device metrics BrowserStack
provides and what mobench currently captures.

Key points:
- BrowserStack does NOT provide built-in CPU/memory/battery profiling
- Performance metrics must be collected by your app code
- We currently capture: logs, videos, network traces, screenshots
- We extract: benchmark timing data from logs
- Future enhancement: Extract custom performance metrics from logs

Provides examples for collecting memory/CPU metrics on Android/iOS
and logging them as JSON for extraction.

References BrowserStack API documentation and platform-specific APIs
for memory profiling.

* feat(mobench): add performance metrics extraction (v0.1.5)

- Add performance metrics types (PerformanceSnapshot, MemoryMetrics, CpuMetrics, etc.)
- Implement extract_performance_metrics() to parse memory/CPU data from device logs
- Add wait_and_fetch_all_results() to fetch both benchmark and performance results
- Update RunSummary to include performance_metrics field
- Add comprehensive tests for performance metrics extraction
- Update CLI --fetch to display performance metrics alongside benchmark results
- Update BROWSERSTACK_METRICS.md to reflect new functionality

Performance metrics are automatically extracted when using --fetch flag if the app
logs them in JSON format with memory/cpu fields or type='performance'.

Example output format:
{
  "memory": {"used_mb": 128.5, "max_mb": 512.0},
  "cpu": {"usage_percent": 45.2}
}

* refactor: remove dead code and fix compiler warnings

- Remove unused `wait_and_fetch_results()` from browserstack.rs (superseded by `wait_and_fetch_all_results()`)
- Add `#[cfg(test)]` to `run_local_smoke()` in main.rs
- Remove unused iOS signing methods (`identity()`, `export_method()`, `create_export_options_plist()`)
- Remove unused imports (`std::io::Write`, `BenchSpec`, `run_closure`)
- Add explanatory comment for dual binary targets in Cargo.toml

This cleanup addresses all compiler warnings and removes 117 lines of dead code.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: build Android test APK and harden BrowserStack fetch

---------

Co-authored-by: tfe-app[bot] <200245884+tfe-app[bot]@users.noreply.github.com>
Co-authored-by: wld-terraform <infrastructure@toolsforhumanity.com>
Co-authored-by: dcbuilder.eth <dcbuilder@protonmail.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* Improve mobench fetch and iOS/Android builders

* Chore: align docs with markdownlint

* Refine rust-analyzer diagnostics

* Bump workspace version to 0.1.5

* Docs: refresh mobench testing and CLI guidance

Update docs to reflect current CLI usage, remove host demo references, and clarify local device workflows. Ignore Cursor project files and sync lockfile version entries.

* feat: add run summaries and CI artifacts

Add JSON/Markdown (optional CSV) summaries for mobench runs and wire CI to publish host + BrowserStack results.

* fix test

* feat: add compare reports and device tag filters

Add a mobench compare command plus device tag filtering from matrix configs, and publish benchmark summaries to CI job summaries. Refresh docs to cover compare usage and updated config examples.

* chore: clean up formatting in tests and bindgen

* address minor pr codex comments

* fix: treat BrowserStack passed builds as complete

Update polling to accept passed/completed build statuses and ignore run summary outputs in git. This prevents fetch timeouts after successful runs.

* Docs: align configs, devices, and rustdoc naming

Refresh markdown docs and rustdocs to use current mobench config names, BrowserStack device strings, and API references. Update codegen templates and examples to match mobench-sdk naming.

---------

Co-authored-by: dcbuilder.eth <dcbuilder@protonmail.com>
- split CLI entrypoint into library and cargo-mobench bin
- update workspace manifests and lockfile for crate changes
- rewrite README with current workflow and crate list
Drop the unused bench-cli and bench-runner crates, update docs to reflect the current mobench-runner workflow, and adjust legacy scripts/comments to reference cargo mobench.
Simplify basic-benchmark to only show #[benchmark] usage and add a new ffi-benchmark example that contains the UniFFI types and entrypoint. Update workspace metadata and docs to reflect the new example layout.
Drop the unused UniFFI UDL file for sample-fns and update build script notes to reflect the proc-macro binding generation flow.
Delete deprecated build scripts, switch CI and docs to cargo mobench commands, and refresh integration guidance for the new flow.
Update CLAUDE, BUILD, and mobench-sdk README to remove script references, clarify the builder flow, and document the new examples.
The repo_root() function now walks up the directory tree looking for
marker files instead of relying on the compile-time manifest path.
This fixes cases where the CLI is run from subdirectories.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
Update workspace version and inter-crate dependencies.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
- Add output_dir field to AndroidBuilder and IosBuilder
- Default to {project_root}/target/mobench/ for all mobile artifacts
- Add output_dir() builder method for customization
- Add --output-dir CLI argument to `cargo mobench build`
- Update all path references in builders to use output_dir

This keeps generated mobile artifacts inside target/, following Rust
conventions and preventing accidental commits of Android/iOS project files.
- Update all path references from target/ios/ to target/mobench/ios/
- Update Android paths to target/mobench/android/
- Document --output-dir CLI flag
- Update troubleshooting sections with correct paths
- Add extensive crate-level documentation to all four crates:
  - mobench-sdk: Full SDK docs with examples, architecture, and best practices
  - mobench-macros: #[benchmark] macro documentation with usage examples
  - mobench-runner: Timing harness docs with runnable examples
  - mobench: CLI documentation with command reference

- Document all public types with examples:
  - BenchSpec, BenchSample, BenchReport, BenchError
  - Target, BuildConfig, BuildProfile, BuildResult
  - InitConfig and builder types

- Configure docs.rs metadata in all Cargo.toml files:
  - Add documentation URLs
  - Add maintenance badges
  - Configure rustdoc-args for docs.rs builds

- Add serde_json dev-dependency to mobench-runner for doc tests
This commit implements all 11 developer experience improvements from
IMPROVEMENTS.md, making mobench significantly more user-friendly.

## Key Changes

### P0 - Critical (Tasks 1-3)
- Fix aws-lc-rs Android NDK incompatibility (ring backend)
- Fix workspace target directory detection (cargo metadata)
- Auto-generate project scaffolding during build

### P1 - High Priority (Tasks 4-6)
- Process template variables during build (TemplateContext)
- Improve uniffi-bindgen handling (local binary + fallback)
- Generate error handling code dynamically (generic catch)

### P2 - Medium Priority (Tasks 7-9)
- Add mobench.toml configuration file support
- Improve error messages with actionable suggestions
- Add --crate-path flag for custom crate locations

### P3 - Nice to Have (Tasks 10-11)
- Add --dry-run and --verbose CLI modes
- Auto-generate local.properties for Android

## Code Quality Improvements

- Extract shared utilities to builders/common.rs (DRY)
- Consistent error message formatting with:
  - Clear description of what failed
  - Context (commands, paths, exit status)
  - Actionable fix suggestions
  - Links to documentation
- Standardized path formatting using display()

## New Files
- crates/mobench/src/config.rs - Configuration file support
- crates/mobench-sdk/src/builders/common.rs - Shared utilities
- IMPROVEMENTS.md - Task tracking document

## Consolidation
- Merged mobench-runner crate into mobench-sdk
- Timing functionality now in mobench-sdk/src/timing.rs
The test `ios_requires_artifacts_for_browserstack` was failing because
iOS project scaffolding was not being generated correctly during
auto-build for BrowserStack.

Root causes and fixes:

1. render_dir() was incorrectly joining prefix with file.path(), but
   file.path() from include_dir already returns the full relative path.
   Removed the prefix parameter entirely.

2. project.yml lacked .template extension, so template variables like
   {{PROJECT_NAME_PASCAL}} were not being substituted. Renamed to
   project.yml.template.

3. xcframework path in project.yml.template was wrong (../../target/ios/).
   Fixed to ../{{LIBRARY_NAME}}.xcframework since the iOS project is at
   target/mobench/ios/BenchRunner/.

4. ensure_ios_project now uses fixed "BenchRunner" for PROJECT_NAME_PASCAL
   to match the template directory structure, while deriving LIBRARY_NAME
   from the actual crate name.

All 37 tests now pass.
README updates:
- Document mobench-runner consolidation into mobench-sdk
- Add mobench.toml configuration file documentation
- Document new CLI flags: --dry-run, --verbose, --crate-path
- Update all artifact paths to target/mobench/
- Add examples for new features

Rust doc comments:
- Add comprehensive module docs to builders/{mod,android,ios,common}.rs
- Document build pipelines, requirements, and examples
- Add dry-run mode documentation
- Note mobench-runner consolidation in timing.rs

docs.rs configuration:
- Add targets = ["x86_64-unknown-linux-gnu"] for docs.rs builds
- Add #![cfg_attr(docsrs, feature(doc_cfg))] attributes
- Add crates.io/docs.rs/license badges to crate roots
- Add #[doc(cfg(...))] annotations for feature-gated items
- Update workspace version from 0.1.8 to 0.1.9
- Update mobench-sdk dependency in mobench crate
- Update mobench-macros dependency in mobench-sdk crate
- All mobench-runner versions have been yanked on crates.io
Critical bugs fixed (12):
- Bugs 1-5: Template variables (PROJECT_NAME, PACKAGE_NAME, LIBRARY_NAME,
  PROJECT_NAME_PASCAL, APP_NAME) now properly substituted
- Bug 6: Added gradle.properties template with AndroidX settings
- Bug 7: Auto-generate Gradle wrapper if missing
- Bug 8: Fixed AGP version from 8.13.2 to 8.2.2
- Bug 9: Package name in Kotlin templates now uses {{PACKAGE_NAME}}
- Bug 10: Added x86_64-apple-ios target for Intel Mac simulators
- Bug 11: Fixed path handling by canonicalizing project root
- Bug 12: DEFAULT_FUNCTION now auto-detected from #[benchmark] functions

High severity issues fixed (8):
- Issue 1: Added post-template validation for unreplaced {{...}} patterns
- Issue 2: codesign_xcframework now returns Err on failure
- Issue 3: generate_xcode_project now returns Err on failure
- Issue 4: Missing native libraries always warn (not just verbose)
- Issue 5: Added validate_project_root() for early validation
- Issue 6: cargo metadata fallback now warns when used
- Issue 7: Kotlin catch block logs exceptions instead of swallowing
- Issue 8: Added validate_build_artifacts() post-build validation

Medium/Low issues fixed (4):
- Added .gitignore templates for Android and iOS
- Added README.md templates for Android and iOS

New files:
- templates/android/.gitignore
- templates/android/README.md
- templates/android/gradle.properties
- templates/ios/BenchRunner/.gitignore
- templates/ios/BenchRunner/README.md
- Fix all path references to use target/mobench/ as default output dir
- Update CLAUDE.md version reference to v0.1.9
- Fix PROJECT_PLAN.md to reflect mobench-runner consolidation into mobench-sdk
- Remove dead links to BROWSERSTACK_RUN_2.md (use BROWSERSTACK_METRICS.md)
- Fix all init-sdk references to use correct init command
- Fix duplicate command and step numbering in TESTING.md
- Update iOS artifact paths in BENCH_SDK_INTEGRATION.md
dcbuild3r and others added 21 commits January 19, 2026 22:21
P0 fixes:
- Add testBuildType "release" to build.gradle templates
- Gradle now creates assembleReleaseAndroidTest task

P1 fixes:
- local.properties only uses ANDROID_HOME/ANDROID_SDK_ROOT env vars
- No longer probes filesystem for hardcoded SDK paths
- Kotlin files moved to correct package directory structure

P2 fixes:
- iOS bundle ID now uses app name: dev.world.benchmobile.BenchRunner
- No longer duplicates crate name in bundle ID
Crate detection (P0):
- Check current directory Cargo.toml before nested paths
- Add read_package_name() helper for parsing Cargo.toml
- Search order: current dir → bench-mobile/ → crates/{name}/ → {name}/
- Add 10 new tests for crate detection logic

Error handling improvements:
- Add Log.e() calls for Android exception handlers
- Add print() statements for iOS config parsing failures
- Log config sources (intent, bench_spec.json, default)
- Show warnings when using fallback defaults

Cross-platform consistency:
- Standardize Android package names (remove underscores like iOS)
- Both platforms now use dev.world.benchmobile format
- Standardize version strings to 1.0.0 on both platforms
- Add 3 new consistency tests

Tests added:
- test_find_crate_dir_current_directory_is_crate
- test_find_crate_dir_nested_bench_mobile
- test_find_crate_dir_crates_subdir
- test_find_crate_dir_not_found
- test_find_crate_dir_explicit_crate_path
- test_read_package_name_standard
- test_read_package_name_with_single_quotes
- test_read_package_name_not_found
- test_read_package_name_no_package_section
- test_cross_platform_naming_consistency
- test_cross_platform_version_consistency
- test_bundle_id_prefix_consistency
- Add --release flag to mobench run command for release builds
  (reduces APK size from ~544MB debug to ~133MB release)
- Add mobench package-xcuitest command for iOS BrowserStack testing
- Add output_dir option to package-ipa command
- Update timing display format from μs to ms (or seconds if >=1000ms)
- Auto-package iOS artifacts in release mode when --release is set
- Update Android/iOS apps to display timing in ms (or seconds if >=1000ms)
- Update CLAUDE.md, TESTING.md, README with --release flag examples
- Document package-xcuitest command across all relevant docs
- Add release build recommendations for BrowserStack workflows
iOS XCUITest was exiting in ~2 seconds without capturing benchmark data,
while Android properly waited and extracted full timing reports.

Changes:
- XCUITest now waits up to 5 minutes for benchmark completion (not 2 sec)
- Extract benchmark JSON via accessibility identifiers
- Output JSON with BENCH_REPORT_JSON_START/END markers for log parsing
- Add iOS-specific JSON extraction in fetch logic (handles NSLog prefixes)
- Both Android and iOS now hold the report screen for 5 seconds so
  BrowserStack video recordings capture the benchmark results

Files updated:
- iOS XCUITest template and reference implementation
- iOS ContentView with completion indicators and JSON exposure
- iOS BenchRunnerFFI with JSON report generation
- BrowserStack fetch logic for iOS log parsing
- Android MainActivity with 5-second display hold
- Add --release flag to BrowserStack examples in README.md
- Update mobench-sdk README and rustdocs with --release recommendation
- Update mobench CLI rustdocs with --release flag
- Expand template READMEs with BrowserStack workflow and video capture info
- Document benchmark report capture mechanism (5-second delay, JSON markers)
- Add Info.plist to XCUITest bundle to fix BrowserStack test detection
  BrowserStack requires Info.plist with XCTContainsUITests=true to
  identify and run tests; without it, builds are skipped with
  "no tests detected"

- Add info: section to UITests target in project.yml templates
  with proper bundle identifier (*.uitests suffix)

- Increase XCUITest delay from 0.5s to 5s after benchmark completion
  to ensure BrowserStack video captures the results

- Update initial display text from "Running benchmark..." to
  "Running benchmarks..." for better UX during video recording
Changes in this release:
- Fix iOS XCUITest BrowserStack detection (Info.plist added to UITests target)
- Improve video capture for BrowserStack (5s delay for video evidence)
- Show "Running benchmarks..." text before results appear
- Sync top-level templates with SDK templates
- Various DX fixes
Changed only-testing filter from testLaunchShowsBenchmarkReport to
testLaunchAndCaptureBenchmarkReport to match what BrowserStack parses
from the xctest bundle.
Fix iOS XCUITest test name mismatch with BrowserStack - changed
only-testing filter to use testLaunchAndCaptureBenchmarkReport.
* Refactor mobench layout and refresh README

- split CLI entrypoint into library and cargo-mobench bin
- update workspace manifests and lockfile for crate changes
- rewrite README with current workflow and crate list

* Remove legacy bench-cli crates and update docs

Drop the unused bench-cli and bench-runner crates, update docs to reflect the current mobench-runner workflow, and adjust legacy scripts/comments to reference cargo mobench.

* Split examples into minimal and FFI variants

Simplify basic-benchmark to only show #[benchmark] usage and add a new ffi-benchmark example that contains the UniFFI types and entrypoint. Update workspace metadata and docs to reflect the new example layout.

* Remove legacy sample_fns UDL

Drop the unused UniFFI UDL file for sample-fns and update build script notes to reflect the proc-macro binding generation flow.

* Remove legacy scripts and update docs

Delete deprecated build scripts, switch CI and docs to cargo mobench commands, and refresh integration guidance for the new flow.

* Refresh docs for mobench build flow

Update CLAUDE, BUILD, and mobench-sdk README to remove script references, clarify the builder flow, and document the new examples.

---------

Co-authored-by: dcbuilder.eth <dcbuilder@protonmail.com>
)

* Refactor mobench layout and refresh README

- split CLI entrypoint into library and cargo-mobench bin
- update workspace manifests and lockfile for crate changes
- rewrite README with current workflow and crate list

* Remove legacy bench-cli crates and update docs

Drop the unused bench-cli and bench-runner crates, update docs to reflect the current mobench-runner workflow, and adjust legacy scripts/comments to reference cargo mobench.

* Split examples into minimal and FFI variants

Simplify basic-benchmark to only show #[benchmark] usage and add a new ffi-benchmark example that contains the UniFFI types and entrypoint. Update workspace metadata and docs to reflect the new example layout.

* Remove legacy sample_fns UDL

Drop the unused UniFFI UDL file for sample-fns and update build script notes to reflect the proc-macro binding generation flow.

* Remove legacy scripts and update docs

Delete deprecated build scripts, switch CI and docs to cargo mobench commands, and refresh integration guidance for the new flow.

* Refresh docs for mobench build flow

Update CLAUDE, BUILD, and mobench-sdk README to remove script references, clarify the builder flow, and document the new examples.

* Improve repo root detection with ancestor search

The repo_root() function now walks up the directory tree looking for
marker files instead of relying on the compile-time manifest path.
This fixes cases where the CLI is run from subdirectories.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Bump version to 0.1.7 for release

Update workspace version and inter-crate dependencies.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add commit guidelines to CLAUDE.md

* Output mobile artifacts to target/mobench/ by default

- Add output_dir field to AndroidBuilder and IosBuilder
- Default to {project_root}/target/mobench/ for all mobile artifacts
- Add output_dir() builder method for customization
- Add --output-dir CLI argument to `cargo mobench build`
- Update all path references in builders to use output_dir

This keeps generated mobile artifacts inside target/, following Rust
conventions and preventing accidental commits of Android/iOS project files.

* Update docs for target/mobench/ output directory

- Update all path references from target/ios/ to target/mobench/ios/
- Update Android paths to target/mobench/android/
- Document --output-dir CLI flag
- Update troubleshooting sections with correct paths

* Add comprehensive docs.rs documentation

- Add extensive crate-level documentation to all four crates:
  - mobench-sdk: Full SDK docs with examples, architecture, and best practices
  - mobench-macros: #[benchmark] macro documentation with usage examples
  - mobench-runner: Timing harness docs with runnable examples
  - mobench: CLI documentation with command reference

- Document all public types with examples:
  - BenchSpec, BenchSample, BenchReport, BenchError
  - Target, BuildConfig, BuildProfile, BuildResult
  - InitConfig and builder types

- Configure docs.rs metadata in all Cargo.toml files:
  - Add documentation URLs
  - Add maintenance badges
  - Configure rustdoc-args for docs.rs builds

- Add serde_json dev-dependency to mobench-runner for doc tests

* Bump version to 0.1.8 for release

* Implement all IMPROVEMENTS.md tasks with enhanced DX

This commit implements all 11 developer experience improvements from
IMPROVEMENTS.md, making mobench significantly more user-friendly.

## Key Changes

### P0 - Critical (Tasks 1-3)
- Fix aws-lc-rs Android NDK incompatibility (ring backend)
- Fix workspace target directory detection (cargo metadata)
- Auto-generate project scaffolding during build

### P1 - High Priority (Tasks 4-6)
- Process template variables during build (TemplateContext)
- Improve uniffi-bindgen handling (local binary + fallback)
- Generate error handling code dynamically (generic catch)

### P2 - Medium Priority (Tasks 7-9)
- Add mobench.toml configuration file support
- Improve error messages with actionable suggestions
- Add --crate-path flag for custom crate locations

### P3 - Nice to Have (Tasks 10-11)
- Add --dry-run and --verbose CLI modes
- Auto-generate local.properties for Android

## Code Quality Improvements

- Extract shared utilities to builders/common.rs (DRY)
- Consistent error message formatting with:
  - Clear description of what failed
  - Context (commands, paths, exit status)
  - Actionable fix suggestions
  - Links to documentation
- Standardized path formatting using display()

## New Files
- crates/mobench/src/config.rs - Configuration file support
- crates/mobench-sdk/src/builders/common.rs - Shared utilities
- IMPROVEMENTS.md - Task tracking document

## Consolidation
- Merged mobench-runner crate into mobench-sdk
- Timing functionality now in mobench-sdk/src/timing.rs

* Fix iOS test failure in auto-build scaffolding

The test `ios_requires_artifacts_for_browserstack` was failing because
iOS project scaffolding was not being generated correctly during
auto-build for BrowserStack.

Root causes and fixes:

1. render_dir() was incorrectly joining prefix with file.path(), but
   file.path() from include_dir already returns the full relative path.
   Removed the prefix parameter entirely.

2. project.yml lacked .template extension, so template variables like
   {{PROJECT_NAME_PASCAL}} were not being substituted. Renamed to
   project.yml.template.

3. xcframework path in project.yml.template was wrong (../../target/ios/).
   Fixed to ../{{LIBRARY_NAME}}.xcframework since the iOS project is at
   target/mobench/ios/BenchRunner/.

4. ensure_ios_project now uses fixed "BenchRunner" for PROJECT_NAME_PASCAL
   to match the template directory structure, while deriving LIBRARY_NAME
   from the actual crate name.

All 37 tests now pass.

* Update documentation for consolidated crates and new features

README updates:
- Document mobench-runner consolidation into mobench-sdk
- Add mobench.toml configuration file documentation
- Document new CLI flags: --dry-run, --verbose, --crate-path
- Update all artifact paths to target/mobench/
- Add examples for new features

Rust doc comments:
- Add comprehensive module docs to builders/{mod,android,ios,common}.rs
- Document build pipelines, requirements, and examples
- Add dry-run mode documentation
- Note mobench-runner consolidation in timing.rs

docs.rs configuration:
- Add targets = ["x86_64-unknown-linux-gnu"] for docs.rs builds
- Add #![cfg_attr(docsrs, feature(doc_cfg))] attributes
- Add crates.io/docs.rs/license badges to crate roots
- Add #[doc(cfg(...))] annotations for feature-gated items

* Bump version to 0.1.9 for release

- Update workspace version from 0.1.8 to 0.1.9
- Update mobench-sdk dependency in mobench crate
- Update mobench-macros dependency in mobench-sdk crate
- All mobench-runner versions have been yanked on crates.io

* Remove IMPROVEMENTS.md after completing all tasks

* Fix all DX issues from mobench 0.1.9 testing

Critical bugs fixed (12):
- Bugs 1-5: Template variables (PROJECT_NAME, PACKAGE_NAME, LIBRARY_NAME,
  PROJECT_NAME_PASCAL, APP_NAME) now properly substituted
- Bug 6: Added gradle.properties template with AndroidX settings
- Bug 7: Auto-generate Gradle wrapper if missing
- Bug 8: Fixed AGP version from 8.13.2 to 8.2.2
- Bug 9: Package name in Kotlin templates now uses {{PACKAGE_NAME}}
- Bug 10: Added x86_64-apple-ios target for Intel Mac simulators
- Bug 11: Fixed path handling by canonicalizing project root
- Bug 12: DEFAULT_FUNCTION now auto-detected from #[benchmark] functions

High severity issues fixed (8):
- Issue 1: Added post-template validation for unreplaced {{...}} patterns
- Issue 2: codesign_xcframework now returns Err on failure
- Issue 3: generate_xcode_project now returns Err on failure
- Issue 4: Missing native libraries always warn (not just verbose)
- Issue 5: Added validate_project_root() for early validation
- Issue 6: cargo metadata fallback now warns when used
- Issue 7: Kotlin catch block logs exceptions instead of swallowing
- Issue 8: Added validate_build_artifacts() post-build validation

Medium/Low issues fixed (4):
- Added .gitignore templates for Android and iOS
- Added README.md templates for Android and iOS

New files:
- templates/android/.gitignore
- templates/android/README.md
- templates/android/gradle.properties
- templates/ios/BenchRunner/.gitignore
- templates/ios/BenchRunner/README.md

* Update documentation for v0.1.9 and fix inconsistencies

- Fix all path references to use target/mobench/ as default output dir
- Update CLAUDE.md version reference to v0.1.9
- Fix PROJECT_PLAN.md to reflect mobench-runner consolidation into mobench-sdk
- Remove dead links to BROWSERSTACK_RUN_2.md (use BROWSERSTACK_METRICS.md)
- Fix all init-sdk references to use correct init command
- Fix duplicate command and step numbering in TESTING.md
- Update iOS artifact paths in BENCH_SDK_INTEGRATION.md

* Bump version to 0.1.10 for release

* Fix CI workflow paths to use target/mobench/ output directory

* Fix DX issues from 0.1.10 report

Android fixes:
- Add APK detection for both signed and unsigned builds
- Parse output-metadata.json for actual APK filename
- Add proguard-rules.pro template for release builds
- Update .gitignore to exclude jniLibs and uniffi bindings

iOS fixes:
- Sanitize bundle identifiers (remove hyphens/underscores)
- Framework bundle IDs now use alphanumeric chars only
- Add logging for config loading failures
- Update .gitignore to exclude xcodeproj, frameworks, bindings

Config fixes:
- Add logging for missing/invalid JSON keys in templates
- Android MainActivity logs warnings for missing config values
- iOS BenchRunnerFFI prints errors when JSON parsing fails

* Bump version to 0.1.11 for release

* Update CLAUDE.md version reference to 0.1.11

* Fix DX issues from 0.1.11 report

P0 fixes:
- Add testBuildType "release" to build.gradle templates
- Gradle now creates assembleReleaseAndroidTest task

P1 fixes:
- local.properties only uses ANDROID_HOME/ANDROID_SDK_ROOT env vars
- No longer probes filesystem for hardcoded SDK paths
- Kotlin files moved to correct package directory structure

P2 fixes:
- iOS bundle ID now uses app name: dev.world.benchmobile.BenchRunner
- No longer duplicates crate name in bundle ID

* Fix all DX issues from bug reports

Crate detection (P0):
- Check current directory Cargo.toml before nested paths
- Add read_package_name() helper for parsing Cargo.toml
- Search order: current dir → bench-mobile/ → crates/{name}/ → {name}/
- Add 10 new tests for crate detection logic

Error handling improvements:
- Add Log.e() calls for Android exception handlers
- Add print() statements for iOS config parsing failures
- Log config sources (intent, bench_spec.json, default)
- Show warnings when using fallback defaults

Cross-platform consistency:
- Standardize Android package names (remove underscores like iOS)
- Both platforms now use dev.world.benchmobile format
- Standardize version strings to 1.0.0 on both platforms
- Add 3 new consistency tests

Tests added:
- test_find_crate_dir_current_directory_is_crate
- test_find_crate_dir_nested_bench_mobile
- test_find_crate_dir_crates_subdir
- test_find_crate_dir_not_found
- test_find_crate_dir_explicit_crate_path
- test_read_package_name_standard
- test_read_package_name_with_single_quotes
- test_read_package_name_not_found
- test_read_package_name_no_package_section
- test_cross_platform_naming_consistency
- test_cross_platform_version_consistency
- test_bundle_id_prefix_consistency

* Add --release flag and package-xcuitest command

- Add --release flag to mobench run command for release builds
  (reduces APK size from ~544MB debug to ~133MB release)
- Add mobench package-xcuitest command for iOS BrowserStack testing
- Add output_dir option to package-ipa command
- Update timing display format from μs to ms (or seconds if >=1000ms)
- Auto-package iOS artifacts in release mode when --release is set

* Update mobile timing display and documentation

- Update Android/iOS apps to display timing in ms (or seconds if >=1000ms)
- Update CLAUDE.md, TESTING.md, README with --release flag examples
- Document package-xcuitest command across all relevant docs
- Add release build recommendations for BrowserStack workflows

* Fix iOS XCUITest benchmark report gap and add video capture delay

iOS XCUITest was exiting in ~2 seconds without capturing benchmark data,
while Android properly waited and extracted full timing reports.

Changes:
- XCUITest now waits up to 5 minutes for benchmark completion (not 2 sec)
- Extract benchmark JSON via accessibility identifiers
- Output JSON with BENCH_REPORT_JSON_START/END markers for log parsing
- Add iOS-specific JSON extraction in fetch logic (handles NSLog prefixes)
- Both Android and iOS now hold the report screen for 5 seconds so
  BrowserStack video recordings capture the benchmark results

Files updated:
- iOS XCUITest template and reference implementation
- iOS ContentView with completion indicators and JSON exposure
- iOS BenchRunnerFFI with JSON report generation
- BrowserStack fetch logic for iOS log parsing
- Android MainActivity with 5-second display hold

* Sync top-level templates with SDK templates

* Update documentation for --release flag and iOS XCUITest features

- Add --release flag to BrowserStack examples in README.md
- Update mobench-sdk README and rustdocs with --release recommendation
- Update mobench CLI rustdocs with --release flag
- Expand template READMEs with BrowserStack workflow and video capture info
- Document benchmark report capture mechanism (5-second delay, JSON markers)

* Fix iOS XCUITest BrowserStack detection and video capture

- Add Info.plist to XCUITest bundle to fix BrowserStack test detection
  BrowserStack requires Info.plist with XCTContainsUITests=true to
  identify and run tests; without it, builds are skipped with
  "no tests detected"

- Add info: section to UITests target in project.yml templates
  with proper bundle identifier (*.uitests suffix)

- Increase XCUITest delay from 0.5s to 5s after benchmark completion
  to ensure BrowserStack video captures the results

- Update initial display text from "Running benchmark..." to
  "Running benchmarks..." for better UX during video recording

* Remove resolved issue tracking docs

* Remove stale DX report doc

* Bump version to 0.1.12 for release

Changes in this release:
- Fix iOS XCUITest BrowserStack detection (Info.plist added to UITests target)
- Improve video capture for BrowserStack (5s delay for video evidence)
- Show "Running benchmarks..." text before results appear
- Sync top-level templates with SDK templates
- Various DX fixes

* Fix error message hints

* Fix iOS XCUITest test name mismatch with BrowserStack

Changed only-testing filter from testLaunchShowsBenchmarkReport to
testLaunchAndCaptureBenchmarkReport to match what BrowserStack parses
from the xctest bundle.

* Bump version to 0.1.13 for release

Fix iOS XCUITest test name mismatch with BrowserStack - changed
only-testing filter to use testLaunchAndCaptureBenchmarkReport.

* Add DX improvements: verify, summary, devices commands and SDK enhancements

CLI improvements:
- Add `mobench verify` command to validate registry, spec, and artifacts
- Add `mobench summary` command to display benchmark result statistics
- Add `mobench devices` command to list available BrowserStack devices
- Add benchmark function validation before runs with helpful error messages
- Add resolved spec and artifact location output at run start
- Add run completion summary with build IDs and artifact paths

BrowserStack improvements:
- Add device listing APIs for Espresso and XCUITest
- Add device validation with fuzzy matching and suggestions
- Add helpful credential error messages with setup instructions
- Add artifact correlation output (build ID, device, local paths)

SDK improvements:
- Add bench_meta.json with spec, commit hash, build time, and profile
- Add embed_bench_spec() for bundling spec into app assets
- Add UniFFI type templates for easier FFI boundary setup
- Add git info helpers (commit, branch, dirty state detection)

* Add comprehensive DX improvements: check command, macro validation, better errors

SDK Improvements:
- Add compile-time validation to #[benchmark] macro (no params, returns ())
- Add debug_benchmarks!() macro for verifying registration
- Enhance UnknownFunction error to show available benchmarks
- Enhance TimingError::NoIterations to show the actual value
- Add Quick Setup Checklist to lib.rs documentation

CLI Improvements:
- Add `cargo mobench check` command for prerequisite validation
- Add --progress flag for simplified build/run output
- Add build progress feedback with status messages
- Print clear results summary at end of runs

BrowserStack Improvements:
- Improve credential error messages with setup instructions
- Add artifact pre-flight validation before uploads
- Add upload progress indication with file sizes
- Print dashboard link immediately after build starts
- Improve device fuzzy matching with OS version suggestions

* Update all documentation for DX improvements v0.1.14

README.md:
- Add new commands to quick start (check, verify, summary, devices)
- Add --progress flag example
- Add v0.1.14 release notes with all new features

CLAUDE.md:
- Update version to v0.1.14
- Add check command as first build step
- Document --progress flag and verify command
- Add debug_benchmarks!() macro documentation
- Document improved BrowserStack error messages

BUILD.md:
- Add new Prerequisites Check section
- Document cargo mobench check command with examples
- Add --progress flag to build commands

TESTING.md:
- Add prerequisite validation section
- Document verify command in testing workflow
- Add BrowserStack device validation section
- Add summary command for viewing results

BENCH_SDK_INTEGRATION.md:
- Add Quick Setup Checklist section
- Document #[benchmark] macro validation requirements
- Add debug_benchmarks!() macro usage guide
- Add verification and troubleshooting section

FETCH_RESULTS_GUIDE.md:
- Add summary command documentation
- Add result analysis examples with different formats
- Update best practices

BROWSERSTACK_CI_INTEGRATION.md:
- Add pre-flight validation section
- Document devices command with fuzzy matching
- Update GitHub Actions example with validation steps
- Expand troubleshooting with credential error messages

PROJECT_PLAN.md:
- Add completed DX improvements section
- Update roadmap with remaining P2 items

* Add setup/teardown support to #[benchmark] macro

This enables expensive setup to be excluded from benchmark timing:

API:
- #[benchmark] - Simple benchmark (unchanged)
- #[benchmark(setup = fn)] - Setup runs once before iterations
- #[benchmark(setup = fn, per_iteration)] - Setup runs before each iteration
- #[benchmark(setup = fn, teardown = fn)] - Setup + cleanup

Implementation:
- timing.rs: Add run_closure_with_setup(), run_closure_with_setup_per_iter(),
  run_closure_with_setup_teardown() functions
- registry.rs: Change BenchFunction.invoke to BenchFunction.runner for
  direct timing control
- mobench-macros: Parse setup/teardown/per_iteration attributes and
  generate appropriate runner code
- runner.rs: Simplify to delegate to registry runner

Example:
```rust
fn setup_proof() -> ProofInput {
    generate_complex_proof()  // Not measured
}

#[benchmark(setup = setup_proof)]
fn verify_proof(input: &ProofInput) {
    verify(&input.proof);  // Only this is measured
}
```

Tests: 135 passing

* Document setup/teardown feature in README, CLAUDE.md, and integration guide

README.md:
- Add "Setup and Teardown" section with problem/solution examples
- Add v0.1.15 release notes for setup/teardown feature

CLAUDE.md:
- Update version to v0.1.15
- Expand SDK Integration Pattern with setup/teardown examples
- Update macro validation notes

BENCH_SDK_INTEGRATION.md:
- Add comprehensive "Setup and Teardown" section
- Cover one-time setup, per-iteration, and teardown patterns
- Add pattern selection guide table

* Update version references to 0.1.13 and consolidate release notes

- Updated CLAUDE.md version from v0.1.15 to v0.1.13
- Updated feature version markers (v0.1.14+, v0.1.15+) to v0.1.13+
- Consolidated README release notes into single v0.1.13 section
- Fixed documentation for setup/teardown feature
- Published mobench-macros, mobench-sdk, mobench v0.1.13 to crates.io

* Fix documentation issues in BENCH_SDK_INTEGRATION.md

- Remove redundant gradle steps (cargo mobench build handles test APK)
- Add devices command to quick setup checklist for BrowserStack users

* Add device selection guide with tier examples for BrowserStack

- Added section 9 with Android and iOS device tiers (6 tiers each)
- Flagship to Lowest performance tiers with real BrowserStack device specs
- Multi-device benchmarking examples
- Device validation commands
- Renumbered section 10 (Verification and Troubleshooting)

---------

Co-authored-by: dcbuilder.eth <dcbuilder@protonmail.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
…lease 0.1.14) (#10)

* docs: map existing codebase

- STACK.md - Technologies and dependencies
- ARCHITECTURE.md - System design and patterns
- STRUCTURE.md - Directory layout
- CONVENTIONS.md - Code style and patterns
- TESTING.md - Test structure
- INTEGRATIONS.md - External services
- CONCERNS.md - Technical debt and issues

* chore: remove obsolete planning documents

* docs: document iOS auto-packaging behavior with progress messages

Add progress output when mobench auto-packages iOS artifacts for
BrowserStack runs, showing the IPA and XCUITest paths that are generated.

Update CLAUDE.md with a new "Automatic iOS Packaging" section that
explains how users can let mobench automatically package iOS artifacts
instead of manually running package-ipa and package-xcuitest commands.

* fix: add emoji indicators to iOS auto-packaging progress messages

* feat(sdk): add unified ffi module for UniFFI integration

Add a new `ffi` module to mobench-sdk that provides a single import point
for all FFI-related types and traits needed to create UniFFI bindings for
mobile platforms.

The module includes:
- BenchSpecFfi, BenchSampleFfi, BenchReportFfi, BenchErrorFfi types
- IntoFfi and FromFfi conversion traits with blanket implementations
- run_benchmark_ffi convenience function for FFI-ready benchmark execution
- Re-exports from uniffi_types for backwards compatibility
- Comprehensive tests for all type conversions

* feat(cli): add extract_benchmark_summary helper for unified result parsing

* docs: clarify single-command BrowserStack flow in CLI and CLAUDE.md

* test(cli): add init-sdk mobench.toml generation tests

Add test module to verify that init-sdk command properly generates
mobench.toml configuration file with correct project settings including
project name, library name (with hyphens converted to underscores),
and all required configuration sections.

* docs: update examples and integration guide with ffi module usage

- Add comment to ffi-benchmark example about mobench_sdk::ffi module alternative
- Add "Using the FFI Module" section to BENCH_SDK_INTEGRATION.md with:
  - Overview of ffi module types (BenchSpecFfi, BenchReportFfi, etc.)
  - Option 1: Using FFI types directly for simple cases
  - Option 2: Defining custom UniFFI types (recommended for full bindings)

* chore: gitignore docs/plans directory

* feat(sdk): add statistical helpers, black_box and inventory re-exports

- Add BenchReport methods: mean_ns(), median_ns(), std_dev_ns(),
  percentile_ns(), min_ns(), max_ns(), summary()
- Add BenchSummary struct for serializable statistics
- Re-export `inventory` crate so users don't need separate dependency
- Re-export `std::hint::black_box` for preventing compiler optimizations

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* feat(cli): add CI/devex helpers (doctor, ci init, junit, device-matrix)

* perf(ci): improve action caching (gradle/target/android sdk root)

* Improve CI template and doctor env/flag behavior

* feat(ci): add ci run orchestration and local action example

* Fix iOS CI target setup and preserve CI outputs on regression exit

* feat(mobench): implement CI contract phases, fixture/report commands, and migration docs

* fix: address open PR review threads

* docs: align guides with latest CI/action behavior

* docs+sdk: refresh rustdocs, package metadata, and concerns resolution

* chore(release): bump mobench crates to v0.1.14

---------

Co-authored-by: dcbuilder.eth <dcbuilder@protonmail.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>
* Initial commit

* Add .github/workflows/relyance-sci.yml

* Update .github/workflows/relyance-sci.yml

* Update .github/workflows/relyance-sci.yml

* Bootstrap mobile-bench-rs with UniFFI integration, BrowserStack runs/fetch, Android logging, iOS UI tests, and docs (#2)

* initial commit

* Fix Android UniFFI integration and benchmark display

This commit resolves multiple issues preventing the Android app from
loading the Rust native library and correctly displaying benchmark results.

Changes implemented:

1. Added JNA dependency (android/app/build.gradle)
   - Added net.java.dev.jna:jna:5.14.0@aar dependency
   - Required for UniFFI's Kotlin bindings to interface with native code
   - Also added NDK version specification and benchmark spec asset directories

2. Fixed library naming mismatch (crates/sample-fns/Cargo.toml)
   - Set explicit lib name = "sample_fns" (not uniffi_sample_fns)
   - Changed crate-type to ["lib", "cdylib", "staticlib"] for UniFFI
   - Added UniFFI dependencies and build configuration
   - Migrated from JNI to UniFFI for cleaner FFI bindings

3. Updated sync script for library renaming (scripts/sync-android-libs.sh)
   - Added TARGET_LIB_NAME variable to rename .so during copy
   - Rust builds libsample_fns.so but JNA expects libuniffi_sample_fns.so
   - Script now copies and renames: libsample_fns.so -> libuniffi_sample_fns.so
   - Ensures FFI symbol prefixes match UniFFI expectations

4. Updated Android MainActivity (android/app/src/main/java/dev/world/bench/MainActivity.kt)
   - Changed System.loadLibrary("sample_fns") to System.loadLibrary("uniffi_sample_fns")
   - Migrated from JNI to UniFFI-generated Kotlin bindings
   - Updated benchmark display to show microseconds (μs) instead of milliseconds
   - Added raw nanosecond display alongside formatted values
   - Improved error handling with UniFFI's BenchException variants
   - Added support for loading benchmark specs from assets (bench_spec.json)

Root cause analysis:
- UniFFI generates Kotlin bindings that expect library name "uniffi_<namespace>"
- The namespace from sample_fns.udl is "sample_fns"
- JNA looks for libuniffi_sample_fns.so based on this naming convention
- Rust builds libsample_fns.so by default (from crate name)
- Solution: Keep Rust lib name simple, rename during Android integration

Benchmark display fix:
- Functions execute in 0-42 nanoseconds (extremely fast)
- Previous millisecond display showed "0.000 ms" for all samples
- Now displays in microseconds with raw nanosecond values for clarity
- Example: "0.042 μs (42 ns)" instead of "0.000 ms"

Testing:
- App builds successfully with ./gradlew :app:assembleDebug
- Native library loads without UnsatisfiedLinkError
- Benchmarks execute and display timing results correctly
- Fibonacci(24) averages ~17 nanoseconds per iteration on ARM64

* Android: log benchmark JSON and fix test matcher

* iOS: add UI test target and accessibility id

* bench-cli: add BrowserStack fetch and artifact download

* Commit remaining workspace changes

* Ignore generated build artifacts

* gitignore: exclude CLI-generated artifacts

- Add run-summary.json (benchmark run results)
- Add bench-config.toml (user configuration template)
- Add device-matrix.yaml (device matrix template)

These files are generated by bench-cli and should not be tracked in git.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* iOS: standardize time units to microseconds

Change benchmark result display from milliseconds (ms) to microseconds (μs)
to match Android's output format. This provides better granularity for
typical function benchmarks and makes cross-platform comparison easier.

Before: 0.045 ms
After:  45.320 μs (45320 ns)

Also add raw nanosecond values in parentheses to match Android formatting.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

* bench-cli: add comprehensive BrowserStack client tests

Add 11 new tests covering:
- Client initialization and configuration
- URL construction and path handling
- Input validation for schedule/upload methods
- Error cases for missing artifacts
- Both Espresso (Android) and XCUITest (iOS) code paths

Also suppress dead_code warning for test-only with_base_url helper.

Test coverage increased from 1 to 12 tests for browserstack.rs module.

Co-Authored-By: Claude Sonnet 4.5 <noreply@anthropic.com>

---------

Co-authored-by: dcbuilder.eth <dcbuilder@protonmail.com>
Co-authored-by: Claude Sonnet 4.5 <noreply@anthropic.com>

* feat: Mobile benchmarking SDK (Phase 1 MVP) + Performance Metrics (v0.1.5) (#4)

* Initial commit

* Add .github/workflows/relyance-sci.yml

* initial commit

* Fix Android UniFFI integration and benchmark display

This commit resolves multiple issues preventing the Android app from
loading the Rust native library and correctly displaying benchmark results.

Changes implemented:

1. Added JNA dependency (android/app/build.gradle)
   - Added net.java.dev.jna:jna:5.14.0@aar dependency
   - Required for UniFFI's Kotlin bindings to interface with native code
   - Also added NDK version specification and benchmark spec asset directories

2. Fixed library naming mismatch (crates/sample-fns/Cargo.toml)
   - Set explicit lib name = "sample_fns" (not uniffi_sample_fns)
   - Changed crate-type to ["lib", "cdylib", "staticlib"] for UniFFI
   - Added UniFFI dependencies and build configuration
   - Migrated from JNI to UniFFI for cleaner FFI bindings

3. Updated sync script for library renaming (scripts/sync-android-libs.sh)
   - Added TARGET_LIB_NAME variable to rename .so during copy
   - Rust builds libsample_fns.so but JNA expects libuniffi_sample_fns.so
   - Script now copies and renames: libsample_fns.so -> libuniffi_sample_fns.so
   - Ensures FFI symbol prefixes match UniFFI expectations

4. Updated Android MainActivity (android/app/src/main/java/dev/world/bench/MainActivity.kt)
   - Changed System.loadLibrary("sample_fns") to System.loadLibrary("uniffi_sample_fns")
   - Migrated from JNI to UniFFI-generated Kotlin bindings
   - Updated benchmark display to show microseconds (μs) instead of milliseconds
   - Added raw nanosecond display alongside formatted values
   - Improved error handling with UniFFI's BenchException variants
   - Added support for loading benchmark specs from assets (bench_spec.json)

Root cause analysis:
- UniFFI generates Kotlin bindings that expect library name "uniffi_<namespace>"
- The namespace from sample_fns.udl is "sample_fns"
- JNA looks for libuniffi_sample_fns.so based on this naming convention
- Rust builds libsample_fns.so by default (from crate name)
- Solution: Keep Rust lib name simple, rename during Android integration

Benchmark display fix:
- Functions execute in 0-42 nanoseconds (extremely fast)
- Previous millisecond display showed "0.000 ms" for all samples
- Now displays in microseconds with raw nanosecond values for clarity
- Example: "0.042 μs (42 ns)" instead of "0.000 ms"

Testing:
- App builds successfully with ./gradlew :app:assembleDebug
- Native library loads without UnsatisfiedLinkError
- Benchmarks execute and display timing results correctly
- Fibonacci(24) averages ~17 nanoseconds per iteration on ARM64

* Android: log benchmark JSON and fix test matcher

* iOS: add UI test target and accessibility id

* bench-cli: add BrowserStack fetch and artifact download

* Commit remaining workspace changes

* Ignore generated build artifacts

* gitignore: exclude CLI-generated artifacts

- Add run-summary.json (benchmark run results)
- Add bench-config.toml (user configuration template)
- Add device-matrix.yaml (device matrix template)

These files are generated by bench-cli and should not be tracked in git.

* iOS: standardize time units to microseconds

Change benchmark result display from milliseconds (ms) to microseconds (μs)
to match Android's output format. This provides better granularity for
typical function benchmarks and makes cross-platform comparison easier.

Before: 0.045 ms
After:  45.320 μs (45320 ns)

Also add raw nanosecond values in parentheses to match Android formatting.

* bench-cli: add comprehensive BrowserStack client tests

Add 11 new tests covering:
- Client initialization and configuration
- URL construction and path handling
- Input validation for schedule/upload methods
- Error cases for missing artifacts
- Both Espresso (Android) and XCUITest (iOS) code paths

Also suppress dead_code warning for test-only with_base_url helper.

Test coverage increased from 1 to 12 tests for browserstack.rs module.

* Migrate from UniFFI UDL to proc macros

Replace manual UDL file with proc macro attributes for better developer
experience and single source of truth in Rust code.

## Changes

### sample-fns crate:
- Add `#[derive(uniffi::Record)]` to BenchSpec, BenchSample, BenchReport
- Add `#[derive(uniffi::Error)]` with `#[uniffi(flat_error)]` to BenchError
- Add `#[uniffi::export]` to run_benchmark function
- Add `uniffi::setup_scaffolding!()` macro to generate scaffolding
- Remove UDL file (sample_fns.udl)
- Update Cargo.toml: enable uniffi "cli" feature
- Update build.rs: remove UDL scaffolding generation (now proc macro-based)
- Update generate-bindings.rs: use library_mode instead of UDL-based generation

### Generated bindings:
- Kotlin bindings regenerated from proc macros
- Swift bindings regenerated from proc macros
- FFI interface remains identical (no breaking changes)

## Benefits

1. **Single source of truth**: Rust code is the only place to define types
2. **Better IDE support**: Type checking and autocomplete in Rust
3. **Automatic sync**: No manual UDL maintenance required
4. **Improved DevEx**: Attributes are inline with type definitions
5. **Type safety**: Compiler enforces FFI boundaries

## Migration notes

- UniFFI 0.28 supports both UDL and proc macros
- Generated bindings are functionally identical
- All tests pass (22 tests)
- CLI demo verified working
- Android/iOS apps use same generated bindings

* docs: update for proc macros and dual workflows

Update documentation to reflect:
1. UniFFI proc macros (no UDL file needed)
2. Two distinct workflows: Local Development vs BrowserStack

## README.md Changes

- Add "Testing Workflows" section with clear separation
- Update UniFFI section for proc macro mode with examples
- Add comprehensive BrowserStack workflow section:
  - Android + Espresso step-by-step
  - iOS + XCUITest step-by-step
  - Config file examples
  - BrowserStack features overview
- Reorganize into Local Development vs BrowserStack sections
- Remove outdated UDL references
- Add requirements for both workflows

## CLAUDE.md Changes

- Update Mobile Integration Flow to mention proc macros
- Rewrite FFI Boundary section with proc macro examples
- Update "Adding New Benchmark Functions" workflow
- Remove references to sample_fns.udl
- Add note that no UDL file is needed

These changes make it much clearer for users:
- How to test locally (fast iteration)
- How to test on BrowserStack (real devices)
- How to add new FFI types with proc macros

* initial procmacros

* feat: Phase 1 - Transform mobile-bench-rs into bench-sdk library crate

This commit implements the complete Phase 1 MVP, transforming mobile-bench-rs
from a standalone tool into a library crate (bench-sdk) that can be imported
into any Rust project for mobile benchmarking.

## Core Features

### 1. Proc Macro System (bench-macros)
- Implement #[benchmark] attribute macro for automatic function registration
- Use inventory crate for compile-time collection, runtime discovery
- Generate fully-qualified function names (e.g., my_crate::my_function)

### 2. Core SDK Library (bench-sdk)
- **types.rs**: Core types (BenchError, Target, BuildConfig, BuildProfile, etc.)
- **registry.rs**: Function discovery via inventory::collect!()
  - discover_benchmarks(), find_benchmark(), list_benchmark_names()
- **runner.rs**: Execution engine with BenchmarkBuilder fluent API
- **codegen.rs**: Template generation system
  - Generates bench-mobile FFI wrapper crate with UniFFI
  - Creates Android/iOS project structures
  - Generates config files and examples
- **builders/android.rs**: Complete Android build pipeline
  - cargo-ndk integration for multi-ABI builds
  - JNI library syncing
  - Gradle APK generation
- **builders/ios.rs**: Complete iOS build pipeline
  - Multi-architecture builds (device + simulator)
  - xcframework creation with proper structure
  - Automatic code signing
  - XcodeGen integration

### 3. CLI Integration (bench-cli)
- Refactor to use SDK API as thin wrapper
- Add new commands:
  - init-sdk: Initialize benchmark project with templates
  - build: Build mobile artifacts using SDK builders
  - list: Discover and list all registered benchmarks
- Maintain backward compatibility with existing commands

### 4. Templates (templates/)
- **Android**: Gradle project, MainActivity, Espresso tests, resources
  - Templatized with package name, library name, etc.
  - Complete build.gradle, settings.gradle, AndroidManifest.xml
- **iOS**: XcodeGen project, SwiftUI app, XCUITest tests
  - Templatized with project name, bundle ID, etc.
  - Complete project.yml, Swift files, bridging headers

### 5. Example Project (examples/basic-benchmark)
- Migrate sample-fns to example demonstrating SDK usage
- Use #[benchmark] attributes with registry-based execution
- Full test coverage (6 passing tests)

## Architecture Changes

### Workspace Structure
```
mobile-bench-rs/
├── crates/
│   ├── bench-sdk/        # Core library (NEW, for crates.io)
│   ├── bench-macros/     # Proc macro crate (NEW)
│   ├── bench-cli/        # CLI tool (REFACTORED)
│   ├── bench-runner/     # Timing harness (UNCHANGED)
│   └── sample-fns/       # Legacy (DEPRECATED)
├── examples/
│   └── basic-benchmark/  # SDK example (NEW)
└── templates/            # Mobile app templates (NEW)
    ├── android/
    └── ios/
```

### Public API Surface
```rust
// Proc macro
#[benchmark]
fn my_function() { /* ... */ }

// Discovery
bench_sdk::discover_benchmarks() -> Vec<&BenchFunction>
bench_sdk::find_benchmark(name) -> Option<&BenchFunction>

// Execution
bench_sdk::run_benchmark(spec) -> Result<BenchReport>
BenchmarkBuilder::new(name).iterations(100).run()

// Builders
AndroidBuilder::new(root, crate_name).build(&config)
IosBuilder::new(root, crate_name).build(&config)

// Codegen
generate_project(&InitConfig) -> Result<PathBuf>
```

## Testing

All tests passing (25 total):
- bench-sdk: 12 tests
- basic-benchmark: 6 tests
- sample-fns: 6 tests (legacy)
- bench-runner: 1 test

## Documentation

- Updated README.md with Phase 1 information
- Inline rustdoc comments throughout
- Working example in examples/basic-benchmark
- Updated references in BUILD.md, TESTING.md

## Migration Path

Users can now:
1. Add bench-sdk to Cargo.toml
2. Annotate functions with #[benchmark]
3. Run `cargo bench-sdk init-sdk` to generate project
4. Run `cargo bench-sdk build` to build mobile artifacts
5. Run `cargo bench-sdk list` to discover benchmarks

## Future Work

Phase 1 provides the foundation for:
- Phase 2: Adaptive iterations, warmup detection
- Phase 3: Statistical analysis, baselines
- Phase 4: Full BrowserStack integration
- Phase 5: cargo bench harness, DevEx improvements
- Phase 6: Caching, reproducibility, CI optimization

* feat: wire sdk scaffolding and bindings

- Render Android/iOS templates with project-specific names and link user crate in bench-mobile

- Run UniFFI binding generation in SDK builders and ensure headers are packaged

- Route CLI builds through SDK builders and detect bench-mobile crate name

- Align Android JNI library naming (sample_fns) and update templates/scripts

- Improve binding generation tooling for ABI-aware Android builds

* docs: align build and binding workflow

- Document ABI-aware Android builds with UNIFFI_ANDROID_ABI

- Update binding regeneration steps to use scripts/generate-bindings.sh

- Simplify Android local/testing steps to use build-android-app.sh

* docs: add bench-sdk integration guide

- Add step-by-step setup for dependencies and annotations

- Document local Android/iOS testing workflow

- Document BrowserStack Espresso/XCUITest runs

* docs: expand integration guide

- Add prerequisites and clarify script availability

- Document CLI build path when scripts are absent

- Link guide from README

* docs: link prerequisite downloads

- Add official download links for Rust, Android, JDK, Xcode, and xcodegen

* docs: clarify JDK requirement

- Use vendor-agnostic JDK 17+ wording and OpenJDK link

- Note AGP official support for Java 17

* feat: Rename bench-cli to mobench and add iOS IPA packaging

Major improvements to CLI tooling and iOS workflow:

1. Rename bench-cli → mobench
   - More memorable and concise name (7 chars)
   - Available on crates.io
   - Dual binaries: mobench + cargo-mobench
   - Updated all documentation and references

2. Add iOS IPA packaging with xcodebuild
   - New command: cargo mobench package-ipa
   - SigningMethod enum: AdHoc and Development
   - Ad-hoc signing (no Apple ID needed) for BrowserStack
   - Development signing for physical devices
   - Pure xcodebuild implementation (no fastlane dependency)
   - Automatic ExportOptions.plist generation

3. Eliminate script dependencies for SDK integrators
   - Added prominent warnings in README and integration docs
   - Deprecation notices in all shell scripts
   - CLI-first approach: cargo mobench build replaces ./scripts/
   - Templates embedded in binary, no repo checkout needed

4. Add package metadata
   - Author: Dominik Clemente - dcbuilder.eth <dc@world.org>
   - Added to mobench, bench-sdk, and bench-macros
   - Repository links and keywords for crates.io

All changes tested and verified:
- 25 tests passing
- cargo mobench --help shows all commands
- package-ipa supports both adhoc and development methods
- Documentation updated across all files

* refactor: Rename bench-sdk → mobench-sdk and bench-macros → mobench-macros

Complete branding consistency across all packages:

1. Crate renames:
   - bench-sdk → mobench-sdk
   - bench-macros → mobench-macros

2. Updated all references:
   - Package names in Cargo.toml files
   - Workspace member names
   - Dependency declarations
   - Import statements (bench_sdk → mobench_sdk)
   - Documentation and code examples
   - CLI help messages

3. All tests passing (25 tests)
   - mobench-sdk: 12 tests
   - sample-fns: 6 tests
   - basic-benchmark: 6 tests
   - mobench CLI verified

Now all three publishable packages have consistent branding:
- mobench (CLI)
- mobench-sdk (core library)
- mobench-macros (proc macros)

* feat: Add metadata to bench-runner for crates.io publication

* fix: Add version requirements to path dependencies in mobench-sdk

* fix: Update repository URLs to worldcoin org and include templates in mobench-sdk package

* fix: Include templates directory in mobench-sdk crate for crates.io packaging

* chore: prepare mobench for crates.io publication

- Update repository URL to worldcoin organization
- Add version requirements to published dependencies (mobench-sdk, bench-runner)

* chore: make sample-fns dependency optional for publishing

- Add 'demo' feature flag for sample-fns dependency
- Feature-gate Demo command to only work when demo feature is enabled
- Users can install with: cargo install mobench --features demo

This allows mobench to be published without requiring sample-fns
(which is not published to crates.io).

* chore: remove Demo command for crates.io publication

- Demo command was only useful for development/testing
- Requires unpublished sample-fns crate
- Move sample-fns to dev-dependencies only
- Published CLI focuses on core functionality

* docs: add BrowserStack test run results and manual test script

Completed test runs on BrowserStack:
- ✅ Android Espresso test PASSED on Pixel 7 (50s duration)
- ⚠️  iOS XCUITest encountered packaging/parsing issues

Build artifacts created:
- Android APK (9.5 MB) + test APK
- iOS IPA (284 KB) + test suite (5.6 MB)

The Android integration is fully functional. iOS XCUITest requires
additional work on test runner packaging to meet BrowserStack's
parsing requirements.

Added test_browserstack.sh for manual BrowserStack API testing,
bypassing CLI's benchmark registry validation.

* refactor: rename bench-runner to mobench-runner for consistency

- Renamed crates/bench-runner to crates/mobench-runner
- Updated package name from bench-runner to mobench-runner
- Updated all imports from bench_runner to mobench_runner
- Updated workspace and all dependent crates:
  - mobench-sdk
  - mobench CLI
  - sample-fns
  - examples/basic-benchmark

This aligns the runner crate naming with the mobench ecosystem
(mobench, mobench-sdk, mobench-macros, mobench-runner).

Preparing for republication to crates.io.

* chore: bump version to 0.1.1 for republication

Updated workspace version to 0.1.1 after:
- Publishing mobench-runner v0.1.0 (new package)
- Republishing mobench-sdk v0.1.1 (updated dependency)
- Republishing mobench v0.1.1 (updated dependency)

All packages now use mobench-runner instead of bench-runner.

* docs: add comprehensive READMEs to all packages for crates.io

Added detailed README files to all packages:

- mobench-runner: Explains timing harness, shows basic usage examples
- mobench-macros: Documents #[benchmark] attribute, macro expansion
- mobench-sdk: Comprehensive SDK guide with examples and architecture
- mobench: Complete CLI documentation with all commands and workflows

Each README includes:
- Feature overview
- Installation instructions
- Usage examples
- API documentation
- Best practices
- Integration with other packages
- Requirements and troubleshooting

Updated Cargo.toml files to include readme = "README.md" field
for proper display on crates.io package pages.

Bumped version to 0.1.2 for republication with documentation.

* chore: add MIT license and update all package licenses

- Added LICENSE.md with MIT license under World Foundation (2026)
- Updated all READMEs to reference MIT license only
- Changed workspace license from 'MIT OR Apache-2.0' to 'MIT'
- Updated license sections in all 4 package READMEs:
  - mobench-runner
  - mobench-macros
  - mobench-sdk
  - mobench
- Bumped version to 0.1.3 for republication

Copyright (c) 2026 World Foundation

* chore: reset version to 0.1.0 for fresh release

Yanked all previous versions (0.1.0-0.1.3) from crates.io.
Starting fresh with proper:
- MIT license under World Foundation (2026)
- Comprehensive READMEs for all packages
- Consistent naming (mobench-runner instead of bench-runner)

This is the canonical first release.

* chore: use version 0.1.4 as canonical first release

Cannot reuse version 0.1.0 even after yanking.
Version 0.1.4 will be the canonical first release with:
- MIT license under World Foundation (2026)
- Comprehensive READMEs
- Proper naming (mobench-runner)

Versions 0.1.0-0.1.3 are yanked.

* docs: update CLAUDE.md to reflect SDK-first architecture and crates.io publication

- Update project overview with published packages (v0.1.4)
- Document recommended cargo mobench build workflow
- Mark scripts/ as legacy for repository development only
- Add SDK integration examples and Quick Start
- Reorganize file structure documentation
- Add template system documentation

* fix: address GitHub Advanced Security and Codex review findings

1. Add explicit workflow permissions (contents: read)
   - Addresses GitHub Advanced Security CodeQL warnings
   - Limits GITHUB_TOKEN permissions to read-only for CI workflow
   - Reduces security risk by following principle of least privilege

2. Fix local smoke test for user benchmarks
   - Only run local smoke test for sample_fns::* functions
   - Skip gracefully for user-defined benchmarks
   - Prevents 'unknown benchmark function' errors
   - User benchmarks aren't linked into CLI binary (will run on device)
   - Addresses Codex P1 review finding

Note: Skipped iOS certificate pinning (Semgrep finding) as the app
does not make network requests. Can be revisited if needed later.

* mobench: support repository structure and fix iOS IPA packaging

Updates CLI and SDK to work seamlessly with both SDK projects (bench-mobile/)
and repository structure (crates/sample-fns/), enabling full end-to-end testing
using only mobench commands.

Changes:

- AndroidBuilder/IosBuilder: Add find_crate_dir() to detect benchmark crate
  in multiple locations (bench-mobile/ or crates/{crate_name}/)

- UniFFI binding generation: Make optional, use pre-existing bindings if
  available, only require uniffi-bindgen CLI for fresh generation

- iOS IPA packaging: Complete rewrite from xcodebuild archive to simpler
  xcodebuild build approach, with ad-hoc signing support for BrowserStack
  testing (no Apple Developer account needed)

- BrowserStack XCUITest: Add only-testing parameter support to specify
  test methods (required by BrowserStack API)

- iOS project: Add schemes configuration to project.yml for proper
  xcodebuild support

Verified working:
- cargo mobench build --target android
- cargo mobench build --target ios
- cargo mobench package-ipa --method adhoc
- cargo mobench run (both Android and iOS on BrowserStack)

* mobench: add --fetch flag for CI-ready result retrieval

Implements automatic polling and result fetching for BrowserStack runs,
making the CLI fully CI-ready with one-command benchmark execution.

BrowserStack Client API:
- poll_build_completion(): Wait for build to finish with configurable timeout
- get_espresso_build_status() / get_xcuitest_build_status(): Check build status
- get_device_logs(): Fetch logs from specific device sessions
- extract_benchmark_results(): Parse benchmark JSON from logs
- wait_and_fetch_results(): Complete workflow (poll + fetch + extract)

CLI Integration:
- --fetch flag on 'run' command triggers automatic result fetching
- Merges benchmark_results into output JSON (device -> results map)
- Configurable timeout (--fetch-timeout-secs, default: 1800)
- Configurable poll interval (--fetch-poll-interval-secs, default: 10)
- Graceful error handling with warnings (command succeeds even if fetch fails)

Output Format Enhancement:
- RunSummary now includes optional benchmark_results field
- Results organized by device name
- Each device has array of benchmark results with samples, mean, min, max

Testing:
- 8 new comprehensive tests for result extraction and parsing
- Tests for BuildStatus conversion and deserialization
- Tests for JSON extraction from logs (single, multiple, invalid, missing)
- All tests passing (21 total in browserstack module)

Documentation:
- FETCH_RESULTS_GUIDE.md: Complete guide for --fetch usage
- BROWSERSTACK_CI_INTEGRATION.md: Programmatic API reference
- GitHub Actions examples with step summaries
- Error handling patterns and best practices

Example Usage:
  cargo mobench run \
    --target android \
    --function sample_fns::fibonacci \
    --iterations 30 \
    --warmup 5 \
    --devices "Google Pixel 7-13.0" \
    --fetch \
    --output results.json

This release makes mobench fully CI-ready with automatic result retrieval,
eliminating the need for manual log parsing or separate fetch commands.

* gitignore: exclude BrowserStack run artifacts and temp files

* mobench: print dashboard URL and result summary with --fetch

Improves CLI output when using --fetch to show:
- Dashboard URL immediately after scheduling (not just on error)
- Summary of benchmark results for each device
- Mean time in both nanoseconds and milliseconds
- Number of samples collected
- Dashboard URL again after successful fetch for easy access

Example output:
  Waiting for build 88f8c5a... to complete...
  Dashboard: https://app-automate.browserstack.com/dashboard/v2/builds/88f8c5a...

  ✓ Successfully fetched results from 1 device(s)

    Device: Google Pixel 7-13.0
      Benchmark 1: sample_fns::fibonacci
        Mean: 1237000 ns (1.24 ms)
        Samples: 30

    View full results: https://app-automate.browserstack.com/...

Makes CI output more informative and actionable without requiring manual
JSON parsing or URL construction.

* docs: document BrowserStack metrics and performance monitoring

Adds comprehensive documentation on what device metrics BrowserStack
provides and what mobench currently captures.

Key points:
- BrowserStack does NOT provide built-in CPU/memory/battery profiling
- Performance metrics must be collected by your app code
- We currently capture: logs, videos, network traces, screenshots
- We extract: benchmark timing data from logs
- Future enhancement: Extract custom performance metrics from logs

Provides examples for collecting memory/CPU metrics on Android/iOS
and logging them as JSON for extraction.

References BrowserStack API documentation and platform-specific APIs
for memory profiling.

* feat(mobench): add performance metrics extraction (v0.1.5)

- Add performance metrics types (PerformanceSnapshot, MemoryMetrics, CpuMetrics, etc.)
- Implement extract_performance_metrics() to parse memory/CPU data from device logs
- Add wait_and_fetch_all_results() to fetch both benchmark and performance results
- Update RunSummary to include performance_metrics field
- Add comprehensive tests for performance metrics extraction
- Update CLI --fetch to display performance metrics alongside benchmark results
- Update BROWSERSTACK_METRICS.md to reflect new functionality

Performance metrics are automatically extracted when using --fetch flag if the app
logs them in JSON format with memory/cpu fields or type='performance'.

Example output format:
{
  "memory": {"used_mb": 128.5, "max_mb": 512.0},
  "cpu": {"usage_percent": 45.2}
}

* refactor: remove dead code and fix compiler warnings

- Remove unused `wait_and_fetch_results()` from browserstack.rs (superseded by `wait_and_fetch_all_results()`)
- Add `#[cfg(test)]` to `run_local_smoke()` in main.rs
- Remove unused iOS signing methods (`identity()`, `export_method()`, `create_export_options_plist()`)
- Remove unused imports (`std::io::Write`, `BenchSpec`, `run_closure`)
- Add explanatory comment for dual binary targets in Cargo.toml

This cleanup addresses all compiler warnings and removes 117 lines of dead code.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* fix: build Android test APK and harden BrowserStack fetch

---------

Co-authored-by: tfe-app[bot] <200245884+tfe-app[bot]@users.noreply.github.com>
Co-authored-by: wld-terraform <infrastructure@toolsforhumanity.com>
Co-authored-by: dcbuilder.eth <dcbuilder@protonmail.com>
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>

* Update .github/workflows/relyance-sci.yml

* Add benchmark summaries, compare command, and CI polish (#5)

* Improve mobench fetch and iOS/Android builders

* Chore: align docs with markdownlint

* Refine rust-analyzer diagnostics

* Bump workspace version to 0.1.5

* Docs: refresh mobench testing and CLI guidance

Update docs to reflect current CLI usage, remove host demo references, and clarify local device workflows. Ignore Cursor project files and sync lockfile version entries.

* feat: add run summaries and CI artifacts

Add JSON/Markdown (optional CSV) summaries for mobench runs and wire CI to publish host + BrowserStack results.

* fix test

* feat: add compare reports and device tag filters

Add a mobench compare command plus device tag filtering from matrix configs, and publish benchmark summaries to CI job summaries. Refresh docs to cover compare usage and updated config examples.

* chore: clean up formatting in tests and bindgen

* address minor pr codex comments

* fix: treat BrowserStack passed builds as complete

Update polling to accept passed/completed build statuses and ignore run summary outputs in git. This prevents fetch timeouts after successful runs.

* Docs: align configs, devices, and rustdoc naming

Refresh markdown docs and rustdocs to use current mobench config names, BrowserStack device strings, and API references. Update codegen templates and examples to match mobench-sdk naming.

---------

Co-authored-by: dcbuilder.eth <dcbuilder@protonmail.com>

* Refactor mobench layout and refresh README

- split CLI entrypoint into library and cargo-mobench bin
- update workspace manifests and lockfile for crate changes
- rewrite README with current workflow and crate list

* Remove legacy bench-cli crates and update docs

Drop the unused bench-cli and bench-runner crates, update docs to reflect the current mobench-runner workflow, and adjust legacy scripts/comments to reference cargo mobench.

* Split examples into minimal and FFI variants

Simplify basic-benchmark to only show #[benchmark] usage and add a new ffi-benchmark example that contains the UniFFI types and entrypoint. Update workspace metadata and docs to reflect the new example layout.

* Remove legacy sample_fns UDL

Drop the unused UniFFI UDL file for sample-fns and update build script notes to reflect the proc-macro binding generation flow.

* Remove legacy scripts and update docs

Delete deprecated build scripts, switch CI and docs to cargo mobench commands, and refresh integration guidance for the new flow.

* Refresh docs for mobench build flow

Update CLAUDE, BUILD, and mobench-sdk README to remove script references, clarify the builder flow, and document the new examples.

* Improve repo root detection with ancestor search

The repo_root() function now walks up the directory tree looking for
marker files instead of relying on the compile-time manifest path.
This fixes cases where the CLI is run from subdirectories.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Bump version to 0.1.7 for release

Update workspace version and inter-crate dependencies.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add commit guidelines to CLAUDE.md

* Output mobile artifacts to target/mobench/ by default

- Add output_dir field to AndroidBuilder and IosBuilder
- Default to {project_root}/target/mobench/ for all mobile artifacts
- Add output_dir() builder method for customization
- Add --output-dir CLI argument to `cargo mobench build`
- Update all path references in builders to use output_dir

This keeps generated mobile artifacts inside target/, following Rust
conventions and preventing accidental commits of Android/iOS project files.

* Update docs for target/mobench/ output directory

- Update all path references from target/ios/ to target/mobench/ios/
- Update Android paths to target/mobench/android/
- Document --output-dir CLI flag
- Update troubleshooting sections with correct paths

* Add comprehensive docs.rs documentation

- Add extensive crate-level documentation to all four crates:
  - mobench-sdk: Full SDK docs with examples, architecture, and best practices
  - mobench-macros: #[benchmark] macro documentation with usage examples
  - mobench-runner: Timing harness docs with runnable examples
  - mobench: CLI documentation with command reference

- Document all public types with examples:
  - BenchSpec, BenchSample, BenchReport, BenchError
  - Target, BuildConfig, BuildProfile, BuildResult
  - InitConfig and builder types

- Configure docs.rs metadata in all Cargo.toml files:
  - Add documentation URLs
  - Add maintenance badges
  - Configure rustdoc-args for docs.rs builds

- Add serde_json dev-dependency to mobench-runner for doc tests

* Bump version to 0.1.8 for release

* Implement all IMPROVEMENTS.md tasks with enhanced DX

This commit implements all 11 developer experience improvements from
IMPROVEMENTS.md, making mobench significantly more user-friendly.

## Key Changes

### P0 - Critical (Tasks 1-3)
- Fix aws-lc-rs Android NDK incompatibility (ring backend)
- Fix workspace target directory detection (cargo metadata)
- Auto-generate project scaffolding during build

### P1 - High Priority (Tasks 4-6)
- Process template variables during build (TemplateContext)
- Improve uniffi-bindgen handling (local binary + fallback)
- Generate error handling code dynamically (generic catch)

### P2 - Medium Priority (Tasks 7-9)
- Add mobench.toml configuration file support
- Improve error messages with actionable suggestions
- Add --crate-path flag for custom crate locations

### P3 - Nice to Have (Tasks 10-11)
- Add --dry-run and --verbose CLI modes
- Auto-generate local.properties for Android

## Code Quality Improvements

- Extract shared utilities to builders/common.rs (DRY)
- Consistent error message formatting with:
  - Clear description of what failed
  - Context (commands, paths, exit status)
  - Actionable fix suggestions
  - Links to documentation
- Standardized path formatting using display()

## New Files
- crates/mobench/src/config.rs - Configuration file support
- crates/mobench-sdk/src/builders/common.rs - Shared utilities
- IMPROVEMENTS.md - Task tracking document

## Consolidation
- Merged mobench-runner crate into mobench-sdk
- Timing functionality now in mobench-sdk/src/timing.rs

* Fix iOS test failure in auto-build scaffolding

The test `ios_requires_artifacts_for_browserstack` was failing because
iOS project scaffolding was not being generated correctly during
auto-build for BrowserStack.

Root causes and fixes:

1. render_dir() was incorrectly joining prefix with file.path(), but
   file.path() from include_dir already returns the full relative path.
   Removed the prefix parameter entirely.

2. project.yml lacked .template extension, so template variables like
   {{PROJECT_NAME_PASCAL}} were not being substituted. Renamed to
   project.yml.template.

3. xcframework path in project.yml.template was wrong (../../target/ios/).
   Fixed to ../{{LIBRARY_NAME}}.xcframework since the iOS project is at
   target/mobench/ios/BenchRunner/.

4. ensure_ios_project now uses fixed "BenchRunner" for PROJECT_NAME_PASCAL
   to match the template directory structure, while deriving LIBRARY_NAME
   from the actual crate name.

All 37 tests now pass.

* Update documentation for consolidated crates and new features

README updates:
- Document mobench-runner consolidation into mobench-sdk
- Add mobench.toml configuration file documentation
- Document new CLI flags: --dry-run, --verbose, --crate-path
- Update all artifact paths to target/mobench/
- Add examples for new features

Rust doc comments:
- Add comprehensive module docs to builders/{mod,android,ios,common}.rs
- Document build pipelines, requirements, and examples
- Add dry-run mode documentation
- Note mobench-runner consolidation in timing.rs

docs.rs configuration:
- Add targets = ["x86_64-unknown-linux-gnu"] for docs.rs builds
- Add #![cfg_attr(docsrs, feature(doc_cfg))] attributes
- Add crates.io/docs.rs/license badges to crate roots
- Add #[doc(cfg(...))] annotations for feature-gated items

* Bump version to 0.1.9 for release

- Update workspace version from 0.1.8 to 0.1.9
- Update mobench-sdk dependency in mobench crate
- Update mobench-macros dependency in mobench-sdk crate
- All mobench-runner versions have been yanked on crates.io

* Remove IMPROVEMENTS.md after completing all tasks

* Fix all DX issues from mobench 0.1.9 testing

Critical bugs fixed (12):
- Bugs 1-5: Template variables (PROJECT_NAME, PACKAGE_NAME, LIBRARY_NAME,
  PROJECT_NAME_PASCAL, APP_NAME) now properly substituted
- Bug 6: Added gradle.properties template with AndroidX settings
- Bug 7: Auto-generate Gradle wrapper if missing
- Bug 8: Fixed AGP version from 8.13.2 to 8.2.2
- Bug 9: Package name in Kotlin templates now uses {{PACKAGE_NAME}}
- Bug 10: Added x86_64-apple-ios target for Intel Mac simulators
- Bug 11: Fixed path handling by canonicalizing project root
- Bug 12: DEFAULT_FUNCTION now auto-detected from #[benchmark] functions

High severity issues fixed (8):
- Issue 1: Added post-template validation for unreplaced {{...}} patterns
- Issue 2: codesign_xcframework now returns Err on failure
- Issue 3: generate_xcode_project now returns Err on failure
- Issue 4: Missing native libraries always warn (not just verbose)
- Issue 5: Added validate_project_root() for early validation
- Issue 6: cargo metadata fallback now warns when used
- Issue 7: Kotlin catch block logs exceptions instead of swallowing
- Issue 8: Added validate_build_artifacts() post-build validation

Medium/Low issues fixed (4):
- Added .gitignore templates for Android and iOS
- Added README.md templates for Android and iOS

New files:
- templates/android/.gitignore
- templates/android/README.md
- templates/android/gradle.properties
- templates/ios/BenchRunner/.gitignore
- templates/ios/BenchRunner/README.md

* Update documentation for v0.1.9 and fix inconsistencies

- Fix all path references to use target/mobench/ as default output dir
- Update CLAUDE.md version reference to v0.1.9
- Fix PROJECT_PLAN.md to reflect mobench-runner consolidation into mobench-sdk
- Remove dead links to BROWSERSTACK_RUN_2.md (use BROWSERSTACK_METRICS.md)
- Fix all init-sdk references to use correct init command
- Fix duplicate command and step numbering in TESTING.md
- Update iOS artifact paths in BENCH_SDK_INTEGRATION.md

* Bump version to 0.1.10 for release

* Fix CI workflow paths to use target/mobench/ output directory

* Fix DX issues from 0.1.10 report

Android fixes:
- Add APK detection for both signed and unsigned builds
- Parse output-metadata.json for actual APK filename
- Add proguard-rules.pro template for release builds
- Update .gitignore to exclude jniLibs and uniffi bindings

iOS fixes:
- Sanitize bundle identifiers (remove hyphens/underscores)
- Framework bundle IDs now use alphanumeric chars only
- Add logging for config loading failures
- Update .gitignore to exclude xcodeproj, frameworks, bindings

Config fixes:
- Add logging for missing/invalid JSON keys in templates
- Android MainActivity logs warnings for missing config values
- iOS BenchRunnerFFI prints errors when JSON parsing fails

* Bump version to 0.1.11 for release

* Update CLAUDE.md version reference to 0.1.11

* Fix DX issues from 0.1.11 report

P0 fixes:
- Add testBuildType "release" to build.gradle templates
- Gradle now creates assembleReleaseAndroidTest task

P1 fixes:
- local.properties only uses ANDROID_HOME/ANDROID_SDK_ROOT env vars
- No longer probes filesystem for hardcoded SDK paths
- Kotlin files moved to correct package directory structure

P2 fixes:
- iOS bundle ID now uses app name: dev.world.benchmobile.BenchRunner
- No longer duplicates crate name in bundle ID

* Fix all DX issues from bug reports

Crate detection (P0):
- Check current directory Cargo.toml before nested paths
- Add read_package_name() helper for parsing Cargo.toml
- Search order: current dir → bench-mobile/ → crates/{name}/ → {name}/
- Add 10 new tests for crate detection logic

Error handling improvements:
- Add Log.e() calls for Android exception handlers
- Add print() statements for iOS config parsing failures
- Log config sources (intent, bench_spec.json, default)
- Show warnings when using fallback defaults

Cross-platform consistency:
- Standardize Android package names (remove underscores like iOS)
- Both platforms now use dev.world.benchmobile format
- Standardize version strings to 1.0.0 on both platforms
- Add 3 new consistency tests

Tests added:
- test_find_crate_dir_current_directory_is_crate
- test_find_crate_dir_nested_bench_mobile
- test_find_crate_dir_crates_subdir
- test_find_crate_dir_not_found
- test_find_crate_dir_explicit_crate_path
- test_read_package_name_standard
- test_read_package_name_with_single_quotes
- test_read_package_name_not_found
- test_read_package_name_no_package_section
- test_cross_platform_naming_consistency
- test_cross_platform_version_consistency
- test_bundle_id_prefix_consistency

* Remove IMPROVEMENTS.md after completing all tasks

* Fix all DX issues from mobench 0.1.9 testing

Critical bugs fixed (12):
- Bugs 1-5: Template variables (PROJECT_NAME, PACKAGE_NAME, LIBRARY_NAME,
  PROJECT_NAME_PASCAL, APP_NAME) now properly substituted
- Bug 6: Added gradle.properties template with AndroidX settings
- Bug 7: Auto-generate Gradle wrapper if missing
- Bug 8: Fixed AGP version from 8.13.2 to 8.2.2
- Bug 9: Package name in Kotlin templates now uses {{PACKAGE_NAME}}
- Bug 10: Added x86_64-apple-ios target for Intel Mac simulators
- Bug 11: Fixed path handling by canonicalizing project root
- Bug 12: DEFAULT_FUNCTION now auto-detected from #[benchmark] functions

High severity issues fixed (8):
- Issue 1: Added post-template validation for unreplaced {{...}} patterns
- Issue 2: codesign_xcframework now returns Err on failure
- Issue 3: generate_xcode_project now returns Err on failure
- Issue 4: Missing native libraries always warn (not just verbose)
- Issue 5: Added validate_project_root() for early validation
- Issue 6: cargo metadata fallback now warns when used
- Issue 7: Kotlin catch block logs exceptions instead of swallowing
- Issue 8: Added validate_build_artifacts() post-build validation

Medium/Low issues fixed (4):
- Added .gitignore templates for Android and iOS
- Added README.md templates for Android and iOS

New files:
- templates/android/.gitignore
- templates/android/README.md
- templates/android/gradle.properties
- templates/ios/BenchRunner/.gitignore
- templates/ios/BenchRunner/README.md

* Update documentation for v0.1.9 and fix inconsistencies

- Fix all path references to use target/mobench/ as default output dir
- Update CLAUDE.md version reference to v0.1.9
- Fix PROJECT_PLAN.md to reflect mobench-runner consolidation into mobench-sdk
- Remove dead links to BROWSERSTACK_RUN_2.md (use BROWSERSTACK_METRICS.md)
- Fix all init-sdk references to use correct init command
- Fix duplicate command and step numbering in TESTING.md
- Update iOS artifact paths in BENCH_SDK_INTEGRATION.md

* Bump version to 0.1.10 for release

* Fix CI workflow paths to use target/mobench/ output directory

* Fix DX issues from 0.1.10 report

Android fixes:
- Add APK detection for both signed and unsigned builds
- Parse output-metadata.json for actual APK filename
- Add proguard-rules.pro template for release builds
- Update .gitignore to exclude jniLibs and uniffi bindings

iOS fixes:
- Sanitize bundle identifiers (remove hyphens/underscores)
- Framework bundle IDs now use alphanumeric chars only
- Add logging for config loading failures
- Update .gitignore to exclude xcodeproj, frameworks, bindings

Config fixes:
- Add logging for missing/invalid JSON keys in templates
- Android MainActivity logs warnings for missing config values
- iOS BenchRunnerFFI prints errors when JSON parsing fails

* Bump version to 0.1.11 for release

* Update CLAUDE.md version reference to 0.1.11

* Fix DX issues from 0.1.11 report

P0 fixes:
- Add testBuildType "release" to build.gradle templates
- Gradle now creates assembleReleaseAndroidTest task

P1 fixes:
- local.properties only uses ANDROID_HOME/ANDROID_SDK_ROOT env vars
- No longer probes filesystem for hardcoded SDK paths
- Kotlin files moved to correct package directory structure

P2 fixes:
- iOS bundle ID now uses app name: dev.world.benchmobile.BenchRunner
- No longer duplicates crate name in bundle ID

* Fix all DX issues from bug reports

Crate detection (P0):
- Check current directory Cargo.toml before nested paths
- Add read_package_name() helper for parsing Cargo.toml
- Search order: current dir → bench-mobile/ → crates/{name}/ → {name}/
- Add 10 new tests for crate detection logic

Error handling improvements:
- Add Log.e() calls for Android exception handlers
- Add print() statements for iOS config parsing failures
- Log config sources (intent, bench_spec.json, default)
- Show warnings when using fallback defaults

Cross-platform consistency:
- Standardize Android package names (remove underscores like iOS)
- Both platforms now use dev.world.benchmobile format
- Standardize version strings to 1.0.0 on both platforms
- Add 3 new consistency tests

Tests added:
- test_find_crate_dir_current_directory_is_crate
- test_find_crate_dir_nested_bench_mobile
- test_find_crate_dir_crates_subdir
- test_find_crate_dir_not_found
- test_find_crate_dir_explicit_crate_path
- test_read_package_name_standard
- test_read_package_name_with_single_quotes
- test_read_package_name_not_found
- test_read_package_name_no_package_section
- test_cross_platform_naming_consistency
- test_cross_platform_version_consistency
- test_bundle_id_prefix_consistency

* Add --release flag and package-xcuitest command

- Add --release flag to mobench run command for release builds
  (reduces APK size from ~544MB debug to ~133MB release)
- Add mobench package-xcuitest command for iOS BrowserStack testing
- Add output_dir option to package-ipa command
- Update timing display format from μs to ms (or seconds if >=1000ms)
- Auto-package iOS artifacts in release mode when --release is set

* Update mobile timing display and documentation

- Update Android/iOS apps to display timing in ms (or seconds if >=1000ms)
- Update CLAUDE.md, TESTING.md, README with --release flag examples
- Document package-xcuitest command across all relevant docs
- Add release build recommendations for BrowserStack workflows

* Fix iOS XCUITest benchmark report gap and add video capture delay

iOS XCUITest was exiting in ~2 seconds without capturing benchmark data,
while Android properly waited and extracted full timing reports.

Changes:
- XCUITest now waits up to 5 minutes for benchmark completion (not 2 sec)
- Extract benchmark JSON via accessibility identifiers
- Output JSON with BENCH_REPORT_JSON_START/END markers for log parsing
- Add iOS-specific JSON extraction in fetch logic (handles NSLog prefixes)
- Both Android and iOS now hold the report screen for 5 seconds so
  BrowserStack video recordings capture the benchmark results

Files updated:
- iOS XCUITest template and reference implementation
- iOS ContentView with completion indicators and JSON exposure
- iOS BenchRunnerFFI with JSON report generation
- BrowserStack fetch logic for iOS log parsing
- Android MainActivity with 5-second display hold

* Sync top-level templates with SDK templates

* Update documentation for --release flag and iOS XCUITest features

- Add --release flag to BrowserStack examples in README.md
- Update mobench-sdk README and rustdocs with --release recommendation
- Update mobench CLI rustdocs with --release flag
- Expand template READMEs with BrowserStack workflow and video capture info
- Document benchmark report capture mechanism (5-second delay, JSON markers)

* Fix iOS XCUITest BrowserStack detection and video capture

- Add Info.plist to XCUITest bundle to fix BrowserStack test detection
  BrowserStack requires Info.plist with XCTContainsUITests=true to
  identify and run tests; without it, builds are skipped with
  "no tests detected"

- Add info: section to UITests target in project.yml templates
  with proper bundle identifier (*.uitests suffix)

- Increase XCUITest delay from 0.5s to 5s after benchmark completion
  to ensure BrowserStack video captures the results

- Update initial display text from "Running benchmark..." to
  "Running benchmarks..." for better UX during video recording

* Remove resolved issue tracking docs

* Remove stale DX report doc

* Bump version to 0.1.12 for release

Changes in this release:
- Fix iOS XCUITest BrowserStack detection (Info.plist added to UITests target)
- Improve video capture for BrowserStack (5s delay for video evidence)
- Show "Running benchmarks..." text before results appear
- Sync top-level templates with SDK templates
- Various DX fixes

* Fix error message hints

* Fix iOS XCUITest test name mismatch with BrowserStack

Changed only-testing filter from testLaunchShowsBenchmarkReport to
testLaunchAndCaptureBenchmarkReport to match what BrowserStack parses
from the xctest bundle.

* Bump version to 0.1.13 for release

Fix iOS XCUITest test name mismatch with BrowserStack - changed
only-testing filter to use testLaunchAndCaptureBenchmarkReport.

* Modernize build flow and examples (#6)

* Refactor mobench layout and refresh README

- split CLI entrypoint into library and cargo-mobench bin
- update workspace manifests and lockfile for crate changes
- rewrite README with current workflow and crate list

* Remove legacy bench-cli crates and update docs

Drop the unused bench-cli and bench-runner crates, update docs to reflect the current mobench-runner workflow, and adjust legacy scripts/comments to reference cargo mobench.

* Split examples into minimal and FFI variants

Simplify basic-benchmark to only show #[benchmark] usage and add a new ffi-benchmark example that contains the UniFFI types and entrypoint. Update workspace metadata and docs to reflect the new example layout.

* Remove legacy sample_fns UDL

Drop the unused UniFFI UDL file for sample-fns and update build script notes to reflect the proc-macro binding generation flow.

* Remove legacy scripts and update docs

Delete deprecated build scripts, switch CI and docs to cargo mobench commands, and refresh integration guidance for the new flow.

* Refresh docs for mobench build flow

Update CLAUDE, BUILD, and mobench-sdk README to remove script references, clarify the builder flow, and document the new examples.

---------

Co-authored-by: dcbuilder.eth <dcbuilder@protonmail.com>

* DX Improvements v0.1.13: Setup/teardown, new commands, better errors (#9)

* Refactor mobench layout and refresh README

- split CLI entrypoint into library and cargo-mobench bin
- update workspace manifests and lockfile for crate changes
- rewrite README with current workflow and crate list

* Remove legacy bench-cli crates and update docs

Drop the unused bench-cli and bench-runner crates, update docs to reflect the current mobench-runner workflow, and adjust legacy scripts/comments to reference cargo mobench.

* Split examples into minimal and FFI variants

Simplify basic-benchmark to only show #[benchmark] usage and add a new ffi-benchmark example that contains the UniFFI types and entrypoint. Update workspace metadata and docs to reflect the new example layout.

* Remove legacy sample_fns UDL

Drop the unused UniFFI UDL file for sample-fns and update build script notes to reflect the proc-macro binding generation flow.

* Remove legacy scripts and update docs

Delete deprecated build scripts, switch CI and docs to cargo mobench commands, and refresh integration guidance for the new flow.

* Refresh docs for mobench build flow

Update CLAUDE, BUILD, and mobench-sdk README to remove script references, clarify the builder flow, and document the new examples.

* Improve repo root detection with ancestor search

The repo_root() function now walks up the directory tree looking for
marker files instead of relying on the compile-time manifest path.
This fixes cases where the CLI is run from subdirectories.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Bump version to 0.1.7 for release

Update workspace version and inter-crate dependencies.

Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>

* Add commit guidelines to CLAUDE.md

* Output mobile artifacts to target/mobench/ by default

- Add output_dir field to AndroidBuilder and IosBuilder
- Default to {project_root}/target/mobench/ for all mobile artifacts
- Add output_dir() builder method for customization
- Add --output-dir CLI argument to `cargo mobench build`
- Update all path references in builders to use output_dir

This keeps generated mobile artifacts inside target/, following Rust
conventions and preventing accidental commits of Android/iOS project files.

* Update docs for target/mobench/ output directory

- Update all path references from target/ios/ to target/mobench/ios/
- Update Android paths to target/mobench/android/
- Document --output-dir CLI flag
- Update troubleshooting sections with correct paths

* Add comprehensive docs.rs documentation

- Add extensive crate-level documentation to all four crates:
  - mobench-sdk: Full SDK docs with examples, architecture, and best practices
  - mobench-macros: #[benchmark] macro documentation with usage examples
  - mobench-runner: Timing harness docs with runnable examples
  - mobench: CLI documentation with command reference

- Document all public types with examples:
  - BenchSpec, BenchSample, BenchReport, BenchError
  - Target, BuildConfig, BuildProfile, BuildResult
  - InitConfig and builder types

- Configure docs.rs metadata in all Cargo.toml files:
  - Add documentation URLs
  - Add maintenance badges
  - Configure rustdoc-args for docs.rs builds

- Add serde_json dev-dependency to mobench-runner for doc tests

* Bump version to 0.1.8 for release

* Implement all IMPROVEMENTS.md tasks with enhanced DX

This commit implements all 11 developer experience improvements from
IMPROVEMENTS.md, making mobench significantly more user-friendly.

## Key Changes

### P0 - Critical (Tasks 1-3)
- Fix aws-lc-rs Android NDK incompatibility (ring backend)
- Fix workspace target directory detection (cargo metadata)
- Auto-generate project scaffolding during build

### P1 - High Priority (Tasks 4-6)
- Process template variables during build (TemplateContext)
- Improve uniffi-bindgen handling (local binary + fallback)
- Generate error handling code dynamically (generic catch)

### P2 - Medium Priority (Tasks 7-9)
- Add mobench.toml configuration file support
- Improve error messages with actionable suggestions
- Add --crate-path flag for custom crate locations

### P3 - Nice to Have (Tasks 10-11)
- Add --dry-run and --verbose CLI modes
- Auto-generate local.properties for Android

## Code Quality Improvements

- Extract shared utilities to builders/common.rs (DRY)
- Consistent error message formatting with:
  - Clear description of what failed
  - Context (commands, paths, exit status)
  - Actionable fix suggestions
  - Links to documentation
- Standardized path formatting using display()

## New Files
- crates/mobench/src/config.rs - Configuration file support
- crates/mobench-sdk/src/builders/common.rs - Shared utilities
- IMPROVEMENTS.md - Task tracking document

## Consolidation
- Merged mobench-runner crate into mobench-sdk
- Timing functionality now in mobench-sdk/src/timing.rs

* Fix iOS test failure in auto-build scaffolding

The test `ios_requires_artifacts_for_browserstack` was failing because
iOS project scaffolding was not being generated correctly during
auto-build for BrowserStack.

Root causes and fixes:

1. render_dir() was incorrectly joining prefix with file.path(), but
   file.path() from include_dir already returns the full relative path.
   Removed the prefix parameter entirely.

2. project.yml lacked .template extension, so template variables like
   {{PROJECT_NAME_PASCAL}} were not being substituted. Renamed to
   project.yml.template.

3. xcframework path in project.yml.template was wrong (../../target/ios/).
   Fixed to ../{{LIBRARY_NAME}}.xcframework since the iOS project is at
   target/mobench/ios/BenchRunner/.

4. ensure_ios_project now uses fixed "BenchRunner" for PROJECT_NAME_PASCAL
   to match the template directory structure, while deriving LIBRARY_NAME
   from the actual crate name.

All 37 tests now pass.

* Update documentation for consolidated crates and new features

README updates:
- Document mobench-runner consolidation into mobench-sdk
- Add mobench.toml configuration file documentation
- Document new CLI flags: --dry-run, --verbose, --crate-path
- Update all artifact paths to target/mobench/
- Add examples for new features

Rust doc comments:
- Add comprehensive module docs to builders/{mod,android,ios,common}.rs
- Document build pipelines, requirements, and examples
- Add dry-run mode documentation
- Note mobench-runner consolidation in timing.rs

docs.rs configuration:
- Add targets = ["x86_64-unknown-linux-gnu"] for docs.rs builds
- Add #![cfg_attr(docsrs, feature(doc_cfg))] attributes
- Add crates.io/docs.rs/license badges to crate roots
- Add #[doc(cfg(...))] annotations for feature-gated items

* Bump version to 0.1.9 for release

- Update workspace version from 0.1.8 to 0.1.9
- Update mobench-sdk dependency in mobench crate
- Update mobench-macros dependency in mobench-sdk crate
- All mobench-runner versions have been yanked on crates.io

* Remove IMPROVEMENTS.md after completing all tasks

* Fix all DX issues from mobench 0.1.9 testing

Critical bugs fixed (12):
- Bugs 1-5: Template variables (PROJECT_NAME, PACKAGE_NAME, LIBRARY_NAME,
  PROJECT_NAME_PASCAL, APP_NAME) now properly substituted
- Bug 6: Added gradle.properties template with AndroidX settings
- Bug 7: Auto-generate Gradle wrapper if missing
- Bug 8: Fixed AGP version from 8.13.2 to 8.2.2
- Bug 9: Package name in Kotlin templates now uses {{PACKAGE_NAME}}
- Bug 10: Added x86_64-apple-ios target for Intel Mac simulators
- Bug 11: Fixed path handling by canonicalizing project root
- Bug 12: DEFAULT_FUNCTION now auto-detected from #[benchmark] functions

High severity issues fixed (8):
- Issue 1: Added post-template validation for unreplaced {{...}} patterns
- Issue 2: codesign_xcframework now returns Err on failure
- Issue 3: generate_xcode_project now returns Err on failure
- Issue 4: Missing native libraries always warn (not just verbose)
- Issue 5: Added validate_project_root() for early validation
- Issue 6: cargo metadata fallback now warns when used
- Issue 7: Kotlin catch block logs exceptions instead of swallowing
- Issue 8: Added validate_build_artifacts() post-build validation

Medium/Low issues fixed (4):
- Added .gitignore templates for Android and iOS
- Added README.md templates for Android and iOS

New files:
- templates/android/.gitignore
- templates/android/README.md
- templates/android/gradle.properties
- templates/ios/BenchRunner/.gitignore
- templates/ios/BenchRunner/README.md

* Update documentation for v0.1.9 and fix inconsistencies

- Fix all path references to use target/mobench/ as default output dir
- Update CLAUDE.md version reference to v0.1.9
- Fix PROJECT_PLAN.md to reflect mobench-runner consolidation into mobench-sdk
- Remove dead links to BROWSERSTACK_RUN_2.md (use BROWSERSTACK_METRICS.md)
- Fix all init-sdk references to use correct init command
- Fix duplicate command and step numbering in TESTING.md
- Update iOS artifact paths in BENCH_SDK_INTEGRATION.md

* Bump version to 0.1.10 for release

* Fix CI workflow paths to use target/mobench/ output directory

* Fix DX issues from 0.1.10 report

Android fixes:
- Add APK detection for both signed and unsigned builds
- Parse output-metadata.json for actual APK filename
- Add proguard-rules.pro template for release builds
- Update .gitignore to exclude jniLibs and uniffi bindings

iOS fixes:
- Sanitize bundle identifiers (remove hyphens/underscores)
- Framework bundle IDs now use alphanumeric chars only
- Add logging for config loading failures
- Update .gitignore to exclude xcodeproj, frameworks, bindings

Config fixes:
- Add logging for missing/invalid JSON keys in templates
- Android MainActivity logs warnings for missing config values
- iOS BenchRunnerFFI prints errors when JSON parsing fails

* Bump version to 0.1.11 for release

* Update CLAUDE.md version reference to 0.1.11

* Fix DX issues from 0.1.11 report

P0 fixes:
- Add testBuildType "release" to build.gradle templates
- Gradle now creates assembleReleaseAndroidTest task

P1 fixes:
- local.properties only uses ANDROID_HOME/ANDROID_SDK_ROOT env vars
- No longer probes filesystem for hardcoded SDK paths
- Kotlin files moved to correct package directory structure

P2 fixes:
- iOS bundle ID now uses app name: dev.world.benchmobile.BenchRunner
- No longer duplicates crate name in bundle ID

* Fix all DX issues from bug reports

Crate detection (P0):
- Check current directory Cargo.toml before nested paths
- Add read_package_name() helper for parsing Cargo.toml
- Search order: current dir → bench-mobile/ → crates/{name}/ → {name}/
- Add 10 new tests for crate detection logic

Error handling improvements:
- Add Log.e() calls for Android exception handlers
- Add print() statements for iOS config parsing failures
- Log config sources (intent, bench_spec.json, default)
- Show warnings when using fallback defaults

Cross-platform consistency:
- Standardize Android package names (remove underscores like iOS)
- Both platforms now use dev.world.benchmobile format
- Standardize version strings to 1.0.0 on both platforms
- Add 3 new consistency tests

Tests added:
- test_find_crate_dir_current_directory_is_crate
- test_find_crate_dir_nested_bench_mobile
- test_find_crate_dir_crates_subdir
- test_find_crate_dir_not_found
- test_find_crate_dir_explicit_crate_path
- test_read_package_name_standard
- test_read_package_name_with_single_quotes
- test_read_package_name_not_found
- test_read_package_name_no_package_section
- test_cross_platform_naming_consistency
- test_cross_platform_version_consistency
- test_bundle_id_prefix_consistency

* Add --release flag and package-xcuitest command

- Add --release flag to mobench run command for release builds
  (reduces APK size from ~544MB debug to ~133MB release)
- Add mobench package-xcuitest command for iOS BrowserStack testing
- Add output_dir option to package-ipa command
- Update timing display format from μs to ms (or seconds if >=1000ms)
- Auto-package iOS artifacts in release mode when --release is set

* Update mobile timing display and documentation

- Update Android/iOS apps to display timing in ms (or seconds if >=1000ms)
- Update CLAUDE.md, TESTIN…
@dcbuild3r dcbuild3r force-pushed the codex/native-c-abi-backend branch from 16de746 to 06be260 Compare May 14, 2026 20:14
@dcbuild3r dcbuild3r force-pushed the codex/native-c-abi-backend branch from 06be260 to 17f4793 Compare May 14, 2026 20:22
@dcbuild3r dcbuild3r closed this May 16, 2026
@dcbuild3r dcbuild3r force-pushed the codex/native-c-abi-backend branch from 33787e1 to cb1f7b5 Compare May 16, 2026 20:03
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants