Skip to content

Add eight feature tours with screenshots from a demo repository - #22

Open
christophwille wants to merge 2 commits into
mainfrom
feature-tours
Open

christophwille wants to merge 2 commits into
mainfrom
feature-tours

Conversation

@christophwille

Copy link
Copy Markdown
Member

Adds docs/tour/: eight short, illustrated tours of what Stampeded! does on a C# repository, written for an experienced developer, each meant to be followed in under five minutes. Start at docs/tour/README.md.

Tour Covers
1 Open a pull request and read it start page, overview, ] [ n p v o, context gaps, unified and side by side
2 Navigate the code in the diff hover, F12, Shift+F12, removed code, decompiled NuGet type, call graph, Structure, Map
3 Read it commit by commit commit scope, Commits pane, blame, History
4 Comment and submit threads, drafts, suggestion, reply, Comments pane, review page, submit
5 Come back after a force push carried viewed flags, since last pass, a comment that followed its line
6 CI, tests and coverage Checks, Run Tests, Run + Coverage, Run A/B
7 Review a local branch branch list, a range without a PR, uncommitted work, Run pane
8 Merge merge state, confirmation, merge queue, offline

No app code changes. 43 PNGs (1280x800, light theme, 7 MB), 43 shot scripts, one PowerShell script, nine markdown files, and one link each from README.md and docs/README.md.

How it was built

1. A demo repository with staged pull requests. christophwille/stampeded-demo is a toy C# solution (Corral: a herd of cattle, brands, pricing; a library, a CLI, NUnit tests, one NuGet dependency, a CI workflow). Every staged branch is kept as a tag under stage/, and its stage.ps1 pushes the tags back over the branches, opens a pull request for each branch that has none open, and replaces the review comments with seed ones. That makes the state repeatable, including after tour 8 merges a pull request.

PR Staged to show
#1 Price herds by weight class four commits, a rename, a removed method still called from removed lines, a call into Humanizer, a markdown change, one open and one resolved thread, a linked issue
#2 Extract brand registry pushed as v1; stage.ps1 -Push2 force-pushes v2, rebased onto a newer main, first commit amended, a third commit added; a comment on a line that moves
#3 Cache herd totals one failing test (red CI), added lines no test reaches
Fix typo in CLI help something to merge; its number changes with every staging
local/dirty-work (stage.ps1 -Local, not pushed) a branch behind main with one commit and an uncommitted edit

All pull requests and comments are authored by one account, so Approve and Request Changes are greyed out in the pictures.

2. Screenshots through the app's own harness. Each image has a script of the same name in docs/tour/shots/ holding ScreenshotWatcher commands (open-url:, open-file:, goto:, key:, press:/release:, menu:, pane:, commit-scope, since-last-pass, ...). docs/tour/shoot.ps1 plays them and adds three directives of its own:

  • --- ends one harness request and starts the next - a command that opens something has not finished when its own capture is taken;
  • sleep:N waits after a request;
  • screen / screen:X,Y takes the image from the operating system instead.

shoot.ps1 -Start sets aside the reader's window, theme, layout, scope and recent-repository settings and writes fixed ones (so no private repository name ends up in a start page shot); -Stop puts them back. -Verify checks that every image is referenced and every reference has an image.

3. Texts written against the images, with every claim checked against either a screenshot, the UI's own labels and tooltips, or the existing docs. Claims that could not be verified were removed.

What did not go as planned

  • Popups are not in the harness capture on Windows. A tooltip, a flyout and the comment editor are native windows there (OverlayPopups is only set for X11). screen asks each visible window of the process to print itself (PrintWindow) and composes them, rather than copying the screen. A tooltip opens where the real pointer is, which a harness-moved pointer is not, so screen:X,Y draws it under the hovered point.
  • A hover tooltip stays open after a harness hover. A shot that hovers ends with a pointer move onto an empty line, which closes it.
  • The rename in PR Apply the fontconfig font mappings only off Windows #1 reads as add + delete in the whole change - too little of the file survives four commits. Tour 1 says so, tour 3 shows it as a rename in its own commit.
  • No "moved with member" banner in tour 5: the comment was found again by content (line 29 to line 38), which is what the tour shows.
  • No pickaxe screenshot: History of Selection found nothing for text the pull request itself added (see below); tour 3 mentions it in a sentence.
  • Described but not shot: the failed-step log (the harness cannot double-click) and the Last Pass Was choices (a flyout).
  • The suggestion in tour 4 is typed, not produced by the Suggest a change button, which sits in the popup the harness cannot click into.

Observed in the app while shooting

Not addressed here; worth their own issues.

  • The overview of a newly opened review kept the previous review's Tests: A/B ... line.
  • The review page's merge line stays at "GitHub has not worked it out yet" until its refresh button is pressed, although gh already reports CLEAN; it reads the same after a successful merge.
  • The History pane and History of Selection run git log without a revision, so they read the clone's checked-out branch and do not see the commits of the pull request under review.

Not done

Nobody has walked a tour by hand with a stopwatch; "under five minutes" is an estimate from the number of steps.

Re-creating this from nothing

Enough to rebuild the feature without any memory of how it was made.

Prerequisites: Windows with PowerShell 7, git, gh logged in with push rights to the demo repository, .NET 10 SDK, dotnet tool install -g dotnet-coverage (tour 6), and a Debug build of the app (dotnet build Stampeded.slnx).

If the demo repository still exists, clone it next to this repository (../stampeded-demo) and:

cd docs/tour
../../../stampeded-demo/stage.ps1                         # PRs, branches, seed comments
./shoot.ps1 -Start -Demo ../../../stampeded-demo -Fresh   # start page
./shoot.ps1 '01-*'; ./shoot.ps1 '02-*'; ./shoot.ps1 '03-*'; ./shoot.ps1 '04-*'   # PR 1; 04-08 posts a review
./shoot.ps1 05-01-first-pass                              # opens PR 2, ticks every file
../../../stampeded-demo/stage.ps1 -Push2                  # the force push
./shoot.ps1 '05-0[2-4]*'
./shoot.ps1 '06-*'                                        # opens PR 3; runs tests three times
../../../stampeded-demo/stage.ps1 -Local
./shoot.ps1 '07-*'
./shoot.ps1 '08-*'                                        # opens and really merges the typo PR
./shoot.ps1 -Stop
git -C ../../../stampeded-demo switch --discard-changes main
../../../stampeded-demo/stage.ps1                         # back to the starting state
./shoot.ps1 -Verify

Things that will need adjusting when doing so:

  • 08-01-merge-state.txt opens pull/4. The typo pull request has a new number after every staging (gh pr list -R christophwille/stampeded-demo); put the current one in.
  • Shots with press:, move:, release: or screen:X,Y hold window coordinates measured at a 1280x800 logical window (window.txt = 80 40 1600 1000 normal at 125 % display scaling; at another scaling change that line in shoot.ps1 so the PNG comes out 1280x800). In the unified diff the text starts at x=340, a character is about 7.67 px wide, a line 17.5 px high. Re-measure after a layout change by taking the shot and reading positions off the image.
  • Harness commands in one request run in the order ScreenshotWatcher handles them, not the order written (callgraph, menu:, click:, pointer, type:, key:, open-file:, goto:). Anything that must happen in sequence goes in separate --- blocks.
  • Bracket keys are key:OemCloseBrackets / key:OemOpenBrackets.
  • 07-02-local-range is best shot in a freshly started app, because of the stale Tests line noted above.
  • Shots within a tour depend on the ones before (a ticked file, a draft, blame on), and tours 1-4 share one session on PR 1.

If the demo repository is gone, rebuild it with these properties, then stage as above:

  • main has three commits: A (the initial solution, tagged stage/main-before), B (adds Animal.Born, AgeInYears, Herd.Yearlings), C (stage.ps1); stage/main = tip.
  • Solution: Corral.slnx; src/Corral (Animal record, Herd with Add, IsValidBrand, RegisterBrand, OwnerOf, TotalWeight, ByBrand; Pricing with PriceFor(Animal), PriceFor(Herd), FlatPrice; HerdReport.Summarize using Humanizer's ToQuantity, formatting with the invariant culture); src/Corral.Cli (top-level program with a --help text containing the typo "woth"); tests/Corral.Tests (NUnit on Microsoft.Testing.Platform, global.json test runner as in this repository); docs/pricing.md; .github/workflows/ci.yml running dotnet build and dotnet test --solution Corral.slnx --report-trx on pull_request.
  • stage/weight-pricing on B, four commits: rename Pricing to PriceCalculator (file and class, tests too); add WeightClass enum, ClassOf (< 350 light, < 600 standard, else heavy) and a factor per class in PriceFor; remove FlatPrice, the weighed parameter and --flat; list classes per brand in the report with Humanize(LetterCasing.LowerCase) and rewrite docs/pricing.md with a table whose limits read differently from the code (that discrepancy is what the seed comment is about).
  • stage/brand-registry-v1 on A, two commits: IBrandRegistry/BrandRegistry extracted, Herd(IBrandRegistry), IsValidBrand rewritten as a block that also refuses all-digit brands; then BrandRegistryTests. stage/brand-registry-v2 on B: the same two commits with IsValidBrand moved to the end of Herd.cs, plus a third commit refusing an empty owner.
  • stage/herd-cache on B, two commits: cache TotalWeight in a nullable field invalidated by Add; add Remove (which forgets to invalidate - the failing test Remove_TakesTheAnimalOutOfTheTotal) and Clear (untested).
  • stage/cli-help on B: "woth" to "worth". stage/local-work on A: ByBrand ordered by tag; stage.ps1 -Local checks it out as local/dirty-work and adds an uncommitted AverageWeight.
  • Seed comments, posted by stage.ps1 against the staged commits, lines found by their text: on PR Apply the fontconfig font mappings only off Windows #1 an open thread on < 350 => WeightClass.Light and a resolved thread with one reply on .OrderBy(g => g.Key) in HerdReport.cs; on PR Run on a newer major runtime than the one built against #2 one comment on if (brand.All(char.IsAsciiDigit)) in Herd.cs at v1. The issue "Heavy animals sell for too little" is created after the pull requests, so they keep numbers 1-4, and PR Apply the fontconfig font mappings only off Windows #1's body ends in Closes #<issue>.

Writing rules the texts follow: one premise sentence, five to eight numbered steps, each step a key or menu command, one image and at most a few sentences on what differs from a web diff; ASCII only; menu paths as they are in MainWindow.axaml (the top-level menus are Review, Navigate, Tools, View, Help); keys as in KeyboardShortcuts.Text; nothing claimed that a screenshot, a UI label or the existing docs does not back.

🤖 Generated with Claude Code

The docs said how the tool is built and nothing showed what it does. The
tours are short on purpose - one topic each, under five minutes - because
one long walkthrough is read by nobody who already reviews code for a
living.

The screenshots are not taken by hand. Each is a script of harness
commands under docs/tour/shots, played by shoot.ps1 against
christophwille/stampeded-demo, whose pull requests are staged for this, so
a change to the UI is one command away from new pictures.

On Windows a tooltip or the comment editor is a window of its own that the
harness's rendering of the main window does not contain. shoot.ps1 asks
each of the app's windows to print itself for those shots rather than
copying the screen, which could photograph whatever lies over the app.

Assisted-by: Claude:claude-fable-5-1:Claude Code
The first draft read like a manual: clipped sentences, a handful of lines
written for effect, and headings that made a point instead of saying what
the step is. The steps and the claims are unchanged; the headings are now
literal, the lines for effect are gone, and the prose talks to a developer
the way one would across a desk.

Assisted-by: Claude:claude-fable-5-1:Claude Code
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