Open the file /home/user/Documents/research_draft.odp in LibreOffice Impress. This 6-slide deck contains TODO placeholder text on every slide. Replace every placeholder with real content as specified below. Do not add or remove slides.

Slide 1 ('Phase III Study Results'): replace the TODO body with 'Final Results: primary endpoint achieved'.
Slide 2 ('Sample Characteristics'): replace the TODO body with 'Sample size: 2413 participants across 14 sites'.
Slide 3 ('Primary Endpoint'): replace the TODO body with 'Primary endpoint met at p<0.001 versus control'.
Slide 4 ('Safety'): replace the TODO body with 'Safety profile consistent with prior phases, no new signals'.
Slide 5 ('Regulatory Plan'): replace the TODO body with 'Submission planned for Q3 2026 to FDA and EMA'.
Slide 6 ('Acknowledgements'): replace the TODO body with 'Thank you to the study coordinators and participating sites'.

No slide should still contain the word TODO anywhere. Save the file (Ctrl+S) keeping the same /home/user/Documents/research_draft.odp path and ODP format.

Still exactly 6 slides

Slide 1 updated

check-slide-contains 1 "Sample size: 2413 participants"

Slide 2 updated

check-slide-contains 2 "Primary endpoint met at p"

Slide 3 updated

check-slide-contains 3 "Safety profile consistent with prior phases"

Slide 4 updated

check-slide-contains 4 "Submission planned for Q3 2026"

Slide 5 updated

check-slide-contains 5 "Thank you to the study coordinators"

Slide 6 updated

'TODO' not in result.get('full_text','')

Slide 1 no TODO

Slide 2 no TODO

Slide 3 no TODO

Slide 4 no TODO

Slide 5 no TODO

Slide 6 no TODO

File saved


Create a new presentation from scratch in LibreOffice Impress with exactly 5 slides for an oral defence of a research poster titled 'Urban Heat Islands in Austin'.

Slide 1 (Title Slide): Title 'Urban Heat Islands in Austin'. Subtitle 'Dr. Maya Chen — Environmental Studies 2026'.
Slide 2: Title 'Background'. Body bullets: 'Temperature anomalies in dense districts', 'Impact on vulnerable populations', 'Gaps in prior work'.
Slide 3: Title 'Methods'. Body bullets: 'Satellite LST imagery 2018-2024', 'Ground sensor network (42 nodes)', 'Mixed-effects regression model'.
Slide 4: Title 'Results'. Body bullets: 'Downtown core 3.8C warmer than suburbs', 'Tree canopy explains 41% of variance', 'Night-time peaks before 4am'.
Slide 5: Title 'Discussion'. Body bullets: 'Policy levers: canopy cover targets', 'Retrofitting dark rooftops', 'Next steps: extend to San Antonio'.

Add speaker notes to EVERY content slide (slides 2-5):
- Slide 2 (index 1) notes: 'Frame the public-health urgency and name the collaborating clinics'.
- Slide 3 (index 2) notes: 'Explain the sensor calibration protocol'.
- Slide 4 (index 3) notes: 'Point out the 41% figure as the key empirical contribution'.
- Slide 5 (index 4) notes: 'Close with the call for funding'.

Save the presentation as /home/user/Documents/heat_island_poster.odp.

Deck has exactly 5 slides

check-slide-title 0 "Urban Heat Islands in Austin"

Slide 1 title

Slide 1 subtitle author

check-slide-contains 0 "Environmental Studies 2026"

Slide 1 subtitle year

Slide 2 title

check-slide-contains 1 "Temperature anomalies"

Slide 2 bullet 1

check-slide-contains 1 "vulnerable populations"

Slide 2 bullet 2

check-slide-contains 1 "Gaps in prior work"

Slide 2 bullet 3

Slide 3 title

check-slide-contains 2 "Satellite LST imagery"

Slide 3 bullet 1

check-slide-contains 2 "Ground sensor network"

Slide 3 bullet 2

check-slide-contains 2 "regression model"

Slide 3 bullet 3

Slide 4 title

Slide 4 bullet 1

Slide 4 bullet 2

check-slide-contains 3 "Night-time peaks"

Slide 4 bullet 3

Slide 5 title

check-slide-contains 4 "canopy cover targets"

Slide 5 bullet 1

Slide 5 bullet 2

Slide 5 bullet 3

check-notes-contain 1 "public-health urgency"

Slide 2 notes

check-notes-contain 2 "sensor calibration"

Slide 3 notes

Slide 4 notes

Slide 5 notes

Output ODP file exists


Open the file /home/user/Documents/annual_review.pptx in LibreOffice Impress. This presentation has 5 slides with titles: 'Annual Review 2025', 'Financial Summary', 'Team Growth', 'Product Milestones', 'Goals for 2026'.

Perform the following edits:

1. On Slide 2 ('Financial Summary'), add a new bullet point at the end of the existing content: 'Net profit margin: 18%'

2. On Slide 5 ('Goals for 2026'), add speaker notes: 'Set quarterly check-in meetings to track progress.'

3. Use File > Save As to save the presentation in ODP format (ODF Presentation) at the path /home/user/Documents/annual_review.odp.

The original file /home/user/Documents/annual_review.pptx should still exist on disk after you save the ODP copy. The presentation should still have exactly 5 slides.

Presentation still has exactly 5 slides

Slide 2 title is 'Financial Summary'

check-slide-contains 1 "Net profit margin: 18%"

Slide 2 contains 'Net profit margin: 18%'

check-notes-contain 4 "Set quarterly check-in meetings to track progress"

Slide 5 notes contain expected text

ODP file exists at expected path

Original PPTX file still exists


Open the file /home/user/Documents/strategy_review.odp in LibreOffice Impress. This 6-slide deck is currently at the standard 4:3 size. You must:

1. Change the slide size to 16:9 widescreen: exactly 13.333 inches wide by 7.5 inches tall, in landscape orientation (Slide > Slide Properties, or Slide > Page Properties; pick the 'Widescreen' preset or set the width/height manually).

2. Insert a header/footer (Insert > Header and Footer) so that EVERY SLIDE FROM SLIDE 2 ONWARDS displays:
   - a fixed footer with the text 'Confidential - Draft 2026-Q2'
   - an automatic slide number
   The first slide (the title slide 'Strategy Review 2026') MUST NOT show the footer. In the Header and Footer dialog, tick 'Do not show on the first slide' (or clear the footer on slide 1 only) before applying 'Apply to All'.

3. Save the file, overwriting /home/user/Documents/strategy_review.odp (do NOT Save As). Keep the file as .odp.

The deck must still have exactly 6 slides when you finish.

strategy_review.odp is saved on disk

check-slide-size /home/user/Documents/strategy_review.odp 13.333 7.5 0.05

Slide size is 16:9 widescreen (13.333in x 7.5in)

check-footer-on-slide /home/user/Documents/strategy_review.odp 1 "Confidential - Draft 2026-Q2"

Slide 2 has footer 'Confidential - Draft 2026-Q2'

check-footer-on-slide /home/user/Documents/strategy_review.odp 2 "Confidential - Draft 2026-Q2"

Slide 3 has footer 'Confidential - Draft 2026-Q2'

check-footer-on-slide /home/user/Documents/strategy_review.odp 5 "Confidential - Draft 2026-Q2"

Slide 6 has footer 'Confidential - Draft 2026-Q2'

Slide 1 (title) does NOT have the footer

Slide 2 shows a slide number

Slide 6 shows a slide number

Deck still has exactly 6 slides


Open the file /home/user/Documents/marketing_plan.odp in LibreOffice Impress. The deck currently has 5 slides in this order: 'Campaign Overview', 'Audience', 'Channels', 'Budget', 'KPIs'.

Insert three section divider slides so the final 8-slide order is:
1. 'Campaign Overview'
2. 'Section: Targeting' (new) - body text 'Who we are reaching'
3. 'Audience'
4. 'Channels'
5. 'Section: Economics' (new) - body text 'How we spend and measure'
6. 'Budget'
7. 'Section: Outcomes' (new) - body text 'What success looks like'
8. 'KPIs'

Do not modify the existing content on the original 5 slides. Save the file (Ctrl+S) keeping the same /home/user/Documents/marketing_plan.odp path and ODP format.

Exactly 8 slides

Slide 1 unchanged

check-slide-title 1 "Section: Targeting"

Slide 2 new section

check-slide-contains 1 "Who we are reaching"

Slide 2 body

Slide 3

Slide 4

check-slide-title 4 "Section: Economics"

Slide 5 new section

check-slide-contains 4 "How we spend and measure"

Slide 5 body

Slide 6

Slide 7 new section

check-slide-contains 6 "What success looks like"

Slide 7 body

Slide 8

File saved


Create a new presentation from scratch in LibreOffice Impress with exactly 6 slides for an 'AI in Finance' webinar follow-up deck.

Slide 1 (Title Slide): Title 'AI in Finance Webinar Recap'. Subtitle 'Follow-Up Resources'.
Slide 2: Title 'Webinar Highlights'. Body bullets: 'Fraud detection breakthroughs', 'Regulatory updates', 'Panel Q&A themes'.
Slide 3: Title 'Attendee Statistics'. Body bullets: '1,450 live attendees', '68% from banks', '22% from insurance'.
Slide 4: Title 'Key Takeaways'. Body bullets: 'Start with explainable models', 'Audit training data quarterly', 'Engage compliance early'.
Slide 5: Title 'Next Steps'. Body bullets: 'Book a follow-up demo', 'Join the monthly newsletter', 'Download the white paper'.
Slide 6: Title 'Q&A'. Body 'Reach out: team@aifin.example'.

Add speaker notes:
- On Slide 2 (index 1): 'Highlight the panel moderator and the fraud live demo'.
- On Slide 5 (index 4): 'Promote the upcoming executive roundtable'.

Save the presentation as /home/user/Documents/webinar_followup.odp (ODF Presentation format).

Deck has exactly 6 slides

check-slide-title 0 "AI in Finance Webinar Recap"

Slide 1 title

check-slide-contains 0 "Follow-Up Resources"

Slide 1 subtitle

check-slide-title 1 "Webinar Highlights"

Slide 2 title

check-slide-contains 1 "Fraud detection breakthroughs"

Slide 2 bullet 1

check-slide-contains 1 "Regulatory updates"

Slide 2 bullet 2

Slide 2 bullet 3

check-slide-title 2 "Attendee Statistics"

Slide 3 title

check-slide-contains 2 "1,450 live attendees"

Slide 3 bullet 1

Slide 3 bullet 2

Slide 3 bullet 3

Slide 4 title

check-slide-contains 3 "explainable models"

Slide 4 bullet 1

check-slide-contains 3 "Audit training data quarterly"

Slide 4 bullet 2

check-slide-contains 3 "Engage compliance early"

Slide 4 bullet 3

Slide 5 title

check-slide-contains 4 "Book a follow-up demo"

Slide 5 bullet 1

check-slide-contains 4 "monthly newsletter"

Slide 5 bullet 2

Slide 5 bullet 3

Slide 6 title

Slide 6 contact email

Slide 2 notes mention panel moderator

Slide 2 notes mention fraud live demo

check-notes-contain 4 "executive roundtable"

Slide 5 notes mention executive roundtable

Output ODP file exists


Open /home/user/Documents/artwork.kra in Krita. Edit document information dialog and set the following fields exactly: Title = 'Sunset Study', Subject = 'Landscape', Keywords = 'sunset, landscape, study', Author full name = 'Jane Painter', and Description / Abstract containing the phrase 'sunset scene'. Save the file in place at /home/user/Documents/artwork.kra.

Title set

Subject set

'sunset' in (result.get('keyword') or '').lower() and 'landscape' in (result.get('keyword') or '').lower()

Keywords include sunset and landscape

Author = Jane Painter

'sunset scene' in (result.get('description') or '').lower()

Description contains 'sunset scene'


Open /home/user/Documents/scene.kra in Krita. It contains two paint layers, 'Background' and 'Overlay'. Add a Filter Mask of type Gaussian Blur (any reasonable radius) as a child of the 'Background' layer and name the mask exactly 'SoftBlur'. Leave 'Overlay' untouched. Save the file in place (Ctrl+S).

scene.kra still exists

Background layer preserved

Overlay layer preserved

check-mask-of /home/user/Documents/scene.kra Background SoftBlur

SoftBlur mask is a child of Background

check-layer-node-type /home/user/Documents/scene.kra SoftBlur filtermask

SoftBlur node type is filtermask


