Skip to content

fix: three correctness/UX bugs from post-launch hunt#409

Merged
kelsonpw merged 1 commit into
mainfrom
kelsonpw/fix-bug-batch
Apr 30, 2026
Merged

fix: three correctness/UX bugs from post-launch hunt#409
kelsonpw merged 1 commit into
mainfrom
kelsonpw/fix-bug-batch

Conversation

@kelsonpw

@kelsonpw kelsonpw commented Apr 30, 2026

Copy link
Copy Markdown
Member

Summary

Three independent fixes from a post-launch bug hunt. Batched to avoid PR sprawl. Each is small and self-contained.

1. Unity & Unreal projects rejected by wizard plan / wizard apply

Cause: src/utils/project-marker.ts:32-46 listed only fixed-name top-level manifests. Unity's marker (ProjectSettings/ProjectVersion.txt) lives in a sub-path; Unreal's filename varies (<ProjectName>.uproject). Neither matched. Both frameworks are in FRAMEWORK_REGISTRY and their detectors work — but every Unity/Unreal user who ran wizard plan or wizard apply from their project root hit "no project manifest" and was told to pass --force or --install-dir.

Fix: Added PROJECT_MARKER_PATHS (sub-path matches; covers Unity) and PROJECT_MARKER_EXTENSIONS (extension matches; covers Unreal) alongside the existing PROJECT_MARKER_FILES. Single non-recursive readdir for the extension scan. Bounded cost.

Tests: 4 new in project-marker.test.ts — Unity layout, Unreal .uproject (with arbitrary names), extension-only-doesn't-match-arbitrary-files sanity check.

2. Dashboard step never wrote the canonical .amplitude/dashboard.json

Cause: Pre-#154 the agent wrote .amplitude-dashboard.json and a file watcher in agent-interface.ts mirrored it to the canonical <installDir>/.amplitude/dashboard.json via persistDashboard(). #154 moved dashboard creation OUT of the agent loop, so the watcher never fires. The step at src/steps/create-dashboard.ts:147 writes ONLY the legacy path; the canonical file is silently never populated. /diagnostics advertises the canonical path. Anything reading from it (skill packs, repeat-runs, external integrations) gets ENOENT.

Fix: Invoke persistDashboard(installDir, result) after the legacy write. Best-effort — persistDashboard already swallows fs errors internally; a failure here must not fail the wizard. The DashboardUrl in ampli.json was already preserved via wizardSuccessExit's setupComplete payload — only the .amplitude/dashboard.json mirror was missing.

3. /debug, /diagnostics, and ScreenErrorBoundary corrupted the TUI by writing to stderr

Cause: All three sites called process.stderr.write(...) while Ink owned the terminal. Ink's diff-based redraw doesn't account for direct stderr writes — the JSON either got painted over or interleaved with the live frame. try/catch only swallows EPIPE; it doesn't fix the corruption. The user reported /debug and /diagnostics "seem buggy" — this is why.

Fix:

  • /debug writes the snapshot to <runDir>/debug-snapshot.json and surfaces the path in the feedback bar. User can cat it after the wizard exits, or paste it directly into a bug report.
  • /diagnostics writes the storage-paths text to <runDir>/diagnostics.txt and surfaces the path. Same shape.
  • ScreenErrorBoundary drops the stderr write entirely; the same payload already goes to the wizard log file via logToFile. Support gets the snapshot at full fidelity from the log; the user gets a clean error screen.

Test plan

  • pnpm test — 62 / 62 in the touched test files (project-marker +4, create-dashboard 24/24, console-commands 26/26)
  • pnpm lint clean
  • CI green
  • Manual: /debug from inside the wizard — feedback bar shows summary + path; live frame stays clean; cat <path> outside the wizard returns the JSON
  • Manual: /diagnostics ditto
  • Manual: wizard plan against a Unity project root with ProjectSettings/ProjectVersion.txt — no longer rejected
  • Manual: wizard plan against an Unreal project root with MyGame.uproject — no longer rejected
  • Manual: successful run → <installDir>/.amplitude/dashboard.json exists with the same content as .amplitude-dashboard.json

🤖 Generated with Claude Code


Note

Medium Risk
Moderate risk because it changes project-root validation logic and alters where diagnostics/debug output is written (filesystem paths/permissions), which could affect CLI/TUI behavior across platforms.

Overview
Fixes three post-launch correctness/UX issues.

Dashboard creation now also mirrors the generated dashboard JSON into the canonical <installDir>/.amplitude/dashboard.json via persistDashboard, restoring downstream consumers that rely on getDashboardFile().

TUI /debug and /diagnostics stop writing to stderr during Ink rendering; they instead save artifacts into the per-run directory (debug-snapshot.json, diagnostics.txt) and only display the path/summary in-console. ScreenErrorBoundary similarly drops its stderr diagnostic dump and relies on log-file capture.

Project-root detection is expanded to accept Unity and Unreal projects by adding sub-path markers (ProjectSettings/ProjectVersion.txt) and root-level extension markers (.uproject), with regression tests covering both cases.

Reviewed by Cursor Bugbot for commit d8e80bf. Bugbot is set up for automated code reviews on this repo. Configure here.

Three independent fixes batched to avoid PR sprawl. Each is small and
self-contained.

