---
name: sintuch-keypad
description: >-
  Key Pad / SinTuch — Generate macro template JSON (`program`, blocks with fixed
  `title`/`color`), optional `presets.json` wiring, Templates paths, and Script
  Builder batch programs (`sb_*` → `scripts/comp`). Use when the user mentions
  Key Pad, SinTuch, key_pad_app, keypad macros, macro editor JSON, presets.json,
  Script Builder, or run_script.
---

# Key Pad / SinTuch / key_pad_app Macro Generator

Companion file: `**examples.md**` — macro patterns, preset wiring, and **Script Builder** program samples.

Behavior is defined by the Key Pad app’s **macro editor** and **Script Builder** (how JSON is saved) and its **runtime** (how macro blocks are converted and executed). Script programs compile to **cmd.exe** batch files. No particular source tree is assumed here.

---

## Purpose

Generate **canvas-format macro templates** (JSON with `program` and blocks using `params`, fixed `title` / `color`) for the Key Pad / SinTuch macro editor and hardware executor. Optionally describe `**presets.json`** merges so a preset slot runs a saved macro file.

Also document or hand-author **Script Builder** programs (`sb_*` block types) that compile to `.bat` under `**scripts/comp`**, and how macros invoke those batches via `**run_script**`.

---

## Activation Keywords


| Kind               | Terms & aliases                                                                                                                      |
| ------------------ | ------------------------------------------------------------------------------------------------------------------------------------ |
| **Product / UI**   | **Key Pad**, **SinTuch**, **Sin Tuch**                                                                                               |
| **Config on disk** | `**key_pad_app`**, `**%APPDATA%\Roaming\key_pad_app**`, `**Templates**`, `**presets.json**`                                          |
| **Task keywords**  | keypad macro, macro blocks, macro editor JSON, template macro, 3×3 button, preset slot, hardware keypad assignment                   |
| **Scripting**      | **Script Builder**, `**scripts/source`**, `**scripts/comp**`, compiled `**.bat**`, `**sb_***` blocks, `**run_script**` `script_path` |


**Treat macro + preset rules as one system** — this skill’s macro schema and `**examples.md`**. Script programs reuse the same `**{ "program": [...] }**` wrapper but **only `sb_*` block types**; do not mix macro executor types into Script Builder JSON.

**Suggested skill blurb:** *Key Pad / SinTuch — Generate macro template JSON (`program`, blocks with fixed `title`/`color`), optional `presets.json` wiring, `Templates` paths, and Script Builder batch programs (`sb_*` → `scripts/comp`). Keywords: Key Pad, SinTuch, key_pad_app, keypad macros, Script Builder.*

---

## When To Use

Activate when the user mentions **Key Pad**, **SinTuch**, **keypad** (this device/app), `**key_pad_app`**, macro **JSON** / **templates** for this app, `**presets.json`** binding, `**Templates**`, **Script Builder**, `**scripts/source`**, `**scripts/comp**`, or compiled **batch** / `**sb_`** blocks.

**End-user prompt checklist** (ask them to specify where helpful):

1. **Goal** — what the macro should do on Windows.
2. **Output** — one JSON object with `program` unless multiple files are explicitly needed.
3. **Constraints** — paths, window titles, coordinates, repeat counts, exact vs partial window match.
4. **Reuse** — existing `Foo.json` template → `template` block with `template_name`: `"Foo"` (no `.json`).
5. **Constants** — every block needs schema-accurate `title` and `color`.
6. **Disambiguate “run”** — “open/launch” vs “in terminal” vs “run script block / no terminal” (see **Run vs Open Rules**).
7. **Preset + key** — preset **1–10** and key **1–9** (top-left = 1) if wiring `**presets.json`**.

Encode if-window checks as `**params.condition**` strings (`check_window:…`, `is_focused:…`), never as fake extra children for the condition slot.

---

## Required Output Rules

- Output **valid JSON only** for macro definitions unless the user explicitly asks for explanation without JSON.
- **Root object** must contain `**"program"`** as an array of blocks (unless legacy array-only format is explicitly requested).
- **Every block** MUST include:
  - `**type`**
  - `**params**` (object; may be `{}`)
  - `**title**` — fixed constant for that `type` (see **Fixed Block Type Table**)
  - `**color`** — fixed constant for that `type` (same table)
