Skip to content

feat(desktop): keep tutorial stats and complete App Logs from the Logs view - #3384

Merged
janicduplessis merged 3 commits into
mainfrom
feat/3377-tutorial-stats-evidence
Oct 10, 2026
Merged

janicduplessis merged 3 commits into
mainfrom
feat/3377-tutorial-stats-evidence

Conversation

@janicduplessis

@janicduplessis janicduplessis commented Oct 10, 2026 •

Copy link
Copy Markdown
Collaborator

Description

The illustrated tutorial (#3376) rewards finished steps with real numbers and achievements. Two gaps made that dishonest:

  • Stats were lost. First build time, the second build's cache result and the agent action count came only from the live TutorialEnvironment workspaces. Finish and Delete remove those workspaces, so a completion card had nothing to show.
  • App Logs had no evidence. The step only ended through Next, recorded as skipped, so Desktop never knew whether the user opened Logs.

Solution

TutorialRecord.stats, a new optional TutorialStats, is written by TutorialProgress.update while the data is visible and never cleared:

  • First build (duration, cache source, start and end), once Make a Change is done. It is the same build the step's own check uses.
  • Second build, once Parallel is done.
  • Agent action count: the largest count of agent_action records seen on the first change's simulator since the tutorial started.
  • Folder sizes: each tutorial folder's largest measured worktreeBytes (both worktrees and the clone), for a "freed" figure after Delete. It uses worktreeBytes only, which includes node_modules. buildBytes is left out because removal archives part of it.

savedMs, buildsOverlapped and measuredBytes are derived from those fields. The record lives in Desktop's own preferences (tutorial.progress), so an older record simply has no stats.

App Logs now completes, with a Logs opened tick, when the user shows a tutorial worktree's Logs while the App Logs step is current. A new TutorialViewerEvent.logsOpened(path) comes from two places:

  • WorkspaceDetail, when its Logs view appears for a live workspace while the tutorial hint's step is logs;
  • the tutorial's Show me button on that step.

TutorialProgress accepts the event only for the two tracked worktree paths. Logs left open from an earlier step, archived logs and the build sheet's logs don't count.

I checked the other steps for the same gap:

No other step relies on Next alone.

Test plan

  • TutorialProgressTests:
    • App Logs completes only for a tutorial worktree's path. This replaces the old "waits for the user to mark it done" case.
    • The fixture's builds are recorded: a 264197 ms compiled first build, then a 7665 ms local cache hit, saving 256532 ms, not overlapping. So are two agent actions and 300 + 200 + 500 bytes for the two worktrees and the clone.
    • The stats don't shrink when a later update shows fewer actions or a smaller folder, and they are identical after every workspace disappears.
    • Records saved before this change, with no stats, still decode (the existing legacy-record case).
  • swift test -Xswiftc -warnings-as-errors passes.
  • stim macos from apps/desktop builds and launches, and stim logs --errors is empty. The screen was locked, so I couldn't click through to Logs in the running app; the event wiring is covered by the build and the unit test above.

Fixes #3377

TutorialRecord.stats keeps the first and second build, the agent action count and each tutorial folder's measured size after the workspaces are removed. App Logs completes when the Logs view of a tutorial workspace appears. Fixes #3377
@janicduplessis

Copy link
Copy Markdown
Collaborator Author

Review: one actionable problem, plus test and ordering notes. Format check and swift test --filter TutorialProgress (49 tests) pass locally.

  1. App Logs completes without the user reading anything (apps/desktop/Sources/StimDesktop/Views/WorkspaceDetail.swift:293, apps/desktop/Sources/StimDesktop/Views/RootView.swift:428, apps/desktop/Sources/StimKit/TutorialProgress.swift:375).

    • The .task(id:) fires when the LogsView is inserted, not when the user looks at it. The tutorial's own Show me button sets showsLogs = true on the logs step, so clicking it mounts LogsView and completes the step. The user has not scrolled, filtered or read a line.
    • showsLogs is an @AppStorage value. If the panel is already open, merely selecting a tutorial worktree page sends the event.
    • logsOpened is a sticky bool on TutorialProgress. Opening Logs during an earlier step (build, parallel) completes App Logs the moment the tutorial reaches it.
    • The tick therefore does not show the user opened Logs, which is what Desktop tutorial: persist step stats and complete App Logs from navigation #3377 asked for. Decide the intended signal, for example:
      • Count only a toggle from hidden to shown that the user made while record.step == "logs". Show me would also need to stop sending the event.
      • Or accept panel visibility but ignore events that arrived before the step began.
    • The website line ("completes when the Logs view ... appears") matches the code, but not the PR intent. Keep whichever behavior you pick consistent in both.
  2. The stats test would pass with a hollow firstBuild (apps/desktop/Tests/StimKitTests/TutorialProgressTests.swift, tutorialStatsOutliveTheWorkspacesThatProducedThem).

    • #expect(stats.firstBuild != nil) does not check the duration, cache source or timestamps. The requirement is that the numbers come from the same build the build checkpoint uses. Assert the fixture's durationMs and cache, and savedMs or buildsOverlapped if the fixture allows.
    • Nothing shows that stats never regress. Add a case where agentActions falls (fewer log records on a later update) and worktreeBytes keeps the last measured value, or drop the "never regress" claim.
    • A TutorialRecord JSON without stats has no decode test. The TutorialRecordStore decode uses try?, so a decode failure would silently reset the tutorial. One decode of a legacy payload is cheap insurance.
  3. Minor: tutorial folder sizes can shrink during Finish (apps/desktop/Sources/StimKit/TutorialProgress.swift, recordStats). worktreeBytes is overwritten with the latest disk.worktreeBytes on every update. If the status payload reports a partial or zero size while removal is in progress, the "freed" figure drops. Consider keeping the max per path, or note that the value is last-seen.

Checked and fine:

  • The first-build selection matches the build checkpoint (earliest ok build since the step time, else lastBuild). The second build matches parallel (ok since the same since).
  • stats is optional, so older records decode.
  • logsOpened is accepted only for trackedPaths.
  • The logs label in TutorialPanel is fine.
  • The comments are acceptable doc comments.
  • The PR description is accurate apart from the point in item 1.

@janicduplessis janicduplessis added the review: ai-approved A fresh AI review found nothing left to fix label Oct 10, 2026
@janicduplessis
janicduplessis marked this pull request as ready for review October 10, 2026 19:54
@janicduplessis

Copy link
Copy Markdown
Collaborator Author

Review: clear. Fresh re-review of the whole diff; swift test -Xswiftc -warnings-as-errors --filter TutorialProgress passes (49 tests).

Earlier findings:

  1. App Logs completing without reading: resolved. logsOpened is emitted only when tutorialHint.step == "logs" (Logs view appearing for a live, non-archive workspace; Show me on the logs step), and TutorialProgress accepts it only for trackedPaths. Logs left open from build or parallel no longer complete the step. Website line and PR description match.
  2. Hollow stats test: resolved. It asserts first and second build duration and cache, savedMs, buildsOverlapped, action count and summed bytes; a later update with fewer actions and a smaller folder leaves stats equal; stats survive all workspaces disappearing. The legacy record case decodes without stats.
  3. Folder sizes shrinking: resolved (max per path).

Also checked: first build uses the same selection and since as the build checkpoint, second build the same as parallel; comments are doc comments; no other issues.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

area: desktop apps/desktop area: website website/ review: ai-approved A fresh AI review found nothing left to fix

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Desktop tutorial: persist step stats and complete App Logs from navigation

1 participant