windowmaker-wl/ACTION_PLAN_PROMPTS.md

667 lines
26 KiB
Markdown

# Prompt Templates for Mechanical Wayland Port Tasks
## Reference Tables (embed in every prompt)
### X11 Event Type → WMEvent Type
```
KeyPress/KeyRelease → WME_KEY_PRESS/WME_KEY_RELEASE → event->u.key.*
ButtonPress/ButtonRelease → WME_BUTTON_PRESS/WME_BUTTON_RELEASE → event->u.button.*
MotionNotify → WME_MOTION → event->u.motion.*
EnterNotify/LeaveNotify → WME_ENTER/WME_LEAVE → event->u.crossing.*
Expose → WME_EXPOSE → event->u.expose.*
ConfigureNotify → WME_CONFIGURE → event->u.configure.*
ConfigureRequest → WME_CONFIGURE_REQUEST → event->u.configureRequest.*
MapNotify → WME_MAP → event->u.lifecycle.*
MapRequest → WME_MAP_REQUEST → event->u.mapRequest.*
UnmapNotify → WME_UNMAP → event->u.lifecycle.*
DestroyNotify → WME_DESTROY → event->u.lifecycle.*
FocusIn/FocusOut → WME_FOCUS_IN/WME_FOCUS_OUT → event->u.focus.*
PropertyNotify → WME_PROPERTY → event->u.property.*
ClientMessage → WME_CLIENT_MESSAGE → event->u.clientMessage.*
SelectionNotify → WME_SELECTION → event->u.selection.*
SelectionRequest → WME_SELECTION_REQUEST → event->u.selection.* (check)
SelectionClear → WME_SELECTION_CLEAR → event->u.selection.* (check)
VisibilityNotify → WME_VISIBILITY → event->u.visibility.*
ColormapNotify → WME_COLORMAP → event->u.colormap.*
MappingNotify → WME_MAPPING → event->u.mapping.*
ReparentNotify → WME_REPARENT → event->u.reparent.*
```
### X11 Event Field → WMEvent Field
```
event->xkey.keycode → event->u.key.keycode
event->xkey.state → event->u.key.state
event->xkey.time → event->u.key.time
event->xkey.window → event->u.key.window
event->xkey.x, y → event->u.key.x, y
event->xkey.x_root → event->u.key.x_root
event->xbutton.button → event->u.button.button
event->xbutton.state → event->u.button.state
event->xbutton.time → event->u.button.time
event->xbutton.window → event->u.button.window
event->xbutton.x, y → event->u.button.x, y
event->xbutton.x_root → event->u.button.x_root
event->xmotion.state → event->u.motion.state
event->xmotion.time → event->u.motion.time
event->xmotion.window → event->u.motion.window
event->xmotion.x, y → event->u.motion.x, y
event->xmotion.x_root → event->u.motion.x_root
event->xcrossing.window → event->u.crossing.window
event->xcrossing.state → event->u.crossing.state
event->xcrossing.time → event->u.crossing.time
event->xcrossing.mode → event->u.crossing.mode
event->xcrossing.detail → event->u.crossing.detail
event->xconfigure.window → event->u.configure.window
event->xconfigure.x, y → event->u.configure.x, y
event->xconfigure.width → event->u.configure.width
event->xconfigure.height → event->u.configure.height
event->xclient.data.l[N] → event->u.clientMessage.data.l[N]
event->xclient.message_type → event->u.clientMessage.atom
event->xclient.window → event->u.clientMessage.window
event->xproperty.atom → event->u.property.atom
event->xproperty.time → event->u.property.time
event->xproperty.window → event->u.property.window
```
---
## Template 1: Change Function Signature from `XEvent*` to `WMEvent*`
**Use for**: A5.1, B.3, E.3, E.4 (and any function that takes an X11 event type as parameter)
```
TASK: Change the function {{FUNCTION_NAME}} in {{FILE}} from taking an X11 event
type to taking the backend-neutral WMEvent type.
GOVERNING PRINCIPLE: Policy code in src/ must never reference X11 types. The
backend-neutral event type is `WMEvent` (defined in WINGs/WINGs/WMEvent.h).
STEPS:
1. Read {{FILE}} and {{HEADER_FILE}} to find the function signature.
2. Change the parameter type:
OLD: {{OLD_PARAM_TYPE}} *{{PARAM_NAME}}
NEW: WMEvent *{{PARAM_NAME}}
3. Update the header file ({{HEADER_FILE}}) with the same signature change.
4. Inside the function body, replace every X11 event field access:
- event->xkey.* → event->u.key.*
- event->xbutton.* → event->u.button.*
- event->xmotion.* → event->u.motion.*
- event->xcrossing.* → event->u.crossing.*
- event->xconfigure.* → event->u.configure.*
- event->xclient.* → event->u.clientMessage.*
- event->xproperty.* → event->u.property.*
- event->type == MotionNotify → event->type == WME_MOTION
- event->type == ButtonPress → event->type == WME_BUTTON_PRESS
- event->type == ButtonRelease → event->type == WME_BUTTON_RELEASE
- event->type == KeyPress → event->type == WME_KEY_PRESS
(Use the X11→WMEvent mapping table for the complete list.)
5. Find ALL call sites by grepping for {{FUNCTION_NAME}} across src/ and WINGs/.
At each call site:
- If the caller has a `WMEvent`, pass it directly.
- If the caller has an `XEvent*` via `_x11_raw`, change to pass the `WMEvent`
directly (this eliminates the `_x11_raw` access).
6. If the function used `XWindowChanges` or other X11 structs internally to call
Xlib functions, replace those Xlib calls with wm_backend->*() vtable calls
using the WMEvent fields.
VERIFICATION:
- `grep -rn '{{OLD_PARAM_TYPE}}' {{FILE}} {{HEADER_FILE}}` returns zero matches.
- `grep -rn '_x11_raw.*{{FUNCTION_NAME}}\|{{FUNCTION_NAME}}.*_x11_raw' src/` returns
zero matches.
- The code compiles.
CONSTRAINTS:
- Do NOT add `#ifdef` guards. Do NOT add `if (dpy)` checks.
- Do NOT change the function's logic — only its interface types.
- Do NOT modify files in src/backend/.
```
---
## Template 2: Eliminate `_x11_raw` Access
**Use for**: R.1, R.2, R.3, E.1, and individual sites in E.2
```
TASK: Eliminate the `_x11_raw` escape hatch at {{FILE}}:{{LINE}}.
GOVERNING PRINCIPLE: Policy code must never reach through the WMEvent abstraction
to access the raw X11 event. The `_x11_raw` field exists only for backend code.
CONTEXT: At line {{LINE}}, the code does:
XEvent *xev = (XEvent *)event->_x11_raw;
and then accesses xev->{{XEVENT_FIELD}} to get {{WHAT_IT_NEEDS}}.
STEPS:
1. Read {{FILE}} around line {{LINE}} (±30 lines) to understand what information
is extracted from the raw XEvent.
2. Identify the equivalent field in the WMEvent struct:
{{XEVENT_FIELD}} → {{WMEVENT_FIELD}}
(Use the X11→WMEvent field mapping table.)
3. Replace the `_x11_raw` cast and XEvent field access with direct WMEvent access:
OLD: XEvent *xev = (XEvent *)event->_x11_raw;
... xev->{{XEVENT_FIELD}} ...
NEW: ... event->{{WMEVENT_FIELD}} ...
4. Delete the `XEvent *xev` declaration and the cast.
5. If the raw XEvent was passed to another function (e.g., `someFunc(xev)`),
that function's signature must also be changed (use Template 1).
6. If the raw XEvent was passed to a `wm_backend->*()` vtable call, change the
vtable call to accept `WMEvent*` instead of `void*`. Update the vtable
signature in backend.h, and update both x11_backend.c and wl_backend.c
implementations. The X11 backend extracts `_x11_raw` internally; the Wayland
backend uses WMEvent fields directly.
VERIFICATION:
- `grep -n '_x11_raw' {{FILE}}` shows one fewer match than before.
- The code compiles.
CONSTRAINTS:
- Do NOT add NULL checks on `_x11_raw`. Do NOT add fallback paths.
- If the information needed is NOT available in WMEvent, STOP and report what
field is missing. Do not invent a workaround.
```
---
## Template 3: Replace Direct Xlib Call with `wm_backend->*()` Vtable Call
**Use for**: C.1, R.4, R.5, B.1, and any `src/*.c` file with direct Xlib calls
```
TASK: Replace the direct Xlib call {{XLIB_FUNCTION}} at {{FILE}}:{{LINE}} with
the backend vtable call {{VTABLE_SLOT}}.
GOVERNING PRINCIPLE: Policy code in src/ calls display operations exclusively
through `wm_backend->*()`. Direct Xlib calls are forbidden.
CONTEXT: The global `wm_backend` pointer is declared in src/backend/backend.h:
extern const WMBackend *wm_backend;
STEPS:
1. Read {{FILE}} around line {{LINE}} (±10 lines) to understand the Xlib call
and its arguments.
2. Find the matching vtable slot in src/backend/backend.h:
`grep -n '{{VTABLE_SLOT}}' src/backend/backend.h`
Read the slot's signature and documentation comment.
3. Replace the Xlib call:
OLD: {{XLIB_FUNCTION}}(dpy, {{ARGS}});
NEW: wm_backend->{{VTABLE_SLOT}}({{TRANSLATED_ARGS}});
Argument translation rules:
- Drop `dpy` (the backend knows its own display connection).
- Drop `GC` arguments (the backend manages its own GCs).
- `scr->root_win` → `scr` (the backend knows the root window).
- X11 `Window` → `WNativeWindow` (same underlying type, no cast needed).
- X11 `Pixmap` → `Pixmap` (same type in both backends).
4. If the vtable slot does NOT exist, STOP and report:
"Need new vtable slot: {{PROPOSED_SIGNATURE}}"
Do not add the slot yourself.
5. Remove any now-unused `#include` of X11 headers if this was the last Xlib
call in the file.
VERIFICATION:
- `grep -n '{{XLIB_FUNCTION}}' {{FILE}}` shows one fewer match.
- The code compiles.
CONSTRAINTS:
- Do NOT add `#ifdef` guards or `if (dpy)` checks.
- Do NOT modify files in src/backend/.
- One Xlib call per task. Do not batch.
```
---
## Template 4: Guard X11-Only Code Block in WINGs
**Use for**: D.1, D.2, D.11, and WINGs files where X11 code must be skipped on Wayland
```
TASK: Guard the X11-only code block at {{FILE}}:{{START_LINE}}-{{END_LINE}} so it
only executes when running on the X11 backend.
GOVERNING PRINCIPLE: WINGs code uses `scr->display != NULL` to detect the X11
backend. When `scr->display` is NULL, the Wayland backend is active and X11
calls must be skipped.
STEPS:
1. Read {{FILE}} from line {{START_LINE}} to {{END_LINE}}.
2. Confirm every line in this range calls Xlib functions or uses X11 types that
have no meaning on Wayland (GC, XCreateGC, XInternAtom, etc.).
3. Wrap the block:
```c
if (scr->display) {
// ... existing X11 code unchanged ...
}
```
Where `scr` is the `W_Screen*` in scope. Find it via:
- Direct variable `scr` or `scrPtr`
- `view->screen`
- `WMWidgetScreen(widget)`
4. If the Wayland backend needs equivalent behavior (e.g., the code creates
cursors or interns atoms), add an `else` block that calls the appropriate
backend vtable:
```c
if (scr->display) {
// X11 path
} else {
// Wayland path — use scr->viewBackend->*() or scr->renderBackend->*()
}
```
If no Wayland equivalent is needed (e.g., GC creation), the `else` is omitted.
VERIFICATION:
- The code compiles.
- Running with `WMAKER_USE_WAYLAND=1` does not crash in this code path (the
X11 block is skipped).
CONSTRAINTS:
- Do NOT move the code to a separate file. This template is for cases where
the X11 code is small (< 50 lines) and inline guarding is cleaner than a split.
- Do NOT delete the X11 code. It must continue to work for the X11 backend.
- The guard condition is always `if (scr->display)`, never `#ifdef WAYLAND`.
```
---
## Template 5: Split File into `_x11.c` / `_wl.c` Backend Pair
**Use for**: D.3, D.5, D.6, and any WINGs file that is entirely X11-specific
```
TASK: Split {{FILE}} into an X11 backend file, a Wayland backend file, and a
thin dispatch layer.
GOVERNING PRINCIPLE: WINGs uses five backend vtables (view, event, render, font,
color). Files that are entirely X11-specific should be split into _x11/_wl pairs
following the existing pattern (e.g., wcolor.c / wcolor_x11.c / wcolor_wl.c).
EXISTING PATTERN (use as reference):
- WINGs/wcolor.c — dispatch layer, calls scr->colorBackend->*()
- WINGs/wcolor_x11.c — X11 implementation, exports W_ColorBackendX11
- WINGs/wcolor_wl.c — Wayland implementation, exports W_ColorBackendWL
STEPS:
1. Read {{FILE}} completely. Identify all public functions (declared in headers).
2. Rename {{FILE}} → {{FILE_BASE}}_x11.c. Keep all code unchanged.
3. Create {{FILE_BASE}}_wl.c with stub implementations of every public function.
Each stub should either:
- Implement the Wayland equivalent if straightforward
- Call `wwarning("{{FUNCTION}}: not yet implemented for Wayland")` and return
a safe default (NULL, 0, False)
4. Create {{FILE_BASE}}.c as a dispatch layer. For each public function:
```c
ReturnType PublicFunction(args...) {
if (scr->display)
return x11_PublicFunction(args...);
else
return wl_PublicFunction(args...);
}
```
OR, if a vtable is more appropriate, define a new backend struct in WINGsP.h.in
following the existing pattern (W_ColorBackend, W_FontBackend, etc.).
5. Update WINGs/Makefile.am:
- Remove {{FILE_BASE}}.c from the source list (it was renamed)
- Add {{FILE_BASE}}.c, {{FILE_BASE}}_x11.c, {{FILE_BASE}}_wl.c
6. Update any header files that declare the public functions — no signature
changes needed.
VERIFICATION:
- `make -C WINGs` compiles successfully.
- The X11 backend path is unchanged (existing behavior preserved).
- `grep -rn 'X[A-Z][a-z]' WINGs/{{FILE_BASE}}.c` returns zero (dispatch layer
has no Xlib calls).
CONSTRAINTS:
- The _wl.c stubs may be incomplete. That is acceptable. Mark incomplete stubs
with `/* TODO: Wayland implementation */`.
- Do NOT change any function signatures.
- Do NOT modify {{FILE_BASE}}_x11.c beyond the rename. All existing code stays.
```
---
## Template 6: Replace Xlib Drawing Call with WINGs Render Backend
**Use for**: D.4, D.7, D.8, D.9, D.10, and WPrefs.app drawing (E.5a-c)
```
TASK: Replace the Xlib drawing call {{XLIB_CALL}} at {{FILE}}:{{LINE}} with a
WINGs render backend call.
GOVERNING PRINCIPLE: Widget code draws through `scr->renderBackend->*()`. Direct
Xlib drawing calls (XFillRectangle, XDrawLine, XCopyArea, etc.) are forbidden
in non-_x11.c files.
RENDER BACKEND VTABLE (from WINGsP.h.in):
scr->renderBackend->pixmap_create(rctx, width, height, depth)
scr->renderBackend->pixmap_free(rctx, pm)
scr->renderBackend->pixmap_copy(rctx, src, dst, sx, sy, w, h, dx, dy)
scr->renderBackend->draw_line(rctx, d, color, x1, y1, x2, y2)
scr->renderBackend->draw_rect(rctx, d, color, x, y, w, h)
scr->renderBackend->fill_rect(rctx, d, color, x, y, w, h)
scr->renderBackend->fill_polygon(rctx, d, color, points, npoints)
scr->renderBackend->fill_arc(rctx, d, color, x, y, w, h, angle1, angle2)
scr->renderBackend->composite_pixmap(rctx, dst, src, sx, sy, w, h, dx, dy)
Where:
rctx = scr->renderBackendCtx
d = the target WMDrawable (Pixmap or window's drawable)
color = a WMColor* (obtain via WMColorGC pattern → WMColor*)
STEPS:
1. Read {{FILE}} around line {{LINE}} (±5 lines).
2. Identify the Xlib call and its arguments.
3. Map to the render backend equivalent:
XFillRectangle(dpy, d, gc, x, y, w, h)
→ scr->renderBackend->fill_rect(scr->renderBackendCtx, d, color, x, y, w, h)
XDrawLine(dpy, d, gc, x1, y1, x2, y2)
→ scr->renderBackend->draw_line(scr->renderBackendCtx, d, color, x1, y1, x2, y2)
XDrawRectangle(dpy, d, gc, x, y, w, h)
→ scr->renderBackend->draw_rect(scr->renderBackendCtx, d, color, x, y, w, h)
XCopyArea(dpy, src, dst, gc, sx, sy, w, h, dx, dy)
→ scr->renderBackend->pixmap_copy(scr->renderBackendCtx, src, dst, sx, sy, w, h, dx, dy)
XCreatePixmap(dpy, drawable, w, h, depth)
→ scr->renderBackend->pixmap_create(scr->renderBackendCtx, w, h, depth)
XFreePixmap(dpy, pm)
→ scr->renderBackend->pixmap_free(scr->renderBackendCtx, pm)
XFillPolygon(dpy, d, gc, points, npoints, shape, mode)
→ scr->renderBackend->fill_polygon(scr->renderBackendCtx, d, color, points, npoints)
XFillArc(dpy, d, gc, x, y, w, h, angle1, angle2)
→ scr->renderBackend->fill_arc(scr->renderBackendCtx, d, color, x, y, w, h, angle1, angle2)
4. For the `color` argument: the Xlib code uses a GC with a foreground color.
Find where the GC's foreground was set (look for `XSetForeground` or
`WMColorGC(someColor)`). Use that `WMColor*` directly.
5. For `scr`: find the WMScreen in scope. Common patterns:
- `WMWidgetScreen(widget)`
- `view->screen`
- local variable `scr`
VERIFICATION:
- `grep -n '{{XLIB_CALL}}' {{FILE}}` shows one fewer match.
- The code compiles.
CONSTRAINTS:
- One call replacement per task.
- If the GC was created with `XCreateGC` just for this drawing sequence, and
this is the last use, also delete the `XCreateGC` and `XFreeGC` calls.
- Do NOT change drawing logic (coordinates, colors, order).
```
---
## Template 7: Remove Compile-Time `#ifdef` Guard Using Backend-Neutral API
**Use for**: A4.1, B.2, H.1, R.7, and any `#ifdef USE_XINERAMA` / `#ifdef USE_XSHAPE` / `#ifdef USE_DOCK_XDND` site
```
TASK: Remove the compile-time guard `#ifdef {{GUARD_NAME}}` at {{FILE}}:{{LINE}}
and replace the guarded code with a backend-neutral API call.
GOVERNING PRINCIPLE: No `#ifdef` guards for backend-specific features in policy
code. Feature availability is determined at runtime by the backend vtable.
STEPS:
1. Read {{FILE}} around line {{LINE}}. Identify the `#ifdef {{GUARD_NAME}}` block
and the corresponding `#else` / `#endif`.
2. Understand what the guarded code does:
- `USE_XINERAMA`: queries per-monitor geometry
- `USE_XSHAPE`: queries window shape
- `USE_DOCK_XDND`: sets up XDND awareness
- `USE_MWM_HINTS`: reads Motif hints
- `USE_RANDR`: handles RandR events
3. Identify the backend-neutral replacement:
- Xinerama monitor queries → `wGetHeadForPoint(scr, point)`,
`wGetUsableAreaForHead(scr, head)`, `wGetRectForHead(scr, head)`.
These functions already exist and are backend-abstracted.
- XShape queries → `wm_backend->window_get_shape()` or equivalent vtable slot.
- XDND setup → move into the backend's `appicon_show` implementation.
- MWM hints → `wm_backend->client_get_mwm_hints()` or equivalent vtable slot.
4. Replace the `#ifdef` / `#else` / `#endif` with the backend-neutral code.
Delete both the guarded block and the else block. Write one unified path.
5. If the `#ifdef` block called Xlib functions that have no vtable equivalent,
STOP and report: "Need vtable slot for {{OPERATION}}".
VERIFICATION:
- `grep -n '{{GUARD_NAME}}' {{FILE}}` shows one fewer match.
- The code compiles with and without the feature flag defined.
CONSTRAINTS:
- Do NOT add a different `#ifdef`. Do NOT add runtime `if (dpy)` checks.
- The replacement must work on both X11 and Wayland backends.
- If the `#else` block was empty (feature simply absent), the replacement is
to call the vtable slot unconditionally — the Wayland backend returns a
sensible default (e.g., "no shape", "single head").
```
---
## Template 8: Replace Xlib Call in WPrefs.app with WINGs API
**Use for**: E.5 sub-tasks (all WPrefs.app Xlib elimination)
```
TASK: Replace the Xlib call {{XLIB_CALL}} at WPrefs.app/{{FILE}}:{{LINE}} with
the equivalent WINGs public API call.
GOVERNING PRINCIPLE: WPrefs.app is a WINGs client application. It must use only
WINGs public APIs (declared in WINGs/WINGs/WINGs.h), never Xlib directly. WINGs
routes all operations through its backend vtables internally.
WINGS API EQUIVALENTS:
XFillRectangle(dpy, d, WMColorGC(c), x, y, w, h)
→ WMFillRectangle(scr, d, c, x, y, w, h)
(if WMFillRectangle does not exist, use:
scr->renderBackend->fill_rect(scr->renderBackendCtx, d, c, x, y, w, h))
XDrawLine(dpy, d, WMColorGC(c), x1, y1, x2, y2)
→ WMDrawLine(scr, d, c, x1, y1, x2, y2)
(if WMDrawLine does not exist, use:
scr->renderBackend->draw_line(scr->renderBackendCtx, d, c, x1, y1, x2, y2))
XCopyArea(dpy, src, dst, gc, sx, sy, w, h, dx, dy)
→ WMCopyArea(scr, src, dst, sx, sy, w, h, dx, dy)
(if WMCopyArea does not exist, use:
scr->renderBackend->pixmap_copy(scr->renderBackendCtx, src, dst, sx, sy, w, h, dx, dy))
XCreatePixmap(dpy, parent, w, h, depth)
→ WMCreatePixmap(scr, w, h, depth, False) [returns WMPixmap*]
then use WMGetPixmapXID(pixmap) to get the drawable
XFreePixmap(dpy, pm)
→ WMReleasePixmap(pixmap) [if using WMPixmap*]
or scr->renderBackend->pixmap_free(scr->renderBackendCtx, pm)
XCreateGC / XFreeGC
→ DELETE. WINGs manages GCs internally. Use WMColor* for color selection.
XParseColor(dpy, cmap, name, &xcolor)
→ WMCreateNamedColor(scr, name, True) [returns WMColor*]
XGrabKeyboard / XUngrabKeyboard
→ No direct WINGs equivalent. Use:
scr->viewBackend->keyboard_grab(scr->viewBackendCtx, view)
(if slot exists; otherwise STOP and report)
XGrabPointer / XUngrabPointer
→ No direct WINGs equivalent. Use:
scr->viewBackend->pointer_grab(scr->viewBackendCtx, view)
(if slot exists; otherwise STOP and report)
XOpenDisplay
→ WMOpenScreen(display_name) [in main.c initialization]
XSendEvent (for WM commands)
→ Write to defaults database + send SIGHUP, or use a WINGs notification.
STOP and report if unclear.
STEPS:
1. Read WPrefs.app/{{FILE}} around line {{LINE}} (±10 lines).
2. Identify the Xlib call and its purpose.
3. Find the WINGs equivalent from the table above.
4. Replace the call. Adjust variable types if needed (e.g., `GC gc` → delete,
`XColor xcolor` → `WMColor *color`).
5. If the WINGs API function does not exist, use the renderBackend/viewBackend
vtable call directly (WPrefs.app includes WINGsP.h for internal access).
VERIFICATION:
- `grep -n '{{XLIB_CALL}}' WPrefs.app/{{FILE}}` shows one fewer match.
- The code compiles.
CONSTRAINTS:
- One call replacement per task.
- Prefer WINGs public API over direct vtable access.
- Do NOT add `#ifdef` guards or `if (dpy)` checks.
```
---
## Template 9: Verify File is X11-Free
**Use for**: F.2, F.3, F.4, G.1, I.1, I.2, C.3, H.5, and any verification task
```
TASK: Verify that {{FILE}} has no X11 dependencies that would break on the
Wayland backend.
STEPS:
1. Run: `grep -nE '\bX[A-Z][a-z]' {{FILE}}`
This finds direct Xlib function calls.
EXPECTED: {{EXPECTED_XLIB_COUNT}} matches.
2. Run: `grep -nE '\bDisplay\b|\bXEvent\b|\bXImage\b|\bXColor\b' {{FILE}}`
This finds X11 type usage.
EXPECTED: {{EXPECTED_TYPE_COUNT}} matches.
3. Run: `grep -n '_x11_raw' {{FILE}}`
This finds raw event escape hatches.
EXPECTED: 0 matches.
4. Run: `grep -n '#ifdef.*USE_X\|#ifdef.*HAVE_X\|#ifdef.*XINERAMA\|#ifdef.*XSHAPE\|#ifdef.*XDND' {{FILE}}`
This finds X11 feature guards.
EXPECTED: {{EXPECTED_IFDEF_COUNT}} matches.
5. If any count exceeds expected:
- For each unexpected match, report the line number and the X11 reference.
- Classify as: (a) actual dependency, (b) comment/string, (c) type used
but never passed to Xlib.
REPORT FORMAT:
```
FILE: {{FILE}}
Xlib calls: N (expected {{EXPECTED_XLIB_COUNT}})
X11 types: N (expected {{EXPECTED_TYPE_COUNT}})
_x11_raw: N (expected 0)
#ifdef guards: N (expected {{EXPECTED_IFDEF_COUNT}})
STATUS: CLEAN / NEEDS WORK
ISSUES: (list any unexpected findings)
```
CONSTRAINTS:
- Do NOT modify the file. This is a read-only verification task.
- Report findings exactly. Do not interpret or fix.
```
---
## Template 10: Batch Instantiation Helper
**Use for**: Generating concrete prompts from templates + the action plan
```
Given the action plan task {{TASK_ID}}, instantiate the appropriate template.
ACTION PLAN TASK:
ID: {{TASK_ID}}
File(s): {{FILES}}
Operation: {{OPERATION_SUMMARY}}
Xlib calls to eliminate: {{COUNT}}
Blocked by: {{DEPENDENCIES}}
Select the template:
- Function signature change (XEvent* → WMEvent*) → Template 1
- _x11_raw elimination → Template 2
- Direct Xlib → wm_backend vtable → Template 3
- Guard X11 block in WINGs → Template 4
- Split into _x11/_wl pair → Template 5
- Xlib drawing → WINGs render backend → Template 6
- Remove #ifdef guard → Template 7
- WPrefs.app Xlib → WINGs API → Template 8
- Verification only → Template 9
Fill in ALL template variables from the action plan data and the codebase.
Include exact line numbers (use `grep -n` to find current line numbers, as they
may have shifted from the original analysis).
Output the fully instantiated prompt, ready to hand to an agent.
```
---
## Usage Notes
1. **One task per prompt.** Never batch multiple Xlib call replacements into a single prompt. The agent should make one surgical change, verify it compiles, and stop.
2. **Always include the mapping tables.** The X11→WMEvent type and field mapping tables should be included verbatim in every Template 1 and Template 2 instantiation. The agent needs them as reference, not from memory.
3. **Line numbers drift.** Before instantiating a template, re-grep for the exact current line number. The analysis line numbers are from the initial read and will shift as changes accumulate.
4. **Compilation is the gate.** Every task ends with "the code compiles." If it doesn't, the task is not done. The agent should fix compilation errors before reporting completion.
5. **STOP conditions are real.** Templates 3, 6, 7, and 8 include "STOP and report" conditions for missing vtable slots or APIs. The agent must actually stop — not invent a workaround. Missing infrastructure is a signal to create a new task, not to hack around it.
6. **Wave ordering matters.** Wave 1 tasks are independent and can be parallelized. Wave 2 tasks depend on Wave 1. Wave 3 (WPrefs.app) depends on Wave 2. Respect this ordering when dispatching to agents.