Ship of Harkinian · lua scripting layer · unattended run · 21 Sep 2026

The Third Brother, driven to the end

A quest written entirely in Lua — an old Poe in the Kakariko graveyard who wants three flames back — and a 23-step script in docs/PLAYTEST.md written for a person with a controller in a dark room. This run is that script executed by ./dev playtest on a machine with no monitor and nobody watching: each step boots its own game, reaches its own quest state, and then either asserts something or files a picture with a question printed beside it. Seventeen of the twenty-three steps now run, and for the first time the runner reaches the end of the quest — the song, the fight, the reward and the ending. It came back with two failures, and one of them is a real bug in the quest.

Runrun-20260921-134450
Hostmonad, DISPLAY=:0
Commit7e307171e604
Working treedrive.py dirty (step 18's relaunch(), another session's)
Wall clock6 min 25 s
17/23steps the runner can drive
15passed
2failed
6not written yet

The run, step by step

Not written means there is no implementation yet, not a skipped test — the suite reports it rather than passing it, which is the difference between tracking the goal and flattering it. The two failures are expanded below; both are reported by the step that found them rather than asserted away.

01It loadedPass
02He is there, and only at nightPass
03Talk to him, and say noPass
04`quest where`, in fullPass
05Say yes, and find roost APass
06Cut it open, and kill the flockPass
07Chase it -- the tuning questionPass
08Roosts B and CPass
09The songstep 9: THE TEAR IS NOT ON THE GROUND IT IS TORN IN. It is at y=181.00, placed at the room load you come back to; the ground under it is 192.45, measured by dropping Link on it from above. main.lua's MAW_FLOOR is 181 -- the terrace's grass -- but the Composer Brothers' grave's stone apron (Bg_Spot02_Objects, dynapoly) covers the tear's whole footprint and its top is 192.45. At 181 the collar and the throat are under opaque geometry that is drawn first, so `G_RM_AA_ZB_XLU_SURF` Z-rejects them and what is left is a flat brown smear: A STAIN, which is the first of the three failures docs/PLAYTEST.md step 9 names. THE SAME ACTOR SPAWNED BY THE SONG floats up to 192.45 (the apron's collision is registered by then) and reads as a real hole, so the quest shows two different pictures of one grave and the broken one is the one every reload gives you. The fix is one number: the placement's y at examples/third_brother/main.lua:4798 and MAW_FLOOR itself.Fail
10The fightPass
11Kill herPass
12The rewardPass
13The endingPass
14Reset, and do it againNot written
15The doorway rule, confirmed on purposePass
16The Queen culling behind a gravestonePass
17The wisp's speed, in either directionPass
18The side-car desyncing across a file copyNot written
19A placement landing inside geometryNot written
20The text box's line breaks at the real font size14 line(s) of this quest are wider than the box they are drawn in. Nothing in the engine wraps a line and `ship.text` does not measure one, so what does not fit runs out of the box and off the screen -- the worst of them, 'Then listen for them. A flame that is being kept makes a sound like breathing.', ends at x=503 in a box that ends at x=290, on a virtual screen 320 wide. This is a `ship.text` finding, not a quest one: the quest's author had nothing to ask.Fail
21DawnNot written
22The live-reload loopNot written
23The abuse listNot written

What the quest is, and which step drives what

Before the failures: the shape of the thing. The quest is a five-stage store with a flame count, and a placement gate that decides who is standing in the room when it loads. Every step below is one question asked of that machine.

Natural is the third Composer Brother. He is in the graveyard at night, his lantern is out, and he asks Link to find the three flames that were taken out of it. They hang in hive sacs — two in the graveyard, one on the Kakariko ledge — and each one has to be cut open, its flock killed, and the loose flame chased down and caught. With three flames he plays a nine-second song that opens a grave, a Hive Queen comes out of it, and what is on the other side of her is a Piece of Heart and four pages of the only speech in the quest.

All of that is one store with two keys — a stage from 0 to 4 and a flame count from 0 to 3 — and the playtest steps hang off the transitions between them:

one flame per roost 0 met dark, and only at night 1 hunt three sacs, three flames 2 song he is gone; the grave is open 3 slain she is dead 4 paid owes nothing, for ever 01 02 03 05 06 07 08 09 10 11 12 13 BELONGING TO NO ONE TRANSITION 04 `quest where` at all eight states 15 the doorway rule, both directions 16 the Queen behind a gravestone 17 the wisp's speed, either direction 20 the text box at the real font size
The spine, and the five steps that sit beside it. Green is a step this run drove; grey is one that has never been written. The five below the rule belong to no single transition — they are the checks that cut across the quest, and step 15 in particular is about the gate itself rather than about any stage.

