Skip to content

docs: record native dashboard app design and work plan - #236

Merged
jeremymcs merged 8 commits into
mainfrom
jeremymcs/native-dashboard-app
Sep 29, 2026
Merged

jeremymcs merged 8 commits into
mainfrom
jeremymcs/native-dashboard-app

Conversation

@jeremymcs

Copy link
Copy Markdown
Member

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

  • Add a proposed ADR for a Tauri 2 dashboard on macOS, Windows, and Linux, backed by the Python daemon in a user-created venv.
  • Add a work plan for installation management, multi-repo health, project charts, app updates, and cross-platform builds.
  • Record the release and migration decisions: separate app-v* tags, unsigned prereleases, Linux .deb and AppImage packages, and replacement of the Swift app after parity.

Risk Assessment

⚠️ Medium: The docs follow the required design, but the macOS update delivery step and one proposed chart need correction before their slices are implemented.

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.

  • Live validation: ⚠️ no-surface - 0 of 3 scenarios driven live against the product
Scenario Result Live Evidence
Reviewer opens the ADR and work plan to review the native app decisions and delivery slices ⏸️ untested no The changed files are design documents. There is no running product behavior to drive for this documentation scenario.
User launches the app to manage installations, updates, and project stats ⏸️ untested no The Tauri app is planned but is not implemented in this commit. A runnable app build is needed for live validation.
A foreign page attempts a daemon write and the daemon rejects it ⏸️ untested no This commit contains no daemon change. The separate A0 implementation and a running daemon are needed to test this guard.
  • Outcome: ⚠️ 1 warning across 1 run (1m33s)

Pipeline

Updates from git push no-mistakes

✅ **intent** - passed

✅ No issues found.

✅ **Rebase** - passed

✅ No issues found.

⚠️ **Review** - 2 warnings
  • 🚨 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/refresh with a bodyless POST in daemon/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 from gsd_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 mentions daemon/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 next app-v* pre-release. Tauri’s documented GitHub releases/latest/download/latest.json endpoint cannot serve it: GitHub excludes pre-releases from latest, 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 treats gsd_daemon uninstall as proof that the old Swift login item was retired. On macOS, Installer.uninstall() runs its osascript removal with check=False and 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 running tray --serve process alive; the app then reuses that process. The old serve.py POST 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 use KeepAlive and Linux units use Restart=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 remain 0.1.0 despite 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 uses pip install --upgrade for 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 /status has no version, but does not establish that the process is a GSD Path daemon. A different local service can return versionless /status JSON 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.gz update 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.
⚠️ **Test** - 1 warning
  • ⚠️ this change has no live-validatable surface; proceed without live validation? (0 of 3 scenarios were driven live against the product); Reviewer opens the ADR and work plan to review the native app decisions and delivery slices: The changed files are design documents. There is no running product behavior to drive for this documentation scenario.; User launches the app to manage installations, updates, and project stats: The Tauri app is planned but is not implemented in this commit. A runnable app build is needed for live validation.; A foreign page attempts a daemon write and the daemon rejects it: This commit contains no daemon change. The separate A0 implementation and a running daemon are needed to test this guard.
  • Live validation: ⚠️ no-surface - 0 of 3 scenarios driven live against the product
Scenario Result Live Evidence
Reviewer opens the ADR and work plan to review the native app decisions and delivery slices ⏸️ untested no The changed files are design documents. There is no running product behavior to drive for this documentation scenario.
User launches the app to manage installations, updates, and project stats ⏸️ untested no The Tauri app is planned but is not implemented in this commit. A runnable app build is needed for live validation.
A foreign page attempts a daemon write and the daemon rejects it ⏸️ untested no This commit contains no daemon change. The separate A0 implementation and a running daemon are needed to test this guard.
  • Read both changed documentation files
  • git diff --name-status cf08cee52dccb92c5f29568f1424d9162e5533b3..7b24e8bc5e26987cfa288fe1a7d23f8e8903a25c
  • git diff --check cf08cee52dccb92c5f29568f1424d9162e5533b3..7b24e8bc5e26987cfa288fe1a7d23f8e8903a25c
  • Checked 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.

@jeremymcs
jeremymcs merged commit 94d1028 into main Sep 29, 2026
9 checks passed
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.

1 participant