fix: three correctness/UX bugs from post-launch hunt#409
Merged
Conversation
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>
Contributor
🧙 Wizard CIRun 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:
Test all apps in a directory:
Test an individual app:
Show more apps
Results will be posted here when complete. |
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.
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 applyCause:
src/utils/project-marker.ts:32-46listed 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 inFRAMEWORK_REGISTRYand their detectors work — but every Unity/Unreal user who ranwizard planorwizard applyfrom their project root hit "no project manifest" and was told to pass--forceor--install-dir.Fix: Added
PROJECT_MARKER_PATHS(sub-path matches; covers Unity) andPROJECT_MARKER_EXTENSIONS(extension matches; covers Unreal) alongside the existingPROJECT_MARKER_FILES. Single non-recursivereaddirfor 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.jsonCause: Pre-#154 the agent wrote
.amplitude-dashboard.jsonand a file watcher inagent-interface.tsmirrored it to the canonical<installDir>/.amplitude/dashboard.jsonviapersistDashboard(). #154 moved dashboard creation OUT of the agent loop, so the watcher never fires. The step atsrc/steps/create-dashboard.ts:147writes ONLY the legacy path; the canonical file is silently never populated./diagnosticsadvertises 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 —persistDashboardalready swallows fs errors internally; a failure here must not fail the wizard. TheDashboardUrlinampli.jsonwas already preserved viawizardSuccessExit's setupComplete payload — only the.amplitude/dashboard.jsonmirror was missing.3.
/debug,/diagnostics, and ScreenErrorBoundary corrupted the TUI by writing to stderrCause: 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/catchonly swallows EPIPE; it doesn't fix the corruption. The user reported/debugand/diagnostics"seem buggy" — this is why.Fix:
/debugwrites the snapshot to<runDir>/debug-snapshot.jsonand surfaces the path in the feedback bar. User cancatit after the wizard exits, or paste it directly into a bug report./diagnosticswrites the storage-paths text to<runDir>/diagnostics.txtand surfaces the path. Same shape.ScreenErrorBoundarydrops the stderr write entirely; the same payload already goes to the wizard log file vialogToFile. 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 lintclean/debugfrom inside the wizard — feedback bar shows summary + path; live frame stays clean;cat <path>outside the wizard returns the JSON/diagnosticsdittowizard planagainst a Unity project root withProjectSettings/ProjectVersion.txt— no longer rejectedwizard planagainst an Unreal project root withMyGame.uproject— no longer rejected<installDir>/.amplitude/dashboard.jsonexists 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.jsonviapersistDashboard, restoring downstream consumers that rely ongetDashboardFile().TUI
/debugand/diagnosticsstop 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.ScreenErrorBoundarysimilarly 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.