The gate is the part that surprises people, so it is worth drawing whole. It is asked only when a room loads. Writing the store from the console moves the numbers and stands nothing up; you have to walk out and back in. That rule has two directions and only the first gets tested by accident, which is why step 15 exists.

GRAVEYARD · NIGHT GRAVEYARD · DAY STAGE / FLAMES 0 / 0 flames Natural · nothing 0 / 3 flames Natural · nothing 1 / 0 flames Natural roost A roost A 1 / 1 flames† Natural roost B roost B 1 / 2 flames† Natural · nothing 1 / 3 flames Natural · nothing 2 / 0 flames open grave open grave 2 / 3 flames open grave open grave 3 / 0 flames Natural · nothing 3 / 3 flames Natural · nothing 4 / 0 flames Natural · nothing 4 / 3 flames Natural · nothing † the two flame counts Appendix B does not print — and the two that move the answer.
Who is standing when the room loads. Three rows look like bugs and are not: Natural is not placed at all at stage 2 (he is gone for the fight), the open grave at stage 2 is the quest's only placement that is not night-gated, and roost A hangs by day as well as by night. The two daggered rows are the flame counts Appendix B does not print — and they are the two that move the answer.

And an actor already standing does what it likes with the store. This run measured three different answers from three quest actors, none of them the gate: Natural re-reads the store every frame and starts the song when the stage moves to 2 under him; En_OpenGrave shuts itself the moment the stage leaves 2, with no doorway crossed; En_HiveRoost has no change detector at all and goes on hanging at a stage that would never have placed it.

The tear, at two heights

Step 9's failure, and the only one of the two that is the quest's own fault. The song opens a tear in the ground beside the Composer Brothers' grave. Whether it reads as a hole depends on a number that is right once and wrong once, in the same session, for the same actor.

docs/PLAYTEST.md names three ways the tear can be wrong — a stain (too flat), a lump (the collar too proud), or invisible (the alpha) — and asks a person to say which. This run found the first one, and found out why.

The tear is painted above the floor on purpose: a translucent throat below ground would be Z-rejected by the ground it is a hole in. main.lua's MAW_FLOOR is 181, the terrace's grass. But the Composer Brothers' grave has a stone apron — Bg_Spot02_Objects, dynapoly — that covers the tear's whole footprint, and the harness measured its surface at 192.45 by dropping Link on it from 400 units up. So the tear is 11.45 units under the ground it is torn in, and the opaque apron is drawn first.

the terrace’s grass — MAW_FLOOR = 181 the grave’s stone apron · Bg_Spot02_Objects, dynapoly opaque, and drawn first 11.45 placed at the room load — y 181 under opaque geometry, so G_RM_AA_ZB_XLU_SURF rejects it: a stain opened by the song — y 192.45 Heights are to scale with each other and not with the graveyard; the vertical is exaggerated so 11.45 units are visible at all.
The same actor, at two heights. Placed at the room load it sits on the grass at 181, underneath the apron, and G_RM_AA_ZB_XLU_SURF throws the collar and the throat away. Spawned by the song it comes to rest at 192.45, on top of the apron. Dynapoly collision is registered after the room has loaded, which is why the same placement finds two different floors.

So the quest shows two different pictures of one grave, and the broken one is the one every reload gives you. Walk out and back in, or die and take the Continue, and you get the stain. The fix is one number, in two places: the placement's y at examples/third_brother/main.lua:4798 and MAW_FLOOR itself.

The graveyard at night. Link stands with his back to the camera in front of the Composer Brothers gravestone. On the grass to his right is a flat pale tan four-sided patch with a hard polygon edge and a thin dark crescent along its top edge, lying on the surface with no depth to it.
The tear, placed at the room load. A flat pale sheet on the grass with a hard edge and a thin dark crescent. It does not read as a hole; it reads as something spilled.
The graveyard in heavy rain. Link stands with his back to the camera facing the grave, whose stone lid is tilted open to his right. A fairy is at his shoulder. The tear itself is almost entirely hidden behind Link and the lid; only a small pink sliver is visible past his shield.
The tear the song opens — and a frame that cannot answer the question. Link and the grave lid stand in front of it, so only a sliver shows. That it comes to rest at 192.45 is measured; that it reads as a hole is not shown here, and this page is not going to claim it from a filename.

What only a person can answer

