The previous client_id pointed to a GitHub App that did not have
device authorization flow enabled, causing "failed to start login"
errors. Switch to the refactoringhq OAuth App (Ov23liwee215tDMs9u4L)
which supports device flow.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The GitHub App (Ov23liCuBz7Z5hKk6T8c) does not have Device
authorization flow enabled — GitHub returns 404. The error message
now includes specific setup steps so the user can fix the
configuration.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
The frontend was swallowing Tauri backend errors (which are strings,
not Error instances) and always showing generic "Failed to start login."
Now the actual error message is displayed. Also adds User-Agent header
to device flow requests, a clear error message for 404 responses, and
a test for the 404 case.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
Coverage was 83.83% (below 85% threshold). Added mockito-based HTTP mock
tests for all OAuth device flow functions, list/create repo, get user,
and send_chat. Coverage now at 90.26%.
- github.rs: 55.99% → 94.85% (added mock tests for all HTTP functions)
- ai_chat.rs: 63.27% → 95.70% (added mock tests for send_chat paths)
- Added mockito = "1" as dev-dependency
- Refactored HTTP functions to accept configurable base URLs for testability
- Add serialization tests for DeviceFlowStart, DeviceFlowPollResult, GitHubUser
- Add SettingsPanel tests for OAuth section: login button, connected state,
disconnect, waiting state with user code, no token field
- All 174 Rust + 475 frontend tests pass
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
- Add github_username to Settings type (Rust + TS)
- Add device flow commands: github_device_flow_start, github_device_flow_poll, github_get_user
- Replace manual token KeyField with "Login with GitHub" OAuth button
- Show connected state with username after successful OAuth
- Add disconnect functionality to clear OAuth token
- Update mock-tauri.ts with device flow mock handlers
- Update all tests for new Settings shape
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* ci: auto-release workflow on merge to main
Rewrite .github/workflows/release.yml to trigger on every push to main
instead of manual tag pushes. The workflow now:
- Computes version as 0.YYYYMMDD.GITHUB_RUN_NUMBER
- Builds aarch64-apple-darwin and x86_64-apple-darwin in parallel
- Merges them into a universal binary using lipo
- Creates a universal .dmg and signed updater tarball
- Generates latest.json with per-arch and universal platform entries
- Publishes a GitHub Release with auto-generated release notes
- Updates a GitHub Pages release history site (gh-pages branch)
Product decisions:
- Universal binary approach: copy arm64 .app as base, lipo the main
executable, keep everything else from arm64 (shared frameworks are
architecture-independent). This is the standard Tauri pattern.
- Per-arch updater tarballs are also uploaded so the Tauri updater can
download the correct arch-specific build (smaller download).
- Release notes are auto-generated from git log since last tag.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* ci: github pages with release history
Use peaceiris/actions-gh-pages@v4 to deploy a release history site.
The page fetches releases.json (also deployed) and renders each release
with date, notes, and download links for .dmg files.
This handles the gh-pages branch creation automatically on first run.
The page is available at https://refactoringhq.github.io/laputa-app/
Product decision: used fetch() to load releases.json at runtime instead
of inlining it, which is cleaner and avoids shell escaping issues with
release note content. The releases.json is deployed alongside index.html.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* feat: in-app update notification UI
Replace the old window.confirm updater with a proper React-based
update notification system:
- useUpdater hook now exposes state machine (idle → available →
downloading → ready) and actions (startDownload, openReleaseNotes,
dismiss)
- UpdateBanner component renders at the top of the app shell:
- "Available" state: shows version, Release Notes link, Update Now
button, dismiss X
- "Downloading" state: animated spinner, progress bar with percentage
- "Ready" state: Restart Now button to apply the update
- Silently checks on startup after 3s delay; fails silently on
network errors or 404
- Release Notes link opens the GitHub Pages release history site
Product decisions:
- Banner at top of app (not a modal) — non-intrusive, visible but
not blocking. User can dismiss and continue working.
- Progress bar shows during download so user knows it's working.
- Separate "Restart Now" state after download so user controls when
the app restarts (they may have unsaved work).
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* test: updater component tests
Rewrite useUpdater hook tests and add UpdateBanner component tests:
Hook tests (10 cases):
- Starts in idle state
- Does nothing when not in Tauri
- Checks for updates after 3s delay
- Stays idle when no update available
- Transitions to available when update found
- Handles missing release body gracefully
- Stays idle on network error (fails silently)
- Dismiss returns to idle
- openReleaseNotes opens correct URL
- startDownload transitions through downloading to ready
Component tests (10 cases):
- Renders nothing when idle
- Renders nothing on error
- Shows version and buttons when available
- Update Now calls startDownload
- Release Notes calls openReleaseNotes
- Dismiss button works
- Shows progress bar during download
- Shows 0% at start of download
- Shows restart button when ready
- Restart button calls restartApp
All 457 tests pass.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* design: auto-build-release wireframes
Copy ui-design.pen as base. Frames to be added for:
1. Update notification banner (visible state) — horizontal bar at
top of app shell with version text, Release Notes link, Update
Now button, and dismiss X
2. Update download progress state — spinner icon, progress bar with
percentage, downloading text
3. "Restart to apply" state — green accent, version text, Restart
Now button
Note: Pencil editor was not available during this session. The base
design file is committed; frames will be added when the editor is
accessible. The implemented component (UpdateBanner.tsx) serves as
the source of truth for the design.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* docs: update ARCHITECTURE.md with release/update system
Add comprehensive documentation for:
- Release pipeline (4-phase workflow: version → build → release → pages)
- Versioning scheme (0.YYYYMMDD.RUN_NUMBER)
- Universal binary strategy (lipo merge)
- Updater endpoint and latest.json manifest
- In-app update UI state machine
- GitHub Pages release history site
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
* fix: rustfmt formatting
* fix: rustfmt build.rs
---------
Co-authored-by: Claude Opus 4.6 <noreply@anthropic.com>
Refactor settings.rs to expose testable internal functions (get_settings_at,
save_settings_at) and add integration tests for file I/O roundtrips, whitespace
trimming, directory creation, and malformed JSON handling. Coverage for
settings.rs improved from 46% to 91%. Overall Rust coverage now 86.2% (above
85% threshold). Also add coverage/ to .gitignore.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
New github.rs module with three commands:
- github_list_repos: lists user's repos via GitHub API (paginated)
- github_create_repo: creates a new repo with auto_init
- clone_repo: git clone with HTTPS+token auth, configures remote
Also extends Settings with github_token field (Rust + TypeScript),
and adds GithubRepo type to shared types.
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>