Merge remote-tracking branch 'origin/main' into auto/frame-blend-draw-path
This commit is contained in:
106
docs/agents/PLAYTEST-2026-09-01.md
Normal file
106
docs/agents/PLAYTEST-2026-09-01.md
Normal file
@@ -0,0 +1,106 @@
|
||||
# Play-test, 2026-09-01 — a human, a real controller, the port
|
||||
|
||||
**The first time a person played this port on real hardware.** It found four
|
||||
things. Two were fixed on the spot by the human; two are open and are the
|
||||
**current focus of both agents**.
|
||||
|
||||
⚠️ This page is a record of observations, not a mission change. `PORT-MISSION.md`
|
||||
and the loop briefs carry the objective.
|
||||
|
||||
## What was found
|
||||
|
||||
| # | finding | status |
|
||||
|---|---|---|
|
||||
| 1 | **Ⓐ and Ⓑ did nothing on the pad.** Could not skip the intro, could not open a submenu. | ✅ fixed by the human — `port/scripts/gamepad.gd` |
|
||||
| 2 | **The left stick moved the cursor far too fast.** | ✅ fixed by the human — latched to one step per deflection |
|
||||
| 3 | **The `PRESS Ⓐ` plate appears too late.** | 🔴 **OPEN** |
|
||||
| 4 | **The splash fade/blur is wrong** — the game's is *more pronounced*. | 🔴 **OPEN** |
|
||||
|
||||
## 1 & 2 — why no check caught them, which matters more than the fixes
|
||||
|
||||
> **`--script` sends `InputEventAction`, which BYPASSES the input map.**
|
||||
|
||||
Every check the port had asserted the code *below* the input map and nothing
|
||||
about the map itself. The map turned out to have **no joypad binding for
|
||||
`ui_accept` or `ui_cancel` at all** — measured on Godot 4.7.2, not remembered,
|
||||
because the remembered answer was wrong:
|
||||
|
||||
```
|
||||
ui_accept key:Enter, key:Kp Enter, key:Space <- no joypad button at all
|
||||
ui_cancel key:Escape <- no joypad button at all
|
||||
ui_up key:Up, JOYBTN:11, JOYAXIS:1- <- d-pad AND left stick
|
||||
ui_down key:Down, JOYBTN:12, JOYAXIS:1+
|
||||
```
|
||||
|
||||
Four actions reached the pad and two did not. Ⓐ was dead for the whole of P5
|
||||
while the unattended walk passed on every iteration.
|
||||
|
||||
The **same blind spot** hid finding 2: an `InputEventAction` is not an analog
|
||||
axis, so nothing could observe that a stick held at deflection emits an event
|
||||
per *jitter*, each reporting the action as pressed — one cursor step per jitter.
|
||||
|
||||
Now asserted by `tools/port/verify-input`, with a control that removes each
|
||||
check's own subject. (Its first version inverted all nine assertions when only
|
||||
two depended on the fix, and reported seven correct checks as broken. Three rows
|
||||
now say plainly they are **not controllable** — they assert Godot's own bindings
|
||||
— and one is a **negative carrying a positive control** rather than a faked
|
||||
inversion.)
|
||||
|
||||
### The standing rule that follows
|
||||
|
||||
**Synthetic input is not a test of input.** Anything injected below the input map
|
||||
is evidence about the code above it and nothing else. A test of input must go in
|
||||
at the device level — `InputEventJoypadButton`, `InputEventJoypadMotion`,
|
||||
`InputEventKey` — or must assert the map directly.
|
||||
|
||||
## 3 — the plate is late
|
||||
|
||||
The port raises the plate at `t=236`, **3.93 s** after the shared clock starts,
|
||||
which it derives as `238 − 118 = 120 units = 2.000 s` after the title's build-in
|
||||
ends. A human watching both says it is **late**.
|
||||
|
||||
This lands in a spot the corpus already knows is soft. All of the following are
|
||||
live:
|
||||
|
||||
* `REFUTED.md`: *"a screen has SETTLED at its `rest.t`"* → ❌ — believing `rest.t`
|
||||
had already put a port's plate **3.97 s late** once.
|
||||
* `REFUTED.md`: the 2.13 s figure was *"a wall-clock reading stretched by Canary
|
||||
presenting at ~28.1 fps"*, corrected to 120 units. **So the conversion between
|
||||
units and seconds is load-bearing here and is exactly what
|
||||
[`TEMPORAL-VERIFICATION.md`](TEMPORAL-VERIFICATION.md) says not to trust from a
|
||||
wall clock.**
|
||||
* The keyframe **time-unit shift** is unresolved (`ui-keyframe-time-unit.md`).
|
||||
* 🔴 After the 2026-09-01 R1 pass, *"the declared keyframe timeline reproduces the
|
||||
captured splash"* is **🟡 `⟨our-reader⟩`**, not ❌ — the record-layout fix
|
||||
re-times a group's final pose and the entry was never re-derived under it.
|
||||
|
||||
**Candidate causes, none established:** the unit→seconds constant; the clock
|
||||
origin (do both builds really start together?); `rest.t` again; the record layout.
|
||||
Settle it by **ordering and counts**, not by a stopwatch.
|
||||
|
||||
## 4 — the splash fade/blur
|
||||
|
||||
The port applies **no blur at all**. It draws declared keyframe alphas. So
|
||||
*"more pronounced in the game"* is consistent with a post-process the export does
|
||||
not describe, a different ramp shape, or both — and nothing in the export can
|
||||
distinguish those.
|
||||
|
||||
🔴 **And the two splashes are the ONLY screens that reach `rest()`'s
|
||||
plateau-less fallback** — title, main menu and `EXTRAS` reach it zero times. So
|
||||
finding 4 lands precisely where our resting-pose heuristic is least trustworthy,
|
||||
and the R1 pass just re-opened that question **in both directions** (see the
|
||||
`rest()` pair in `REFUTED.md`). That is not a coincidence to step around.
|
||||
|
||||
## The human's verdict on method
|
||||
|
||||
> *"It seems the agents were essentially guessing and trying to copy what one
|
||||
> would see, but while they did get close it still is not quite right."*
|
||||
|
||||
Close-but-not-right is the signature of reproducing **appearance** instead of
|
||||
deriving **mechanism**. A ramp tuned until it looks right is wrong in a way
|
||||
nobody can name and has no reach to the next screen.
|
||||
|
||||
The instruction that follows: for the splashes, **find out what the game is
|
||||
doing** — is there a post-process pass, how many, what shader, what blend, what
|
||||
render targets, and where do its parameters come from — before proposing any
|
||||
curve. See the Decoder's brief.
|
||||
139
docs/agents/TEMPORAL-VERIFICATION.md
Normal file
139
docs/agents/TEMPORAL-VERIFICATION.md
Normal file
@@ -0,0 +1,139 @@
|
||||
# Verifying things that MOVE
|
||||
|
||||
**Both agents read this.** Set by the human on 2026-09-01, after a play-test
|
||||
found the splash fade and the `PRESS Ⓐ` plate visibly wrong while every check
|
||||
either agent had was green.
|
||||
|
||||
## The diagnosis, in one sentence
|
||||
|
||||
> **We have been trying to photograph the game at time *t*, and *t* is never the
|
||||
> same twice.**
|
||||
|
||||
Every temporal claim in this corpus rests on grabbing a frame at a wall-clock
|
||||
instant and comparing it to something. That instant drifts — emulator speed
|
||||
varies with host load, Canary presents at ~28.1 fps rather than 30, the capture
|
||||
path costs a variable 0.1–10.8 s, and a long-lived `x11grab` stream degrades and
|
||||
then freezes. So the comparison is between *our render at the time we meant* and
|
||||
*the game at some other time*, and the difference between those two things is
|
||||
being read as a difference in the **content**.
|
||||
|
||||
The register already carries four separate refutations of this exact shape:
|
||||
|
||||
* *"a latency read off a classified `x11grab` stream is a duration"* — ❌. At
|
||||
1503 ms per classification against an 8 fps stream the consumer ran at
|
||||
0.64 fps; four "durations" died. A screen transition, a button press and a
|
||||
plate fade all came out at ~20–25 s, which is the tell.
|
||||
* *"2 391 frames over 600 s, max glyph 0, therefore the title never appears"* —
|
||||
withdrawn: **the instrument stalls**, repeating one stale frame, reading
|
||||
surface mean 5.21 where `import` read 125.65 at the same moment.
|
||||
* *"the boot harness fails because its polling loop samples every ~41 s"* —
|
||||
the defect was real and fixing it (13.7×) **did not change the answer**.
|
||||
* *"the in-box capture noise of 0.32 between sessions"* — it was not noise, it
|
||||
was the **trigger**: gating on the plate pulse phase-locks the shutter, so
|
||||
0.32 is a lower bound produced by the instrument. At an arbitrary phase the
|
||||
honest figure is 11.9.
|
||||
|
||||
That last one is the important one, and it cuts both ways: **gating hides
|
||||
variance, and not gating produces it.** Neither is a measurement of the game.
|
||||
|
||||
## What to do instead
|
||||
|
||||
The rule is simple and it removes the whole class:
|
||||
|
||||
> **Never compare at an absolute time. Record a SEQUENCE, and align it by
|
||||
> CONTENT.**
|
||||
|
||||
### 1. Capture a film, not a photograph
|
||||
|
||||
Record a continuous run of frames with an index and a timestamp each, spanning
|
||||
the whole animation with margin at both ends. One frame is a sample of a
|
||||
distribution you have not characterised; a film *is* the distribution.
|
||||
|
||||
**State the achieved rate against the requested rate, every time.** A capture
|
||||
that asked for 4 fps and delivered 1.6 is not a slow capture, it is a
|
||||
**different capture**, and it has already produced two withdrawn findings here.
|
||||
An instrument that cannot report its own completeness may not be trusted (R3).
|
||||
|
||||
### 2. Align by content, then measure
|
||||
|
||||
Find the offset that best matches, rather than assuming offset zero:
|
||||
|
||||
* reduce each frame to a scalar or a small vector — mean of a region, an
|
||||
element's alpha, a per-tile amplitude;
|
||||
* do the same for the prediction;
|
||||
* **search the lag** that maximises agreement, and report *both* the lag and the
|
||||
agreement at it.
|
||||
|
||||
The lag is not an error to be minimised away — **it is a measurement**. A
|
||||
consistent lag across runs is a real offset in our model. A lag that varies
|
||||
run to run is the harness, and says so.
|
||||
|
||||
### 3. Prefer quantities that have no phase
|
||||
|
||||
Ranked by how much they survive a drifting clock:
|
||||
|
||||
| quantity | survives drift? |
|
||||
|---|---|
|
||||
| **ordering** — A finishes before B starts | ✅ completely |
|
||||
| **counts** — 83 frames at full alpha | ✅ (given a known, reported rate) |
|
||||
| **durations and ratios** — ramp is 2× the hold | ✅ |
|
||||
| **shape** — monotone, eased, stepped, its inflections | ✅ |
|
||||
| a value **at a named event** — alpha when the plate first appears | 🟡 needs the event found, not the time |
|
||||
| a value **at wall-clock t** | ❌ this is the thing that has been failing |
|
||||
|
||||
The two strongest existing results in the corpus are both of this kind: the
|
||||
**hold duration** (83 frames of full alpha) is called *calibration-free* in
|
||||
`ui-keyframe-time-unit.md` and decided the question; and the `_eff` glows'
|
||||
**exact steps of 34** are a shape, not a sample.
|
||||
|
||||
### 4. Anchor on an event
|
||||
|
||||
Quote everything relative to a frame you can *find* rather than a time you
|
||||
requested: the first frame an element is non-black, the frame the plate first
|
||||
appears, the last frame of the previous screen. Then a drifting start costs
|
||||
nothing, because every number is a difference.
|
||||
|
||||
### 5. Say what you expected before you look (R2)
|
||||
|
||||
*"This ramp declares 80 units, so at 30 fps I expect ~80 frames and I will
|
||||
accept 74–86."* Written first, it makes a near-miss legible as a near-miss
|
||||
instead of something to rationalise. Written after, any number can be explained.
|
||||
|
||||
### 6. Convert units deliberately
|
||||
|
||||
⚠️ **Canary presents at ~28.1 fps, so a wall-clock duration off this emulator is
|
||||
~6 % long.** A measured interval landing near a round number of keyframe units
|
||||
probably *is* that number of units — that is how `2.13 s` turned out to be
|
||||
`120 units = 2.000 s`. Quote the unit count, then the seconds, then the fps you
|
||||
divided by. Never the seconds alone.
|
||||
|
||||
## The other half: stop reproducing by eye
|
||||
|
||||
The play-test's verdict on the splashes was *"close, but not quite right"*, and
|
||||
that is the signature of **matching appearance instead of deriving mechanism**.
|
||||
A ramp tuned until it looks right will be wrong in a way nobody can name, and
|
||||
"looks right" has no reach — it does not tell you what the next screen will do.
|
||||
|
||||
So for anything visual that is still not exact, the question is not *"what
|
||||
curve fits?"* but **"what is the game actually doing?"**:
|
||||
|
||||
* Is there a **post-process pass at all** — a blur, a bloom, a fade quad, a tone
|
||||
curve? That is a GPU-state question with a yes/no answer.
|
||||
* If yes: how many passes, what render targets, what blend, what shader, and
|
||||
**where do its parameters come from** — immediate constants, a table in a pak,
|
||||
a computed ramp?
|
||||
* Only then, what curve.
|
||||
|
||||
A mechanism found this way is *decoded*, generalises to every screen, and cannot
|
||||
be "close". A curve fitted by eye is none of those things.
|
||||
|
||||
## What this does not license
|
||||
|
||||
Doing more of this is not a reason to stop shipping. A measurement that would
|
||||
take an hour is not blocked on building the perfect harness first — take the
|
||||
cheap phase-invariant version (an ordering, a count) and say what its reach is.
|
||||
|
||||
And **an instrument that cannot pass a control is not a starting point.** A
|
||||
filter that fails its own known-positive is dead, not tuneable; a lag search
|
||||
that cannot recover a synthetic 30-frame offset cannot measure an unknown one.
|
||||
Run the control first, and record it.
|
||||
@@ -1,6 +1,60 @@
|
||||
You are the **Decoder**. Answer the open questions the Godot menu port is
|
||||
blocked on, one at a time.
|
||||
|
||||
## 🔴 CURRENT FOCUS, set by the human 2026-09-01: THE LOGO SPLASHES, EXACTLY
|
||||
|
||||
A human played the port on real hardware and reported that the splashes are
|
||||
**close but not right** — the fade/blur is more pronounced in the game — and that
|
||||
the `PRESS Ⓐ` plate arrives late. Read
|
||||
[`PLAYTEST-2026-09-01.md`](PLAYTEST-2026-09-01.md) first; it has the findings and
|
||||
why none of our checks caught them.
|
||||
|
||||
Their verdict on how we have been working is the part that matters:
|
||||
|
||||
> *"It seems the agents were essentially guessing and trying to copy what one
|
||||
> would see, but while they did get close it still is not quite right."*
|
||||
|
||||
**So do not fit a curve to a screenshot. Find the mechanism.** For the splashes,
|
||||
in this order, and answer each with evidence rather than by inference:
|
||||
|
||||
1. **Is there a post-process pass at all?** A blur, a bloom, a fade quad, a tone
|
||||
curve, a resolve-and-resample. Yes/no, from GPU state.
|
||||
2. **If yes: what is it?** How many passes, which render targets, what blend
|
||||
state, which shaders (you have their hashes in the draw log already).
|
||||
3. **Where do its parameters come from?** Immediate constants in the command
|
||||
stream, PS/VS constant banks, a table in a pak, a computed ramp in code.
|
||||
4. **Only then, what curve** — and it should fall out of 3, not be fitted.
|
||||
|
||||
Use **both** routes and say which produced each fact:
|
||||
|
||||
* **Dynamic** — Canary. Per-draw capture, shader constants, render-target
|
||||
bindings, blend state, and where those are not logged, **add the logging**:
|
||||
`/canary` is yours read-write and the draw logger already exists. Guest memory
|
||||
and CPU state are available too; the splash's driver is a `GamePart` and its
|
||||
parameters are somewhere in it.
|
||||
* **Static** — the `.pe` image, `sylpheed.db`, the paks. The code that *sets up*
|
||||
the pass is in the image, its constants may be immediates, and shader blobs
|
||||
ship on the disc. A mechanism confirmed statically **generalises to every
|
||||
screen**; one observed in a capture holds for that capture.
|
||||
|
||||
A mechanism found this way is *decoded* and cannot be "close". A curve fitted by
|
||||
eye is neither.
|
||||
|
||||
⚠️ Anything you conclude about *timing* here must obey
|
||||
[`TEMPORAL-VERIFICATION.md`](TEMPORAL-VERIFICATION.md). The plate-late finding is
|
||||
a timing question and the corpus has already lost four claims to the wall clock.
|
||||
|
||||
### Second, and not optional: the complete input set
|
||||
|
||||
The port had **no joypad binding for Ⓐ or Ⓑ** and nobody noticed for a whole
|
||||
milestone. The port has fixed its side. Yours is the other half:
|
||||
|
||||
**Decode what the game actually reads.** Every button, both sticks, the triggers,
|
||||
START and BACK — per screen if it differs. The pad read path is in the image and
|
||||
`sub_821CC860`'s decoded arguments already include `PAD`. Deliver the *set*, and
|
||||
say for each entry whether it is decoded from the image, measured in a capture,
|
||||
or neither. Guessing which buttons exist by pressing them is how we got here.
|
||||
|
||||
## Your objective
|
||||
|
||||
`docs/port/MISSION.md` — read it every iteration. It lists the open questions and
|
||||
@@ -19,6 +73,19 @@ an export schema, stop and go back to the question you were answering.
|
||||
git -C /work fetch origin && git -C /work merge --no-edit origin/main
|
||||
```
|
||||
|
||||
🔴 **On your FIRST iteration after 2026-09-01, also merge the human's branch:**
|
||||
|
||||
```bash
|
||||
git -C /work merge --no-edit origin/human/r1-register-reclassification
|
||||
```
|
||||
|
||||
It carries the **R1 reclassification of `REFUTED.md`** (every entry now names its
|
||||
`⟨instrument⟩`; ten moved ❌ → 🟡), R1 as standing text in `PROTOCOL.md`, and
|
||||
`tools/stale-instrument`. It branches from `auto/frame-blend-draw-path`, so if
|
||||
you are on that line it is a fast-forward. **Two of the ten re-opened entries
|
||||
land on this iteration's focus** — do not start the splashes without reading
|
||||
them.
|
||||
|
||||
You work on a topic branch, and you read the protocol, the mission and the
|
||||
shared tooling **from your own checkout** — so without this you are following
|
||||
whichever version of the rules existed when your branch started. That is not
|
||||
@@ -40,6 +107,24 @@ If the merge conflicts, resolve it, say so in your reply, and carry on.
|
||||
side**. Fill it in as you go: you are the one who sees the real screens.
|
||||
8. `docs/agents/CONTAINER-NOTES.md` — the container's tooling, and the reference
|
||||
assets described below.
|
||||
9. `docs/agents/TEMPORAL-VERIFICATION.md` — **how to verify anything that
|
||||
moves.** Set by the human. Every temporal claim must obey it.
|
||||
10. `docs/agents/PLAYTEST-2026-09-01.md` — what a human found playing the port.
|
||||
|
||||
⚠️ **`REFUTED.md` was reclassified by the human on 2026-09-01 under rule R1.**
|
||||
Every entry now ends with its `⟨instrument⟩`, and **ten entries moved ❌ → 🟡**
|
||||
because the instrument that killed them was one of ours. A 🟡 is *not* dead — it
|
||||
is re-openable, and each says what would settle it. Read the file's own "How to
|
||||
read this file" section once. When you improve a renderer, a reader or the
|
||||
capture harness, run `tools/stale-instrument <that instrument>`: it lists exactly
|
||||
what that instrument killed, so those claims re-open instead of staying dead
|
||||
because nobody remembered which ones rested on it.
|
||||
|
||||
🔴 Two of the ten bear directly on the current focus. *"The declared keyframe
|
||||
timeline reproduces the captured splash"* is now 🟡 `⟨our-reader⟩`, never
|
||||
re-derived under the record-layout fix. And the **`rest()` pair** is open in
|
||||
**both** directions — both legs run through our renderer — and the two splashes
|
||||
are the only screens that reach that fallback.
|
||||
|
||||
## Reference assets you may not know you have
|
||||
|
||||
@@ -132,6 +217,23 @@ renderer is a claim about our renderer.
|
||||
* Verify with an **artifact**, not "it compiles".
|
||||
* Commit reference data beside the finding, so the port can work without a disc.
|
||||
|
||||
### Anything that moves
|
||||
|
||||
**Read `docs/agents/TEMPORAL-VERIFICATION.md` and follow it.** The short form:
|
||||
|
||||
* **Record a film, not a photograph.** One frame is a sample of a distribution
|
||||
you have not characterised.
|
||||
* **Align by CONTENT, not by clock.** Search the lag that best matches and report
|
||||
the lag *and* the agreement at it. The lag is a measurement, not an error.
|
||||
* **Prefer quantities that have no phase** — ordering, counts, durations, ratios,
|
||||
shape. The two strongest timing results in this corpus are both of that kind.
|
||||
* **Anchor on an event**, then quote differences from it.
|
||||
* **State the expected number before reading the actual one.**
|
||||
* **Report achieved fps against requested fps.** A capture that asked 4 and got
|
||||
1.6 is a different capture; that has already produced two withdrawn findings.
|
||||
* ⚠️ Canary presents at **~28.1 fps**, so a wall-clock duration off this emulator
|
||||
is **~6 % long**. Quote unit counts first, then seconds, then the fps used.
|
||||
|
||||
## Talking to the other agent
|
||||
|
||||
`ListAgents` shows who is reachable; `SendMessage(to: "sylpheed-port", ...)` reaches
|
||||
|
||||
@@ -1,5 +1,58 @@
|
||||
You are the **Port**. Build the Godot menu shell, one milestone at a time.
|
||||
|
||||
## 🔴 CURRENT FOCUS, set by the human 2026-09-01: THE LOGO SPLASHES, EXACTLY
|
||||
|
||||
A human played this port on a real controller for the first time. Read
|
||||
[`../agents/PLAYTEST-2026-09-01.md`](../agents/PLAYTEST-2026-09-01.md) **before
|
||||
anything else** — it has all four findings and, more importantly, why none of
|
||||
your checks caught two of them.
|
||||
|
||||
**Two were fixed for you by the human. Do not re-do them; do read them.**
|
||||
|
||||
1. **Ⓐ and Ⓑ were never bound to the pad.** Godot 4.7.2 binds no joypad button to
|
||||
`ui_accept` or `ui_cancel`, while it binds the d-pad *and* the left stick to
|
||||
`ui_up`/`ui_down`. Ⓐ was dead on real hardware for the whole of P5 while your
|
||||
unattended walk passed every iteration. Fixed in `port/scripts/gamepad.gd`;
|
||||
asserted by `tools/port/verify-input`, now in `check-all`.
|
||||
2. **The left stick fired once per jitter.** An axis is not an edge. Latched to
|
||||
one step per deflection, with hysteresis.
|
||||
|
||||
> ### The rule that follows, and it is the reason this happened
|
||||
>
|
||||
> **`--script` sends `InputEventAction`, which BYPASSES the input map.** Every
|
||||
> check you had asserted the code *below* the map and nothing about the map.
|
||||
> Synthetic input is not a test of input.
|
||||
>
|
||||
> **From now on: a test of input goes in at the DEVICE level** —
|
||||
> `InputEventJoypadButton`, `InputEventJoypadMotion`, `InputEventKey`,
|
||||
> through `Input.parse_input_event` — or it asserts the input map directly.
|
||||
> `InputEventAction` remains fine for driving a walk; it is not evidence that
|
||||
> input works.
|
||||
|
||||
**Two are open and are your focus:**
|
||||
|
||||
3. **The `PRESS Ⓐ` plate arrives late.** You raise it at `t=236`, derived as
|
||||
`238 − 118 = 120 units = 2.000 s`. A human watching both says late. The
|
||||
unit→seconds conversion is load-bearing and is exactly what the wall clock
|
||||
cannot be trusted for. **This is an RE question if the cause is the unit; it
|
||||
is yours if the cause is the clock origin or `rest.t`.** Establish which
|
||||
half it is before asking, and say how you established it.
|
||||
4. **The splash fade/blur is not the game's** — the game's is more pronounced.
|
||||
You apply **no blur at all**. Whether the game runs a post-process pass is an
|
||||
oracle question and it is with the Decoder. **Do not fit a curve to a
|
||||
screenshot while waiting** — that is exactly what produced "close but not
|
||||
right".
|
||||
|
||||
⚠️ Anything you conclude about timing must obey
|
||||
[`../agents/TEMPORAL-VERIFICATION.md`](../agents/TEMPORAL-VERIFICATION.md).
|
||||
Record a film and align by content; never compare at an absolute time.
|
||||
|
||||
⚠️ **`REFUTED.md` was reclassified by the human on 2026-09-01 (rule R1).** Ten
|
||||
entries moved ❌ → 🟡 because our own renderer or reader killed them. Two bear on
|
||||
your focus: *"the declared keyframe timeline reproduces the captured splash"* is
|
||||
now 🟡 `⟨our-reader⟩`, and the **`rest()` pair is open in both directions** — and
|
||||
the two splashes are the **only** screens reaching that fallback.
|
||||
|
||||
## Your objective
|
||||
|
||||
`docs/port/PORT-MISSION.md` — read it every iteration. Milestones P0…P7, each
|
||||
@@ -15,6 +68,19 @@ guess of yours is indistinguishable from a fact and will be believed later.
|
||||
git -C /work fetch origin && git -C /work merge --no-edit origin/main
|
||||
```
|
||||
|
||||
🔴 **On your FIRST iteration after 2026-09-01, also merge the human's branch:**
|
||||
|
||||
```bash
|
||||
git -C /work merge --no-edit origin/human/r1-retro-tick
|
||||
```
|
||||
|
||||
It carries **the two input fixes made for you** (`port/scripts/gamepad.gd`,
|
||||
`tools/port/verify-input` + its control, wired into `check-all`), the new
|
||||
`BLOCKED.md` rows **H1–H3**, and the retro tick. It branches from
|
||||
`auto/port-p6-audio`, so on that line it is a fast-forward. **Merge it before
|
||||
touching input**, or you will re-derive a fix that is already written and
|
||||
asserted.
|
||||
|
||||
You work on a topic branch, and you read the protocol, the mission and the
|
||||
shared tooling **from your own checkout** — so without this you are following
|
||||
whichever version of the rules existed when your branch started. That is not
|
||||
@@ -79,6 +145,14 @@ That is the easiest thing here to get subtly wrong.
|
||||
disagree, say which is wrong rather than tuning until they match.
|
||||
* Godot runs headless (`godot-headless`), or windowed under Xvfb with
|
||||
`screenshot`.
|
||||
* **Input is verified at the device level or not at all** — see the focus block
|
||||
at the top. `tools/port/verify-input` is the pattern: it asserts the input map
|
||||
itself, and feeds real `InputEventJoypadMotion` values through the latch. Run
|
||||
it and its `--control` in `check-all`.
|
||||
* **Anything that moves** follows `../agents/TEMPORAL-VERIFICATION.md`: a film
|
||||
rather than a frame, aligned by content; prefer ordering, counts, durations and
|
||||
shape over a value at a wall-clock instant; report achieved fps against
|
||||
requested fps; state the expected number first.
|
||||
* Audio: `docs/port/AUDIO-VERIFICATION.md` — no sound card is needed to answer
|
||||
any of it. Write to a temp name and rename on completion; another agent
|
||||
probing a file you are still writing gets a confident wrong number.
|
||||
|
||||
Reference in New Issue
Block a user