docs/PLAYTEST.md collects six judgement calls, and says plainly that none of them has a right answer in the code. Two of them — #5 and #6 — had no picture beside them until this run, because nothing had ever driven the quest that far.

A wooden Ocarina of Time text box at the bottom of the screen reading 'She is under the stones again, and' -- the line runs off the right edge of the screen with no wrap. Above it Natural leans in close: a teal-grey hood with a gold spiral, a sun-shaped sigil and narrow glowing pink eyes, with Link's green cap beside him.
Judgement call #5

Is the four-page reward speech too long?

He has been silent for the whole fight, and this is the only speech in the quest.

The card suspects it is two pages too many and says FREED is the only thing to change. All four pages are filed — they are in the strip below — and Sharp renders in red on page 3 as it should.

But read the frame before answering the question. The line runs off the right edge of the screen. All four pages of this speech overflow their box, so the question “are four pages too many?” is being asked about a speech you cannot finish reading. That is step 20's subject, and it lands hardest here.

text id 0xE008 · 4 pages · 4 lines over the box's right edge by 82, 61, 34 and 35

The pause menu's quest status page. The heart-piece kaleidoscope is a heart outline divided into four quarters with exactly one quarter, the upper left, filled solid red. Below it are the twelve ocarina song notes and the medallion hexagon.
Judgement call #6 — the gate holds

Handed a heart piece by walking into range

The right feel, or should he offer it mid-conversation?

Still a person's call, but the thing it is a question about is now proven. Step 12 takes the hand-over apart into two negatives and a positive: 120 frames at 25 units without ever speaking to him hands over nothing; 120 frames at 80 units after the conversation hands over nothing either; walking to 25 units and pressing nothing takes it on the next stepped frame, with input state read back through the hand-over as held: none | timed: none | stick: off.

So the choice really is between “he says the line and then holds it out” and “he thrusts it at anyone who walks past”. The third possibility — that the gate is already broken and it is the second one — is ruled out.

And the digit is not the counter. The kaleidoscope shows one quarter of four; it wraps, because the fourth piece becomes a heart container. The count that was asserted is the cumulative one, 36 → 37.

pause state 6 · 3 START presses and 4 turns of R · cumulative 36 → 37

The graveyard at night with the area title 'Graveyard' on screen. Link stands in the foreground. To his right, Natural is a completely flat navy-blue silhouette -- a featureless dark shape with no face, no shading and no visible lantern, against the gravestones.
Judgement call #1

Does the dark tint read as an unlit lantern?

Or as a model that failed to load?

This is him at zero flames, and it is the reading the first playtest gave: a flat navy silhouette with no face. It is also on purpose — the colours scale with the flame count, which is what keeps him a progress bar — so the real question is what happens next. It does: by one flame he has glowing eyes, a shaded robe and a Triforce sigil, and the strip below has all four.

The measurement does not settle it. The harness sampled a rectangle of his body at each flame count and got #181e27, #283133, #202b25, #242f28 — luminance 29.1, 46.4, 39.1, 42.7. That does not rise with the flames, so “he brightens as you make progress” is not what a body sample shows. The doc's claim is about his head — segment 0x08 reaches limb 10 and nothing else — and a body rectangle cannot see it. The pictures are the instrument here, not the number.

0 flames · body #181e27, luminance 29.1 · he is at (660, 181, 20)

The rainy graveyard seen from behind a gravestone. Large translucent violet crystal shards -- the Hive Queen -- fill the left half of the frame with an orange glow behind them, and Link stands in the middle with his back to the camera.
Judgement call — step 16

Does the Queen pop behind a gravestone?

`draw_culling_disabled` is not a number, and a pixel count cannot tell a boss hidden behind a stone from a boss that stopped being drawn.

She has update_culling_disabled and draw_culling_disabled both set, which should make popping impossible — but “impossible” here means two flags in a Lua table. The update half is settled by measurement: she kept updating from all five stands, including from the graveyard entrance with a wall and a stairwell between her and Link.

The draw half is what the five frames are for. Read them knowing this: in two of the five she is not in shot at all, and in at least one of those — the stand in the open — she is a violet sliver in the top-right corner, off the side of the camera rather than absent from the world. Framing, not culling. Whether she ever pops is the part a person still has to watch for.

5 stands · she updated from all of them

The graveyard in rain. Link stands small in the middle of the frame beside a gravestone with his shield on his back. A single small violet shard creature hangs in the air to his right, and a thin magenta spike enters from the top edge. Most of the frame is empty wet ground and stone.
Open

