docs: record native dashboard app design and work plan - #236
Merged
Merged
Conversation
ADR 0005 picks one Tauri 2 app for macOS, Windows, and Linux, with the Python daemon as its backend in a venv. The work plan splits it into slices A0-A6 with a proof for each. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Intent
Docs-only PR: record the design and work plan for a native dashboard app. The owner wants installation and management of GSD Path to be easier, especially with multi-repo, and wants a native app for each OS (macOS, Windows, Linux) that manages installations for projects, updates the plugin and the app itself, and shows visual stats on projects. Owner rulings recorded 2026-09-29: Tauri 2 as the shell (over Electron or three native shells); replace the existing Swift macOS app in daemon/macos once the new app reaches parity; ship unsigned builds first and add OS code signing before a public release; the app uses its own app-v* release tags separate from the npm version; Linux ships .deb and AppImage only (no .rpm). Deliberate design choice: the Python daemon stays the backend and runs from a venv built with the user's Python 3.9+, NOT a frozen PyInstaller sidecar, because projects need Python anyway and the daemon runs install.py and status_runtime.py via sys.executable which breaks when frozen. The app never copies helper logic; it calls install.py/members.py. Joining a multi-repo member stays in the router (owner ruling); the app only does member hook install and marker repair. Slice A0 (same-origin checks on daemon POST routes) is tracked separately in the jeremymcs/daemon-post-same-origin branch and must land before any app build is published. Files: docs/adr/0005-native-dashboard-app.md (status: proposed) and docs/native-app-work.md. Use simplified technical English. PR body must not credit AI beyond the required attribution footer.
What Changed
app-v*tags, unsigned prereleases, Linux.deband AppImage packages, and replacement of the Swift app after parity.Risk Assessment
Testing
The patch integrity and documentation links checked out. The commit contains no runnable app, daemon change, or UI surface, so no live scenario or visual artifact could be produced.
Pipeline
Updates from git push no-mistakes
✅ **intent** - passed
✅ No issues found.
✅ **Rebase** - passed
✅ No issues found.
docs/native-app-work.md:26- A2 attaches builds with no OS code signing to a GitHub Release. That conflicts with the required owner ruling, “add OS code signing before a public release.” Decide where unsigned builds will be kept for testing, or require OS signing before publishing this release.docs/native-app-work.md:24- A0 requires a JSON body on every POST route, but the existing dashboard calls/api/refreshwith a bodyless POST indaemon/gsd_daemon/serve.py. Applying A0 as written breaks refresh. Include the client request change in A0's plan and proof.docs/native-app-work.md:25- A1 says the app reuses a daemon already on the port and stops the daemon on quit. If the daemon was started by the existing login service or CLI, quitting the app would stop a process it did not start. Specify whether a reused daemon stays running; if so, stop only an app-owned process.docs/native-app-work.md:30- A6 removes autostart fromgsd_daemon install, although the contract keeps that CLI installer for scripts. An existing script that installs the background daemon would lose its startup behavior. The owner ruling requires replacing the Swift app, not removing this CLI behavior; remove this part of A6 unless the owner authorizes that change.docs/native-app-work.md:53- A6's proof checks only that source text no longer mentionsdaemon/macos; this new ADR and plan themselves mention it, and text absence cannot prove the replacement launches correctly. Use an executable install and launch check for the behavior, and review active documentation separately.docs/native-app-work.md:25- A1 adds an offline first-run guarantee and bundled wheels across the supported systems and Python versions. No stated intent requirement needs offline installation. Remove that guarantee and its wheel-bundling work unless the owner wants it in scope.🔧 Fix applied.
1 error still open:
docs/native-app-work.md:30- A6 removes the autostart installer code but does not retire registrations made by earlier installs. An existing LaunchAgent, Startup shortcut, systemd unit, or Swift login item can still start at login after the new app is installed, contradicting the stated decision that the app becomes the only autostart path. Plan a migration using the existing uninstall behavior, and prove it with an upgrade from an installed version.🔧 Fix applied.
2 errors still open:
docs/native-app-work.md:27- A3 has no stable way to find the nextapp-v*pre-release. Tauri’s documented GitHubreleases/latest/download/latest.jsonendpoint cannot serve it: GitHub excludes pre-releases fromlatest, and this repository also publishes npm releases there. A URL pinned to one app tag cannot discover N+1. Choose an app-specific update index and prove a pre-release update after a newer npm release. That release-routing choice extends the stated plan and needs owner approval. Tauri updater, GitHub release behavior.docs/native-app-work.md:30- A6 treatsgsd_daemon uninstallas proof that the old Swift login item was retired. On macOS,Installer.uninstall()runs itsosascriptremoval withcheck=Falseand returns success even if removal fails. If System Events denies that request, the old item remains and both apps start at the next login. Require the migration to verify removal and surface a failed cleanup before claiming that only the new app autostarts.🔧 Fix applied.
1 error still open:
docs/native-app-work.md:25- A1 reuses a daemon already on the port without requiring the A0 protections. On Windows, an upgrade removes the old Startup shortcut but leaves its runningtray --serveprocess alive; the app then reuses that process. The oldserve.pyPOST handler accepts JSON without checking Host, Origin, or Content-Type, so a foreign page can still reach write routes after A0 lands. Decide whether the app should replace an incompatible daemon or block writes until it is restarted; that choice changes the approved reuse behavior.🔧 Fix applied.
2 errors still open:
docs/native-app-work.md:25- A2 can publish a tester build before A6, but A1 must replace an old daemon already on the port. Existing macOS LaunchAgents useKeepAliveand Linux units useRestart=always, so stopping that daemon makes it restart and reclaim the port. Move legacy autostart cleanup before replacement, or require A6 before the first published build.docs/native-app-work.md:25- The reuse check needs a version that advances with daemon code. Both current daemon version definitions remain0.1.0despite later code changes. If app N+1 bundles changed daemon code with that same version, it will reuse N’s process and may miss the backend behavior it needs. Require a daemon version bump for changed builds and prove the check with two distinct builds.🔧 Fix applied.
2 errors still open:
docs/native-app-work.md:25- A1 installs the bundled daemon into the shared venv before comparing the running daemon’s version. The existing installer usespip install --upgradefor that local package. If a newer CLI daemon is running, launching an older app can replace its installed files with the older bundle, reuse the newer process, then run old code when that process restarts. Compare versions before changing the venv, and keep the newer installed package. pip install behavior.docs/native-app-work.md:25- A1 says to stop a process on the dashboard port when/statushas no version, but does not establish that the process is a GSD Path daemon. A different local service can return versionless/statusJSON and reach that stop path. The missing policy decision is whether the app may stop a process it cannot identify as its daemon; require daemon identity before replacement and define the port-conflict behavior.🔧 Fix applied.
2 warnings still open:
docs/native-app-work.md:26- A2 lists a DMG for macOS, but A3 needs a downloadable signed.app.tar.gzupdate bundle. A Mac installed at version N cannot update from the listed DMG alone. Add publication of the macOS updater bundle and its signature to the release plan. Tauri updater documentation.docs/native-app-work.md:29- The new time-per-phase chart has no reliable record for phases completed while the app-owned daemon is stopped: the daemon records phase changes only while watching, and the project log keeps dates rather than elapsed times. No stated requirement needs this specific chart. Remove it from A5 rather than imply complete phase durations.Read both changed documentation filesgit diff --name-status cf08cee52dccb92c5f29568f1424d9162e5533b3..7b24e8bc5e26987cfa288fe1a7d23f8e8903a25cgit diff --check cf08cee52dccb92c5f29568f1424d9162e5533b3..7b24e8bc5e26987cfa288fe1a7d23f8e8903a25cChecked both linked documentation targets exist and the worktree remains clean✅ **Document** - passed
✅ No issues found.
✅ **Lint** - passed
✅ No issues found.
✅ **Push** - passed
✅ No issues found.