Open /home/user/Documents/sunset.kra in Krita. It contains one paint layer named 'Ground'. Add a new Fill Layer that uses a Gradient generator and name the new layer exactly 'SkyGradient'. Configure the gradient to interpolate from pure orange (#FF8C00) at the top to pure yellow (#FFFF00) at the bottom. Save the file.

sunset.kra still exists

Ground layer preserved

SkyGradient layer added

SkyGradient is a generated/fill layer

'gradient' in (result.get('generator_name','') or '').lower() or result.get('node_type','') in ('generatedlayer','filllayer','generatorlayer')

Generator is gradient (or generic fill layer acceptable)


Open /home/user/Documents/portrait_mask.kra in Krita. The file contains a single paint layer named 'Portrait'. Add a Transparency Mask as a child of the 'Portrait' layer and name the mask exactly 'FadeEdges'. Do not rename or delete the Portrait layer. Save the file in place (Ctrl+S) so the result is written back to /home/user/Documents/portrait_mask.kra.

portrait_mask.kra still exists

Portrait layer preserved

check-mask-of /home/user/Documents/portrait_mask.kra Portrait FadeEdges

FadeEdges mask is a child of Portrait

check-layer-node-type /home/user/Documents/portrait_mask.kra FadeEdges transparencymask

FadeEdges node type is transparencymask


Open /home/user/Documents/bounce.kra in Krita. It contains one paint layer named 'Ball' and the document framerate is currently 12 fps. Change the document framerate to 24 fps, add the 'Ball' layer to the animation timeline, and create at least 3 animation keyframes on the 'Ball' layer (for example at times 0, 12 and 24; empty frames are fine). Save the file in place (Ctrl+S).

bounce.kra still exists

Ball layer preserved

Document framerate is 24

Ball layer is in the timeline

check-keyframe-count /home/user/Documents/bounce.kra Ball 3

Ball layer has at least 3 keyframes


Open /home/user/Documents/photo_rgba.kra in Krita. The document is currently RGBA 8-bit with an sRGB profile. Convert the image to the Grayscale/Alpha (8-bit) color space, using any standard Grayscale profile.  Keep the 'Photo' layer. Save the file in place — the saved .kra must have colorspace GRAYA.

photo_rgba.kra still exists

Photo layer preserved

Document color space is GRAYA

'gray' in (result.get('profile_name','').lower()) or 'gray' in (result.get('colorspacename','').lower())

Color profile references a Gray profile


In Krita, create a new document with these exact properties: width 1500 pixels, height 1500 pixels, resolution 300 DPI, color model RGBA 8-bit. The initial background/paint layer should be filled with solid color hex #2E86AB. Add a second paint layer named exactly 'Overlay' above the background, set its blending mode to 'Multiply' and its opacity to 50% (≈128/255). Save the document as /home/user/Documents/new_canvas.kra. You may close and ignore the template file that is pre-opened.

new_canvas.kra was saved

check-image-size /home/user/Documents/new_canvas.kra 1500 1500

Canvas is 1500x1500

Resolution is 300 DPI

Color space is RGBA

Overlay layer present

Overlay blend mode = multiply

110 <= int(result.get('opacity',0)) <= 145

Overlay opacity ≈ 50% (128±)


Open /home/user/Documents/photo_crop.kra in Krita (currently 1600x900). First, crop the canvas to a centered 1200x800 region. Then expand the canvas back outwards by 30 pixels on every side so that the final canvas is exactly 1260x860 — the existing 1200x800 image content must sit centered inside a 30-pixel-wide solid black frame. Save the file in place at /home/user/Documents/photo_crop.kra.

File saved

check-image-size /home/user/Documents/photo_crop.kra 1260 860

Final canvas is 1260x860

result.get('width') == 1260 and result.get('height') == 860

Merged preview matches new canvas size


Open /home/user/Documents/logo.kra in Krita. Export the same image to three files in /home/user/Pictures/: logo.png (PNG), logo.jpg (JPEG), and logo.webp (WebP). Do not modify the canvas size or the layer contents — the source logo.kra itself should not be edited (only exported from).

PNG export exists

JPEG export exists

WebP export exists

PNG non-trivial

JPEG non-trivial

WebP non-trivial

check-image-size /home/user/Documents/logo.kra 512 512

Source canvas size unchanged


Open /home/user/Documents/multilayer.kra in Krita. It has 5 paint layers. Flatten all layers into a single merged paint layer and rename that resulting layer exactly 'Flattened'. Then export the flattened image to /home/user/Pictures/multilayer_flat.png as a PNG. Save the .kra file in place so that /home/user/Documents/multilayer.kra contains exactly one layer named 'Flattened'.

.kra saved

Exactly one layer remains

Layer named Flattened exists

check-image-size /home/user/Documents/multilayer.kra 1024 768

Canvas dimensions preserved

Exported PNG exists

Exported PNG non-trivial


Open /home/user/Documents/illustration.kra in Krita. It contains four paint layers named 'Sky', 'Mountains', 'Trees', and 'Character'. Group 'Sky' and 'Mountains' into a new group layer named 'Background_Elements'. Group 'Trees' and 'Character' into a new group layer named 'Foreground_Elements'. Reorder the two groups so that 'Foreground_Elements' sits above 'Background_Elements' in the layer stack. Do not delete or rename any of the four original paint layers. Save the file in place at /home/user/Documents/illustration.kra.

Background_Elements group exists

Foreground_Elements group exists

Background_Elements is a group layer

Foreground_Elements is a group layer

any(l.get('full_path')=='Background_Elements/Sky' for l in result) and any(l.get('full_path')=='Background_Elements/Mountains' for l in result)

Sky and Mountains nested under Background_Elements

any(l.get('full_path')=='Foreground_Elements/Trees' for l in result) and any(l.get('full_path')=='Foreground_Elements/Character' for l in result)

Trees and Character nested under Foreground_Elements

[l['name'] for l in result if l.get('node_type')=='grouplayer'][:2] == ['Foreground_Elements','Background_Elements']

Foreground_Elements ordered above Background_Elements


Open /home/user/Documents/walk_cycle.kra in Krita. It contains an animated paint layer named 'Character' with three existing keyframes (at frames 0, 6 and 12). Enable Onion Skinning on the 'Character' layer. Save the file.

walk_cycle.kra still exists

Character layer preserved

Character layer still in timeline

Onion skin enabled on Character layer


Open /home/user/Documents/photo.kra in Krita. It is currently 1920x1080. Scale the entire image (canvas + contents) down to 1280x720 using a high-quality interpolation filter. Then export the scaled image to /home/user/Pictures/photo_web.jpg as a JPEG. Save the .kra file in place so /home/user/Documents/photo.kra itself is also 1280x720 after the task.

photo.kra still exists

check-image-size /home/user/Documents/photo.kra 1280 720

photo.kra resized to 1280x720

Exported JPEG exists

Exported JPEG is non-trivial


Open /home/user/Documents/mask_demo.kra in Krita. It contains one paint layer named 'Foreground'. With the 'Foreground' layer selected, make any rectangular selection on the canvas, then convert that selection into a Local Selection Mask named exactly 'LocalSel'. Save the file in place.

mask_demo.kra still exists

Foreground layer preserved

check-mask-of /home/user/Documents/mask_demo.kra Foreground LocalSel

LocalSel mask is a child of Foreground

check-layer-node-type /home/user/Documents/mask_demo.kra LocalSel selectionmask

LocalSel node type is selectionmask


In /home/user/Documents/multi.kra, which has three paint layers named 'A', 'B', and 'C' (top to bottom), make the following changes and save the file in place: (1) rename layer 'A' to 'Main'; (2) rename layer 'C' to 'Accent'; (3) hide layer 'B' (toggle its visibility off); (4) set the opacity of layer 'Main' to 80% (≈204/255). Layer 'B' must still exist — only hidden, not deleted.

A renamed to Main

C renamed to Accent

Layer B still exists

Three layers preserved

Layer B is hidden

190 <= int(result.get('opacity',0)) <= 215

Main opacity ≈ 80% (204±)


Open /home/user/Documents/transform.kra in Krita. It contains one paint layer named 'Subject'. Add a Transform Mask named exactly 'Rotate15' as a child of the 'Subject' layer, and apply a rotation of roughly 15 degrees via the transform tool on the mask. Save the file in place (Ctrl+S).

transform.kra still exists

Subject layer preserved

check-mask-of /home/user/Documents/transform.kra Subject Rotate15

Rotate15 mask is a child of Subject

check-layer-node-type /home/user/Documents/transform.kra Rotate15 transformmask

Rotate15 node type is transformmask


Open /home/user/Documents/pattern.kra in Krita. Enable Wrap-Around mode so that seamless-tile painting is active. Additionally, switch Krita's canvas background to the mid-gray checkered pattern. Save the file.

pattern.kra still exists

Wrap-around mode enabled in kritarc


Create a meeting agenda in LibreOffice Writer. Add a Heading 1 'Board Meeting Agenda' and make it bold. Add a paragraph 'Date: April 10, 2026'. Add a paragraph 'Time: 2:00 PM - 4:00 PM'. Add a paragraph 'Location: Conference Room B'. Add a Heading 2 'Agenda Items'. Insert a table named 'Table1' with 6 rows and 3 columns. Header: 'Item', 'Presenter', 'Duration'. Row 2: 'Opening Remarks', 'Chairman Wilson', '10 min'. Row 3: 'Financial Review', 'CFO Roberts', '30 min'. Row 4: 'Product Launch Update', 'VP Marketing', '20 min'. Row 5: 'Hiring Plan', 'HR Director', '15 min'. Row 6: 'Open Discussion', 'All', '45 min'. Add a footer with text 'Confidential'. Save as /home/user/Documents/board_agenda.odt.

check-heading-exists "Board Meeting Agenda" 1

Heading 1 exists

Heading 1 is bold

Contains date

Contains location

Heading 2 exists

File is saved

len(result.get('tables', [])) >= 1 and result['tables'][0].get('rows', 0) == 6

Table has 6 rows

any(len(t.get('data', [])) >= 2 and t['data'][1][0] == 'Opening Remarks' for t in result.get('tables', []))

Row 2: Opening Remarks

any(len(t.get('data', [])) >= 3 and t['data'][2][1] == 'CFO Roberts' for t in result.get('tables', []))

Row 3: CFO Roberts

any(len(t.get('data', [])) >= 6 and t['data'][5][0] == 'Open Discussion' for t in result.get('tables', []))

Row 6: Open Discussion

result.get('footer_text', '').strip() == 'Confidential'

Footer: Confidential

File exists


Create a new LibreOffice Writer document that is a reference page for an HTTP API called PaymentsAPI. Add a Heading 1 'PaymentsAPI Reference v2' at the top. Add three Heading 2 sections in order: 'Endpoints', 'Parameters', 'Status Codes'. Under 'Endpoints' insert a table named Table1 with 5 rows and 3 columns. Header row: 'Method', 'Path', 'Description'. Row 2: 'POST', '/v2/charges', 'Create a new charge'. Row 3: 'GET', '/v2/charges/{id}', 'Retrieve a charge'. Row 4: 'POST', '/v2/refunds', 'Create a refund'. Row 5: 'GET', '/v2/customers', 'List customers'. Under 'Parameters' insert a second table with 5 rows and 3 columns. Header: 'Name', 'Type', 'Required'. Row 2: 'amount', 'integer', 'yes'. Row 3: 'currency', 'string', 'yes'. Row 4: 'description', 'string', 'no'. Row 5: 'metadata', 'object', 'no'. Under 'Status Codes' insert a third table with 6 rows and 2 columns. Header: 'Code', 'Meaning'. Row 2: '200', 'OK'. Row 3: '201', 'Created'. Row 4: '400', 'Bad Request'. Row 5: '401', 'Unauthorized'. Row 6: '500', 'Server Error'. Save the document to /home/user/Documents/paymentsapi_reference.odt.

paymentsapi_reference.odt exists

check-heading-exists "PaymentsAPI Reference v2" 1

Heading 1

Heading 2 Endpoints

Heading 2 Parameters

Heading 2 Status Codes

At least 3 tables

any(t.get('data', [[]])[0] == ['Method', 'Path', 'Description'] for t in result.get('tables', []))

Endpoints header row

any(len(t.get('data', [])) >= 5 and t['data'][1][0] == 'POST' and t['data'][1][1] == '/v2/charges' for t in result.get('tables', []))

First endpoint row correct

any(t.get('data', [[]])[0] == ['Name', 'Type', 'Required'] for t in result.get('tables', []))

Parameters header row

any(len(t.get('data', [])) >= 5 and t['data'][1][0] == 'amount' and t['data'][1][2] == 'yes' for t in result.get('tables', []))

amount parameter row correct

any(t.get('data', [[]])[0] == ['Code', 'Meaning'] for t in result.get('tables', []))

Status Codes header row

any(len(t.get('data', [])) >= 6 and t['data'][5][0] == '500' and t['data'][5][1] == 'Server Error' for t in result.get('tables', []))

500 Server Error row


Open /home/user/Documents/changelog.odt in LibreOffice Writer. The document already has entries for versions 1.0 and 1.1. Add a Heading 2 'Version 1.2 - April 2026' at the end of the document. Below it, add a paragraph 'New Features:'. Add a paragraph '- Added dark mode support'. Add a paragraph '- Improved search functionality'. Add a paragraph '- Added export to PDF option'. Then add another Heading 2 'Version 1.3 - May 2026'. Add a paragraph 'New Features:'. Add a paragraph '- Multi-language support'. Add a paragraph '- Performance improvements'. Save the file.

check-heading-exists "Version 1.2 - April 2026" 2

Heading 2 Version 1.2 exists

check-text-contains "Added dark mode support"

Contains dark mode feature

check-text-contains "Improved search functionality"

Contains search feature

check-text-contains "Added export to PDF option"

Contains PDF export feature

check-heading-exists "Version 1.3 - May 2026" 2

Heading 2 Version 1.3 exists

Contains multi-language feature

Contains performance feature


Open /home/user/Documents/manual.odt in LibreOffice Writer. The document contains 6 paragraphs. Add a bookmark named 'section_intro' at the beginning of the first paragraph. Add a bookmark named 'section_setup' at the beginning of the third paragraph. Add a bookmark named 'section_faq' at the beginning of the fifth paragraph. Save the file.

'section_intro' in result.get('bookmarks', [])

Bookmark 'section_intro' exists

'section_setup' in result.get('bookmarks', [])

Bookmark 'section_setup' exists

'section_faq' in result.get('bookmarks', [])

Bookmark 'section_faq' exists

At least 3 bookmarks exist


Create a new LibreOffice Writer document for a sprint bug triage report. The document must begin exactly in this order: paragraph index 0 is Heading 1 'Sprint 42 Bug Triage Report'; paragraph index 1 is Heading 2 'Summary'; paragraph index 2 is a bold body paragraph (at least 25 words) summarizing the overall bug status for Sprint 42. After that, add three more Heading 2 sections in order: 'Severity Breakdown', 'Top Bugs', 'Action Items'. Under 'Severity Breakdown' insert a table named Table1 with 5 rows and 3 columns. Header row: 'Severity', 'Open', 'Closed'. Row 2: 'Critical', '1', '3'. Row 3: 'High', '4', '7'. Row 4: 'Medium', '8', '12'. Row 5: 'Low', '6', '15'. Under 'Top Bugs' insert a second table with 6 rows and 3 columns. Header: 'ID', 'Title', 'Owner'. Row 2: 'BUG-101', 'Login loop on mobile', 'Alice'. Row 3: 'BUG-115', 'Checkout timeout', 'Bob'. Row 4: 'BUG-122', 'Cart total rounding', 'Carol'. Row 5: 'BUG-130', 'Search returns empty', 'Dan'. Row 6: 'BUG-140', 'Profile image upload fails', 'Eve'. Under 'Action Items' add a paragraph listing at least three next steps (at least 20 words). Add bookmarks named 'sev_critical', 'sev_high', and 'sev_medium' anchored at paragraphs within the Severity Breakdown area. Save the document to /home/user/Documents/bug_triage.odt.

bug_triage.odt exists

check-heading-exists "Sprint 42 Bug Triage Report" 1

Heading 1

Heading 2 Summary

check-heading-exists "Severity Breakdown" 2

Heading 2 Severity Breakdown

Heading 2 Top Bugs

Heading 2 Action Items

Summary body paragraph (index 2) is bold

At least 2 tables

any(t.get('data', [[]])[0] == ['Severity', 'Open', 'Closed'] for t in result.get('tables', []))

Severity table header

any(len(t.get('data', [])) >= 5 and t['data'][1][0] == 'Critical' and t['data'][1][1] == '1' for t in result.get('tables', []))

Critical severity row correct

any(t.get('data', [[]])[0] == ['ID', 'Title', 'Owner'] for t in result.get('tables', []))

Top Bugs header

any(len(t.get('data', [])) >= 6 and t['data'][5][0] == 'BUG-140' and t['data'][5][2] == 'Eve' for t in result.get('tables', []))

BUG-140 row correct

'sev_critical' in result.get('bookmarks', []) and 'sev_high' in result.get('bookmarks', []) and 'sev_medium' in result.get('bookmarks', [])

Severity bookmarks exist


Open /home/user/Documents/service_agreement.odt in LibreOffice Writer. Use Find & Replace to replace every occurrence of 'OldCo' with 'NewCo Holdings' and every occurrence of 'ClientX' with 'Globex Limited'. After the existing contract text, add a Heading 1 with text 'Amendment No. 1'. Below that heading, add a paragraph of at least 20 words describing the amendment (e.g., noting the parties have agreed to new terms effective immediately). Then insert a signatures table named Table1 with 4 rows and 3 columns. Header row: 'Party', 'Name', 'Date'. Row 2: 'Provider', 'NewCo Holdings', '2026-04-10'. Row 3: 'Client', 'Globex Limited', '2026-04-10'. Row 4: 'Witness', 'Jane Doe', '2026-04-10'. Add a bookmark named 'signature_party' anchored at the Party row of the signatures table area. Save the file at its original path.

NewCo Holdings present

Globex Limited present

No occurrences of OldCo remain

No occurrences of ClientX remain

check-heading-exists "Amendment No. 1" 1

Heading 1 'Amendment No. 1'

len(result.get('tables', [])) >= 1 and result['tables'][0].get('rows', 0) == 4 and result['tables'][0].get('cols', 0) == 3

Signatures table is 4x3

any(t.get('data', [[]])[0] == ['Party', 'Name', 'Date'] for t in result.get('tables', []))

Header row

any(len(t.get('data', [])) >= 4 and t['data'][1][1] == 'NewCo Holdings' and t['data'][2][1] == 'Globex Limited' for t in result.get('tables', []))

Provider and Client rows correct

'signature_party' in result.get('bookmarks', [])

Bookmark 'signature_party' exists


Open /home/user/Documents/article.odt in LibreOffice Writer. The document has 5 paragraphs of plain text. Change the style of the first paragraph ('The Future of Renewable Energy') to 'Heading 1'. Change the style of the third paragraph ('Solar Power Advancements') to 'Heading 2'. Add a new paragraph at the end with the text 'Last updated: April 2026'. Make this last paragraph bold. Save the file.

Paragraph 0 style is Heading 1

Paragraph 2 style is Heading 2

check-text-contains "Last updated: April 2026"

Contains 'Last updated: April 2026'

any(p.get('text', '') == 'Last updated: April 2026' for p in result.get('paragraphs', []))

Last paragraph has correct text

Last paragraph is bold


Open /home/user/Documents/inventory.odt in LibreOffice Writer. The document contains a table named 'Table1' with product inventory data (5 rows including header: Product, Stock, Price). The current data rows are: Laptop/50/999, Keyboard/200/79, Mouse/150/25, Monitor/30/450. Change the stock of 'Laptop' (row 2, column 2) from '50' to '75'. Change the price of 'Mouse' (row 4, column 3) from '25' to '30'. Add a new row at the end of the table with: 'Webcam', '100', '45'. Save the file.

any(len(t.get('data', [])) >= 2 and t['data'][1][1] == '75' for t in result.get('tables', []))

Laptop stock changed to 75

any(len(t.get('data', [])) >= 4 and t['data'][3][2] == '30' for t in result.get('tables', []))

Mouse price changed to 30

any(len(t.get('data', [])) >= 6 and t['data'][5][0] == 'Webcam' for t in result.get('tables', []))

New row: Webcam

Webcam: stock=100, price=45


Create an employee directory in LibreOffice Writer. Add a Heading 1 'Employee Directory'. Add a Heading 2 'Engineering Department'. Insert a table named 'Table1' with 5 rows and 4 columns. Header: 'Name', 'Title', 'Email', 'Extension'. Row 2: 'Alice Wang', 'Lead Engineer', 'alice@company.com', '1001'. Row 3: 'Bob Martinez', 'Senior Developer', 'bob@company.com', '1002'. Row 4: 'Carol Singh', 'DevOps Engineer', 'carol@company.com', '1003'. Row 5: 'David Kim', 'Junior Developer', 'david@company.com', '1004'. Add a Heading 2 'Marketing Department'. Insert a table named 'Table2' with 4 rows and 4 columns. Header: 'Name', 'Title', 'Email', 'Extension'. Row 2: 'Eva Brown', 'Marketing Manager', 'eva@company.com', '2001'. Row 3: 'Frank Lee', 'Content Writer', 'frank@company.com', '2002'. Row 4: 'Grace Patel', 'Social Media Lead', 'grace@company.com', '2003'. Save as /home/user/Documents/employee_directory.odt.

check-heading-exists "Employee Directory" 1

Heading 1 exists

check-heading-exists "Engineering Department" 2

Heading 2 Engineering

check-heading-exists "Marketing Department" 2

Heading 2 Marketing

At least 2 tables

result['tables'][0].get('rows', 0) == 5 and result['tables'][0].get('cols', 0) == 4

Table1: 5 rows, 4 cols

result['tables'][0]['data'][1][0] == 'Alice Wang'

Table1 Row 2: Alice Wang

Table1 Row 5 ext: 1004

result['tables'][1]['data'][1][0] == 'Eva Brown'

Table2 Row 2: Eva Brown

Table2 Row 4: grace email

File exists


Open /home/user/Documents/contract.odt in LibreOffice Writer. Use Find & Replace to replace all occurrences of 'ACME Corp' with 'GlobalTech Industries'. Then replace all occurrences of '2025' with '2026'. Save the file.

No occurrences of 'ACME Corp' remain

Document contains 'GlobalTech Industries'

No occurrences of '2025' remain

Document contains '2026'


Create a formal business letter in LibreOffice Writer. The first paragraph should be the sender address: '123 Main Street, Springfield, IL 62704'. The second paragraph should be the date: 'April 1, 2026'. The third paragraph should be 'Dear Mr. Johnson,'. The fourth paragraph should be the body: 'I am writing to confirm our meeting scheduled for next week. Please bring the quarterly reports and budget proposals.' The fifth paragraph should be 'Sincerely,'. The sixth paragraph should be 'Jane Smith'. Make the first paragraph (sender address) bold. Save the file as /home/user/Documents/formal_letter.odt.

check-paragraph-text 0 "123 Main Street, Springfield, IL 62704"

Paragraph 0 is sender address

Paragraph 0 is bold

Paragraph 1 is date

check-paragraph-text 2 "Dear Mr. Johnson,"

Paragraph 2 is salutation

check-text-contains "quarterly reports and budget proposals"

Body contains key phrase

Paragraph 4 is closing

Paragraph 5 is signature

File exists at expected path


Create a new LibreOffice Writer document for a grant proposal. Add a Heading 1 'Grant Proposal: Community Literacy Initiative' at the top. Add four Heading 2 sections in order: 'Executive Summary', 'Budget', 'Timeline', 'Expected Outcomes'. Under 'Executive Summary' add a paragraph of at least 40 words summarizing the initiative. Under 'Budget' insert a table named Table1 with 6 rows and 2 columns. Header: 'Category', 'Amount USD'. Row 2: 'Teaching Materials', '15000'. Row 3: 'Instructor Stipends', '40000'. Row 4: 'Venue Rental', '8000'. Row 5: 'Outreach and Marketing', '5000'. Row 6: 'Administration', '7000'. Under 'Timeline' insert a second table with 5 rows and 3 columns. Header: 'Phase', 'Start', 'End'. Row 2: 'Planning', '2026-05-01', '2026-06-15'. Row 3: 'Recruitment', '2026-06-16', '2026-07-31'. Row 4: 'Instruction', '2026-08-01', '2026-11-30'. Row 5: 'Evaluation', '2026-12-01', '2026-12-31'. Under 'Expected Outcomes' add a paragraph (at least 25 words). Set all four page margins (top, bottom, left, right) to 2.5 cm. Enable the page header and set its text to 'Literacy Initiative Grant Proposal'. Save to /home/user/Documents/grant_proposal.odt.

grant_proposal.odt exists

check-heading-exists "Grant Proposal: Community Literacy Initiative" 1

Heading 1

check-heading-exists "Executive Summary" 2

Heading 2 Executive Summary

Heading 2 Budget

Heading 2 Timeline

check-heading-exists "Expected Outcomes" 2

Heading 2 Expected Outcomes

At least 2 tables

any(t.get('data', [[]])[0] == ['Category', 'Amount USD'] for t in result.get('tables', []))

Budget table header

any(len(t.get('data', [])) >= 6 and t['data'][2][1] == '40000' for t in result.get('tables', []))

Instructor Stipends amount is 40000

any(t.get('data', [[]])[0] == ['Phase', 'Start', 'End'] for t in result.get('tables', []))

Timeline header

Instruction phase ends 2026-11-30

abs(result.get('margin_top', 0) - 2500) <= 50 and abs(result.get('margin_bottom', 0) - 2500) <= 50 and abs(result.get('margin_left', 0) - 2500) <= 50 and abs(result.get('margin_right', 0) - 2500) <= 50

All four margins are 2.5 cm

result.get('header_text', '').strip() == 'Literacy Initiative Grant Proposal'

Header text correct


Create a new document in LibreOffice Writer. Set the page orientation to landscape. Set all four margins (top, bottom, left, right) to 1500 (1.5cm). Add a header with text 'Project Phoenix - Status Report'. Add a footer with text 'Page 1 of 1'. Add a Heading 1 'Project Phoenix Status'. Add a paragraph with at least 30 words describing a fictional project status update. Save as /home/user/Documents/project_status.odt.

Orientation is landscape

Top margin is 1500

Bottom margin is 1500

Left margin is 1500

Right margin is 1500

result.get('header_text', '').strip() == 'Project Phoenix - Status Report'

Header text correct

result.get('footer_text', '').strip() == 'Page 1 of 1'

Footer text correct

check-heading-exists "Project Phoenix Status" 1

Heading 1 exists

Word count at least 30

File exists


Open /home/user/Documents/photo_album.odt in LibreOffice Writer. Insert the image /home/user/Pictures/photo1.png into the document below the existing text. Then insert the image /home/user/Pictures/photo2.png below the first image. The document should contain exactly 2 images when done. Save the file.

Document contains exactly 2 images


Create an invoice document in LibreOffice Writer. Add a Heading 1 'INVOICE'. Add a paragraph 'Invoice Number: INV-2026-001'. Add a paragraph 'Date: April 3, 2026'. Add a paragraph 'Bill To: Acme Corporation'. Insert a table named 'Table1' with 5 rows and 3 columns. Header row: 'Item', 'Quantity', 'Price'. Row 2: 'Web Development', '40', '4000'. Row 3: 'Database Setup', '10', '1500'. Row 4: 'Testing', '20', '2000'. Row 5: 'Total', '', '7500'. Save as /home/user/Documents/invoice.odt.

Heading 1 'INVOICE' exists

Contains invoice number

Contains bill-to

len(result.get('tables', [])) >= 1 and result['tables'][0].get('rows', 0) == 5

Table has 5 rows

any(t.get('data', [[]])[0] == ['Item', 'Quantity', 'Price'] for t in result.get('tables', []))

Header: Item, Quantity, Price

any(len(t.get('data', [])) >= 2 and t['data'][1][0] == 'Web Development' for t in result.get('tables', []))

Row 2: Web Development

any(len(t.get('data', [])) >= 5 and t['data'][4][0] == 'Total' and t['data'][4][2] == '7500' for t in result.get('tables', []))

Row 5: Total = 7500

File exists at expected path


Create a new LibreOffice Writer document for a physics lab report about pendulum period measurements. The document must begin exactly in this order: paragraph index 0 is a Heading 1 with text 'Lab Report: Pendulum Period Measurement'; paragraph index 1 is a Heading 2 with text 'Hypothesis'; paragraph index 2 is a bold body paragraph (at least 20 words) stating the hypothesis about how pendulum period relates to length. After that, add five more Heading 2 sections in order: 'Materials', 'Procedure', 'Results', 'Discussion', 'Conclusion'. Under 'Materials' add a paragraph listing at least three items. Under 'Procedure' add a paragraph describing the method (at least 25 words). Under 'Results' insert a table named Table1 with 6 rows and 3 columns. Header row: 'Trial', 'Length cm', 'Period s'. Row 2: '1', '20', '0.90'. Row 3: '2', '40', '1.27'. Row 4: '3', '60', '1.55'. Row 5: '4', '80', '1.79'. Row 6: '5', '100', '2.00'. Under 'Discussion' add a paragraph (at least 25 words) interpreting the results. Under 'Conclusion' add a paragraph (at least 15 words). Save to /home/user/Documents/lab_report.odt. The total document word count must be at least 150.

lab_report.odt exists

check-heading-exists "Lab Report: Pendulum Period Measurement" 1

Heading 1

Heading 2 Hypothesis

Heading 2 Materials

Heading 2 Procedure

Heading 2 Results

Heading 2 Discussion

Heading 2 Conclusion

Hypothesis body paragraph (index 2) is bold

len(result.get('tables', [])) >= 1 and result['tables'][0].get('rows', 0) == 6 and result['tables'][0].get('cols', 0) == 3

Results table is 6x3

any(t.get('data', [[]])[0] == ['Trial', 'Length cm', 'Period s'] for t in result.get('tables', []))

Header row correct

Row 5 data correct

At least 150 words


Create a meeting minutes document in LibreOffice Writer. Add a Heading 1 titled 'Team Meeting Minutes', followed by a Heading 2 'Attendees', then a paragraph listing 'Alice, Bob, Charlie'. Add another Heading 2 'Action Items', then insert a 3-row, 2-column table named 'Table1' with headers 'Task' and 'Owner' in the first row. Fill row 2 with 'Update website' and 'Alice', row 3 with 'Fix login bug' and 'Bob'. Save the file as /home/user/Documents/meeting_minutes.odt.

check-heading-exists "Team Meeting Minutes" 1

Heading 1 'Team Meeting Minutes' exists

Heading 2 'Attendees' exists

check-text-contains "Alice, Bob, Charlie"

Text contains attendee list

Heading 2 'Action Items' exists

len(result.get('tables', [])) >= 1 and result['tables'][0].get('rows', 0) == 3

Table exists with 3 rows

any(t.get('data', [[]])[0] == ['Task', 'Owner'] for t in result.get('tables', []))

Table header row is Task, Owner

any(len(t.get('data', [])) >= 2 and t['data'][1] == ['Update website', 'Alice'] for t in result.get('tables', []))

Row 2: Update website, Alice

any(len(t.get('data', [])) >= 3 and t['data'][2] == ['Fix login bug', 'Bob'] for t in result.get('tables', []))

Row 3: Fix login bug, Bob

File exists at expected path


Open /home/user/Documents/user_guide.odt in LibreOffice Writer. The document already has a Heading 1 'Product X User Guide'. Add a Heading 2 'Getting Started'. Add a paragraph explaining initial setup (at least 30 words). Add a Heading 2 'Configuration'. Add a paragraph about configuration options (at least 30 words). Add a Heading 2 'Troubleshooting'. Insert a table named 'Table1' with 4 rows and 2 columns. Header: 'Problem', 'Solution'. Row 2: 'App crashes on startup', 'Clear cache and restart'. Row 3: 'Slow performance', 'Check system requirements'. Row 4: 'Connection timeout', 'Verify network settings'. Add a header with text 'User Guide v2.0'. Add a footer with text 'Internal Use Only'. Save the file.

check-heading-exists "Getting Started" 2

Heading 2 'Getting Started'

Heading 2 'Configuration'

Heading 2 'Troubleshooting'

len(result.get('tables', [])) >= 1 and result['tables'][0].get('rows', 0) == 4

Table has 4 rows

any(t.get('data', [[]])[0] == ['Problem', 'Solution'] for t in result.get('tables', []))

Header: Problem, Solution

any(len(t.get('data', [])) >= 2 and t['data'][1][1] == 'Clear cache and restart' for t in result.get('tables', []))

Row 2 solution: Clear cache and restart

any(len(t.get('data', [])) >= 4 and t['data'][3][1] == 'Verify network settings' for t in result.get('tables', []))

Row 4 solution: Verify network settings

result.get('header_text', '').strip() == 'User Guide v2.0'

Header text correct

result.get('footer_text', '').strip() == 'Internal Use Only'

Footer text correct

Word count at least 60


Create a sales report in LibreOffice Writer. Add a Heading 1 'Annual Sales Report 2025'. Add a Heading 2 'Q1 Sales'. Insert a table named 'Table1' with 4 rows and 3 columns. Header: 'Product', 'Units', 'Revenue'. Row 2: 'Widget A', '500', '25000'. Row 3: 'Widget B', '300', '18000'. Row 4: 'Widget C', '150', '12000'. Add a Heading 2 'Q2 Sales'. Insert a second table named 'Table2' with 4 rows and 3 columns. Header: 'Product', 'Units', 'Revenue'. Row 2: 'Widget A', '600', '30000'. Row 3: 'Widget B', '350', '21000'. Row 4: 'Widget C', '200', '16000'. Save as /home/user/Documents/sales_report.odt.

check-heading-exists "Annual Sales Report 2025" 1

Heading 1 exists

Heading 2 Q1 Sales exists

Heading 2 Q2 Sales exists

At least 2 tables exist

result['tables'][0].get('rows', 0) == 4 and result['tables'][0].get('cols', 0) == 3

Table1 has 4 rows and 3 cols

Table1 Row 2: Widget A, 25000

Table2 Row 2: Widget A, 30000

File exists


Create a company newsletter in LibreOffice Writer. Add a Heading 1 'TechCorp Monthly Newsletter - April 2026' and make it bold. Add a Heading 2 'Company Updates'. Add a paragraph: 'We are excited to announce the opening of our new office in Austin, Texas. The new facility will house 200 employees and features state-of-the-art research labs.' Add a Heading 2 'Employee Spotlight'. Add a paragraph: 'This month we celebrate Sarah Chen, who has been with TechCorp for 10 years. Sarah leads our AI research division and has published over 30 papers.' Add a Heading 2 'Upcoming Events'. Insert a table named 'Table1' with 4 rows and 3 columns. Header: 'Event', 'Date', 'Location'. Row 2: 'Tech Summit', 'April 15', 'Main Auditorium'. Row 3: 'Team Building', 'April 22', 'City Park'. Row 4: 'Board Meeting', 'April 30', 'Conference Room A'. Save as /home/user/Documents/newsletter.odt.

check-heading-exists "TechCorp Monthly Newsletter - April 2026" 1

Heading 1 exists

Heading 1 is bold

check-heading-exists "Company Updates" 2

Heading 2 'Company Updates'

Contains Austin, Texas

check-heading-exists "Employee Spotlight" 2

Heading 2 'Employee Spotlight'

Contains Sarah Chen

check-heading-exists "Upcoming Events" 2

Heading 2 'Upcoming Events'

Table has 4 rows

any(len(t.get('data', [])) >= 2 and t['data'][1][0] == 'Tech Summit' for t in result.get('tables', []))

Row 2: Tech Summit

any(len(t.get('data', [])) >= 4 and t['data'][3][0] == 'Board Meeting' for t in result.get('tables', []))

Row 4: Board Meeting

File exists


Create a new LibreOffice Writer document for the Acme Corp HR Policy Handbook. Add a Heading 1 'Acme Corp HR Policy Handbook' at the top. Add four Heading 2 sections in this order: 'Code of Conduct', 'Leave Policy', 'Remote Work Policy', 'Acknowledgment'. Under each of the first three Heading 2 sections add a paragraph of at least 20 words describing that policy. Under 'Acknowledgment', insert a table named Table1 with 5 rows and 3 columns. Header row: 'Policy', 'Acknowledged', 'Date'. Row 2: 'Code of Conduct', 'Yes', '2026-03-01'. Row 3: 'Leave Policy', 'Yes', '2026-03-01'. Row 4: 'Remote Work Policy', 'Yes', '2026-03-01'. Row 5: 'Data Security Policy', 'Yes', '2026-03-01'. Enable the page header with text 'Acme Corp - HR Handbook' and the page footer with text 'Revision 2026.1'. Add bookmarks named 'policy_conduct', 'policy_leave', and 'policy_remote' at the three policy Heading 2 paragraphs. Save the document to /home/user/Documents/hr_handbook.odt.

hr_handbook.odt exists

check-heading-exists "Acme Corp HR Policy Handbook" 1

Heading 1

check-heading-exists "Code of Conduct" 2

Heading 2 'Code of Conduct'

Heading 2 'Leave Policy'

check-heading-exists "Remote Work Policy" 2

Heading 2 'Remote Work Policy'

Heading 2 'Acknowledgment'

len(result.get('tables', [])) >= 1 and result['tables'][0].get('rows', 0) == 5 and result['tables'][0].get('cols', 0) == 3

Acknowledgment table is 5x3

any(t.get('data', [[]])[0] == ['Policy', 'Acknowledged', 'Date'] for t in result.get('tables', []))

Header row Policy, Acknowledged, Date

any(len(t.get('data', [])) >= 5 and t['data'][4][0] == 'Data Security Policy' for t in result.get('tables', []))

Row 5 first column is 'Data Security Policy'

result.get('header_text', '').strip() == 'Acme Corp - HR Handbook'

Header text correct

result.get('footer_text', '').strip() == 'Revision 2026.1'

Footer text correct

'policy_conduct' in result.get('bookmarks', []) and 'policy_leave' in result.get('bookmarks', []) and 'policy_remote' in result.get('bookmarks', [])

Policy bookmarks exist


Create a new LibreOffice Writer document named Orion Platform project charter. Structure: Heading 1 'Project Charter: Orion Platform' at top. Then five Heading 2 sections in order: 'Objective', 'Scope', 'Stakeholders', 'Risks', 'Timeline'. Under 'Objective' and 'Scope' add paragraphs of at least 20 words each describing the respective content. Under 'Stakeholders' insert a table with 5 rows and 3 columns: header 'Name', 'Role', 'Department'; row 2 'Alice Chen', 'Sponsor', 'Executive'; row 3 'Bob Kumar', 'Project Manager', 'PMO'; row 4 'Carla Diaz', 'Tech Lead', 'Engineering'; row 5 'Dan Park', 'QA Lead', 'Quality'. Under 'Risks' insert a second table with 5 rows and 3 columns: header 'Risk', 'Impact', 'Mitigation'; row 2 'Scope creep', 'High', 'Strict change control'; row 3 'Resource shortage', 'Medium', 'Hire contractors'; row 4 'Tech debt', 'Medium', 'Dedicated refactor sprints'; row 5 'Vendor delays', 'Low', 'Multiple vendor contracts'. Under 'Timeline' insert a third table with 6 rows and 2 columns: header 'Milestone', 'Date'; row 2 'Kickoff', '2026-04-01'; row 3 'Design Complete', '2026-05-15'; row 4 'Beta Release', '2026-08-01'; row 5 'General Availability', '2026-10-15'; row 6 'Post-launch Review', '2026-11-30'. Save the file to /home/user/Documents/project_charter.odt.

project_charter.odt exists

check-heading-exists "Project Charter: Orion Platform" 1

Heading 1

Heading 2 Objective

Heading 2 Scope

Heading 2 Stakeholders

Heading 2 Risks

Heading 2 Timeline

At least 3 tables

any(t.get('data', [[]])[0] == ['Name', 'Role', 'Department'] for t in result.get('tables', []))

Stakeholders header

any(t.get('data', [[]])[0] == ['Risk', 'Impact', 'Mitigation'] for t in result.get('tables', []))

Risks header

any(t.get('data', [[]])[0] == ['Milestone', 'Date'] for t in result.get('tables', []))

Timeline header

any(len(t.get('data', [])) >= 5 and t['data'][4][0] == 'Dan Park' for t in result.get('tables', []))

Stakeholders row 5 Dan Park

Timeline last row date


Create a recipe document in LibreOffice Writer. Add a Heading 1 'Classic Chocolate Chip Cookies'. Add a Heading 2 'Ingredients'. Insert a table named 'Table1' with 9 rows and 2 columns. Header row: 'Ingredient', 'Amount'. Fill the remaining rows: 'Butter', '1 cup'; 'Sugar', '3/4 cup'; 'Brown Sugar', '3/4 cup'; 'Eggs', '2'; 'Vanilla Extract', '1 tsp'; 'Flour', '2 1/4 cups'; 'Baking Soda', '1 tsp'; 'Chocolate Chips', '2 cups'. Add a Heading 2 'Instructions'. Add a paragraph with at least 60 words describing how to make the cookies (preheat oven, mix ingredients, bake, etc.). Save as /home/user/Documents/recipe.odt.

check-heading-exists "Classic Chocolate Chip Cookies" 1

Heading 1 exists

Heading 2 'Ingredients'

Heading 2 'Instructions'

len(result.get('tables', [])) >= 1 and result['tables'][0].get('rows', 0) == 9

Table has 9 rows

result['tables'][0].get('data', [[]])[0] == ['Ingredient', 'Amount']

Header: Ingredient, Amount

Row 2: Butter

result['tables'][0]['data'][8][0] == 'Chocolate Chips' and result['tables'][0]['data'][8][1] == '2 cups'

Row 9: Chocolate Chips, 2 cups

Word count at least 60

File exists


Open /home/user/Documents/draft_report.odt in LibreOffice Writer. Add a header with the text 'Quarterly Report Q1 2026'. Add a footer with the text 'Confidential'. Then change the page orientation to landscape. Save the file as TXT to /home/user/Documents/draft_report.txt

result.get('header_text', '').strip() == 'Quarterly Report Q1 2026'

Header text is 'Quarterly Report Q1 2026'

result.get('footer_text', '').strip() == 'Confidential'

Footer text is 'Confidential'

Page orientation is landscape

File is saved as TXT format

TXT file contains header text

TXT file contains footer text


Create a research paper structure in LibreOffice Writer. Add a Heading 1 'Machine Learning in Healthcare: A Review'. Add a Heading 2 'Abstract'. Add a paragraph with at least 60 words summarizing a fictional research paper about ML applications in healthcare diagnostics. Add a Heading 2 'Introduction'. Add a paragraph with at least 50 words about the introduction. Add a Heading 2 'Methodology'. Add a paragraph with at least 40 words. Add a Heading 2 'Results'. Insert a table named 'Table1' with 4 rows and 3 columns. Header: 'Model', 'Accuracy', 'F1 Score'. Row 2: 'Random Forest', '0.89', '0.87'. Row 3: 'Neural Network', '0.94', '0.92'. Row 4: 'SVM', '0.85', '0.83'. Add a Heading 2 'Conclusion'. Add a paragraph with at least 30 words. Add a footer with text 'Draft - Not for Distribution'. Save as /home/user/Documents/research_paper.odt.

check-heading-exists "Machine Learning in Healthcare" 1

Heading 1 exists

Heading 2 'Abstract'

Heading 2 'Methodology'

Heading 2 'Results'

Heading 2 'Conclusion'

len(result.get('tables', [])) >= 1 and result['tables'][0].get('rows', 0) == 4

Table has 4 rows

any(len(t.get('data', [])) >= 3 and t['data'][2][0] == 'Neural Network' and t['data'][2][1] == '0.94' for t in result.get('tables', []))

Row 3: Neural Network, 0.94

result.get('footer_text', '').strip() == 'Draft - Not for Distribution'

Footer text correct

Word count at least 180

File exists


Create a resume document in LibreOffice Writer. Add a Heading 1 'John Anderson'. Below that, add a paragraph with 'Software Engineer | john.anderson@email.com'. Add a Heading 2 'Experience'. Add a paragraph 'Senior Developer at TechCorp (2020-2025)'. Add another paragraph 'Built and maintained microservices handling 10M requests per day'. Add a Heading 2 'Education'. Add a paragraph 'B.S. Computer Science, MIT, 2019'. Make the Heading 1 'John Anderson' bold. Save as /home/user/Documents/resume_docx.docx and /home/user/Documents/resume_html.html.

Heading 1 'John Anderson' exists

Contains 'Software Engineer'

Contains email

Heading 2 'Experience' exists

check-text-contains "Senior Developer at TechCorp"

Contains experience entry

check-text-contains "microservices handling 10M requests"

Contains experience detail

Heading 2 'Education' exists

check-text-contains "B.S. Computer Science, MIT, 2019"

Contains education entry

Heading 1 paragraph is bold

DOCX file format is correct

HTML file format is correct


Open /home/user/Documents/requirements_draft.odt in LibreOffice Writer. The document currently contains only plain paragraphs. Restructure it into a formal technical specification. At the very top, add a Heading 1 with the text 'Technical Specification'. Convert the section label paragraphs 'Overview', 'Functional Requirements', 'Non-Functional Requirements', 'System Architecture', and 'Revision History' to Heading 2 style. Under the 'Revision History' heading, insert a table named Table1 with 4 rows and 3 columns. Row 1 (header): 'Version', 'Date', 'Author'. Row 2: '0.1', '2026-01-15', 'Alice'. Row 3: '0.2', '2026-02-10', 'Bob'. Row 4: '1.0', '2026-03-01', 'Carol'. Add bookmarks named 'sec_overview', 'sec_functional', 'sec_nonfunctional', and 'sec_architecture' anchored at each of the corresponding Heading 2 paragraphs. Save the file (keep the .odt format at the original path).

requirements_draft.odt exists on disk

check-heading-exists "Technical Specification" 1

Heading 1 'Technical Specification' exists

Heading 2 'Overview' exists

check-heading-exists "Functional Requirements" 2

Heading 2 'Functional Requirements' exists

check-heading-exists "Non-Functional Requirements" 2

Heading 2 'Non-Functional Requirements' exists

check-heading-exists "System Architecture" 2

Heading 2 'System Architecture' exists

check-heading-exists "Revision History" 2

Heading 2 'Revision History' exists

len(result.get('tables', [])) >= 1 and result['tables'][0].get('rows', 0) == 4 and result['tables'][0].get('cols', 0) == 3

Table has 4 rows and 3 columns

any(t.get('data', [[]])[0] == ['Version', 'Date', 'Author'] for t in result.get('tables', []))

Header row is Version, Date, Author

any(len(t.get('data', [])) >= 4 and t['data'][3][2] == 'Carol' for t in result.get('tables', []))

Row 4 author is Carol

'sec_overview' in result.get('bookmarks', []) and 'sec_functional' in result.get('bookmarks', []) and 'sec_nonfunctional' in result.get('bookmarks', []) and 'sec_architecture' in result.get('bookmarks', [])

All four section bookmarks exist


Open /home/user/Documents/test_plan_draft.odt in LibreOffice Writer. At the very top of the document add a Heading 1 with the text 'Login Module Test Plan'. Convert the four section-label paragraphs 'Scope', 'Approach', 'Test Cases', 'Exit Criteria' to Heading 2 style. Under the 'Test Cases' heading, replace the placeholder paragraph with a table named Table1 that has 6 rows and 4 columns. Header row: 'ID', 'Description', 'Steps', 'Expected'. Row 2: 'TC-01', 'Valid login', 'Enter valid credentials and submit', 'Dashboard is shown'. Row 3: 'TC-02', 'Invalid password', 'Enter wrong password and submit', 'Error message displayed'. Row 4: 'TC-03', 'Empty username', 'Leave username empty and submit', 'Field validation error'. Row 5: 'TC-04', 'Locked account', 'Submit credentials for locked user', 'Account locked message'. Row 6: 'TC-05', 'Session timeout', 'Idle for 30 minutes', 'Redirected to login'. Enable the page header with text 'QA Test Plan - Login' and page footer with text 'Document Version 1.0'. Save the file.

check-heading-exists "Login Module Test Plan" 1

Heading 1

Heading 2 Scope

Heading 2 Approach

Heading 2 Test Cases

Heading 2 Exit Criteria

len(result.get('tables', [])) >= 1 and result['tables'][0].get('rows', 0) == 6 and result['tables'][0].get('cols', 0) == 4

Table is 6x4

any(t.get('data', [[]])[0] == ['ID', 'Description', 'Steps', 'Expected'] for t in result.get('tables', []))

Header row correct

Test case IDs span TC-01 to TC-05

any(len(t.get('data', [])) >= 6 and 'Dashboard' in t['data'][1][3] for t in result.get('tables', []))

TC-01 expected mentions Dashboard

result.get('header_text', '').strip() == 'QA Test Plan - Login'

Header text correct

result.get('footer_text', '').strip() == 'Document Version 1.0'

Footer text correct


Create a new LibreOffice Writer document and build a user manual for a product called CloudSync Pro. The document must contain: a Heading 1 'CloudSync Pro User Manual' at the top; a Heading 2 'Installation' followed by a paragraph of at least 25 words describing how to install the app; a Heading 2 'Features' followed by a feature comparison table named Table1 with 5 rows and 3 columns: header row 'Feature', 'Free', 'Pro'; row 2 'Cloud Storage', '5 GB', '1 TB'; row 3 'Sync Devices', '2', '10'; row 4 'Support', 'Email', '24/7 Chat'; row 5 'Offline Mode', 'No', 'Yes'; a Heading 2 'Frequently Asked Questions' followed by a second table Table2 with 5 rows and 2 columns: header row 'Question', 'Answer'; row 2 'How do I reset my password', 'Use the forgot password link on login'; row 3 'Is my data encrypted', 'Yes, AES-256 at rest and TLS in transit'; row 4 'Can I cancel anytime', 'Yes, from your account settings'; row 5 'What platforms are supported', 'Windows, macOS, Linux, iOS, Android'. Enable the page header and set its text to 'CloudSync Pro v3.2 - User Manual'. Enable the page footer and set its text to 'Confidential'. Save the document to /home/user/Documents/cloudsync_manual.odt.

cloudsync_manual.odt exists on disk

check-heading-exists "CloudSync Pro User Manual" 1

Heading 1 exists

Heading 2 'Installation'

Heading 2 'Features'

check-heading-exists "Frequently Asked Questions" 2

Heading 2 'Frequently Asked Questions'

At least 2 tables exist

any(t.get('data', [[]])[0] == ['Feature', 'Free', 'Pro'] for t in result.get('tables', []))

Feature comparison header row

any(len(t.get('data', [])) >= 5 and t['data'][1][2] == '1 TB' for t in result.get('tables', []))

Pro tier cloud storage is 1 TB

any(t.get('data', [[]])[0] == ['Question', 'Answer'] for t in result.get('tables', []))

FAQ table header row

any(len(t.get('data', [])) >= 5 and 'AES-256' in t['data'][2][1] for t in result.get('tables', []))

FAQ mentions AES-256 encryption

'CloudSync Pro v3.2' in result.get('header_text', '') and 'User Manual' in result.get('header_text', '')

Header text is correct

result.get('footer_text', '').strip() == 'Confidential'

Footer text is 'Confidential'

Document has at least 120 words


MuseScore 3 is already open with the file /home/user/Documents/fanfare.mscz. The score has 4 measures of quarter notes and the current Composer is 'Anonymous'.

Perform these steps in order:
1. Open File > Score Properties. Change the Composer to exactly: Test Composer. Click OK.
2. Save the score with Ctrl+S so the updated composer is written into /home/user/Documents/fanfare.mscz.
3. Open File > Export.... Set the format to 'Standard MIDI File (*.mid)' and set the destination path to exactly /home/user/Documents/fanfare.mid. Click Export.
4. Open File > Export... again. Set the format to 'Uncompressed MusicXML (*.musicxml)' and set the destination path to exactly /home/user/Documents/fanfare.musicxml. Click Export.
5. Open File > Export... one more time. Set the format to 'PDF File (*.pdf)' and set the destination path to exactly /home/user/Documents/fanfare.pdf. Click Export.

All three exports must land at the exact paths shown. The original fanfare.mscz must still exist with the updated composer. The MIDI must contain at least 2 notes, the MusicXML must have at least 1 part, and the PDF must have a valid %PDF- header.

fanfare.mscz still exists

check-meta-tag /home/user/Documents/fanfare.mscz composer Test Composer

Composer is 'Test Composer'

Exported fanfare.mid exists

fanfare.mid has at least 2 notes

Exported fanfare.musicxml exists

fanfare.musicxml has exactly 1 part

Exported fanfare.pdf exists and has %PDF- header


MuseScore 3 is already open with the file /home/user/Documents/piano_only.mscz. The score currently has one part: Piano.

Add a Flute instrument so the final score has exactly two parts.

1. Press the keyboard shortcut I (or use Edit > Instruments...) to open the Instruments dialog.
2. In the instrument list, find Woodwinds > Flute.
3. Click Add to add the Flute to the current score. The new Flute staff should appear in the instrument list on the right side.
4. Click OK to close the dialog.
5. Save the file with Ctrl+S.

The saved score must have exactly 2 parts: the original Piano and the newly added Flute. The file must remain at /home/user/Documents/piano_only.mscz.

piano_only.mscz still exists

Score has exactly 2 parts

Flute instrument exists in the score

Piano instrument still exists in the score


MuseScore 3 is already open with the file /home/user/Documents/melody.mscz. The score has a single piano staff with 8 quarter notes (2 measures, 4 notes each) in 4/4 time and currently has no lyrics.

Perform these steps:
1. Click the very first note of the melody to select it.
2. Press Ctrl+L to begin adding lyrics on that note.
3. Type the word 'hello' attached to the first note (type 'hello' and then press space to advance — this will write 'hello' as a single syllable under the first note).
4. Type 'world' under the second note and press space.
5. Type 'sing' under the third note and press space.
6. Type 'out' under the fourth note.
7. Press Escape to exit lyric entry mode.
8. Save the file with Ctrl+S.

The file must still be at /home/user/Documents/melody.mscz. After saving, the score must contain at least one lyric syllable and one of the lyric syllables must contain the substring 'hel' (from 'hello').

melody.mscz still exists

Score contains at least one lyric syllable

A lyric syllable contains the substring 'hel'


MuseScore 3 is already open with the file /home/user/Documents/hymn.mscz. The score is a single-staff melody with 3 measures of quarter notes in C major 4/4 and no lyrics at all.

Add a three-syllable lyric line to the first three notes of the first staff. The three lyric syllables, in order, must be exactly:

  sing
  for
  joy

1. Click the very first note in measure 1 to select it.
2. Press Ctrl+L to enter lyric input mode on that note.
3. Type 'sing' and press the spacebar to advance to the next note.
4. Type 'for' and press the spacebar to advance to the next note.
5. Type 'joy' and press Escape to exit lyric input mode.
6. Save the file with Ctrl+S.

The saved score must contain at least three lyric syllables and each of the words 'sing', 'for', and 'joy' must appear as lyric text. The file must remain at /home/user/Documents/hymn.mscz.

hymn.mscz still exists

Score has at least one lyric syllable

A lyric syllable contains 'sing'

A lyric syllable contains 'for'

A lyric syllable contains 'joy'


MuseScore 3 is already open with the file /home/user/Documents/allegretto.mscz. The score currently has 8 measures of quarter notes in 4/4 time and a tempo marking on the first measure of 90 BPM (quarter note = 90).

Perform these steps:
1. Click on the existing tempo text at the top-left of measure 1 to select it.
2. Change the BPM value to exactly 144 (quarter note = 144). You can double-click the tempo marking to edit it in place, then type the new number, or delete it and add a new tempo marking from Add > Text > Tempo Marking set to 144 BPM.
3. Click somewhere outside the tempo marking to deselect.
4. Save the file with Ctrl+S.

The file must remain at /home/user/Documents/allegretto.mscz. The first Tempo marking must equal 144 BPM (beats-per-minute) after you save.

allegretto.mscz still exists

First Tempo marking is 144 BPM (within ±0.5)


MuseScore 3 is already open with the file /home/user/Documents/suite.mscz. The score has 6 measures of quarter notes in C major 4/4.

Export the score to five different formats, each at an exact path in /home/user/Documents/. Use File > Export... once per format. For each export, set the destination path exactly as shown and click Export.

1. Standard MIDI File (*.mid)  ->  /home/user/Documents/suite.mid
2. Uncompressed MusicXML (*.musicxml)  ->  /home/user/Documents/suite.musicxml
3. PDF File (*.pdf)  ->  /home/user/Documents/suite.pdf
4. PNG Images (*.png)  ->  /home/user/Documents/suite.png (confirm any per-page dialog so a single suite.png is written)
5. Wave Audio (*.wav)  ->  /home/user/Documents/suite.wav

The original suite.mscz must still exist at /home/user/Documents/suite.mscz. All five exported files must end up at the exact paths listed: the MIDI must contain at least 4 notes, the MusicXML must have at least 1 part, the PDF must have a valid %PDF- header, the PNG must have a valid PNG header, and the WAV must have a duration of at least 1 second.

suite.mscz still exists

Exported suite.mid exists

suite.mid has at least 4 notes

Exported suite.musicxml exists

suite.musicxml has exactly 1 part

Exported suite.pdf exists with %PDF- header

Exported suite.png exists with PNG header

suite.wav duration is at least 1 second


MuseScore 3 is already open with the file /home/user/Documents/duet.mscz. The score is a two-part duet (Flute and Cello) in 4/4 time with 4 measures per part.

Perform these steps:
1. Open the File menu and click Export....
2. In the Export dialog, set the format to 'Uncompressed MusicXML (*.musicxml)'. If the available option is 'MusicXML (*.musicxml)' that is also acceptable. Do NOT use compressed MusicXML (.mxl).
3. Set the destination file path to exactly: /home/user/Documents/duet.musicxml
4. Click Export / OK.
5. If prompted, accept the default options.

The original /home/user/Documents/duet.mscz must still exist. The exported file must exist at exactly /home/user/Documents/duet.musicxml and must parse as valid MusicXML containing exactly 2 parts.

Original duet.mscz still exists

Exported MusicXML file exists

Exported MusicXML has exactly 2 parts


MuseScore 3 is already open with the file /home/user/Documents/chorale.mscz. The score has 4 measures of quarter notes in C major 4/4.

Export the score to two formats, each at an exact path:
1. Open File > Export.... Set the format to 'PNG Images (*.png)' and set the destination path to exactly /home/user/Documents/chorale.png. Click Export and accept any per-page confirmation so that a PNG is written to /home/user/Documents/chorale.png.
2. Open File > Export... again. Set the format to 'Standard MIDI File (*.mid)' and set the destination path to exactly /home/user/Documents/chorale.mid. Click Export.

Both exports must land at the exact paths shown. The original chorale.mscz must still exist. The PNG must have a valid PNG header, and the MIDI must contain at least 4 notes.

chorale.mscz still exists

Exported chorale.png exists with valid PNG header

Exported chorale.mid exists

chorale.mid has at least 4 notes


MuseScore 3 is already open with /home/user/Documents/expression_study.mscz. Add an accent (>) articulation to the first note of measure 2, and a tenuto (-) articulation to the first note of measure 3. Do not add any other articulations. Save in place.

File saved

check-articulation-in-measure /home/user/Documents/expression_study.mscz 2 accent

Accent in measure 2

check-articulation-in-measure /home/user/Documents/expression_study.mscz 3 tenuto

Tenuto in measure 3


MuseScore 3 is open with /home/user/Documents/leadsheet.mscz (single melody staff, 4 measures in C major). Add chord symbols above the first note of each measure: measure 1 = C, measure 2 = F, measure 3 = G7, measure 4 = C. Use Add > Text > Chord Symbol (Ctrl+K). Save in place.

File saved

check-chord-symbol-in-measure /home/user/Documents/leadsheet.mscz 1 C

C chord symbol at measure 1

check-chord-symbol-in-measure /home/user/Documents/leadsheet.mscz 2 F

F chord symbol at measure 2

check-chord-symbol-in-measure /home/user/Documents/leadsheet.mscz 3 G7

G7 chord symbol at measure 3

check-chord-symbol-in-measure /home/user/Documents/leadsheet.mscz 4 C

C chord symbol at measure 4


MuseScore 3 is open with /home/user/Documents/swell.mscz (4 measures). Add a crescendo hairpin spanning measures 1 through 2, and a decrescendo hairpin spanning measures 3 through 4. Save in place.

File saved

Crescendo hairpin present

Decrescendo hairpin present


MuseScore 3 is open with /home/user/Documents/sonatina_dc.mscz (4 measures). Add a 'Fine' marker at measure 2 (so the piece ends there on the repeat) and a 'D.C. al Fine' jump at the end of measure 4. Use Add > Text > Tempo & Jumps or the Lines/Repeats palette. Save in place.

File saved

Fine marker present

D.C. jump present


MuseScore 3 is open with /home/user/Documents/dynamic_arc.mscz. Add a mezzo-forte (mf) dynamic marking at the first note of measure 1, and a fortissimo (ff) dynamic marking at the first note of measure 3. Save in place.

File saved

check-dynamic-in-measure /home/user/Documents/dynamic_arc.mscz 1 mf

mf dynamic at measure 1

check-dynamic-in-measure /home/user/Documents/dynamic_arc.mscz 3 ff

ff dynamic at measure 3


MuseScore 3 is open with /home/user/Documents/finger_study.mscz (piano staff, 4 quarter notes per measure). Add piano fingering numbers 1, 2, 3, 5 to the first four notes of measure 1 (one number per note in order). Use Add > Text > Fingering or the Fingering palette. Save in place.

File saved

check-fingering-count-in-measure /home/user/Documents/finger_study.mscz 1 4

At least 4 fingering annotations in measure 1


MuseScore 3 is open with /home/user/Documents/woodwind_switch.mscz (single clarinet staff, 4 measures). Add a mid-score instrument change at the start of measure 3 so that the staff switches from Clarinet to Flute from measure 3 onwards. Use the Text palette's 'Change Instrument' element (Add > Text > Change Instr.) or the 'Change Instrument' palette entry. Save in place.

File saved

check-instrument-change-at /home/user/Documents/woodwind_switch.mscz 3 flute

Instrument change to Flute at measure 3


MuseScore 3 is open with /home/user/Documents/score_layout.mscz (currently US Letter, 8.5 x 11 inches). Change the page dimensions to A4 sized in inches: page width 8.27 in and page height 11.69 in, via Format > Page Settings. Save the file in place.

File saved

check-style-value /home/user/Documents/score_layout.mscz pageWidth 8.27

Page width ~ 8.27 inches

check-style-value /home/user/Documents/score_layout.mscz pageHeight 11.69

Page height ~ 11.69 inches


MuseScore 3 is open with /home/user/Documents/pedal_study.mscz (piano staff, 4 measures). Add a piano sustain pedal line (Ped. ... *) spanning from the start of measure 1 to the end of measure 2, using the Lines palette's Pedal marking. Save in place.

File saved

Pedal line present in score


MuseScore 3 is open with /home/user/Documents/folk_tune.mscz (4 measures). Mark the score with a start-repeat barline at the beginning of measure 1, an end-repeat barline at the end of measure 4, and add a 1st-ending volta bracket over measure 3 and a 2nd-ending volta bracket over measure 4. Save in place.

File saved

Start-repeat at measure 1

End-repeat at measure 4

Volta at measure 3

Volta at measure 4


MuseScore 3 is already open with the file /home/user/Documents/draft_song.mscz. Update the Score Properties so the score is ready for publishing, then save.

Open File > Score Properties and set the following five fields to these exact values:
- Work Title: Autumn Reverie
- Composer: Marie Durand
- Lyricist: Paul Verlaine
- Arranger: Chamber Ensemble
- Copyright: Public Domain 2024

Click OK to close the dialog, then save the file with Ctrl+S. The file must stay at /home/user/Documents/draft_song.mscz.

draft_song.mscz still exists

check-meta-tag /home/user/Documents/draft_song.mscz workTitle Autumn Reverie

workTitle metaTag is 'Autumn Reverie'

check-meta-tag /home/user/Documents/draft_song.mscz composer Marie Durand

composer metaTag is 'Marie Durand'

check-meta-tag /home/user/Documents/draft_song.mscz lyricist Paul Verlaine

lyricist metaTag is 'Paul Verlaine'

check-meta-tag /home/user/Documents/draft_song.mscz arranger Chamber Ensemble

arranger metaTag is 'Chamber Ensemble'

check-meta-tag /home/user/Documents/draft_song.mscz copyright Public Domain 2024

copyright metaTag is 'Public Domain 2024'


MuseScore 3 is already open with the file /home/user/Documents/waltz_draft.mscz. The score currently has 4 measures in C major (no sharps or flats), 4/4 time, a first-measure tempo of 120 BPM, and an empty composer.

Rebuild the score header so it reads as a D-major waltz. Make all four of the following changes, then save:
1. Change the time signature at measure 1 to 3/4. Use the Palettes panel (View > Palettes), expand Time Signatures, select measure 1, and apply 3/4.
2. Change the first tempo marking to exactly 108 BPM (quarter note = 108). Edit the existing tempo text in place or replace it via Add > Text > Tempo Marking set to 108.
3. Change the key signature at the start to D major (two sharps). Expand the Key Signatures palette, select measure 1, and apply the 2-sharps key signature.
4. Open File > Score Properties and set the Composer field to exactly: Yvette Chauvire. Click OK.

Then save the file with Ctrl+S.

After saving, the first TimeSig must equal 3/4, the first Tempo must equal 108 BPM, the first KeySig accidental count must equal 2, and the composer metaTag must equal 'Yvette Chauvire'. The file must stay at /home/user/Documents/waltz_draft.mscz.

waltz_draft.mscz still exists

check-time-signature /home/user/Documents/waltz_draft.mscz 3 4

First TimeSig equals 3/4

First Tempo equals 108 BPM

First KeySig has 2 accidentals (D major, two sharps)

check-meta-tag /home/user/Documents/waltz_draft.mscz composer Yvette Chauvire

composer metaTag equals 'Yvette Chauvire'


MuseScore 3 is already open with the placeholder file /home/user/Documents/placeholder.mscz. You do not need to edit the placeholder score itself — this task is only about changing the MuseScore 3 application preferences.

Perform these steps:
1. Open the Edit menu and click Preferences....
2. Go to the Save section / tab (it may be called 'General > Save' or 'I/O' depending on the layout).
3. Make sure 'Auto Save' is checked (enabled).
4. Set 'Save every ___ minutes' (the Auto Save interval) to exactly 7.
5. Click OK to close the Preferences dialog. This writes the change to ~/.config/MuseScore/MuseScore3.ini.

You do not need to save the placeholder score. After the preferences dialog closes, the autoSave key must be 'true' and the autoSaveInterval key must be '7' in the INI file.

Auto Save is enabled in MuseScore3.ini

Auto Save interval is set to 7 minutes


MuseScore 3 is already open with the file /home/user/Documents/prelude.mscz. The current Work Title is 'Untitled Score' and the Composer is 'Anonymous'.

Perform these steps:
1. Open File > Score Properties.
2. Set Work Title to exactly: Morning Prelude
3. Set Composer to exactly: Ada Lovelace
4. Set Copyright to exactly: 2024 Public Domain
5. Click OK to close the dialog.
6. Save the file with Ctrl+S so the .mscz file on disk is updated.

Do not rename or move the file. It must still be at /home/user/Documents/prelude.mscz when you are done.

prelude.mscz still exists at the original path

check-meta-tag /home/user/Documents/prelude.mscz workTitle Morning Prelude

Work Title is 'Morning Prelude'

check-meta-tag /home/user/Documents/prelude.mscz composer Ada Lovelace

Composer is 'Ada Lovelace'

check-meta-tag /home/user/Documents/prelude.mscz copyright 2024 Public Domain

Copyright is '2024 Public Domain'


MuseScore 3 is already open with the file /home/user/Documents/jig.mscz. The score currently has 8 measures of quarter notes in 4/4 time with a tempo marking of 90 BPM on the first measure.

Make two changes and save:
1. Change the time signature at the start of the score to 6/8.
   - Open the Palettes panel (View > Palettes if needed), expand Time Signatures, click on measure 1, and double-click the 6/8 time signature (or drag it onto measure 1).
2. Change the tempo marking on the first measure to exactly 168 BPM (quarter note = 168).
   - Double-click the existing tempo text at the top-left of measure 1 and edit the number to 168, or delete the existing marking and insert a new Tempo Marking from Add > Text > Tempo Marking set to 168.

Click outside any selected element to deselect, then save the file with Ctrl+S.

After saving, the first TimeSig must equal 6/8 and the first Tempo marking must equal 168 BPM. The file must stay at /home/user/Documents/jig.mscz.

jig.mscz still exists

check-time-signature /home/user/Documents/jig.mscz 6 8

First TimeSig equals 6/8

First Tempo marking equals 168 BPM


MuseScore 3 is already open with the file /home/user/Documents/etude_c.mscz. The score is currently in C major (0 sharps / 0 flats) with 4 measures of quarter notes.

Perform these steps:
1. Press Ctrl+A to select the entire score.
2. Open the Tools menu and click Transpose....
3. In the Transpose dialog, choose 'Transpose by Key' (or 'Transpose Chromatically' if the dialog requires it).
4. Set the target key to G major.
5. Make sure 'Transpose key signatures' is checked, and set direction to Up (or choose the closest distance).
6. Click OK.
7. The new key signature should be G major (1 sharp) at the start of the score.
8. Save the file with Ctrl+S.

The file must still be at /home/user/Documents/etude_c.mscz. The first KeySig accidental count must equal 1 (for G major).

etude_c.mscz still exists

First key signature has 1 sharp (G major)


MuseScore 3 is already open with the file /home/user/Documents/catalog_entry.mscz. Populate the catalog-style Score Properties for this movement and save.

Open File > Score Properties and set the following five fields to these exact values (they map directly to MuseScore's metaTag fields 'workTitle', 'workNumber', 'movementNumber', 'movementTitle', 'source'):
- Work Title: String Quartet No 2
- Work Number: Op 18
- Movement Number: 3
- Movement Title: Andante cantabile
- Source: Urtext Edition 1894

Click OK, then save the file with Ctrl+S. The file must remain at /home/user/Documents/catalog_entry.mscz.

catalog_entry.mscz still exists

check-meta-tag /home/user/Documents/catalog_entry.mscz workTitle String Quartet No 2

workTitle is 'String Quartet No 2'

check-meta-tag /home/user/Documents/catalog_entry.mscz workNumber Op 18

workNumber is 'Op 18'

check-meta-tag /home/user/Documents/catalog_entry.mscz movementNumber 3

movementNumber is '3'

check-meta-tag /home/user/Documents/catalog_entry.mscz movementTitle Andante cantabile

movementTitle is 'Andante cantabile'

check-meta-tag /home/user/Documents/catalog_entry.mscz source Urtext Edition 1894

source is 'Urtext Edition 1894'


A scene collection has already been set up with a single scene named 'Live Stream' containing one Display Capture source named 'Screen'. Your task is to add four more sources to the 'Live Stream' scene WITHOUT creating any new scenes: 1. Add a Video Capture Device source named exactly 'Camera'. 2. Add a Text (FreeType 2) source named exactly 'Now Playing'. 3. Add an Image source named exactly 'Channel Logo'. Set its file path to /home/user/Pictures/channel_logo.png. 4. Add a Color Source named exactly 'Lower Third BG'. 5. All five sources must be visible. 6. Do NOT create or delete any scenes. The collection should still have exactly 1 scene. 7.

Scene 'Live Stream' exists

Exactly 1 scene in the collection

check-source-in-scene Screen 'Live Stream'

Original source 'Screen' still exists in 'Live Stream' scene

check-source-in-scene Camera 'Live Stream'

Source 'Camera' exists in 'Live Stream' scene

check-source-in-scene 'Now Playing' 'Live Stream'

Source 'Now Playing' exists in 'Live Stream' scene

check-source-in-scene 'Channel Logo' 'Live Stream'

Source 'Channel Logo' exists in 'Live Stream' scene

check-source-in-scene 'Lower Third BG' 'Live Stream'

Source 'Lower Third BG' exists in 'Live Stream' scene

Source 'Screen' is visible

Source 'Camera' is visible

Source 'Channel Logo' is visible


The scene collection already contains three scenes, each with one source: - 'Cam A' scene containing source 'Webcam A' - 'Cam B' scene containing source 'Webcam B' - 'Graphics' scene containing source 'Lower Third' Your task is to consolidate everything into one new scene named 'Unified'. 1. Create a new scene named exactly 'Unified'. 2. Add three sources to the 'Unified' scene with these exact names: 'Webcam A', 'Webcam B', 'Lower Third'. (You may use any source type from the Add Source menu; only the names matter.) 3. Delete the original three scenes: 'Cam A', 'Cam B', 'Graphics'. 4. The final collection must have exactly 1 scene, 'Unified', containing those three sources, all visible. 5.

Scene 'Unified' exists

Original 'Cam A' deleted

Original 'Cam B' deleted

Original 'Graphics' deleted

Exactly 1 scene

check-source-in-scene 'Webcam A' Unified

'Webcam A' in 'Unified'

check-source-in-scene 'Webcam B' Unified

'Webcam B' in 'Unified'

check-source-in-scene 'Lower Third' Unified

'Lower Third' in 'Unified'

'Webcam A' visible

'Webcam B' visible

'Lower Third' visible


Set up a scene collection with multiple scenes and sources. 1. OBS may start with a default 'Scene' --. 2. Create three scenes with the exact names: 'Intro', 'Main Content', 'Outro'. 3. Select the 'Intro' scene. Add a new source of type 'Color Source' and name it exactly 'Background'. 4. Select the 'Main Content' scene. Add a new source of type 'Display Capture' and name it exactly 'Desktop'. 5. The 'Outro' scene can remain empty (no sources needed). 6. All sources must be visible. 7. The final scene collection should have exactly 3 scenes: 'Intro', 'Main Content', and 'Outro'. Remove any extra default scenes if present.

Scene 'Intro' exists

Scene 'Main Content' exists

Scene 'Outro' exists

Exactly 3 scenes in the collection

Source 'Background' exists in 'Intro' scene

check-source-in-scene Desktop 'Main Content'

Source 'Desktop' exists in 'Main Content' scene


Open OBS Studio. The scene collection already contains 6 scenes: 'Intro', 'Main', 'BRB', 'Outro', 'Debug', 'Archive'. Each scene contains a single placeholder source.

Your task is to prune the collection down to only 2 scenes: 'Main' and 'Outro'. Delete the other 4 scenes entirely.

Rules:
1. Delete these scenes: 'Intro', 'BRB', 'Debug', 'Archive'.
2. Keep these scenes: 'Main', 'Outro'.
3. Do NOT rename, add, or create any scene.
4. Do NOT modify the contents of 'Main' or 'Outro'.
5. The final collection must have exactly 2 scenes.
6. Close OBS or let it auto-save.

Scene 'Main' kept

Scene 'Outro' kept

Scene 'Intro' deleted

Scene 'BRB' deleted

Scene 'Debug' deleted

Scene 'Archive' deleted

Exactly 2 scenes in collection

'Main Cam' still in 'Main'

check-source-in-scene 'Outro Roll' Outro

'Outro Roll' still in 'Outro'


Build a fresh scene collection for a multi-camera live event with six scenes. 1. OBS may start with a default 'Scene' -- delete it. 2. Create exactly six scenes with these exact names: 'Pre-Show', 'Keynote', 'Q and A', 'Demo', 'Interview', 'Wrap-Up'. 3. In the 'Pre-Show' scene, add: a. Image source named exactly 'Countdown' pointing at /home/user/Pictures/countdown.png. b. Text (FreeType 2) source named exactly 'Welcome Message'. 4. In the 'Keynote' scene, add: a. Display Capture source named exactly 'Keynote Screen'. b. Video Capture Device source named exactly 'Speaker Cam'. 5. In the 'Q and A' scene, add: a. Video Capture Device source named exactly 'Audience Cam'. b. Text (FreeType 2) source named exactly 'Question Prompt'. 6. In the 'Demo' scene, add: a. Display Capture source named exactly 'Demo Screen'. b. Video Capture Device source named exactly 'Demo Presenter'. 7. In the 'Interview' scene, add: a. Video Capture Device source named exactly 'Interviewer'. b. Video Capture Device source named exactly 'Guest'. 8. In the 'Wrap-Up' scene, add: a. Color Source named exactly 'Outro BG'. b. Text (FreeType 2) source named exactly 'Thanks'. 9. All sources must be visible. 10. The final collection must have exactly 6 scenes and no other scenes. 11.

Scene 'Pre-Show' exists

Scene 'Keynote' exists

Scene 'Q and A' exists

Scene 'Demo' exists

Scene 'Interview' exists

Scene 'Wrap-Up' exists

Exactly 6 scenes

'Countdown' in 'Pre-Show'

check-source-in-scene 'Welcome Message' Pre-Show

'Welcome Message' in 'Pre-Show'

check-source-in-scene 'Keynote Screen' Keynote

'Keynote Screen' in 'Keynote'

check-source-in-scene 'Speaker Cam' Keynote

'Speaker Cam' in 'Keynote'

check-source-in-scene 'Audience Cam' 'Q and A'

'Audience Cam' in 'Q and A'

check-source-in-scene 'Question Prompt' 'Q and A'

'Question Prompt' in 'Q and A'

check-source-in-scene 'Demo Screen' Demo

'Demo Screen' in 'Demo'

check-source-in-scene 'Demo Presenter' Demo

'Demo Presenter' in 'Demo'

'Interviewer' in 'Interview'

'Guest' in 'Interview'

check-source-in-scene 'Outro BG' Wrap-Up

'Outro BG' in 'Wrap-Up'

'Thanks' in 'Wrap-Up'

'Countdown' visible

'Speaker Cam' visible


Open OBS Studio and create a broadcast-ready scene collection with five scenes and various sources.

1. OBS may start with a default 'Scene' -- delete it.
2. Create five scenes with the exact names: 'Pre-Show', 'Interview', 'Screen Share', 'BRB', and 'End Card'.
3. Select the 'Pre-Show' scene. Add a Color Source named exactly 'Countdown BG'.
4. Select the 'Interview' scene. Add a Video Capture Device source named exactly 'Camera'.
5. Select the 'Screen Share' scene. Add a Display Capture (or Screen Capture) source named exactly 'Monitor'.
6. Select the 'BRB' scene. Add an Image source named exactly 'BRB Image'. Set its file path to /home/user/Pictures/brb.png.
7. Select the 'End Card' scene. Add a Color Source named exactly 'EndBG'. Then add a Text (FreeType 2) source named exactly 'Thanks'.
8. Make sure all added sources are visible (eye icon enabled).
9. Remove any extra default scenes -- the collection should have exactly 5 scenes.
10. Close OBS or let it auto-save.

Scene 'Pre-Show' exists

Scene 'Interview' exists

Scene 'Screen Share' exists

Scene 'BRB' exists

Scene 'End Card' exists

Exactly 5 scenes in the collection

check-source-in-scene 'Countdown BG' 'Pre-Show'

Source 'Countdown BG' exists in 'Pre-Show' scene

Source 'Camera' exists in 'Interview' scene

check-source-in-scene Monitor 'Screen Share'

Source 'Monitor' exists in 'Screen Share' scene

Source 'BRB Image' exists in 'BRB' scene

Source 'EndBG' exists in 'End Card' scene

Source 'Thanks' exists in 'End Card' scene


Set up a gaming stream layout with three scenes and multiple source types. 1. OBS may start with a default 'Scene' -- delete it. 2. Create three scenes with the exact names: 'Gaming', 'Just Chatting', and 'Starting Soon'. 3. Select the 'Gaming' scene and add these three sources: a. A Display Capture source named exactly 'Game'. b. A Video Capture Device source named exactly 'Webcam'. c. A Text (FreeType 2) source named exactly 'Stream Title'. 4. Select the 'Just Chatting' scene and add these two sources: a. A Video Capture Device source named exactly 'Main Camera'. b. An Image source named exactly 'Chat Frame'. Set its file path to /home/user/Pictures/frame.png. 5. Select the 'Starting Soon' scene and add these two sources: a. An Image source named exactly 'Start Screen'. Set its file path to /home/user/Pictures/starting.png. b. A Color Source named exactly 'Backdrop'. 6. Make sure all sources are visible (eye icon enabled) in all scenes. 7. Remove any extra default scenes. The collection should have exactly 3 scenes. 8.

Scene 'Gaming' exists

Scene 'Just Chatting' exists

Scene 'Starting Soon' exists

Exactly 3 scenes in the collection

Source 'Game' exists in 'Gaming' scene

Source 'Webcam' exists in 'Gaming' scene

check-source-in-scene 'Stream Title' Gaming

Source 'Stream Title' exists in 'Gaming' scene

check-source-in-scene 'Main Camera' 'Just Chatting'

Source 'Main Camera' exists in 'Just Chatting' scene

check-source-in-scene 'Chat Frame' 'Just Chatting'

Source 'Chat Frame' exists in 'Just Chatting' scene

check-source-in-scene 'Start Screen' 'Starting Soon'

Source 'Start Screen' exists in 'Starting Soon' scene

check-source-in-scene Backdrop 'Starting Soon'

Source 'Backdrop' exists in 'Starting Soon' scene


Set up a green-screen keyed layout. 1. OBS may start with a default 'Scene'. 2. Create a scene named exactly 'Live'. 3. In the 'Live' scene, add an Image source named exactly 'WebCam' whose file is /home/user/Pictures/green_plate.png. 4. Apply a Chroma Key filter to the 'WebCam' source. Name the filter exactly 'Green Screen'. 5. Configure the filter: Key Color Type = Green, Similarity = 420, Smoothness = 100. 6. The 'WebCam' source must be visible. 7..

Scene 'Live' exists

Source 'WebCam' is in the 'Live' scene

check-source-has-filter WebCam 'Green Screen'

Filter 'Green Screen' exists on 'WebCam'

source-filter-info WebCam 'Green Screen'

'chroma_key' in (result.get('type') or '')

'Green Screen' filter is a chroma key filter

str(result.get('settings', {}).get('key_color_type', '')).lower() == 'green'

Chroma key color type set to green

int(result.get('settings', {}).get('similarity', 0)) == 420

Chroma key similarity is 420

int(result.get('settings', {}).get('smoothness', 0)) == 100

Chroma key smoothness is 100


Open OBS Studio and build a color-graded Image source with two stacked filters.

1. OBS may start with a default 'Scene' — delete it.
2. Create a scene named exactly 'Color Grade'.
3. Add an Image source named exactly 'Footage' pointing at /home/user/Pictures/raw_footage.png.
4. Apply a Color Correction filter to 'Footage' named exactly 'Grade'. Use settings: Saturation = 0.4, Contrast = 0.15, Brightness = -0.05, Gamma = 0.1.
5. Apply an Apply LUT filter to 'Footage' named exactly 'Warm LUT'. Use LUT file /home/user/Pictures/warm_lut.png and amount = 1.0.
6. Close OBS or let it auto-save.

Scene 'Color Grade' exists

check-source-in-scene Footage 'Color Grade'

Source 'Footage' is in the 'Color Grade' scene

Filter 'Grade' exists on 'Footage'

'color_filter' in (result.get('type') or '')

'Grade' filter is a color correction filter

abs(float(result.get('settings', {}).get('saturation', 0)) - 0.4) < 0.01 and abs(float(result.get('settings', {}).get('contrast', 0)) - 0.15) < 0.01 and abs(float(result.get('settings', {}).get('brightness', 0)) - (-0.05)) < 0.01 and abs(float(result.get('settings', {}).get('gamma', 0)) - 0.1) < 0.01

Color correction saturation/contrast/brightness/gamma match

check-source-has-filter Footage 'Warm LUT'

Filter 'Warm LUT' exists on 'Footage'

'clut' in (result.get('type') or '') or 'lut' in (result.get('type') or '').lower()

'Warm LUT' filter is an Apply LUT filter

'warm_lut.png' in str(result.get('settings', {}).get('image_path', ''))

Apply LUT references warm_lut.png

abs(float(result.get('settings', {}).get('clut_amount', result.get('settings', {}).get('amount', 0))) - 1.0) < 0.01

Apply LUT amount = 1.0


The scene collection already contains a single scene named 'Live' with 6 sources, all currently visible: 'Camera A', 'Camera B', 'Screen', 'Title Text', 'Logo', 'Alert Box'. Your task is to toggle the eye (visibility) icon OFF for exactly 3 sources while leaving them in the scene, and leave the other 3 visible. Rules: 1. Hide (eye icon OFF) these 3 sources: 'Camera B', 'Logo', 'Alert Box'. 2. Keep these 3 sources visible (eye icon ON): 'Camera A', 'Screen', 'Title Text'. 3. Do NOT delete any source. All 6 sources must still be in the 'Live' scene. 4. Do NOT add, rename, or move any source. Do NOT create or delete any scene — the collection must still have exactly 1 scene named 'Live'. 5.

Scene 'Live' exists

Exactly 1 scene

'Camera A' still in 'Live'

'Camera B' still in 'Live'

'Screen' still in 'Live'

'Title Text' still in 'Live'

'Logo' still in 'Live'

'Alert Box' still in 'Live'

'Camera A' visible

'Screen' visible

'Title Text' visible

'Camera B' hidden

'Logo' hidden

'Alert Box' hidden


Create a scene collection for a virtual event with four scenes and many sources. 1. OBS may start with a default 'Scene' -- delete it. 2. Create four scenes with the exact names: 'Welcome', 'Speaker', 'Panel', and 'Closing'. 3. Select the 'Welcome' scene and add two sources: a. An Image source named exactly 'Event Banner'. Set its file path to /home/user/Pictures/banner.png. b. A Text (FreeType 2) source named exactly 'Event Title'. 4. Select the 'Speaker' scene and add two sources: a. A Display Capture source named exactly 'Slides'. b. A Video Capture Device source named exactly 'Speaker Cam'. 5. Select the 'Panel' scene and add three Video Capture Device sources: a. Named exactly 'Panelist 1'. b. Named exactly 'Panelist 2'. c. Named exactly 'Panelist 3'. 6. Select the 'Closing' scene and add two sources: a. A Color Source named exactly 'Closing BG'. b. A Text (FreeType 2) source named exactly 'Goodbye'. 7. Make sure all sources are visible (eye icon enabled) in all scenes. 8. Remove any extra default scenes. The collection should have exactly 4 scenes. 9.

Scene 'Welcome' exists

Scene 'Speaker' exists

Scene 'Panel' exists

Scene 'Closing' exists

Exactly 4 scenes in the collection

check-source-in-scene 'Event Banner' Welcome

Source 'Event Banner' exists in 'Welcome' scene

check-source-in-scene 'Event Title' Welcome

Source 'Event Title' exists in 'Welcome' scene

Source 'Slides' exists in 'Speaker' scene

check-source-in-scene 'Speaker Cam' Speaker

Source 'Speaker Cam' exists in 'Speaker' scene

check-source-in-scene 'Panelist 1' Panel

Source 'Panelist 1' exists in 'Panel' scene

check-source-in-scene 'Panelist 2' Panel

Source 'Panelist 2' exists in 'Panel' scene

check-source-in-scene 'Panelist 3' Panel

Source 'Panelist 3' exists in 'Panel' scene

check-source-in-scene 'Closing BG' Closing

Source 'Closing BG' exists in 'Closing' scene

Source 'Goodbye' exists in 'Closing' scene


Create a scene with multiple source types. 1. Delete any existing default scenes so you start fresh. 2. Create a scene named exactly 'Presentation'. 3. With 'Presentation' selected, add the following three sources: a. A 'Display Capture' source named exactly 'Screen'. b. An 'Image' source named exactly 'Logo'. Point it to the file /home/user/Pictures/logo.png. c. A 'Text (FreeType 2)' source (or 'Text' source) named exactly 'Title'. Set the text content to anything you like. 4. Make sure all three sources are visible in the scene. 5. The scene collection should contain exactly 1 scene ('Presentation') with all 3 sources. 6. Remove any other scenes besides 'Presentation'.

Scene 'Presentation' exists

Exactly 1 scene in the collection

Source 'Screen' exists in 'Presentation' scene

Source 'Logo' exists in 'Presentation' scene

Source 'Title' exists in 'Presentation' scene

Source 'Screen' is visible

Source 'Logo' is visible

Source 'Title' is visible


Build a scene collection for a TV news broadcast. 1. OBS may start with a default 'Scene' -- delete it. 2. Create exactly three scenes with these exact names: 'Studio', 'Field Report', 'Weather'. 3. In the 'Studio' scene, add these four sources with these exact names: a. Video Capture Device named exactly 'Anchor Cam'. b. Color Source named exactly 'Lower Third'. c. Text (FreeType 2) source named exactly 'Headline Ticker' (set the text to any value). d. Image source named exactly 'Network Logo' pointing at /home/user/Pictures/news_logo.png. 4. In the 'Field Report' scene, add these two sources: a. Video Capture Device named exactly 'Reporter Cam'. b. Text (FreeType 2) source named exactly 'Location Bug' (set the text to any value). 5. In the 'Weather' scene, add these two sources: a. Image source named exactly 'Weather Map' pointing at /home/user/Pictures/weather_map.png. b. Text (FreeType 2) source named exactly 'Forecast Caption' (set the text to any value). 6. All sources must be visible. 7. The final collection must have exactly 3 scenes. 8.

Scene 'Studio' exists

Scene 'Field Report' exists

Scene 'Weather' exists

Exactly 3 scenes

check-source-in-scene 'Anchor Cam' Studio

'Anchor Cam' in 'Studio'

check-source-in-scene 'Lower Third' Studio

'Lower Third' in 'Studio'

check-source-in-scene 'Headline Ticker' Studio

'Headline Ticker' in 'Studio'

check-source-in-scene 'Network Logo' Studio

'Network Logo' in 'Studio'

check-source-in-scene 'Reporter Cam' 'Field Report'

'Reporter Cam' in 'Field Report'

check-source-in-scene 'Location Bug' 'Field Report'

'Location Bug' in 'Field Report'

check-source-in-scene 'Weather Map' Weather

'Weather Map' in 'Weather'

check-source-in-scene 'Forecast Caption' Weather

'Forecast Caption' in 'Weather'

'Anchor Cam' visible

'Network Logo' visible

'Weather Map' visible


Open OBS Studio and create a podcast recording setup with four scenes.

1. OBS may start with a default 'Scene' -- delete it.
2. Create four scenes with the exact names: 'Solo', 'Dual', 'Screen Demo', and 'Intermission'.
3. Select the 'Solo' scene and add these two sources:
   a. A Video Capture Device source named exactly 'Host Camera'.
   b. A Color Source named exactly 'Solo BG'.
4. Select the 'Dual' scene and add these two sources:
   a. A Video Capture Device source named exactly 'Host'.
   b. A Video Capture Device source named exactly 'Guest'.
5. Select the 'Screen Demo' scene and add these two sources:
   a. A Display Capture (or Screen Capture) source named exactly 'Shared Screen'.
   b. A Text (FreeType 2) source named exactly 'Topic'. Set the text to any value.
6. Select the 'Intermission' scene. Add an Image source named exactly 'Break Slide'. Set its file path to /home/user/Pictures/break.png.
7. Make sure all sources are visible (eye icon enabled) in all scenes.
8. Remove any extra default scenes. The collection should have exactly 4 scenes.
9. Close OBS or let it auto-save.

Scene 'Solo' exists

Scene 'Dual' exists

Scene 'Screen Demo' exists

Scene 'Intermission' exists

Exactly 4 scenes in the collection

check-source-in-scene 'Host Camera' Solo

Source 'Host Camera' exists in 'Solo' scene

Source 'Solo BG' exists in 'Solo' scene

Source 'Host' exists in 'Dual' scene

Source 'Guest' exists in 'Dual' scene

check-source-in-scene 'Shared Screen' 'Screen Demo'

Source 'Shared Screen' exists in 'Screen Demo' scene

check-source-in-scene Topic 'Screen Demo'

Source 'Topic' exists in 'Screen Demo' scene

check-source-in-scene 'Break Slide' Intermission

Source 'Break Slide' exists in 'Intermission' scene