## 1. Unity & Unreal projects rejected by `wizard plan` / `wizard apply`

`src/utils/project-marker.ts:32-46` listed only fixed-name top-level
manifests. Unity's marker (`ProjectSettings/ProjectVersion.txt`) lives
in a sub-path and Unreal's filename varies (`<ProjectName>.uproject`),
so neither matched. Both frameworks are in `FRAMEWORK_REGISTRY` and
their detectors work, but every Unity/Unreal user who ran `wizard plan`
or `wizard apply` from their project root hit "no project manifest" and
was told to pass `--force` or `--install-dir`.

Fix: add `PROJECT_MARKER_PATHS` (sub-path matches; covers Unity) and
`PROJECT_MARKER_EXTENSIONS` (extension matches; covers Unreal), plus a
single non-recursive `readdir` for the extension scan. 4 new tests in
`project-marker.test.ts`: Unity layout, Unreal `.uproject` (any name),
extension-only-doesn't-match-arbitrary-files sanity check.

## 2. Dashboard step never wrote the canonical `.amplitude/dashboard.json`

Pre-#154 the agent wrote `.amplitude-dashboard.json` and a watcher in
`agent-interface.ts` mirrored it to the canonical
`<installDir>/.amplitude/dashboard.json` via `persistDashboard()`.
Since #154 moved dashboard creation OUT of the agent loop, the watcher
never fires. The step at `src/steps/create-dashboard.ts:147` writes
ONLY the legacy path, so the canonical file is silently never
populated. `/diagnostics` advertises the canonical path; reading from
that path (skill packs, repeat-runs, external integrations) returns
ENOENT.

Fix: invoke `persistDashboard(installDir, result)` after the legacy
write. Best-effort — `persistDashboard` already swallows fs errors
internally; a failure here must not fail the wizard. ampli.json
`DashboardUrl` was already preserved via `wizardSuccessExit`'s
setupComplete payload — only the `.amplitude/dashboard.json` mirror
was missing.

## 3. `/debug`, `/diagnostics`, and ScreenErrorBoundary corrupted Ink

All three sites called `process.stderr.write(...)` while Ink owned the
terminal. Ink's diff-based redraw doesn't account for direct stderr
writes — the JSON either got painted over or interleaved with the
live frame. `try/catch` only swallows EPIPE; it doesn't fix the
corruption. The user reported `/debug` and `/diagnostics` "seem
buggy" — this is why.

Fix:
- `/debug` writes the snapshot to
  `<runDir>/debug-snapshot.json` and surfaces the path in the
  feedback bar. User can `cat` it after the wizard exits.
- `/diagnostics` writes the storage-paths text to
  `<runDir>/diagnostics.txt` and surfaces the path. Same shape.
- `ScreenErrorBoundary` drops the stderr write entirely; the same
  payload already goes to the wizard log file via `logToFile`.
  Support gets the snapshot at full fidelity from the log; the user
  gets a clean error screen.

## Tests

- `project-marker.test.ts`: 8 → 12 (4 new Unity/Unreal cases)
- `create-dashboard.test.ts`: 24 / 24 (existing tests cover the
  parser; the new mirror call is a fire-and-forget side effect on
  an already-tested path)
- `console-commands.test.ts`: 26 / 26 (no behavior change — the file
  paths shown in feedback are constructed from the same `getRunDir`
  helper the diagnostics text already uses)

Lint clean.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
@kelsonpw kelsonpw requested a review from a team as a code owner April 30, 2026 01:23
@github-actions

Copy link
Copy Markdown
Contributor

🧙 Wizard CI

Run the Wizard CI and test your changes against wizard-workbench example apps by replying with a GitHub comment using one of the following commands:

Test all apps:

  • /wizard-ci all

Test all apps in a directory:

  • /wizard-ci django
  • /wizard-ci fastapi
  • /wizard-ci flask
  • /wizard-ci javascript-node
  • /wizard-ci javascript-web
  • /wizard-ci next-js
  • /wizard-ci python
  • /wizard-ci react-router
  • /wizard-ci vue

Test an individual app:

  • /wizard-ci django/django3-saas
  • /wizard-ci fastapi/fastapi3-ai-saas
  • /wizard-ci flask/flask3-social-media
Show more apps
  • /wizard-ci javascript-node/express-todo
  • /wizard-ci javascript-node/fastify-blog
  • /wizard-ci javascript-node/hono-links
  • /wizard-ci javascript-node/koa-notes
  • /wizard-ci javascript-node/native-http-contacts
  • /wizard-ci javascript-web/saas-dashboard
  • /wizard-ci next-js/15-app-router-saas
  • /wizard-ci next-js/15-app-router-todo
  • /wizard-ci next-js/15-pages-router-saas
  • /wizard-ci next-js/15-pages-router-todo
  • /wizard-ci python/meeting-summarizer
  • /wizard-ci react-router/react-router-v7-project
  • /wizard-ci react-router/rrv7-starter
  • /wizard-ci react-router/saas-template
  • /wizard-ci react-router/shopper
  • /wizard-ci vue/movies

Results will be posted here when complete.

@kelsonpw kelsonpw enabled auto-merge (squash) April 30, 2026 01:24
@kelsonpw kelsonpw merged commit 2fa7c57 into main Apr 30, 2026
13 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