- **Canonical key order** (matches the macro editor): `**type`** → `**params**` → `**title**` → `**color**` → `**children**` (containers only). Emit JSON objects in this order.
- `**title` and `color` are not customizable** — copy exact strings and hex from the table. Do not localize, rename, or recolor.
- **Never invent unsupported block types.** For **macros**, only types in **Fixed Block Type Table** / macro **Params Reference**. For **Script Builder**, only `**sb_*`** types in **Script Block Type Table**.
- `**children`** allowed **only** on `**if_condition`**, `**repeat**`, `**while**`, with correct `**area**` keys. **Script Builder programs do not use `children`** — flat `**program**` list only.

---

## Response Modes


| Mode            | Behavior                                                                                                                                                                                                                                                                                                                                                                                                                                                                             |
| --------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| **Default**     | Single fenced JSON object: `{ "program": [ … ] }` only (minimal prose after if needed).                                                                                                                                                                                                                                                                                                                                                                                              |
| **Placeholder** | Use `YOUR_…` / `YOUR_ABSOLUTE_SCRIPT_PATH` / `YOUR_PROJECT_ROOT` etc. when paths unknown; add **one short line** listing what each placeholder replaces.                                                                                                                                                                                                                                                                                                                             |
| **Multi-file**  | When user asks for macro **+** `presets.json` update **or** macro **+** nested template file: emit **each** JSON artifact clearly labeled (e.g. `MyMacro.json`, `CommonSave.json`, `presets.json` merge instructions). Preserve `**__global__`** and unrelated preset data when describing merges. When user asks for a **Script Builder script**: emit **both** `**scripts/source/<Stem>.json`** and `**scripts/comp/<Stem>.bat**` (same `<Stem>`) per **Script deliverable rule**. |


---

## Never Do