Is a boss designed in a test room worse in a graveyard?

The fight works as machinery. Does it work as a fight?

Steps 10, 11 and 16 assert the machinery and it holds: she stays above the terrace, she is not stuck, she survives the camera leaving her, dying to her is survivable, and six blows of four through her own damage path take her from 24 to 0. Her heart container then hovers at (570, ~220, 110), fixed in x and z over 120 frames and bobbing between 216.8 and 223.9 — 37 to 44 units above the terrace.

None of that is the question. This is the player's own view of the fight, and it is a sparse picture: one small shard creature, a lot of wet stone. A boss built in a test room is being asked to carry a real room, and no assertion in the suite can say whether it does.

stage 2 · 24 hp · she updated from every stand tried

The quest, in order

Five frames out of the forty-eight this run filed — the progress bar lighting up, the speech, the drop, and the morning after. Every frame the run took is listed at the foot of the page.

The graveyard at night with the 'Graveyard' title card on screen. Natural stands to the right of Link as a dark hooded figure, now with two small glowing green eyes and a faint gold sigil visible on his robe, against a gravestone.
02 — one flame back. He has a face again.
The graveyard at night. Natural stands at the right as a pale sage-green robed Poe with a gold spiral on his chest, a gold Triforce on his robe, narrow white glowing eyes, and a dark lantern with a pale green glowing core in his hand. Link stands in front of him with a fairy over a gravestone to the left.
02 — three flames. Gold Triforce, and the lantern has a core.
A wooden text box reading 'I can finish it now. Sharp will hat' -- the word Sharp is in orange-red and the line is cut off by the right edge of the screen. Natural leans in above the box as a dark hood with glowing pink eyes and a gold spiral.
12 — page 3 of 4, and Sharp is red.
A large pink and white Heart Container floats above Link against a dark blue get-item background, with the message 'You got a Heart Container! Your maximum life' below it.
11 — her drop, not his. 24 hp in six blows of four.
The graveyard in daylight with the 'Graveyard' title card on screen. Link stands with his back to the camera in front of the Composer Brothers gravestone, with pale motes drifting in front of the stone. Natural is nowhere in the frame.
13 — noon at stage 4. He is not there, as at every stage.

The other failure, and the frame that proves it

Step 20, and it is not the quest's fault — it is ship.text's. It also demonstrates the trap that this report is built to avoid.

A wooden Ocarina of Time text box at the bottom of the screen. The single line of text reads 'Then listen for them. A flame that' and is cut off by BOTH edges of the screen -- the T of 'Then' is clipped at the left edge and 'that' runs off the right. Above the box, Natural is a flat dark navy silhouette in close-up with Link's arm and cap at the lower right.

Fourteen lines run out of their box

Nothing in the engine wraps a line and ship.text does not measure one, so what does not fit runs out of the box and off the screen. Fourteen lines of this quest do it. The worst ends at x=503 in a box that ends at x=290, on a virtual screen 320 wide — and this is that exact line, caught by step 5 on its way past: “Then listen for them. A flame that…” clipped at both edges, with the rest of the sentence simply not on the screen.

Note which frame this is. It is not step20_FAIL.png. That one is the runner's best-effort capture, taken after the step raised on whatever frame the game happened to be on — it shows Natural standing over Link in the rain with no text box on screen at all, and it would prove nothing. The frame that shows the failure was filed five steps earlier by a step that passed. A caption written from a filename gets this exactly backwards, which is why report.py refuses a featured frame with no alt text: you cannot describe a frame you have not opened.

What has still never run

Six of the twenty-three steps have no implementation, and they are no longer the end of the quest — they are the edges of it.

14, 23 — quest reset, and the abuse list. 19 — a placement landing inside geometry, which the tear above is arguably the first real instance of. 21 — dawn, and the u16 that wraps. 22 — the live-reload loop.

And 18, the side-car's round trip to disk, which is the one the quest itself keeps running into. Step 13 tries four ways of getting the world back — standing there, lua_reload, leaving to Kakariko and returning, and dying and taking the Continue — and he never offers a second Piece of Heart through any of them. What it cannot do is save, quit and relaunch: ./dev drive boots with DebugSaveFileMode=2 on save slot 255, ScriptedSave_SlotIsReal takes 0..SCRIPTED_SAVE_SLOT_MAX, so this game never flushes a side-car at all. The step asserts the slot rather than asserting a claim it did not make. A harness that boots into the file select is in progress as this page is written.

Every frame this run filed (48)