How do I capture screenshots for a manual chapter?

Table of Contents

Follows How do I document an entity?, which leaves a chapter with every screenshot as a [SCREENSHOT NEEDED] placeholder carrying a # Capture: instruction. This recipe turns each placeholder into a real, cropped, correctly-named image, driven by the QA Validation Runner. The Capture screenshots for the Currency Pairs manual chapter scenario is the worked exemplar this recipe generalises from.

Question

How do I turn a manual chapter's [SCREENSHOT NEEDED] placeholders into real, correctly-named, correctly-cropped screenshots?

Answer

Prerequisites

Run these three steps, in order, before touching the chapter's placeholders — every time. Capturing screenshots against a stale build or an unprovisioned tenant produces screenshots that don't match what ships.

  1. Ask the user whether a new build is necessary before doing anything else. If nothing has changed since the last build, skip straight to step 2:

    ./compass.sh build --preset <preset>
    
  2. Ready the environment — confirm the database is recent (recreate only if it's not) and the Acme Corporation tenant is provisioned, per How do I ready up an environment? steps 1-5 (skip that recipe's step 6, client start — the scenario in step 2 below starts its own client with the scenario preloaded).
  3. Confirm the chapter itself already builds before capturing anything, so a broken link or missing include isn't mistaken for a capture problem later:

    ./compass.sh build --direct manual
    

Create a test scenario, one step per placeholder

Count the placeholders and scaffold a test_scenario doc under the entity's story directory:

grep -c "SCREENSHOT NEEDED" doc/manual/user_guide/chapter_<plural>.org

./compass.sh add test_scenario \
  --slug <plural>-manual-screenshots \
  --parent-dir doc/agile/versions/v0/<sprint>/<story-slug> \
  --parent-id <task-uuid> \
  --parent-title "<the manual-chapter task's title>" \
  --title "Capture screenshots for the <Plural> manual chapter" \
  --description "Set up UI state and capture the N screenshot placeholders in chapter_<plural>.org."

Fill in the * Scenario Info table before writing steps. Clients must be genuinely empty (no placeholder text at all, not even "single client") for the common single-client case — this field is not just documentation: the QA Validation Runner treats any non-empty value here as "multi-client" and then only looks for steps nested one level deeper, under a per-client ** heading. A stray placeholder with flat ** steps silently loads zero steps, no error shown. Then add one ** Capture <target_filename>.png step per placeholder, in the chapter's top-to-bottom order, each body copying that placeholder's # Capture: instruction verbatim (adjust only if the concrete data on file differs from the instruction's example, e.g. a different pair code than the one the instruction names — note the substitution in the step body). Do not invent extra steps among the capture steps — the count of capture steps should equal the placeholder count exactly — but the scenario is not complete without the two closing review steps below, which are mandatory and not counted against the placeholder count:

  • ** Read the manual in the Qt client — after the chapter is wired in and the images are captured (steps 3-5 below), rebuild the Qt-embedded HTML help and open the chapter inside the running client's own manual viewer (Help → User Manual, or wherever the entity's window links to it), reading it top to bottom exactly as an end user would: does the prose read correctly, do the segues work, does every screenshot appear where expected and actually show what its caption claims?
  • ** Check the built PDF — open the rebuilt user_manual.pdf (e.g. via zathura or evince) at the new chapter's pages and confirm layout, figure numbering, and captions look correct in the PDF's own rendering, which can differ from the HTML view (page breaks, figure placement, the List of Figures entries).

Both steps exist because the HTML/Qt-help and LaTeX/PDF renderers are independent pipelines from the same org source, and either can surface a problem the other doesn't (a caption that overflows a PDF column, an image path that resolves for LaTeX but not for the Qt help export, etc.). Do not mark the scenario PASSED without having actually looked at both.

Run the scenario in the client

Start (or restart) the client with the scenario preloaded so the QA Validation Runner panel opens with it already loaded. --open-scenario requires an absolute path — a relative one silently fails to load the scenario, so resolve it explicitly rather than typing a doc/agile/...-style relative path by hand:

./compass.sh client start --colour <colour> \
  --open-scenario "$(realpath doc/agile/versions/v0/<sprint>/<story-slug>/scenario_<plural>-manual-screenshots.org)"