- Never invent **block `type`** values not in this skill.
- Never invent or alter `**title**` / `**color**` per block (must match **Fixed Block Type Table** exactly).
- Never emit **invalid JSON** (no trailing commas; escape `\` in Windows paths inside strings).
- Never add `**children`** to blocks other than `**if_condition**`, `**repeat**`, `**while**`.
- Never represent `**if_condition**` window tests as separate JSON children (use `**params.condition**` strings only).
- Never modify `**__global__**`, preset `**icon**` arrays, or unrelated `**buttons**` when patching `**presets.json**` unless explicitly requested.
- Never fabricate `**full_path**` for presets — it must match the real saved macro absolute path under `**Templates**` (or user-provided path).
- Never deliver `**scripts/comp/<Stem>.bat**` without the paired `**scripts/source/<Stem>.json**` (Script Builder format, same stem, same logic) — see **Script deliverable rule**. The user must always be able to **Load** the JSON in Script Builder to read and edit what the batch does.

---

## Invalid Requests

- Do **not** create **fake schema extensions**, nonexistent block fields, or alternate JSON shapes “for convenience.”
- If the user asks for behavior **impossible** with supported blocks (e.g. OCR, arbitrary HTTP without `run_script`/terminal pattern), **state the limitation briefly** and propose the **closest supported composition** (`launch_app`, `run_script`, terminal + `type_text`, etc.).
- Do not silently substitute unrelated apps or paths; use placeholders when unknown.

---

## Universal Intent Mapping

Use for **open-ended** prompts not copied verbatim from `**examples.md`**:

1. **Decompose** the request into ordered steps (open → wait → focus → type → shortcut → branch → loop).
2. **Map steps** to blocks using **Params Reference** and `**examples.md`** by analogy; compose primitives even when no single example matches.
3. Insert `**wait**` between UI transitions (often **0.2–1.5 s**); longer after launches or UAC.
4. **Branches** → `**if_condition`** + `**condition**` strings; **loops** → `**repeat`** / `**while**`.
5. **Ambiguity** → default `**exact_match: false`** / `**condition_exact_match: false**` for partial titles unless user demands exact; use `**YOUR_…**` placeholders and list replacements.
6. **Snap layouts** → use **macro blocks** (`open_folder` → `focus_window` → `press` + `wait`) — **not** batch/PowerShell for snapping. **Robust snap-assist pattern** (battle-tested on Explorer):
  ```
   press win+arrow1  →  wait 0.1s  →  press esc  →  press win+arrow2  →  wait 0.1s  →  press esc
  ```
   **No wait between `esc` and the second arrow** — go straight to the next arrow key. Only **0.1s waits** before each `esc` (after each arrow). Pre-snap: `**open_folder`** → `**wait` 0.7s** → `**focus_window`** (partial title) → `**wait` 0.3s** → snap sequence.
   Corner arrows: top-left = `left` then `up`; top-right = `right` then `up`; bottom-left = `left` then `down`; bottom-right = `right` then `down`. If a heavy window mis-snaps, try **0.2s** before each `esc` only (keep **no wait** between `esc` and the second arrow).
7. **“Run file” / “execute file”** → apply **Run vs Open Rules**; state your assumption in one sentence if still ambiguous.
8. **Preset + button** → compute `**"row,col"`** from button index **1–9**; merge `**presets.json`** per **presets.json Rules**.
9. Prefer `**focus_window`** + short `**wait**` after `**open_folder**` / `**launch_app**` when the next action needs a specific foreground window — especially when another app (e.g. a slow launcher) may steal focus before snap.

---

## Run vs Open Rules

Users confuse **open like double-click** with **execute script**. Use **extension + cues**:


| User intent (words + extension)                                       | Block                                                                                          | Typical cues                                                                                        |
| --------------------------------------------------------------------- | ---------------------------------------------------------------------------------------------- | --------------------------------------------------------------------------------------------------- |
| **Open / launch** as Windows would (app, installer, document, `.lnk`) | `**launch_app`**                                                                               | “open”, “start”, “launch”, “double-click”, `.exe` without “in terminal”, Office/PDF/media           |
| **Execute script without a terminal window** (Key Pad subprocess)     | `**run_script`**                                                                               | `.py`, `.bat`, `.ps1`, … **only if** background / no shell; not “show output”, “PowerShell”, “venv” |
| **Run a CLI in a shell**                                              | `**launch_app`** / `**focus_window**` terminal → `**type_text**` CLI → `**press**` `**enter**` | “in terminal”, “cmd/PowerShell”, `**py …**`, cwd, venv, visible output                              |


**Ambiguous phrases** (“run this file”, “execute `foo.py`”, “run the installer”):

1. `**.exe`, `.msi`, `.lnk`, Office/media** → almost always `**launch_app`** (unless explicit headless-from-Key-Pad).
2. **Scripts** without terminal language → `**run_script`** vs `**launch_app**` (double-click `.bat`); **state which you chose**.
3. Always **state assumption** when fuzzy.

### `run_script` vs terminal


| Approach         | Pattern                                                                             | When                                                   |
| ---------------- | ----------------------------------------------------------------------------------- | ------------------------------------------------------ |
| `**run_script`** | One block: `**script_path**`                                                        | Key Pad starts file as subprocess; **no** terminal UI. |
| **Terminal**     | Terminal → `**wait`** → `**focus_window**` → `**type_text**` full CLI → `**enter**` | User would paste into shell; needs cwd/venv/output.    |


**Rule:** Paste-into-terminal → **no `run_script`**. Double-click behavior → `**launch_app**`. Headless script from Key Pad → `**run_script**` may fit.

### Scripts vs macro blocks (window / folder workflows)


| Task                                     | Use                                                                       | Do **not** default to                                            |
| ---------------------------------------- | ------------------------------------------------------------------------- | ---------------------------------------------------------------- |
| Headless export, CLI, compiled batch     | `**run_script`** (Script Builder → `.bat` / `.py`)                        | HID blocks                                                       |
| Open a folder in Explorer                | `**open_folder**` with `**full_path**`                                    | `explorer` in a batch (unless user explicitly wants script-only) |
| Bring a window to front before snap/type | `**focus_window**` (partial `**window_title**`, `**exact_match: false**`) | PowerShell `Activate()` in a batch                               |
| Snap a quarter of the screen             | `**press**` (`meta`+arrows) + `**wait**` + `**esc**` per **Snap layouts** | Snap logic hidden in `.bat`                                      |


**Compose:** `run_script` (heavy work) → `**wait`** (let slow apps finish) → `**open_folder**` → `**focus_window**` → snap `**press**` chain. See `**examples.md**` — **Open Folder And Snap Explorer Top Left**, **Open Folder And Snap Explorer Top Right**, **Export Then Snap Today Folder** (template).

**Editor note:** For `**open_folder`**, prefer `**full_path**` in `**params**` (not only `path`) so the macro editor displays the folder; runtime accepts both.

### Launching common apps (battle-tested patterns)


| Goal                              | Pattern                                                                                                                                                                                                                                                    |
| --------------------------------- | ---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- |
| **Windows Terminal / PowerShell** | `launch_app` with **full path** to `powershell.exe` (`C:/Windows/System32/WindowsPowerShell/v1.0/powershell.exe`) is more reliable than `wt`/`powershell` shorthand on machines without those on PATH.                                                     |
| **Plain cmd**                     | `launch_app` with `cmd` (or full path `C:/Windows/System32/cmd.exe`).                                                                                                                                                                                      |
| **Elevated cmd (admin)**          | Use the **Run-dialog elevation pattern** below — `launch_app cmd` does not elevate.                                                                                                                                                                        |
| **Explorer at a specific folder** | Two options: **(a)** `open_folder` block with `full_path` (forward slashes), **OR (b)** Run-dialog: `win+r` → wait → `type_text` path → `enter`. (b) sometimes maps more reliably onto user habit when the macro is composed alongside `cd` / shell input. |


### Admin / UAC elevation pattern

Launching elevated processes can't be done with `launch_app` alone — UAC needs to fire and be confirmed. Canonical sequence:

```
press win+r            ← open Run dialog
wait 0.2s
type_text "cmd"        ← or whatever exe
press ctrl+shift+enter ← request elevation
wait 0.5s              ← let UAC dialog appear
press tab              ← move focus from default to "Yes" group
press tab              ← (Win 11 default UAC: two tabs land on Yes)
press enter            ← confirm
wait 1.0s              ← let elevated process spawn
```

Notes:

- Don't follow this with `focus_window "Administrator"` — the new elevated window is already foreground after UAC accepts.
- Tab count to reach **Yes** depends on UAC layout; `tab` × 2 is the Windows 11 default. If the macro mis-presses, try 1 or 3 tabs.
- The wait after `ctrl+shift+enter` (0.5s) must be long enough for the UAC dialog to render. Slow disks → bump to 1s.

### `type_text` paths vs `full_path` paths

Path slashes differ by context:

- `**full_path` (in `launch_app`, `open_folder`, `run_script`):** use **forward slashes**, single string — `C:/Users/foo/Documents`. Backslashes also work but require JSON escaping.
- **Inside `type_text`** (typing into a shell or Run dialog): use **escaped backslashes** — `cd C:\\Users\\foo\\Documents`. The user is going to see backslashes in their shell exactly as typed.

**CLI in `type_text`:** e.g. `py YOUR_PROJECT_ROOT\\tools\\script.py`, `powershell -NoProfile -File "YOUR_SCRIPT_PATH.ps1"`. Escape `\` for JSON. `**./script.py`** needs correct cwd — use absolute path or prior **`cd` / `Set-Location`** line + Enter.

---

## Execution Rules

- **Templates directory:** `%USERPROFILE%\AppData\Roaming\key_pad_app\Templates\`
- **Macro files:** `<name>.json`
- `**template` block:** `template_name` is **basename only** (no `.json`); loads from **Templates** folder.
- **Runner shape:** expects `**type`** + `**args**`. Editor saves `**type**` + `**params**`. Runtime **maps `params` → `args`** and preserves `**children**` for containers.
- **Template / editor JSON:** always `**params`** + fixed `**title**` / `**color**` per block.
- **Raw execution-only payloads** (unusual): may use `**args`** instead of `**params**`; `**title`/`color**` not required for execution only.
- **Legacy load:** root may be **only** an array of blocks (no `**program`** key); prefer `**program**` wrapper otherwise.
- **Window snap:** `**meta` (alias `win`) + arrow** → `**wait` 0.1s** → `**esc`** → **next arrow immediately** → `**wait` 0.1s** → `**esc`** — see **Universal Intent Mapping** point 6. Precede with `**open_folder`** + `**focus_window**` when snapping Explorer.
- `**repeat`:** body must be non-empty or executor errors (“No blocks specified for repeat action”).
- `**template`:** no circular includes.

---

## Script Builder (compiled `.bat`)

SinTuch’s **Script Builder** is a separate canvas from the **macro** editor. It produces **Windows cmd.exe batch** scripts, not HID/automation sequences.

### Paths (Windows)


| Role                                        | Directory                                                            |
| ------------------------------------------- | -------------------------------------------------------------------- |
| **Source JSON** (saved from Script Builder) | `%APPDATA%\Roaming\key_pad_app\scripts\source\` — file `<stem>.json` |
| **Compiled batch** (written on Save)        | `%APPDATA%\Roaming\key_pad_app\scripts\comp\` — file `<stem>.bat`    |


Saving a script writes **both** the JSON and the `.bat`. The app’s **built-in batch compiler** emits one or more cmd.exe lines per block, plus a standard wrapper (`@echo off`, `setlocal EnableExtensions`, and `exit /b 0`).

### JSON shape

Same top-level object as macros:

```json
{ "program": [ /* script blocks only */ ] }
```

Each block has `**type**`, `**params**`, `**title**`, `**color**` — `**title` / `color` must match the Script Block Type Table** (editor-enforced constants).

### Script Block Type Table


| `type`       | `title` (exact) | `color` (exact) |
| ------------ | --------------- | --------------- |
| `sb_comment` | `Comment`       | `#94a3b8`       |
| `sb_run_cmd` | `Run command`   | `#ff6b6b`       |
| `sb_set_var` | `Set variable`  | `#a78bfa`       |
| `sb_delay`   | `Delay`         | `#4facfe`       |
| `sb_start`   | `Start process` | `#84a98c`       |
| `sb_raw`     | `Raw line`      | `#ffd93d`       |


### Script block params (compiler contract)


| `type`       | `params`                                               | Emitted batch (summary)                                       |
| ------------ | ------------------------------------------------------ | ------------------------------------------------------------- |
| `sb_comment` | `text`                                                 | `REM …`                                                       |
| `sb_set_var` | `name`, `value`                                        | `set "NAME=value"` (sanitized name; cmd quote rules on value) |
| `sb_delay`   | `seconds` (int)                                        | `timeout /t N /nobreak >nul`                                  |
| `sb_run_cmd` | `command`                                              | **First line only**, verbatim                                 |
| `sb_start`   | `start_title`, `executable`, `arguments` (string list) | `start "title" "exe" "arg" …`                                 |
| `sb_raw`     | `text`                                                 | **First line only**, verbatim                                 |


`**sb_run_cmd` vs `sb_raw`:** same emission rules today; use **Run command** for “execute this cmd line” and **Raw line** when you want a literal batch line pasted as-is (mental model only).

**Limitations:** no containers (`if`/`repeat` as macro-style JSON) — express branching with batch syntax inside `**sb_run_cmd`** / `**sb_raw**`. Sub-second waits are not represented in `**sb_delay**` (compiler clamps integer seconds).

### UI integration

- **Load** reads a `**.json`** file from disk (file dialog starts under `**scripts/source**`, but you can pick any path). If the JSON matches this schema, **blocks appear on the canvas** in program order.
- **Save** prompts for a name under `**scripts/source`** and refreshes `**scripts/comp\<stem>.bat**`.
- **Test Run** (Script Builder footer) runs the compiled `**<stem>.bat`** if it exists (save first).
- **Export** can write JSON anywhere; only **Save** updates `**scripts/comp`**.

### Script deliverable rule

When the user asks for a **Script Builder script** (with or without a macro that calls it), deliver **transparently**: every batch must have a matching Script Builder JSON source the user can open in the app.

**Pairing (required):**


| File                             | Role                                                                                                                                                                                                                           |
| -------------------------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------ |
| `**scripts/source/<Stem>.json`** | **Source of truth for editing** — `{ "program": [ … ] }` with `**sb_*` blocks only**, fixed `**title`** / `**color**` per **Script Block Type Table**. User **Load**s this in Script Builder to review commands on the canvas. |
| `**scripts/comp/<Stem>.bat`**    | **What `run_script` executes** — cmd.exe batch. AI **may** generate this file directly so the script runs immediately without an extra Save step.                                                                              |


**Rules:**

1. **Same `<Stem>`** for both files (e.g. `ExportCase.json` + `ExportCase.bat`).
2. **Same logic** — JSON blocks must correspond to the batch lines (`sb_comment` → `REM`, `sb_run_cmd` → command line, `sb_delay` → `timeout`, etc.). No hidden commands in `.bat` that are not represented in the JSON.
3. **Order does not matter** — AI may write `.bat` first or JSON first, but **both must appear in the same response** (label each file clearly in **Multi-file** mode).
4. **Never deliver `.bat` alone** — without the paired `**scripts/source/<Stem>.json`**.
5. **JSON alone is allowed** only if you tell the user to **Save** in Script Builder once to create `**scripts/comp/<Stem>.bat`** before first `**run_script**` use.
6. Map each meaningful batch line to `**sb_run_cmd**`, `**sb_raw**`, `**sb_comment**`, `**sb_delay**`, `**sb_set_var**`, or `**sb_start**` — do not dump opaque batch as a single block unless one line truly is one command.

**User workflow (recommended):** save both files → Script Builder → **Load** the JSON → review blocks → **Save** (refreshes `.bat` if they edited). User may also run the AI-provided `.bat` directly via `**run_script`** when paths match.

**Runtime note:** `run_script` executes the `**.bat`**, not the JSON. JSON is for **transparency and editing** in Script Builder; `.bat` is for **execution**.

### JSON from an LLM (skill-assisted)

An assistant that follows this skill can output **ready-to-load** Script Builder JSON: same `{ "program": [ … ] }` shape, only `**sb_*`** types, and `**title` / `color**` copied from **Script Block Type Table**.

**What the user does:** paste or save that JSON as a **UTF-8** `.json` file → open **Script Builder** in Key Pad → **Load** → choose the file → blocks render for reading and editing → **Save** when satisfied (writes `**scripts/source`** copy and compiles `**scripts/comp\<stem>.bat**`).

The LLM does **not** need the app to “draw” blocks: the **app** parses JSON on **Load**. The LLM only needs the documented schema.

### Macro hook: `run_script`

The macro block `**run_script`** / `**script_path**` runs a file **as a subprocess from Key Pad** (no terminal UI). Point `**script_path`** at the absolute path of a compiled batch, e.g.  
`%USERPROFILE%\AppData\Roaming\key_pad_app\scripts\comp\MyScript.bat`  
(expanded to a real absolute path in JSON). The macro editor’s **Run Script** file picker **defaults to `scripts/comp`** so compiled batches are easy to pick.

See `**examples.md**` — **Script Builder program (minimal)** and **Run External Script** (with `scripts/comp` note).

---

## Container Rules

- **Root:** `**program`** is ordered siblings (top → bottom execution).
- **Containers with `children`:** only `**if_condition`**, `**repeat**`, `**while**`. Nesting allowed.

`**children` item shape:**

```json
{ "area": "<area_name>", "blocks": [] }
```

Replace `**blocks**` with full block objects (`type`, `params`, `title`, `color`, …).


| Parent             | `area` values                                                                                              |
| ------------------ | ---------------------------------------------------------------------------------------------------------- |
| `**if_condition**` | `**then**`, `**else**` — each area at most once with non-empty `**blocks**` if used; omit unused branches. |
| `**repeat**`       | `**repeat**`                                                                                               |
| `**while**`        | `**while**` — toggle/stop semantics on hardware; editor test-run may run body once.                        |


**If-condition:** Window existence/focus is **not** nested JSON under `**if_condition`**. Use `**params.condition**` + `**condition_exact_match**` (see **Full Schema Reference** — condition grammar).

### Container skeletons (required `title` / `color`)

`**if_condition`:**

```json
{
  "type": "if_condition",
  "params": {
    "condition": "<string>",
    "condition_exact_match": false
  },
  "title": "If Condition",
  "color": "#a78bfa",
  "children": [
    {
      "area": "then",
      "blocks": []
    },
    {
      "area": "else",
      "blocks": []
    }
  ]
}
```

`**repeat`:**

```json
{
  "type": "repeat",
  "params": {
    "times": 3
  },
  "title": "Repeat",
  "color": "#a78bfa",
  "children": [
    {
      "area": "repeat",
      "blocks": []
    }
  ]
}
```

Executor also accepts `**count**` as alias for `**times**` (in `**args**`).

`**while`:**

```json
{
  "type": "while",
  "params": {},
  "title": "While toggled",
  "color": "#a78bfa",
  "children": [
    {
      "area": "while",
      "blocks": []
    }
  ]
}
```

---

## presets.json Rules

- **Path (Windows):** `%APPDATA%\Roaming\key_pad_app\presets.json` — filename `**presets.json`** (lowercase); “presets.JSON” means the same file.
- **Top-level:** keys `**"1"` … `"10"`** (presets). Optional `**"__global__"**` — **preserve** when editing unless user asks to change global theme/colors.
- **Each preset:** `**name`**, `**icon**` (large array — do not wipe when patching one button), `**p_color**`, `**buttons**` map.

### Grid keys (`buttons`)

**Formula** for physical key **B** (1–9, top-left = 1):  
`row = (B - 1) // 3`, `col = (B - 1) % 3`, key `**"{row},{col}"`**.


| Button # | Key                     |
| -------- | ----------------------- |
| 1–3      | `"0,0"` `"0,1"` `"0,2"` |
| 4–6      | `"1,0"` `"1,1"` `"1,2"` |
| 7–9      | `"2,0"` `"2,1"` `"2,2"` |


### Macro slot payload

```json
{
  "text": "SHORT LABEL ON KEY",
  "type": "macro",
  "full_path": "ABSOLUTE_PATH_TO_MACRO_FILE.json"
}
```

- `**full_path`:** absolute path to macro JSON (typically `**...\key_pad_app\Templates\YourMacro.json`**). Runtime loads `**program**` or legacy list from that file.
- `**text`:** label on the key.

### When user says preset **P**, button **B**

1. Emit macro JSON to `**Templates\….json`** (canvas format).
2. Give exact `**full_path**` for JSON (escaped for JSON).
3. **Merge:** read `**presets.json`** → under `**presets[str(P)]**` ensure `**buttons**` → set `**buttons["row,col"]**` → write back; keep `**__global__**`, other presets, other `**buttons**`, `**icon**`, `**p_color**`, `**name**` unchanged unless requested.
4. **Risk:** UI save may overwrite file edits — prefer app **closed** or reload after edit.

---

## Fixed Block Type Table


| `type`         | `title` (exact) | `color` (exact) |
| -------------- | --------------- | --------------- |
| `click`        | `Click`         | `#ff6b6b`       |
| `mouse_select` | `Mouse Drag`    | `#ff6b6b`       |
| `press`        | `Press`         | `#ff6b6b`       |
| `type_text`    | `Type Text`     | `#ff6b6b`       |
| `launch_app`   | `Launch App`    | `#ff6b6b`       |
| `open_folder`  | `Open Folder`   | `#ff6b6b`       |
| `focus_window` | `Focus Window`  | `#6bcf7f`       |
| `check_window` | `Check Window`  | `#6bcf7f`       |
| `is_focused`   | `Is Focused`    | `#6bcf7f`       |
| `if_condition` | `If Condition`  | `#a78bfa`       |
| `repeat`       | `Repeat`        | `#a78bfa`       |
| `while`        | `While toggled` | `#a78bfa`       |
| `wait`         | `Wait`          | `#4facfe`       |
| `run_script`   | `Run Script`    | `#ffd93d`       |
| `template`     | `Template`      | `#ff8e53`       |


---

## Params Reference

Leaf blocks: no `**children`** (ignored if present).


| `type`         | `params` keys                                                                                                                                          | Notes                                                      |
| -------------- | ------------------------------------------------------------------------------------------------------------------------------------------------------ | ---------------------------------------------------------- |
| `click`        | `x`, `y` (integers), `click_type` (`Left Click` / `Right Click` / `Middle Click`), optional `hid_between`, `hid_after`, optional `duration` (fallback) | Screen coordinates.                                        |
| `mouse_select` | `start_x`, `start_y`, `end_x`, `end_y`, `select_type` (`Left Drag` / `Right Drag` / `Middle Drag`), optional `hid_between`, `hid_after`                |                                                            |
| `press`        | `combo` preferred (`ctrl+c`, `meta+shift+s`); or `key`, or `keys` (list). Optional `hid_between`, `hid_after`.                                         |                                                            |
| `type_text`    | `text`; optional `hid_between`, `hid_after`                                                                                                            | HID may skip unsupported chars.                            |
| `wait`         | `seconds` (editor) or `duration` (runtime alias)                                                                                                       | Seconds.                                                   |
| `launch_app`   | `path` or `full_path`                                                                                                                                  |                                                            |
| `open_folder`  | `path` or `full_path`                                                                                                                                  | Prefer `**full_path**` in saved JSON (editor displays it). |
| `focus_window` | `window_title`, optional `exact_match` (default **true** if omitted in executor)                                                                       |                                                            |
| `check_window` | `window_title`, optional `exact_match` (default **true**)                                                                                              | As action; in `**if`**, use `**condition**` string.        |
| `is_focused`   | `window_title`, optional `exact_match` (default **true**)                                                                                              |                                                            |
| `run_script`   | `script_path`                                                                                                                                          | Async `.py`, `.bat`, `.ps1`, `.exe`, etc.                  |
| `template`     | `template_name`                                                                                                                                        | Basename only; loads from **Templates**.                   |


---

## Examples Reference

Full JSON patterns live in `**examples.md`**. Use them as the pattern library:


| Example                                     | Topics                                                                       |
| ------------------------------------------- | ---------------------------------------------------------------------------- |
| Delay Then Shortcut                         | `wait`, `press`                                                              |
| Type Text And Confirm                       | `type_text`, `enter`                                                         |
| Click And Drag                              | `click`, `mouse_select`                                                      |
| Apps And Folders                            | `launch_app`, `open_folder`, `%USERNAME%` path note                          |
| Focus If Window Exists                      | `if_condition`, `check_window`, `focus_window`, `launch_app`                 |
| Only When Focused                           | `if_condition`, `is_focused`                                                 |
| Repeat Loop                                 | `repeat`, `children` area `repeat`                                           |
| Nested Repeat In If                         | nested containers                                                            |
| Run External Script                         | `run_script`, headless                                                       |
| Template Two-File                           | `template`, second JSON file                                                 |
| While Toggle Body                           | `while`, toggle semantics note                                               |
| While Drag Select And Click                 | `while`, `mouse_select`, `click`, nested `**area**` `while`                  |
| Release Workflow                            | UAC tab/enter, snap, folder, F5, dual terminals, `type_text` vs `run_script` |
| Open Folder And Snap Explorer Top Left      | `open_folder`, `focus_window`, snap (corrected timing)                       |
| Open Folder And Snap Explorer Top Right     | same pattern, top-right arrows                                               |
| Open Folder And Snap Explorer Bottom Left   | `open_folder`, `focus_window`, snap (corrected timing)                       |
| Export Then Snap Today Folder               | `run_script` + `template` (dated open/focus/snap macro blocks)               |
| Terminal Run Script Typed                   | `launch_app`, `focus_window`, `type_text`, `py` path                         |
| Wire Macro Preset Button                    | `presets.json` merge, formula for `row,col`                                  |
| **Schema parity:** Sequence Wait Type Enter | minimal chain (same as historical schema runnable example)                   |
| **Schema parity:** If Else Notepad Window   | window branch sample                                                         |
| **Schema parity:** Repeat Click Wait        | loop body click + wait                                                       |
| **Script Builder program (minimal)**        | `sb_*` types, `title`/`color` table, compile → `.bat`                        |
| **Run External Script**                     | `run_script`, `**scripts/comp`** path note                                   |


---

## Full Schema Reference

### Canvas block object fields

**Preferred property order:** `**type`**, `**params**`, `**title**`, `**color**`, `**children**` (when present).


| Field      | Required       | Meaning                                             |
| ---------- | -------------- | --------------------------------------------------- |
| `type`     | Yes            | Block kind string.                                  |
| `params`   | Yes            | Arguments object (may `{}`).                        |
| `title`    | Yes            | Must match **Fixed Block Type Table** for `type`.   |
| `color`    | Yes            | Must match **Fixed Block Type Table** for `type`.   |
| `children` | Container only | Only `**if_condition`**, `**repeat**`, `**while**`. |


After runtime conversion: `{ "type": "…", "args": { … }, "children": … }` — `**title`/`color**` not used by executor.

### Root JSON shapes

**Preferred:**

```json
{
  "program": []
}
```

**Legacy:** root may be a bare array of blocks.

### `if_condition`: condition grammar

Stored in `**params.condition`**.


| Pattern                                             | Meaning                                                  |
| --------------------------------------------------- | -------------------------------------------------------- |
| `check_window:<window_title>`                       | Window exists; matching via `**condition_exact_match**`. |
| `is_focused:<window_title>`                         | Window is foreground.                                    |
| `true`, `false`, `1`, `0`, `yes`, `no`, `on`, `off` | Booleans.                                                |
| `$variableName`                                     | Runtime variable; missing → false.                       |
| Other non-empty string                              | Truthy if non-empty after strip.                         |


`**condition_exact_match`:** boolean in `**params`**; if omitted in if-branch evaluation, defaults `**false**`.

**Standalone** `**check_window`**, `**is_focused**`, `**focus_window`:** use `**exact_match`** in `**params**`; executor defaults `**true**` when omitted — **stricter** than if-condition default. Prefer setting explicitly.

### Authoring checklist

1. Use `**"program": [...]`** unless legacy array-only is intended.
2. Every block: `**type**`, `**params**`, `**title**`, `**color**` — exact table match; prefer that **property order** in JSON (then `**children`** on containers).
3. Template files use `**params**`; runtime maps to `**args**`.
4. Only `**if_condition**`, `**repeat**`, `**while**` have `**children**`; each child needs `**area**` + `**blocks**`.
5. `**template**`: stem name only; no circular references.
6. `**repeat**`: non-empty `**children**` body required.
7. Preset **P** + button **B`:** merge `**presets.json`** per **presets.json Rules**; preserve **`global`**, **`icon`**, unrelated **`buttons`**.

### Implementation note

Authoritative behavior lives in the Key Pad application sources: macro canvas serialization, canvas→execution conversion, per-type executors, and **Script Builder** save/compile. This skill stays **path-agnostic** for sharing except for the **standard AppData layout** in **Script Builder (compiled `.bat`)**.