Commit a59b8d7
Release 2.3.2: Mobile UX, Localization, and Test Automation (#655)
* Security fixes for SonarCloud blockers and version bump to 2.3.1
- Add _validate_config_path() to config.py to validate config paths
are within allowed directories before file write operations
- Sanitize all task_id, task.name, and defer_until values in scheduler
service logs to prevent log injection (CWE-117)
- Bump version to 2.3.1-stable (versionCode 77)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Document HTTPExceptions in FastAPI route responses
- Add RESPONSES_400_404_500_503 and RESPONSES_400_500_503 combined patterns
- Document 404 in cancel_scheduled_task endpoint
- Use cleaner combined response patterns in scheduler and telemetry_export
Fixes SonarCloud code smells about undocumented HTTPException status codes.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add iOS Documents/ciris path to config allowlist
iOS defaults to ~/Documents/ciris/.env when CIRIS_HOME is unset.
The previous allowlist only included ~/ciris, blocking valid iOS installs.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Patch _validate_config_path in LLM config tests
Tests use tmp_path which isn't in the config path allowlist.
Patch the validation function to pass through for test directories.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Remove unused exception variables in scheduler service
When fixing log injection (CWE-117), removed {e} from log messages
but left 'as e' in except clauses. Now using bare 'except Exception:'.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Remove f-string prefix from strings without replacements
F-strings without {} are confusing and wasteful. Changed to regular strings.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix mobile credits display and add pre-flight credit check
- Credits badge now shows daily free uses when paid/free credits are 0
- Added pre-flight credit check before sendMessage() to block send when no credits
- Added user-friendly error message handling (no raw JSON shown to users)
- Added credit renewal countdown (hours until midnight UTC) when exhausted
- Added 7 new localized credit error strings in all 16 languages:
- credits_no_credits, credits_no_credits_short, credits_purchase_required
- credits_renews_at, credits_error_generic, credits_error_network, credits_error_server
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix SonarCloud scan action - use sonarcloud-github-action
Switch from sonarqube-scan-action@v6 to sonarcloud-github-action@v5.
The sonarqube-scan-action is for self-hosted SonarQube servers and was
failing with 403 errors from binaries.sonarsource.com. Since we use
SonarCloud, the sonarcloud-github-action is the correct choice.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix SonarCloud path injection by returning new validated Path
SECURITY: The _validate_config_path() function now returns a NEW Path
object constructed from validated components (allowed_parent / relative_path)
instead of returning the original tainted path. This breaks the taint chain
that SonarCloud tracks from user-controlled input to file operations.
Before: _validate_config_path(path) returned the same tainted path
After: _validate_config_path(path) returns Path(allowed_parent / relative_path)
The caller now uses the returned validated path for file operations.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix circular imports and improve code architecture
- Extract Dialect and ConflictResolution enums to types.py to break
dialect.py ↔ query_builder.py circular import
- Move telemetry helper imports to top level in service.py (helpers.py
only imports GraphTelemetryService under TYPE_CHECKING)
- Extract startup logging utilities to startup_logging.py to break
module_loader.py ↔ service_initializer.py circular import
- Update all dependent imports to use new module locations
Files added:
- ciris_engine/logic/persistence/db/types.py
- ciris_engine/logic/runtime/startup_logging.py
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Replace Dict[str, Any] with typed schemas in protocols (Phase 1)
- authentication.py: verify_token_sync() now returns TokenVerification
- scheduler.py: schedule_deferred_task() context param uses DeferralContext
- wa_auth.py: create_oauth_wa() profile param uses OAuthUserProfile
- authentication/service.py: Updated implementation to return TokenVerification
Note: configurable.py handle_oauth_callback() intentionally kept as Dict[str, Any]
because it's used for both OAuth tokens AND device auth status (different structures).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add typed schemas for LLM service state tracking
Phase 2 of Dict[str, Any] cleanup - create typed schemas for internal data structures:
- RetryState: Tracks retry count, previous errors, and request correlation
- LLMRequestMetadata: Metadata for proxy requests with billing/tracing info
- EndpointStats: Statistics for LLM endpoint monitoring
Analysis found that adapter_configuration and discovery_service Dict[str, Any]
usages are legitimate serialization edges (user input) and DI patterns (kwargs).
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix mypy: restore ErrorContext type alias
The ErrorContext type alias was accidentally removed during Phase 2
Dict[str, Any] cleanup. This is a legitimate use case for Dict[str, Any]
since error context contains arbitrary debugging information for logging.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix test patches after startup_logging module extraction
Update test patches to reference ciris_engine.logic.runtime.startup_logging
instead of ciris_engine.logic.runtime.service_initializer for:
- _services_started
- _current_phase
- _log_service_started
These were moved to startup_logging.py to break the circular import between
module_loader and service_initializer.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix language rotation not stopping after startup completes
The rotation LaunchedEffect had a while(true) loop that never checked
if startup completed. This caused the temporary rotation language to
overwrite the user's preferred language (or English default) after
resetToPersistedLanguage() was called.
Fix: Add `phase` as a dependency and stop rotation when phase becomes
READY or FIRST_RUN_SETUP.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix 4 failing tests: JWT verification + my_data timeouts
1. test_sync_token_verification: Updated to use TokenVerification
object attributes instead of dict subscripts after return type
changed from dict to Pydantic model.
2. test_my_data.py (3 tests): Fixed timeouts caused by:
- Fixture name collision: renamed mock_runtime to my_data_mock_runtime
to avoid conflict with conftest.py fixture
- Signing key hang: added mock_signing_key_fallback fixture to prevent
_compute_agent_id_hash_from_signer() from blocking while trying to
initialize ciris_verify singleton in test environment
Test suite: 10,303 passed, 47 skipped, 0 failed
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add missing localization keys + location search API + lint tool
- Add 58 missing mobile.settings_* localization keys visible in Settings screen
- Fix CIRISApiClient: add HttpClient instances for searchLocations/getCountries
- Add tools/check_kotlin_localizations.py to detect missing keys
- Sync en.json to Android and Desktop localization directories
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Sync localization keys across all 16 languages
- Remove extra keys not in en.json from am, es, fr, ja, tr, ur
- Add missing startup/system/status sections to fr, ja
- Sync all language files to mobile directories
Test suite: 10,308 passed, 47 skipped
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add location search API to KMP protocol + desktop localizations
- Add searchLocations() and getCountries() to CIRISApiClientProtocol
- Add LocationResultData, LocationSearchResponse, CountryInfoData,
CountriesResponse data models
- Update SetupScreen, SetupState, SetupViewModel for location search
- Sync desktop localization files with ur.json (Urdu)
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add version display to BillingScreen + comprehensive help guide
Features:
- Add getAppVersion() and getAppBuildNumber() platform functions
- Display version at bottom of BillingScreen (v2.3.1 (77))
- Create HELP_INDEX.md with complete UI/UX documentation:
- 26 screens with purpose, features, and usage
- Troubleshooting guide
- Localization reference (16 languages)
- Keyboard shortcuts
Platform implementations:
- Android: PackageManager with caching
- iOS: NSBundle Info.plist
- Desktop: JAR manifest with fallback constant
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix adapter wizard button visibility in setup wizard
The "Configure Now" button wasn't appearing for adapters like Home Assistant
that have interactive configuration (wizard) workflows during first-run setup.
Root cause: Mobile app was incorrectly deriving requires_config from
requiredEnvVars instead of the adapter's interactive_config manifest field.
Changes:
- Add requires_config and config_fields to backend AdapterConfig model
- Add has_interactive_config to ModuleTypeInfo schema
- Update adapter discovery to detect interactive_config from manifest
- Update setup helpers to set requires_config from has_interactive_config
- Update mobile API model with new fields
- Update CIRISApiClient to use backend's requires_config value
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Complete localization (16 languages) + signing key preservation feature
Localization:
- Full UI translations for am, ar, de, es, fr, hi, it, ja, ko, pt, ru, sw, tr, ur, zh
- Localized DMA prompts for all 16 languages
- Localized conscience prompts for all 16 languages
- ACCORD polyglot compression and summaries
- Help guide translations
- Credit strings and new mobile UI strings
Signing Key Preservation (Data Management):
- Add clearDataOnly() to EnvFileUpdater (Android/iOS/Desktop)
- Soft reset preserves signing key for wallet access retention
- New "Wipe Signing Key" danger option with severe warnings
- Full translations for reset/wipe strings in all languages
Wallet & Providers:
- Add paymaster client for gas abstraction
- Provider validation and audit improvements
- Balance monitor enhancements
Infrastructure:
- Minimal dream processor refactor
- Location search API for setup wizard
- Attestation platform improvements
- Streaming verification enhancements
Testing & QA:
- Mobile QA runner improvements
- iOS physical device test support
- Localization completeness tests
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix localization sync: add mobile.setup_include_location to all languages
- Add setup_include_location key to mobile section in all 15 language files
- Sync localization files to mobile/androidApp, mobile/desktopApp, and mobile/shared
- Fixes test_localization_completeness and test_kotlin_localizations tests
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix SonarCloud code quality issues
- partnership.py: Merge implicitly concatenated strings
- location.py: Use Annotated type hints, remove redundant response_model
- system_snapshot_helpers.py: Merge implicitly concatenated strings
- dream_memorize_handler.py: Mark unused variables with _
- minimal_dream_processor.py: Re-raise CancelledError, use suppress() for intentional catch
- hashes.py: Merge implicitly concatenated strings
- llm.py: Define constant for duplicated literal "Total tokens used"
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add ISO 6709 coordinate storage and location utilities
- Add location_latitude/longitude fields to SetupCompleteRequest (ISO 6709 decimal degrees)
- Store coordinates in graph memory and .env during setup completion
- Create location_utils.py with UserLocation dataclass and helper functions:
- get_user_location(): Read location from env vars for tool context
- get_location_for_context_enrichment(): Format for context enrichment
- format_coordinates_for_trace(): Consent-gated trace metadata
- Update CIRISAccord metrics to include lat/long in correlation metadata
- Tools can now access user coordinates via environment variables when nav/weather enabled
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add user location support to weather and navigation adapters
Weather adapter:
- Use user location from setup as default (replaces separate config)
- Add weather:my_location context enrichment tool (5min cache)
- Dynamic tool descriptions show user's configured location
Navigation adapter:
- Store user location coordinates for routing
- Add navigation:my_location context enrichment tool (1hr cache)
- Add navigation:route_from_me tool for implicit start location
- Tools only appear when user location is available from setup
Both adapters now automatically consume location data set during
setup wizard, making weather and navigation features work seamlessly
without separate configuration.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix wallet attestation level and startup language rotation
Wallet (x402_provider.py):
- Fix attestation level showing 0/5 when hardware trust degraded
- Now fetches actual attestation level BEFORE checking hardware trust
- Passes real level to SpendingAuthority instead of hardcoding 0
Startup screen (StartupScreen.kt):
- Always rotate languages during startup as visual effect
- Removed hasExplicitLanguage condition that blocked rotation
- Language indicator now shows based on phase, not language selection
- Resets to persisted language when startup completes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add consolidator startup indication to mobile app
Backend (tsdb_consolidation/service.py):
- Add console output for mobile app: [CONSOLIDATOR] messages
- Output when checking for missed windows, processing periods, complete
Mobile (StartupViewModel.kt):
- Parse [CONSOLIDATOR] messages from console output
- Track consolidator status in StateFlow
- Don't timeout while consolidator is actively running
- Clear status 2 seconds after completion
Mobile (StartupScreen.kt):
- Display consolidator status with yellow indicator
- Shows "Checking for missed windows...", "Processing period X...", etc.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix flaky TSDB edge creation tests for parallel execution
Root cause: Tests were using global patching of get_db_connection which
caused race conditions when multiple tests ran in parallel. Multiple
tests patching the same global function simultaneously led to interference.
Fix:
- Replaced mock_db_connection fixture with test_db_path fixture using
unique temporary files (pytest's tmp_path) for true test isolation
- Tests now use separate SQLite database files per test
- Close connections before calling EdgeManager methods that create
their own connections to avoid WAL mode lock conflicts
- Removed all global patching except for explicit retry behavior tests
All 22 tests now pass reliably with -n 8 parallel execution.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add pre-commit hook to check localization sync
New pre-commit hook that BLOCKS commits if localization files are out
of sync with en.json. This prevents adding new English strings without
corresponding translations in all 16 supported languages.
Features:
- Checks all 16 language files against en.json keys
- Reports missing translations per language
- Reports extra keys that should be removed
- Only runs when localization/*.json files are modified
- Clear error messages with fix instructions
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add desktop scroll support and improve language selector UX
- Add PlatformScrollbar component (expect/actual) for desktop scrollbars
- Add scroll support to LoginScreen, StartupScreen, TelemetryScreen
- Center and highlight language selector on login screen
- Show "Interface + Agent" hint to clarify language affects reasoning
- Fix z-order so language selector is clickable on desktop
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix desktop factory reset, consent partnership, FFI loading, and test automation
Major fixes for the desktop wipe → setup wizard → agent flow:
- Fix CIRISVerify FFI loading: platform-aware suffix ordering (.dylib before
.so on macOS) with pip-installed package fallback. Symlink macOS dylib.
- Fix factory reset on desktop: preserve signing keys during data wipe,
delete databases in both ~/ciris/data/ and CWD/data/ (dev mode), detect
git repo root for correct data directory resolution.
- Fix .env location: remove CWD .env check (XDG best practices), use
~/ciris/.env as canonical location. Clear stale CIRIS_CONFIGURED env var
when .env file is deleted.
- Fix founding partnership consent node: use consent/{wa_id} pattern matching
ConsentService lookups. Pass wa_cert.wa_id instead of username.
- Fix config_migration partnership backfill: check consent/{wa_id} pattern.
- Fix _get_agent_id: add signing key fallback + detailed logging for
lens-identifier endpoint debugging.
- Fix desktop app restart after wipe: don't call exitProcess(), use
pythonRuntime.shutdown() + local-shutdown API, navigate to Startup screen.
- Fix PythonRuntime.desktop: treat empty cognitive_state as healthy (not stuck).
- Add /screenshot endpoint to test automation server (java.awt.Robot, gated
behind CIRIS_TEST_MODE).
- Add /mouse-click and /mouse-click-xy endpoints for real AWT mouse events
(works with ExposedDropdownMenuBox and other Compose popups).
- Add testableClickable to provider and model dropdowns in SetupScreen.
- Add postLocalShutdown() to CIRISApiClient for server restart.
- Add input_location_search testable tag and location_result_* tags.
- Add SwiftCapture-based video recording to demo clip script.
- Add E2E test script: tools/test_desktop_wipe_setup.sh.
- Bump version to 2.3.2.
Known issue: startup language rotation prevents E2E test from completing
autonomously (app stuck on Startup screen cycling through languages).
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix language rotation recomposition storm and consent node_id pattern
- Fix language sync to backend: only sync when user explicitly selects
a language (hasExplicitLanguageSelection), not during temporary
login screen language rotation. Prevents API spam and recomposition.
- Fix InteractViewModel pipeline label updates: skip temporary language
rotations, only update on explicit selection or English default.
- Fix founding partnership consent node_id: use consent/{wa_id} pattern
matching ConsentService lookups (was consent/{username}).
- Fix config_migration partnership backfill: check consent/{wa_id}.
- Fix test script: export OPENROUTER_API_KEY, wait for Login screen.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix CIRIS_ prefix env var support for LLM service initialization
The setup wizard writes CIRIS_OPENAI_API_KEY etc to .env, but the LLM
service only checked unprefixed OPENAI_API_KEY. This caused the server
to fail with "No API key found" after a clean setup.
- Add _env() helper to check CIRIS_ prefix first, then unprefixed
- Fix _detect_provider_from_env: check CIRIS_OPENAI_API_BASE
- Fix _get_api_key_for_provider: check CIRIS_ prefixed keys
- Fix main.py startup key check: include CIRIS_ prefixed vars
- Fix service_initializer fallback: check CIRIS_OPENAI_API_KEY
- Fix E2E test: clean data state before run, longer login timeout
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Bump version strings for iOS/Android and update Xcode project
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix wizard select step skip, document E2E UI automation workflow
- Fix AdapterWizardDialog: send "skip" for optional select steps with no
selection, preventing infinite re-fetch of options on cameras step.
- Fix server-side select step handler: accept "skip" and empty selection
for optional steps (step.optional=True), advancing to next step.
- Update mobile/CLAUDE.md: document full E2E automation workflow, all
test server endpoints, key testTags, platform differences (desktop
HTTP server vs iOS XCTest vs Android Espresso).
- Update tools/qa_runner/CLAUDE.md: document desktop E2E test script,
Home Assistant adapter setup flow, platform notes.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Replace login C with CIRIS signet, add first-run welcome message, fix iOS data wipe
- Replace plain "C" text with CIRISSignet composable on login screen
- Add first-run welcome message: "Welcome! Choose how to set up your AI assistant."
Localized to all 16 languages (am, ar, de, en, es, fr, hi, it, ja, ko, pt, ru, sw, tr, ur, zh)
- Show welcome message only on isFirstRun, returning users see normal tagline
- Fix iOS EnvFileUpdater.clearDataOnly: preserve agent_signing* files during
soft reset (same fix as desktop), prevents CIRISVerify key generation crash
- Sync localization files across all 3 directories (master, iOS bundle, desktop resources)
- Sync master localization to iOS app bundle (fixes missing _full keys on Data Management)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Add cross-platform test automation server (iOS POSIX sockets)
The test automation HTTP server is now available on iOS in addition to
desktop. iOS uses a POSIX socket server (no Ktor dependency needed for
K/N), providing the same endpoints: /health, /tree, /click, /input,
/wait, /screen, /element/{tag}.
Architecture:
- TestAutomationState (commonMain): shared element registry, click
handlers, screen tracking — used by all platforms
- TestAutomationHandler (commonMain): pure handler logic for endpoints
- TestServerModels (commonMain): serializable request/response models
- IOSTestAutomationServer (iosMain): POSIX socket HTTP server
- iOS TestAutomation actual: now functional (was no-op), delegates
to TestAutomationState, tracks element positions via onGloballyPositioned
- startTestAutomationServer() expect/actual: iOS starts POSIX server,
desktop no-op (Main.kt handles), Android TODO
Usage on iOS:
xcrun devicectl device process launch -d DEVICE_ID \
--environment-variables '{"CIRIS_TEST_MODE":"true"}' ai.ciris.mobile
iproxy 18091 8091 -u IDEVICE_ID &
curl http://127.0.0.1:18091/health # {"status":"ok","testMode":true}
curl http://127.0.0.1:18091/screen # {"screen":"Login"}
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Fix is_first_run content check, make login buttons automatable
- Fix is_first_run: check .env file contents for CIRIS_CONFIGURED="true",
not just file existence. Stub .env files (from failed wipe or manual push)
no longer prevent first-run detection.
- Make btn_local_login and btn_apple_signin testableClickable for automation
- iOS E2E validated: wipe → setup wizard → OpenRouter LLM → HA adapter
all driven via test automation server (POSIX sockets on port 8091)
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Update docs: cross-platform test automation, iOS E2E workflow
- mobile/CLAUDE.md: Document iOS POSIX socket test server, full iOS E2E
workflow (launch → iproxy → drive UI → HA OAuth via Chrome → verify),
iOS-specific gotchas (2s input delay, terminate-existing, callback
forwarding), split endpoint tables into shared vs desktop-only
- tools/qa_runner/CLAUDE.md: Add platform automation comparison table,
iOS E2E commands, iOS-specific gotchas section
- tools/CLAUDE.md: Add record_demo_clips.py and test_desktop_wipe_setup.sh
to standalone scripts table, add iOS E2E and demo recording to workflows
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Add 2.3.2 changelog entry
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Backfill 2.3.1 changelog entry
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Add Android test automation HTTP server (Ktor CIO)
- Add Ktor server dependencies to androidMain
- Create AndroidTestAutomationServer with same endpoints as Desktop/iOS
- Update TestAutomation.android.kt to track element positions
- Enable test mode via /data/local/tmp/ciris_test_mode file
- Start server in MainActivity.onCreate(), stop in onDestroy()
- Remove broken macOS dylib symlink
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix duplicate user messages: widen dedup window to 30 seconds
The optimistic local message add and the server-fetched message could
have timestamps on different sides of a 5-second boundary, producing
different dedup keys and showing the same message twice.
Widen the dedup window from 5s/10s to 30s for both USER and AGENT
messages. This prevents duplicates from the optimistic add + poll cycle
while still allowing legitimately repeated messages sent 30+ seconds apart.
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* Merge conflict resolution for test_prompt_formatting.py
* fix: robust CIRIS_HOME detection for Android/iOS settings persistence
Add multi-strategy path detection for Android and iOS platforms that
doesn't rely solely on CIRIS_HOME environment variable being set:
Android (_get_android_ciris_home):
1. Check CIRIS_HOME env var if set
2. Probe known package paths (/data/data/ai.ciris.mobile{,.debug}/files/ciris)
3. Fallback to Path.home()/ciris (Chaquopy sets HOME correctly)
iOS (_get_ios_ciris_home):
1. Check CIRIS_HOME env var if set
2. Probe Documents/ciris in iOS sandbox
3. Fallback with warning if path doesn't look like iOS
This fixes settings not persisting when the Python backend wrote to
a different path than where the mobile app expected to read config.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* docs: update CHANGELOG for 2.3.2 with CIRIS_HOME and dedup fixes
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* fix: update tests for 2.3.2 changes and add missing localization key
Localization:
- Add mobile.login_first_run_welcome key to all 15 language files
- Sync localization files to mobile/androidApp and mobile/shared
Test fixes for 2.3.2 behavioral changes:
- first_run tests: Update for standardized ~/ciris/.env config path
- founding_partnership tests: Update assertions for wa_id format (wa-{name})
- founding_partnership_migration tests: Fix helper to use correct consent node IDs
- my_data tests: Mock signing key fallback to prevent test hangs
All 10294 tests pass.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix P1/P2 issues from bot review
P2: Fix location parsing order - parse in same order as setup writes
(Country, Region, City instead of reversed order)
P1: Add coordinate parsing error handling - guard against invalid
float conversion with try/except and log warnings
P1: Document smart-account sender issue - ERC-4337 paymaster sends
assume deployed smart account but _evm_address is EOA. Added FIXME
comment and Known Issues section in CHANGELOG for #656.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
* Fix test_first_run tests for 2.3.2 behavior
Updated tests to reflect 2.3.2 changes:
- CWD-based .env detection was removed for consistency
- CIRIS_CONFIGURED env var alone is not sufficient; valid .env required
- Use CIRIS_CONFIG_DIR for explicit dev/test override
Tests now verify:
- test_is_first_run_with_env_var_only: env var alone IS first run
- test_is_first_run_cwd_env_not_auto_detected: CWD .env not detected
- test_is_first_run_with_config_dir_override: explicit override works
Also updated get_config_paths() docstring to match implementation.
🤖 Generated with [Claude Code](https://claude.com/claude-code)
Co-Authored-By: Claude Opus 4.5 <noreply@anthropic.com>
---------
Co-authored-by: Claude Opus 4.5 <noreply@anthropic.com>1 parent c0d2348 commit a59b8d7
217 files changed
Lines changed: 36715 additions & 23525 deletions
File tree
- android/app/src/main/python
- ciris_adapters
- ciris_accord_metrics
- ciris_verify/ffi_bindings
- wallet/providers
- ciris_engine
- logic
- adapters/api
- routes
- setup
- dma/prompts/localized
- am
- ar
- de
- es
- fr
- hi
- it
- ja
- ko
- pt
- ru
- sw
- tr
- ur
- zh
- persistence
- runtime
- services/runtime
- adapter_configuration
- llm_service
- setup
- utils
- ios/CirisiOS/src/ciris_ios
- localization
- mobile
- androidApp
- src/main
- assets/localization
- kotlin/ai/ciris/mobile
- python
- desktopApp/src/main
- kotlin/ai/ciris/desktop
- testing
- resources/localization
- iosApp
- iosApp.xcodeproj
- iosApp
- localization
- qa_reports
- tests
- adapters/api
- ciris_engine/logic
- adapters/api/routes
- dma
- runtime
- setup
- tools
- qa_runner
Some content is hidden
Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
5 | 5 | | |
6 | 6 | | |
7 | 7 | | |
| 8 | + | |
| 9 | + | |
| 10 | + | |
| 11 | + | |
| 12 | + | |
| 13 | + | |
| 14 | + | |
| 15 | + | |
| 16 | + | |
| 17 | + | |
| 18 | + | |
| 19 | + | |
| 20 | + | |
| 21 | + | |
| 22 | + | |
| 23 | + | |
| 24 | + | |
| 25 | + | |
| 26 | + | |
| 27 | + | |
| 28 | + | |
| 29 | + | |
| 30 | + | |
| 31 | + | |
| 32 | + | |
| 33 | + | |
| 34 | + | |
| 35 | + | |
| 36 | + | |
| 37 | + | |
| 38 | + | |
| 39 | + | |
| 40 | + | |
| 41 | + | |
| 42 | + | |
| 43 | + | |
8 | 44 | | |
9 | 45 | | |
10 | 46 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
17 | 17 | | |
18 | 18 | | |
19 | 19 | | |
20 | | - | |
| 20 | + | |
21 | 21 | | |
22 | 22 | | |
23 | 23 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
10 | | - | |
| 10 | + | |
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
503 | 503 | | |
504 | 504 | | |
505 | 505 | | |
506 | | - | |
507 | | - | |
| 506 | + | |
| 507 | + | |
| 508 | + | |
| 509 | + | |
| 510 | + | |
| 511 | + | |
| 512 | + | |
| 513 | + | |
| 514 | + | |
| 515 | + | |
| 516 | + | |
| 517 | + | |
508 | 518 | | |
509 | 519 | | |
510 | 520 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
305 | 305 | | |
306 | 306 | | |
307 | 307 | | |
308 | | - | |
| 308 | + | |
309 | 309 | | |
310 | | - | |
| 310 | + | |
| 311 | + | |
| 312 | + | |
| 313 | + | |
| 314 | + | |
| 315 | + | |
| 316 | + | |
311 | 317 | | |
312 | 318 | | |
313 | 319 | | |
314 | 320 | | |
| 321 | + | |
| 322 | + | |
| 323 | + | |
| 324 | + | |
| 325 | + | |
| 326 | + | |
| 327 | + | |
| 328 | + | |
| 329 | + | |
| 330 | + | |
| 331 | + | |
| 332 | + | |
315 | 333 | | |
316 | 334 | | |
317 | 335 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
717 | 717 | | |
718 | 718 | | |
719 | 719 | | |
| 720 | + | |
| 721 | + | |
| 722 | + | |
| 723 | + | |
| 724 | + | |
| 725 | + | |
| 726 | + | |
| 727 | + | |
720 | 728 | | |
721 | 729 | | |
722 | 730 | | |
723 | | - | |
| 731 | + | |
724 | 732 | | |
725 | 733 | | |
726 | 734 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
3 | 3 | | |
4 | 4 | | |
5 | 5 | | |
6 | | - | |
| 6 | + | |
7 | 7 | | |
8 | 8 | | |
9 | 9 | | |
10 | | - | |
| 10 | + | |
11 | 11 | | |
12 | 12 | | |
13 | 13 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
52 | 52 | | |
53 | 53 | | |
54 | 54 | | |
| 55 | + | |
| 56 | + | |
55 | 57 | | |
56 | 58 | | |
57 | 59 | | |
| |||
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
175 | 175 | | |
176 | 176 | | |
177 | 177 | | |
| 178 | + | |
| 179 | + | |
178 | 180 | | |
179 | 181 | | |
180 | 182 | | |
181 | | - | |
| 183 | + | |
| 184 | + | |
| 185 | + | |
| 186 | + | |
182 | 187 | | |
183 | 188 | | |
184 | 189 | | |
185 | 190 | | |
186 | 191 | | |
187 | 192 | | |
188 | 193 | | |
| 194 | + | |
189 | 195 | | |
| 196 | + | |
| 197 | + | |
| 198 | + | |
| 199 | + | |
| 200 | + | |
| 201 | + | |
| 202 | + | |
190 | 203 | | |
191 | 204 | | |
192 | 205 | | |
193 | 206 | | |
194 | 207 | | |
195 | 208 | | |
| 209 | + | |
196 | 210 | | |
| 211 | + | |
| 212 | + | |
| 213 | + | |
| 214 | + | |
| 215 | + | |
197 | 216 | | |
198 | 217 | | |
199 | 218 | | |
200 | 219 | | |
201 | 220 | | |
202 | 221 | | |
203 | | - | |
| 222 | + | |
204 | 223 | | |
| 224 | + | |
| 225 | + | |
| 226 | + | |
| 227 | + | |
205 | 228 | | |
206 | 229 | | |
207 | 230 | | |
208 | 231 | | |
| 232 | + | |
209 | 233 | | |
210 | 234 | | |
211 | | - | |
212 | | - | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
| 238 | + | |
| 239 | + | |
| 240 | + | |
| 241 | + | |
| 242 | + | |
| 243 | + | |
| 244 | + | |
| 245 | + | |
| 246 | + | |
| 247 | + | |
| 248 | + | |
| 249 | + | |
| 250 | + | |
213 | 251 | | |
214 | 252 | | |
215 | 253 | | |
216 | | - | |
| 254 | + | |
| 255 | + | |
217 | 256 | | |
218 | 257 | | |
219 | 258 | | |
| |||
297 | 336 | | |
298 | 337 | | |
299 | 338 | | |
| 339 | + | |
300 | 340 | | |
301 | 341 | | |
| 342 | + | |
| 343 | + | |
| 344 | + | |
| 345 | + | |
302 | 346 | | |
303 | 347 | | |
304 | 348 | | |
| |||
Lines changed: 30 additions & 15 deletions
| Original file line number | Diff line number | Diff line change | |
|---|---|---|---|
| |||
194 | 194 | | |
195 | 195 | | |
196 | 196 | | |
197 | | - | |
| 197 | + | |
198 | 198 | | |
199 | 199 | | |
200 | 200 | | |
| |||
203 | 203 | | |
204 | 204 | | |
205 | 205 | | |
206 | | - | |
207 | | - | |
| 206 | + | |
| 207 | + | |
| 208 | + | |
| 209 | + | |
| 210 | + | |
208 | 211 | | |
209 | 212 | | |
210 | 213 | | |
| |||
214 | 217 | | |
215 | 218 | | |
216 | 219 | | |
217 | | - | |
| 220 | + | |
218 | 221 | | |
219 | 222 | | |
220 | 223 | | |
| |||
228 | 231 | | |
229 | 232 | | |
230 | 233 | | |
| 234 | + | |
| 235 | + | |
| 236 | + | |
| 237 | + | |
231 | 238 | | |
232 | | - | |
| 239 | + | |
233 | 240 | | |
234 | 241 | | |
235 | 242 | | |
| 243 | + | |
236 | 244 | | |
237 | 245 | | |
238 | 246 | | |
| |||
252 | 260 | | |
253 | 261 | | |
254 | 262 | | |
255 | | - | |
| 263 | + | |
| 264 | + | |
| 265 | + | |
256 | 266 | | |
257 | 267 | | |
258 | 268 | | |
| |||
377 | 387 | | |
378 | 388 | | |
379 | 389 | | |
380 | | - | |
381 | | - | |
382 | | - | |
383 | | - | |
384 | | - | |
385 | | - | |
| 390 | + | |
| 391 | + | |
| 392 | + | |
386 | 393 | | |
387 | | - | |
388 | | - | |
| 394 | + | |
| 395 | + | |
389 | 396 | | |
390 | 397 | | |
391 | 398 | | |
| |||
760 | 767 | | |
761 | 768 | | |
762 | 769 | | |
763 | | - | |
| 770 | + | |
| 771 | + | |
| 772 | + | |
| 773 | + | |
| 774 | + | |
| 775 | + | |
| 776 | + | |
| 777 | + | |
| 778 | + | |
764 | 779 | | |
765 | 780 | | |
766 | 781 | | |
| |||
0 commit comments