Log in, then work each step: set up the described UI state and click the runner's Screenshot button, which saves a full-desktop PNG next to the scenario file (named <scenario-slug>_step<N>_<timestamp>.png) and links it into that step's *** Result as Notes | [[file:...]], then click Pass.

A step can fail to auto-capture. If the UI state to capture is a modal dialog (e.g. a validation-rejection warning), the runner's own panel cannot receive the Screenshot/Pass click while that dialog holds focus — the step has to be captured with the desktop's own screenshot tool instead (e.g. a Screenshot from <timestamp>.png landing wherever the desktop environment saves them, often a tmp/ or Screenshots/ directory) and then processed by hand through steps 3-4 below like any other capture. Do not treat this as a scenario-authoring mistake — file it as the known message-box modality gap rather than trying to route around it in the scenario itself.

Locate and identify each capture

find doc/agile/versions/v0/<sprint>/<story-slug> \
  -iname "<scenario-slug>_step*" -o -iname "<scenario-slug>_2026*"

Open each one (or the scenario doc's per-step Notes links) and match it against the placeholder it was meant to satisfy — the step title already names the target filename, so this is a direct lookup, not a guess.

Crop to just the dialog or window, following the naming convention

Every published manual screenshot is cropped tightly to the window or dialog of interest — never the full desktop, and never with the QA Validation Runner panel or other chrome in frame. Use the raw capture's pixel bounds for the window in question (read them off the image; a quick Python/Pillow one-liner is enough, no dedicated tool):

python3 -c "
from PIL import Image
im = Image.open('<raw_capture>.png')
im.crop((left, top, right, bottom)).save('/tmp/<crop_name>.png')
"

View the crop before finalising it — check no other window's edge, no scenario-runner overlay, and no cut-off button bleeds into frame; widen the box and re-crop if anything does. Name the final file per How do I document an entity?§"Name screenshots to the standard" (the plural/singular rule) — the target name is already fixed by the placeholder's TODO_<name>.png, so cropping just drops the TODO_ prefix:

cp /tmp/<crop_name>.png assets/images/<final_name>.png

Wire the real images into the chapter and rebuild

Replace each placeholder's link and caption:

#+caption: [SCREENSHOT NEEDED] <what to show>.
# Capture: <instruction>.
[[proj:assets/images/TODO_<name>.png]]

becomes

#+caption[<Short caption>]: <Long caption describing what the reader sees, naming the concrete record shown if relevant>.
[[proj:assets/images/<name>.png]]

Then rebuild the PDF and confirm every new figure appears in the List of Figures:

./compass.sh build --direct manual
pdftotext -layout doc/manual/user_guide/user_manual.pdf - | grep -A20 "List of Figures"

Also rebuild the Qt-embedded HTML help so the client's own in-app manual viewer reflects the change — this is a separate pipeline from the PDF and does not update just because deploy_manual ran:

# Exports the self-contained HTML (build/output/help/) …
./compass.sh build --direct help
# … then recompiles the .qch resource the Qt client actually ships and
# reads (projects/ores.qt/application/resources/help/user_manual.qch).
# This step needs the full cmake build, not --direct: it isn't an emacs
# script, and the recompiled resource has to be picked up by rebuilding
# and restarting ores.qt before the "Read the manual in the Qt client"
# step below will show anything new.
./compass.sh build deploy_help_qch --preset <preset>

Both builds are prerequisites for the two review steps in step 1 above — do them before working those steps, not after.

Close out

Update the screenshot task's Status/Result and the scenario's Test Scenarios table entry, commit the chapter, the PDF, and the new images together, and note in the task's * Notes if any concrete data (pair codes, currency codes, dates) differs from what the chapter's # Capture: instructions originally named. At this point the chapter is ready for human review — nothing else in the authoring flow is outstanding.

Script

No dedicated wrapper — compass add test_scenario (scaffold), the QA Validation Runner panel (capture), and a short inline Python/Pillow snippet (crop) compose the flow. See Capture screenshots for the Currency Pairs manual chapter for a fully worked example of every step above.

Tested by

The manual build (compass build --direct manual) confirms every real image resolves and appears in the List of Figures; there is no automated check that a screenshot's content matches its caption — that is what the human review pass (recipe How do I document an entity?'s closing note) is for.

See also

Emacs 29.3 (Org mode 9.6.15)