Problem
layout.gadget children are invisible to structural walking on classic
AmigaOS 3.x (no public enumeration API — see the documented "Confirmed
limit" in docs/implementation-plan.md). This blocks tier-1 (manifest)
and tier-2 (semantic) locators for any window.class/layout.gadget
ReAction UI whose scriptable gadgets are nested inside a layout object
rather than attached directly to window->FirstGadget — which in
practice is most ReAction apps, including our own classact-app
fixture and, outside this repo, AmiAuth's dialogs.
A manifest can currently only name gadgets the walker can already
reach (manifest/SPEC.md, "Resolution semantics") — it deliberately
has no way to express "unreachable but trust me," so this isn't fixable
from the manifest side alone.
Proposed design (already sketched in the implementation plan)
A tiny, optional ARexx port the application itself exposes, answering
a WHERE <logical-name> command: it calls
GetAttr(GA_Left/GA_Top/GA_Width/GA_Height) on its own live object
pointers (which it already holds for its own event dispatch) and
returns window-relative geometry as text.
AmiPilot then acts on that answer with a genuine input.device click at
the resolved coordinates — discovery is cooperative (the app tells us
where things are), but actuation stays real input through the real
event path, unlike the MUI tier where the port does the acting too.
No coordinates ever appear in a script; they're resolved live at
action time by the app itself, so relayout and font changes can't
break anything — the same immunity the manifest tier has, extended to
the one place structural walking can't reach.
Manifest integration
The manifest format would gain a record declaring the port's name
(e.g. WHEREPORT <port-name>), so a consumer knows to resolve a
logical gadget name via that port instead of GA_ID when the gadget
sits behind the layout.gadget wall. This is a version bump per
manifest/SPEC.md's versioning policy (new optional record type).
Scope
- Client-side (host
client.py / wire protocol): resolve a manifest
entry with a declared WHEREPORT by sending WHERE <name> to that
port instead of walking, then act on the returned geometry.
- Server-side / protocol doc: document the
WHERE command contract
(request/response shape, units, error case when the name is
unknown) so third-party apps can implement it without reading this
repo's source.
- Fixture: extend
classact-app (or add a sibling fixture) to
implement a WHERE port and demonstrate end-to-end resolution
through it, replacing its current "names no gadgets" honest-limits
manifest.
Why now
This is called out as "a future tier between 1 and 2 — design note,
not yet scheduled" in docs/implementation-plan.md. Filing it as a
tracked issue since it's the only path to per-gadget automation for
any window.class/layout.gadget app (real-world example: AmiAuth's
GUI, entirely built this way) — otherwise those apps are stuck at
window-level assertions only.
Problem
layout.gadgetchildren are invisible to structural walking on classicAmigaOS 3.x (no public enumeration API — see the documented "Confirmed
limit" in
docs/implementation-plan.md). This blocks tier-1 (manifest)and tier-2 (semantic) locators for any
window.class/layout.gadgetReAction UI whose scriptable gadgets are nested inside a layout object
rather than attached directly to
window->FirstGadget— which inpractice is most ReAction apps, including our own
classact-appfixture and, outside this repo, AmiAuth's dialogs.
A manifest can currently only name gadgets the walker can already
reach (
manifest/SPEC.md, "Resolution semantics") — it deliberatelyhas no way to express "unreachable but trust me," so this isn't fixable
from the manifest side alone.
Proposed design (already sketched in the implementation plan)
A tiny, optional ARexx port the application itself exposes, answering
a
WHERE <logical-name>command: it callsGetAttr(GA_Left/GA_Top/GA_Width/GA_Height)on its own live objectpointers (which it already holds for its own event dispatch) and
returns window-relative geometry as text.
AmiPilot then acts on that answer with a genuine input.device click at
the resolved coordinates — discovery is cooperative (the app tells us
where things are), but actuation stays real input through the real
event path, unlike the MUI tier where the port does the acting too.
No coordinates ever appear in a script; they're resolved live at
action time by the app itself, so relayout and font changes can't
break anything — the same immunity the manifest tier has, extended to
the one place structural walking can't reach.
Manifest integration
The manifest format would gain a record declaring the port's name
(e.g.
WHEREPORT <port-name>), so a consumer knows to resolve alogical gadget name via that port instead of
GA_IDwhen the gadgetsits behind the layout.gadget wall. This is a version bump per
manifest/SPEC.md's versioning policy (new optional record type).Scope
client.py/ wire protocol): resolve a manifestentry with a declared
WHEREPORTby sendingWHERE <name>to thatport instead of walking, then act on the returned geometry.
WHEREcommand contract(request/response shape, units, error case when the name is
unknown) so third-party apps can implement it without reading this
repo's source.
classact-app(or add a sibling fixture) toimplement a
WHEREport and demonstrate end-to-end resolutionthrough it, replacing its current "names no gadgets" honest-limits
manifest.
Why now
This is called out as "a future tier between 1 and 2 — design note,
not yet scheduled" in
docs/implementation-plan.md. Filing it as atracked issue since it's the only path to per-gadget automation for
any
window.class/layout.gadgetapp (real-world example: AmiAuth'sGUI, entirely built this way) — otherwise those apps are stuck at
window-level assertions only.