From de973cf02520e901c4a0abfa35300b0d650081ea Mon Sep 17 00:00:00 2001 From: Samuel Estok Date: Tue, 27 Oct 2026 12:39:38 -0700 Subject: [PATCH 01/16] docs(gravity-forms-abilities): document field property merge and id reuse on forms-update --- change_log.txt | 3 +++ skills/gravity-forms-abilities/SKILL.md | 6 +++++- 2 files changed, 8 insertions(+), 1 deletion(-) diff --git a/change_log.txt b/change_log.txt index 0e896ff..eb751d5 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,3 +1,6 @@ +### 1.1.3 | 2026-10-27 +- gravity-forms-abilities: Document that forms-update merges a round-tripped field's unsent properties by id, and that field IDs can be reused after a delete across separate calls. + ### 1.1.2 | 2026-08-14 - gravity-forms-abilities: Add a WordPress multisite section covering per-subsite endpoints and tool allowlists, per-subsite capabilities, HTML filtering for non-super-admin users, and network-inherited license info. diff --git a/skills/gravity-forms-abilities/SKILL.md b/skills/gravity-forms-abilities/SKILL.md index 121bf9b..8599d1b 100644 --- a/skills/gravity-forms-abilities/SKILL.md +++ b/skills/gravity-forms-abilities/SKILL.md @@ -113,7 +113,11 @@ Use `{admin_email}` for site admin, or a specific address. `{all_fields}` render 2. Modify the returned fields array (add/remove/change) 3. Call `forms-update` with the complete form object -`notifications` and `confirmations` passed to `forms-update` merge by key — handy when standing up a whole form at once. For **targeted edits to a single notification or confirmation — including deletion — use the dedicated tools below**, not `forms-update` (they don't round-trip the whole form, so they can't drop fields). `fields` does NOT merge. +**Which fields exist is replaced; a field's properties are merged.** A submitted field whose `id` matches a stored field of the same `type` keeps every stored property you did not resend (`inputs`, `size`, `productField`, `validateState`, ...). Send a property as an empty value (`""`, `[]`) to clear it. A field with a changed `type` is a replacement and inherits nothing. Fields without an `id` are new. + +**Field IDs can be reused after a delete.** Like the form editor, Gravity Forms computes the next field ID from the highest ID currently on the form. Within one `forms-update` call new fields always get IDs above every stored ID, but if you remove the highest field in one call and add an ID-less field in a later call, the new field takes the old ID. Entry values and conditional-logic rules from the removed field then attach to the new one. To avoid it: remove and add in the same call, or give the new field an explicit `id` above the old maximum, and check `forms-analyze-logic` for rules that point at removed fields. + +`notifications` and `confirmations` passed to `forms-update` merge by key — handy when standing up a whole form at once. For **targeted edits to a single notification or confirmation — including deletion — use the dedicated tools below**, not `forms-update` (they don't round-trip the whole form, so they can't drop fields). The `fields` list itself does NOT merge: omitted fields are deleted. ### Notifications & Confirmations From 9b97fca7da0cdaedd74ca0f85ef9335b16145415 Mon Sep 17 00:00:00 2001 From: Samuel Estok Date: Tue, 27 Oct 2026 12:47:02 -0700 Subject: [PATCH 02/16] docs(gravity-forms-abilities): document the entries-delete form ownership check --- change_log.txt | 1 + skills/gravity-forms-abilities/references/entry-operations.md | 2 ++ 2 files changed, 3 insertions(+) diff --git a/change_log.txt b/change_log.txt index eb751d5..2610b93 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,4 +1,5 @@ ### 1.1.3 | 2026-10-27 +- gravity-forms-abilities: Document that entries-delete rejects an entry_id and form_id pair when the entry belongs to another form. - gravity-forms-abilities: Document that forms-update merges a round-tripped field's unsent properties by id, and that field IDs can be reused after a delete across separate calls. ### 1.1.2 | 2026-08-14 diff --git a/skills/gravity-forms-abilities/references/entry-operations.md b/skills/gravity-forms-abilities/references/entry-operations.md index 0e056c7..8c849f8 100644 --- a/skills/gravity-forms-abilities/references/entry-operations.md +++ b/skills/gravity-forms-abilities/references/entry-operations.md @@ -127,6 +127,8 @@ For large result sets: `entries-delete` supports bulk mode — pass `form_id` instead of `entry_id` to delete all entries for a form server-side. +Passing both `entry_id` and `form_id` is a single delete with a safety check: the entry must belong to that form, or the call is rejected with `gf_ability_form_entry_mismatch` and nothing is deleted. Use the pair when you know the form, so a mixed-up ID can never delete an entry elsewhere. + ### Delete all entries for one form ```json From e8349cfdcb1e09a42531d7dd3bae624fd65da052 Mon Sep 17 00:00:00 2001 From: Samuel Estok Date: Tue, 27 Oct 2026 12:58:05 -0700 Subject: [PATCH 03/16] docs(gravity-forms-abilities): document orphaned logic rules and forms-update warnings --- change_log.txt | 1 + skills/gravity-forms-abilities/SKILL.md | 4 +++- .../gravity-forms-abilities/references/conditional-logic.md | 1 + 3 files changed, 5 insertions(+), 1 deletion(-) diff --git a/change_log.txt b/change_log.txt index 2610b93..e6e0494 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,4 +1,5 @@ ### 1.1.3 | 2026-10-27 +- gravity-forms-abilities: Document orphaned conditional logic rules in forms-analyze-logic output and the warnings array returned by forms-update. - gravity-forms-abilities: Document that entries-delete rejects an entry_id and form_id pair when the entry belongs to another form. - gravity-forms-abilities: Document that forms-update merges a round-tripped field's unsent properties by id, and that field IDs can be reused after a delete across separate calls. diff --git a/skills/gravity-forms-abilities/SKILL.md b/skills/gravity-forms-abilities/SKILL.md index 8599d1b..a5c04fb 100644 --- a/skills/gravity-forms-abilities/SKILL.md +++ b/skills/gravity-forms-abilities/SKILL.md @@ -332,10 +332,12 @@ Conditional logic (CL) controls show/hide behavior of fields, notifications, con ### Analyzing Logic Call `forms-analyze-logic` instead of parsing raw CL from `forms-get`. It returns: -- **`summary`** — rule counts across all locations +- **`summary`** — rule counts across all locations, including `orphaned_rules` - **`dependency_map`** — reverse map showing what each source field controls (most useful view) - Per-location arrays: `field_logic`, `notification_logic`, `confirmation_logic`, `submit_button_logic`, `page_logic` +**Orphaned rules.** A rule whose source field is not on the form (deleted, or never existed) carries `orphaned: true`, and so does its `dependency_map` entry; `summary.orphaned_rules` counts them. `forms-update` does not refuse to remove a field that drives logic (the editor only warns too), but it returns a `warnings` array naming the orphaned rules. Repair or remove them right away: a new field that reuses the id silently takes the rules over. + ### Adding/Modifying Logic CL is a property on individual fields (or notifications/confirmations). To add or change: diff --git a/skills/gravity-forms-abilities/references/conditional-logic.md b/skills/gravity-forms-abilities/references/conditional-logic.md index 6532a61..24be0f9 100644 --- a/skills/gravity-forms-abilities/references/conditional-logic.md +++ b/skills/gravity-forms-abilities/references/conditional-logic.md @@ -116,6 +116,7 @@ The ability returns: - **`submit_button_logic`** — `null` if no CL on submit button, otherwise `{action, logic_type, rules}`. - **`page_logic`** — Array of page button CL (multi-page forms only). - **`dependency_map`** — **Most useful view.** Keyed by source field ID, shows everything that field controls. Use this to answer "what happens when field X changes?" +- **`orphaned`** — On every rule and every `dependency_map` entry. `true` when the source field is not on the form (deleted, or an ID that never existed); `source_field_label` is then empty. `summary.orphaned_rules` counts them. Fix orphaned rules before adding fields: a new field that reuses the ID takes the rules over. ## Workflow: Auditing Form Logic From 3abddeccf0d0ab0b0a1265059a129ddf5a4b7caa Mon Sep 17 00:00:00 2001 From: Samuel Estok Date: Tue, 27 Oct 2026 13:14:49 -0700 Subject: [PATCH 04/16] docs(gravity-forms-abilities): document corrected system-field-types metadata --- change_log.txt | 1 + skills/gravity-forms-abilities/SKILL.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/change_log.txt b/change_log.txt index e6e0494..e16343d 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,4 +1,5 @@ ### 1.1.3 | 2026-10-27 +- gravity-forms-abilities: Document the corrected system-field-types metadata: has_inputs for consent, product and checkbox, inputs_per_choice, and inputs_note. - gravity-forms-abilities: Document orphaned conditional logic rules in forms-analyze-logic output and the warnings array returned by forms-update. - gravity-forms-abilities: Document that entries-delete rejects an entry_id and form_id pair when the entry belongs to another form. - gravity-forms-abilities: Document that forms-update merges a round-tripped field's unsent properties by id, and that field IDs can be reused after a delete across separate calls. diff --git a/skills/gravity-forms-abilities/SKILL.md b/skills/gravity-forms-abilities/SKILL.md index a5c04fb..2444a3b 100644 --- a/skills/gravity-forms-abilities/SKILL.md +++ b/skills/gravity-forms-abilities/SKILL.md @@ -383,7 +383,7 @@ For CL structure details, operators, and common patterns, see [references/condit **Choice fields** (`supports_choices: true`): `select`, `radio`, `checkbox`, `multiselect`, `image_choice` — require `choices: [{text, value}]` array. **Multiselect values must be submitted as arrays** (`"input_1": ["Red", "Blue"]`), not comma-separated strings. -**Compound fields** (`has_inputs: true`): `name`, `address`, `time` — store values across sub-inputs with ID suffixes. Call `system-field-types` to see `default_inputs` for exact suffix mappings. **Name fields require `"nameFormat": "advanced"` and `"size": "large"`** — without these, sub-inputs render stacked instead of side-by-side. +**Compound fields** (`has_inputs: true`): `name`, `address`, `time`, `consent`, `product` (single product) and `checkbox` — store values across sub-inputs with ID suffixes. Call `system-field-types` to see `default_inputs` for exact suffix mappings; `checkbox` has `inputs_per_choice: true` (one sub-input per choice, `{field_id}.{n}`, n skips multiples of 10), and types whose inputs depend on configuration (`product`, `date`, `multi_choice`, `image_choice`) carry an `inputs_note`. **Name fields require `"nameFormat": "advanced"` and `"size": "large"`** — without these, sub-inputs render stacked instead of side-by-side. **File upload fields**: `fileupload` — configure `allowedExtensions` (comma-separated, no dots), `maxFileSize` (MB), `maxFiles`, `multipleFiles`. These properties are NOT returned by `system-field-types` — see [references/field-config.md](references/field-config.md) for full type-specific config reference. File upload fields can be configured via abilities, but actual file submission requires the rendered form (MCP cannot transport binary data). From 26c86fd15357e9ea077643b233aec9819341d7bd Mon Sep 17 00:00:00 2001 From: Samuel Estok Date: Tue, 27 Oct 2026 13:20:01 -0700 Subject: [PATCH 05/16] docs(gravity-forms-abilities): document the notifications-send sent and skipped response --- change_log.txt | 1 + skills/gravity-forms-abilities/SKILL.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/change_log.txt b/change_log.txt index e16343d..95cde5e 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,4 +1,5 @@ ### 1.1.3 | 2026-10-27 +- gravity-forms-abilities: Document the notifications-send response: sent lists only active, matching notifications, and skipped gives a reason per id. - gravity-forms-abilities: Document the corrected system-field-types metadata: has_inputs for consent, product and checkbox, inputs_per_choice, and inputs_note. - gravity-forms-abilities: Document orphaned conditional logic rules in forms-analyze-logic output and the warnings array returned by forms-update. - gravity-forms-abilities: Document that entries-delete rejects an entry_id and form_id pair when the entry belongs to another form. diff --git a/skills/gravity-forms-abilities/SKILL.md b/skills/gravity-forms-abilities/SKILL.md index 2444a3b..b75d0c5 100644 --- a/skills/gravity-forms-abilities/SKILL.md +++ b/skills/gravity-forms-abilities/SKILL.md @@ -26,7 +26,7 @@ metadata: **Integrations** → `feeds-list`, `feeds-create`, `feeds-update`, `feeds-delete` -**Notifications** → `notifications-list`, `notifications-create` / `notifications-update` / `notifications-delete` (targeted config edits — the canonical path, NOT forms-update), `notifications-send` (re-send for an existing entry) +**Notifications** → `notifications-list`, `notifications-create` / `notifications-update` / `notifications-delete` (targeted config edits — the canonical path, NOT forms-update), `notifications-send` (re-send for an existing entry; returns `sent`, the active and matching notifications handed to the pipeline, which may be queued, plus `skipped` with a reason per id: `inactive`, `event`, `conditional_logic`, `not_found`) **Confirmations** → `confirmations-list`, `confirmations-create` / `confirmations-update` / `confirmations-delete` (the message / page / redirect a submitter sees after submitting) From 554487783ab587055e7c7404f4cae0195a2efa43 Mon Sep 17 00:00:00 2001 From: Samuel Estok Date: Tue, 27 Oct 2026 13:30:39 -0700 Subject: [PATCH 06/16] docs(gravity-forms-abilities): document field_values dynamic population --- change_log.txt | 1 + skills/gravity-forms-abilities/SKILL.md | 2 ++ 2 files changed, 3 insertions(+) diff --git a/change_log.txt b/change_log.txt index 95cde5e..7d55090 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,4 +1,5 @@ ### 1.1.3 | 2026-10-27 +- gravity-forms-abilities: Document field_values dynamic population on submissions-submit and submissions-validate. - gravity-forms-abilities: Document the notifications-send response: sent lists only active, matching notifications, and skipped gives a reason per id. - gravity-forms-abilities: Document the corrected system-field-types metadata: has_inputs for consent, product and checkbox, inputs_per_choice, and inputs_note. - gravity-forms-abilities: Document orphaned conditional logic rules in forms-analyze-logic output and the warnings array returned by forms-update. diff --git a/skills/gravity-forms-abilities/SKILL.md b/skills/gravity-forms-abilities/SKILL.md index b75d0c5..1b9c7c1 100644 --- a/skills/gravity-forms-abilities/SKILL.md +++ b/skills/gravity-forms-abilities/SKILL.md @@ -147,6 +147,8 @@ For most compound fields (name, address), use dot-notation sub-input keys: `inpu For **multiselect fields**, pass values as an array: `"input_3": ["Red", "Blue"]`. Never use comma-separated strings — values containing commas cause data loss. +**Dynamic population:** `field_values` is keyed by parameter name (a field's `inputName`, or a sub-input's `name`), e.g. `"field_values": {"promo": "SPRING26"}`. It fills fields that have `allowsPrepopulate: true` when `input_values` carries no value for them; an explicit `input_values` entry always wins. `submissions-validate` accepts it too. + **`submissions-submit` vs `entries-create`:** - `submissions-submit` = full pipeline (validation → entry → notifications → feeds) - `entries-create` = raw DB insert, bypasses everything — use only for data migration From 0051065c874712b8f27a6ce1ffd876e6f9c3c573 Mon Sep 17 00:00:00 2001 From: Samuel Estok Date: Tue, 27 Oct 2026 13:41:43 -0700 Subject: [PATCH 07/16] docs(gravity-forms-abilities): document paused-by-default feeds and is_active on feeds-update --- change_log.txt | 1 + skills/gravity-forms-abilities/SKILL.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/change_log.txt b/change_log.txt index 7d55090..2696c6f 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,4 +1,5 @@ ### 1.1.3 | 2026-10-27 +- gravity-forms-abilities: Document that feeds-create starts feeds inactive unless is_active is true, and that feeds-update accepts is_active alone to pause or resume. - gravity-forms-abilities: Document field_values dynamic population on submissions-submit and submissions-validate. - gravity-forms-abilities: Document the notifications-send response: sent lists only active, matching notifications, and skipped gives a reason per id. - gravity-forms-abilities: Document the corrected system-field-types metadata: has_inputs for consent, product and checkbox, inputs_per_choice, and inputs_note. diff --git a/skills/gravity-forms-abilities/SKILL.md b/skills/gravity-forms-abilities/SKILL.md index 1b9c7c1..cf27e6b 100644 --- a/skills/gravity-forms-abilities/SKILL.md +++ b/skills/gravity-forms-abilities/SKILL.md @@ -24,7 +24,7 @@ metadata: **Manage data** → `entries-search` (filter/paginate), `entries-get` (single entry), `entries-count` (efficient count), `entries-create` (raw insert, no validation), `entries-update`, `entries-delete` (trash by default; single by entry_id OR bulk by form_id + optional search_criteria; `force: true` for permanent) -**Integrations** → `feeds-list`, `feeds-create`, `feeds-update`, `feeds-delete` +**Integrations** → `feeds-list`, `feeds-create` (new feeds start **inactive** unless `is_active: true`; review, then activate), `feeds-update` (pass only what changes: `feed_meta` replaces the stored meta, `is_active` pauses or resumes, `form_id` moves the feed), `feeds-delete` **Notifications** → `notifications-list`, `notifications-create` / `notifications-update` / `notifications-delete` (targeted config edits — the canonical path, NOT forms-update), `notifications-send` (re-send for an existing entry; returns `sent`, the active and matching notifications handed to the pipeline, which may be queued, plus `skipped` with a reason per id: `inactive`, `event`, `conditional_logic`, `not_found`) From 868a2db320a2aa9775e62899deb19260edf9ebef Mon Sep 17 00:00:00 2001 From: Samuel Estok Date: Tue, 27 Oct 2026 13:43:58 -0700 Subject: [PATCH 08/16] docs(gravity-forms-abilities): document the default admin notification on forms-create --- change_log.txt | 1 + skills/gravity-forms-abilities/SKILL.md | 6 +++--- 2 files changed, 4 insertions(+), 3 deletions(-) diff --git a/change_log.txt b/change_log.txt index 2696c6f..3e37ffa 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,4 +1,5 @@ ### 1.1.3 | 2026-10-27 +- gravity-forms-abilities: Document that forms-create adds the editor default admin notification when notifications is omitted, and that an empty object opts out. - gravity-forms-abilities: Document that feeds-create starts feeds inactive unless is_active is true, and that feeds-update accepts is_active alone to pause or resume. - gravity-forms-abilities: Document field_values dynamic population on submissions-submit and submissions-validate. - gravity-forms-abilities: Document the notifications-send response: sent lists only active, matching notifications, and skipped gives a reason per id. diff --git a/skills/gravity-forms-abilities/SKILL.md b/skills/gravity-forms-abilities/SKILL.md index cf27e6b..70b2a85 100644 --- a/skills/gravity-forms-abilities/SKILL.md +++ b/skills/gravity-forms-abilities/SKILL.md @@ -75,7 +75,7 @@ The agent does not need to know which mode is active — the MCP client handles 1. Call `system-field-types` — discover available types and capabilities 2. Build form object with `title` and `fields` array — for `phone` fields, ALWAYS set `phoneFormat` explicitly (see the phone section below) -3. **Include a `notifications` object** — `forms-create` does NOT auto-create a default admin notification (unlike the GF admin UI). Without one, submissions are saved but no email is sent. +3. Decide on notifications — when the form object has **no `notifications` key**, `forms-create` adds the editor's default Admin Notification (`{admin_email}`, `{all_fields}`), the same as the GF admin UI. Pass your own `notifications` object to replace it, or an explicit empty object `{}` for a form that sends no email. 4. Call `forms-create` — returns `form_id` and `edit_url` Never guess field types. `system-field-types` returns `supports_choices`, `has_inputs`, `default_inputs`, and support flags for each type. @@ -85,7 +85,7 @@ Never guess field types. `system-field-types` returns `supports_choices`, `has_i - **Reading** (`entries-get` / `entries-search`): a formatted phone comes back as that JSON object, not a plain number — parse it (use `e164` for the canonical number), don't treat it as a string. - **Writing / submitting** (`entries-update`, `submissions-submit`, `submissions-validate`): supply the JSON object with a valid `e164`, not a bare number, or validation fails. (`entries-create` is a raw insert, so match the same shape to keep the value usable.) -**Default admin notification template:** +**Admin notification template** (what `forms-create` adds by default; use it as the starting point for a custom one): ```json { "notifications": { @@ -370,7 +370,7 @@ For CL structure details, operators, and common patterns, see [references/condit | Parsing raw CL from `forms-get` manually | Error-prone, misses notifications/confirmations/buttons | Use `forms-analyze-logic` instead | | Using `is_active: '0'` to pause a form | Form disappears entirely — page shows nothing | Use `scheduleForm` + `scheduleEnd` instead | | Fileupload field without `allowedExtensions`/`maxFileSize` | Accepts any file type/size — security risk | Always set `allowedExtensions` and `maxFileSize` — see field-config reference | -| Creating a form without `notifications` | Submissions saved but no email sent — admin never notified | Always include a notification object — see "Creating a Form" workflow | +| Passing `notifications: {}` on `forms-create` by habit | No email is ever sent for the form — the empty object opts out of the default Admin Notification | Omit the key to get the editor default, or pass a real notification object — see "Creating a Form" workflow | | Creating a name field without `nameFormat: "advanced"` | First/Last sub-inputs render stacked vertically instead of side-by-side | Always set `"nameFormat": "advanced"` and `"size": "large"` on name fields — see field-config reference | | Creating a phone field without an explicit `phoneFormat` (or with an invented value) | On older GF versions the field fatals when rendered (form editor and frontend); format behavior is undefined | ALWAYS set `phoneFormat` explicitly to one of the values `system-field-types` reports in `format_options` (`"standard"`, `"international"`, `"formatted"`) — see field-config reference | | Passing multiselect values as comma-separated string | Data loss when values contain commas (e.g., "Atlanta, GA") | Always pass multiselect values as an **array**: `"input_1": ["Red", "Blue"]` — see field-config reference | From f3fa5772d97891a6d78be6e4d13b13989cf820e0 Mon Sep 17 00:00:00 2001 From: Samuel Estok Date: Tue, 27 Oct 2026 13:47:15 -0700 Subject: [PATCH 09/16] docs(gravity-forms-abilities): document confirmation on notification and confirmation deletes --- change_log.txt | 1 + skills/gravity-forms-abilities/SKILL.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/change_log.txt b/change_log.txt index 3e37ffa..ad297e9 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,4 +1,5 @@ ### 1.1.3 | 2026-10-27 +- gravity-forms-abilities: Document that notifications-delete and confirmations-delete require the id echoed back as confirmation. - gravity-forms-abilities: Document that forms-create adds the editor default admin notification when notifications is omitted, and that an empty object opts out. - gravity-forms-abilities: Document that feeds-create starts feeds inactive unless is_active is true, and that feeds-update accepts is_active alone to pause or resume. - gravity-forms-abilities: Document field_values dynamic population on submissions-submit and submissions-validate. diff --git a/skills/gravity-forms-abilities/SKILL.md b/skills/gravity-forms-abilities/SKILL.md index 70b2a85..53e4218 100644 --- a/skills/gravity-forms-abilities/SKILL.md +++ b/skills/gravity-forms-abilities/SKILL.md @@ -129,7 +129,7 @@ Notifications (emails) and confirmations (the message / page / redirect shown af - A notification needs `name`, `event` (e.g. `form_submission`), `to` (an email, or a field id / routing per `toType`), `subject`, and `message` (merge tags + HTML OK). - A confirmation needs `name` and a `type`: `message` (needs `message`), `page` (needs `pageId`), or `redirect` (needs `url`). - **Update** → `notifications-update` / `confirmations-update` with the `notification_id` / `confirmation_id` and only the keys to change (partial merge; the id is immutable). The result must still satisfy the required fields above. -- **Delete** → `notifications-delete` / `confirmations-delete` by id. The form's **default confirmation cannot be deleted** (edit it instead) — every form keeps one fallback. +- **Delete** → `notifications-delete` / `confirmations-delete` by id, echoing the same id back as `confirmation` (the delete is permanent, like every other permanent delete). The form's **default confirmation cannot be deleted** (edit it instead) — every form keeps one fallback. - **Route by condition** → add a `conditionalLogic` object (`{actionType, logicType, rules}`) so a notification sends — or a confirmation shows — only on matching submissions. For notifications `actionType: "show"` means "send when matched"; the default confirmation shows when none match. See [references/conditional-logic.md](references/conditional-logic.md). Common shapes: route different emails to clinicians vs patients (two notifications, each with `conditionalLogic` on a role/type field); show a tailored thank-you page per department (conditional confirmations + the default as fallback). From 0807a8d17876fa08bb3c0ee28386a139e9d853a9 Mon Sep 17 00:00:00 2001 From: Samuel Estok Date: Tue, 27 Oct 2026 13:51:01 -0700 Subject: [PATCH 10/16] docs(gravity-forms-abilities): document routing notifications and published-page confirmations --- change_log.txt | 1 + skills/gravity-forms-abilities/SKILL.md | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/change_log.txt b/change_log.txt index ad297e9..da7ce78 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,4 +1,5 @@ ### 1.1.3 | 2026-10-27 +- gravity-forms-abilities: Document routing notifications (routing rules instead of to) and that page confirmations need a published page. - gravity-forms-abilities: Document that notifications-delete and confirmations-delete require the id echoed back as confirmation. - gravity-forms-abilities: Document that forms-create adds the editor default admin notification when notifications is omitted, and that an empty object opts out. - gravity-forms-abilities: Document that feeds-create starts feeds inactive unless is_active is true, and that feeds-update accepts is_active alone to pause or resume. diff --git a/skills/gravity-forms-abilities/SKILL.md b/skills/gravity-forms-abilities/SKILL.md index 53e4218..875adbb 100644 --- a/skills/gravity-forms-abilities/SKILL.md +++ b/skills/gravity-forms-abilities/SKILL.md @@ -126,8 +126,8 @@ Notifications (emails) and confirmations (the message / page / redirect shown af **Always read before you write.** Call `notifications-list` / `confirmations-list` first to get the `id` of the item to change (the list carries the full objects; there is no separate "get one"). - **Create** → `notifications-create` / `confirmations-create` with a settings object; the tool generates and returns the id. - - A notification needs `name`, `event` (e.g. `form_submission`), `to` (an email, or a field id / routing per `toType`), `subject`, and `message` (merge tags + HTML OK). - - A confirmation needs `name` and a `type`: `message` (needs `message`), `page` (needs `pageId`), or `redirect` (needs `url`). + - A notification needs `name`, `event` (e.g. `form_submission`), a recipient, `subject`, and `message` (merge tags + HTML OK). The recipient is `to` (an email for `toType: email`, a field id for `toType: field`) or, for `toType: routing`, a non-empty `routing` array of `{fieldId, operator, value, email}` rules with no `to` at all; every matching rule's `email` receives the notification. + - A confirmation needs `name` and a `type`: `message` (needs `message`), `page` (needs `pageId` of a **published** page; drafts and missing ids are rejected), or `redirect` (needs `url`). - **Update** → `notifications-update` / `confirmations-update` with the `notification_id` / `confirmation_id` and only the keys to change (partial merge; the id is immutable). The result must still satisfy the required fields above. - **Delete** → `notifications-delete` / `confirmations-delete` by id, echoing the same id back as `confirmation` (the delete is permanent, like every other permanent delete). The form's **default confirmation cannot be deleted** (edit it instead) — every form keeps one fallback. - **Route by condition** → add a `conditionalLogic` object (`{actionType, logicType, rules}`) so a notification sends — or a confirmation shows — only on matching submissions. For notifications `actionType: "show"` means "send when matched"; the default confirmation shows when none match. See [references/conditional-logic.md](references/conditional-logic.md). From c36bb573e6536919b3290151f82a3c9e967bb8f2 Mon Sep 17 00:00:00 2001 From: Samuel Estok Date: Tue, 27 Oct 2026 13:55:49 -0700 Subject: [PATCH 11/16] docs(gravity-forms-abilities): document form write warnings for titles and layout rows --- change_log.txt | 1 + skills/gravity-forms-abilities/SKILL.md | 4 ++-- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/change_log.txt b/change_log.txt index da7ce78..97893bc 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,4 +1,5 @@ ### 1.1.3 | 2026-10-27 +- gravity-forms-abilities: Document the warnings array on forms-create and forms-update for de-duplicated titles and layout rows over 12 columns. - gravity-forms-abilities: Document routing notifications (routing rules instead of to) and that page confirmations need a published page. - gravity-forms-abilities: Document that notifications-delete and confirmations-delete require the id echoed back as confirmation. - gravity-forms-abilities: Document that forms-create adds the editor default admin notification when notifications is omitted, and that an empty object opts out. diff --git a/skills/gravity-forms-abilities/SKILL.md b/skills/gravity-forms-abilities/SKILL.md index 875adbb..23b7929 100644 --- a/skills/gravity-forms-abilities/SKILL.md +++ b/skills/gravity-forms-abilities/SKILL.md @@ -76,7 +76,7 @@ The agent does not need to know which mode is active — the MCP client handles 1. Call `system-field-types` — discover available types and capabilities 2. Build form object with `title` and `fields` array — for `phone` fields, ALWAYS set `phoneFormat` explicitly (see the phone section below) 3. Decide on notifications — when the form object has **no `notifications` key**, `forms-create` adds the editor's default Admin Notification (`{admin_email}`, `{all_fields}`), the same as the GF admin UI. Pass your own `notifications` object to replace it, or an explicit empty object `{}` for a form that sends no email. -4. Call `forms-create` — returns `form_id` and `edit_url` +4. Call `forms-create` — returns `form_id`, `edit_url` and, when something was saved differently than asked, a `warnings` array (a title already in use is saved with a " (n)" suffix; a layout row over 12 columns wraps). Read and act on every warning; `forms-update` returns the same key. Never guess field types. `system-field-types` returns `supports_choices`, `has_inputs`, `default_inputs`, and support flags for each type. @@ -393,7 +393,7 @@ For CL structure details, operators, and common patterns, see [references/condit **Layout fields** (no data): `html`, `section`, `page` — visual only, do not collect submissions. -**Layout grid**: Control field width and row grouping with `layoutGridColumnSpan` (1–12, default full width) and `layoutGroupId` (any string — fields sharing the same value render on the same row). See [references/field-config.md](references/field-config.md) §Layout Grid for patterns and natural language mapping. +**Layout grid**: Control field width and row grouping with `layoutGridColumnSpan` (1–12, default full width) and `layoutGroupId` (any string — fields sharing the same value render on the same row). Keep each row's spans at 12 or less; a row that adds up to more saves but wraps, and the write returns a `warnings` entry naming the row. See [references/field-config.md](references/field-config.md) §Layout Grid for patterns and natural language mapping. **Pricing fields**: `product`, `option`, `quantity`, `shipping`, `total`. Product variants (single product, dropdown, calculation, hidden, user-defined price) are set via `inputType` on a `product` field — never as standalone types (`singleproduct`, `calculation`, etc. are not valid `type` values and are excluded from `system-field-types`). Choice-based products submit `value|price` (e.g. `"input_2": "Pro|30"` for a $30.00 choice). See [references/field-config.md](references/field-config.md) §Pricing Fields for the full pattern table and submission formats. From 283864da6718f22ea3dbe19318f6dbe15127d01d Mon Sep 17 00:00:00 2001 From: Samuel Estok Date: Tue, 27 Oct 2026 14:00:27 -0700 Subject: [PATCH 12/16] docs(gravity-forms-abilities): document entry timestamps and unknown field id warnings --- change_log.txt | 1 + skills/gravity-forms-abilities/references/entry-operations.md | 2 ++ 2 files changed, 3 insertions(+) diff --git a/change_log.txt b/change_log.txt index 97893bc..ee279b4 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,4 +1,5 @@ ### 1.1.3 | 2026-10-27 +- gravity-forms-abilities: Document date_created on entries-create, the date_updated stamp on entries-update, and the warnings array for unknown field ids. - gravity-forms-abilities: Document the warnings array on forms-create and forms-update for de-duplicated titles and layout rows over 12 columns. - gravity-forms-abilities: Document routing notifications (routing rules instead of to) and that page confirmations need a published page. - gravity-forms-abilities: Document that notifications-delete and confirmations-delete require the id echoed back as confirmation. diff --git a/skills/gravity-forms-abilities/references/entry-operations.md b/skills/gravity-forms-abilities/references/entry-operations.md index 8c849f8..ca76db1 100644 --- a/skills/gravity-forms-abilities/references/entry-operations.md +++ b/skills/gravity-forms-abilities/references/entry-operations.md @@ -36,6 +36,8 @@ Key format: `"{field_id}"` for simple fields, `"{field_id}.{suffix}"` for compou **These are different formats.** `submissions-submit` prefixes with `input_`. `entries-create` uses bare field IDs. +**Imports:** `entries-create` accepts `date_created` as a UTC timestamp (`YYYY-MM-DD HH:MM:SS`, or `YYYY-MM-DD`); without it the entry is stamped now. `entries-update` always sets `date_updated` to now. Both return a `warnings` array when a key names a field or input id that is not on the form; those values are not saved, so fix the ids and retry. + ### Checkbox Values Each checked choice is a separate input keyed by choice index (starting at 1): From 03a1c6c73d87fe709f92572fe1a192ca7d56d5fc Mon Sep 17 00:00:00 2001 From: Samuel Estok Date: Tue, 27 Oct 2026 14:02:36 -0700 Subject: [PATCH 13/16] docs(gravity-forms-abilities): document empty source_url on API entries --- change_log.txt | 1 + skills/gravity-forms-abilities/references/entry-operations.md | 2 ++ 2 files changed, 3 insertions(+) diff --git a/change_log.txt b/change_log.txt index ee279b4..a25cb5b 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,4 +1,5 @@ ### 1.1.3 | 2026-10-27 +- gravity-forms-abilities: Document that API-created entries store an empty source_url. - gravity-forms-abilities: Document date_created on entries-create, the date_updated stamp on entries-update, and the warnings array for unknown field ids. - gravity-forms-abilities: Document the warnings array on forms-create and forms-update for de-duplicated titles and layout rows over 12 columns. - gravity-forms-abilities: Document routing notifications (routing rules instead of to) and that page confirmations need a published page. diff --git a/skills/gravity-forms-abilities/references/entry-operations.md b/skills/gravity-forms-abilities/references/entry-operations.md index ca76db1..cc9b0a2 100644 --- a/skills/gravity-forms-abilities/references/entry-operations.md +++ b/skills/gravity-forms-abilities/references/entry-operations.md @@ -36,6 +36,8 @@ Key format: `"{field_id}"` for simple fields, `"{field_id}.{suffix}"` for compou **These are different formats.** `submissions-submit` prefixes with `input_`. `entries-create` uses bare field IDs. +**Entry metadata for API entries:** `source_url` is empty, because the entry has no embedding page; `ip` and `user_agent` describe the API caller. + **Imports:** `entries-create` accepts `date_created` as a UTC timestamp (`YYYY-MM-DD HH:MM:SS`, or `YYYY-MM-DD`); without it the entry is stamped now. `entries-update` always sets `date_updated` to now. Both return a `warnings` array when a key names a field or input id that is not on the form; those values are not saved, so fix the ids and retry. ### Checkbox Values From 3c21c7db0bf67c797d6461b96f635b2220740c07 Mon Sep 17 00:00:00 2001 From: Samuel Estok Date: Tue, 27 Oct 2026 14:05:34 -0700 Subject: [PATCH 14/16] docs(gravity-forms-abilities): document submit guards for files, form state, and the speed check --- change_log.txt | 1 + skills/gravity-forms-abilities/SKILL.md | 4 +++- 2 files changed, 4 insertions(+), 1 deletion(-) diff --git a/change_log.txt b/change_log.txt index a25cb5b..e7bff6e 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,4 +1,5 @@ ### 1.1.3 | 2026-10-27 +- gravity-forms-abilities: Document that submissions refuse file upload values, name inactive and trashed forms, and that the speed check does not run for API submissions. - gravity-forms-abilities: Document that API-created entries store an empty source_url. - gravity-forms-abilities: Document date_created on entries-create, the date_updated stamp on entries-update, and the warnings array for unknown field ids. - gravity-forms-abilities: Document the warnings array on forms-create and forms-update for de-duplicated titles and layout rows over 12 columns. diff --git a/skills/gravity-forms-abilities/SKILL.md b/skills/gravity-forms-abilities/SKILL.md index 23b7929..32900e4 100644 --- a/skills/gravity-forms-abilities/SKILL.md +++ b/skills/gravity-forms-abilities/SKILL.md @@ -147,6 +147,8 @@ For most compound fields (name, address), use dot-notation sub-input keys: `inpu For **multiselect fields**, pass values as an array: `"input_3": ["Red", "Blue"]`. Never use comma-separated strings — values containing commas cause data loss. +**Form state and anti-spam:** an inactive form answers `gf_ability_form_inactive` and a trashed form `gf_ability_form_trashed`; schedule and entry-limit blocks come back as plain-text errors. The honeypot still runs for API submissions, but the submit speed check (`enableSubmitSpeedCheck`) cannot: no page was rendered, so there is no timing to compare. File upload fields cannot receive a value (see Field Configuration). + **Dynamic population:** `field_values` is keyed by parameter name (a field's `inputName`, or a sub-input's `name`), e.g. `"field_values": {"promo": "SPRING26"}`. It fills fields that have `allowsPrepopulate: true` when `input_values` carries no value for them; an explicit `input_values` entry always wins. `submissions-validate` accepts it too. **`submissions-submit` vs `entries-create`:** @@ -387,7 +389,7 @@ For CL structure details, operators, and common patterns, see [references/condit **Compound fields** (`has_inputs: true`): `name`, `address`, `time`, `consent`, `product` (single product) and `checkbox` — store values across sub-inputs with ID suffixes. Call `system-field-types` to see `default_inputs` for exact suffix mappings; `checkbox` has `inputs_per_choice: true` (one sub-input per choice, `{field_id}.{n}`, n skips multiples of 10), and types whose inputs depend on configuration (`product`, `date`, `multi_choice`, `image_choice`) carry an `inputs_note`. **Name fields require `"nameFormat": "advanced"` and `"size": "large"`** — without these, sub-inputs render stacked instead of side-by-side. -**File upload fields**: `fileupload` — configure `allowedExtensions` (comma-separated, no dots), `maxFileSize` (MB), `maxFiles`, `multipleFiles`. These properties are NOT returned by `system-field-types` — see [references/field-config.md](references/field-config.md) for full type-specific config reference. File upload fields can be configured via abilities, but actual file submission requires the rendered form (MCP cannot transport binary data). +**File upload fields**: `fileupload` — configure `allowedExtensions` (comma-separated, no dots), `maxFileSize` (MB), `maxFiles`, `multipleFiles`. These properties are NOT returned by `system-field-types` — see [references/field-config.md](references/field-config.md) for full type-specific config reference. File upload fields can be configured via abilities, but actual file submission requires the rendered form (MCP cannot transport binary data). `submissions-submit` and `submissions-validate` refuse any non-empty value for a file upload field with `gf_ability_unsupported_input`; leave the field out. **Consent fields**: `consent` — GDPR-style checkbox with `checkboxLabel` (the agreement text next to the checkbox) and `description` (longer explanatory text below). Always set `isRequired: true` for GDPR compliance. See [references/field-config.md](references/field-config.md) for examples. From 203e5ef43b2041e72464af2a45cf4149e8fc16db Mon Sep 17 00:00:00 2001 From: Samuel Estok Date: Tue, 27 Oct 2026 14:12:36 -0700 Subject: [PATCH 15/16] docs(gravity-forms-abilities): add an API conventions section --- change_log.txt | 1 + skills/gravity-forms-abilities/SKILL.md | 10 ++++++++++ 2 files changed, 11 insertions(+) diff --git a/change_log.txt b/change_log.txt index e7bff6e..cbc8fb0 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,4 +1,5 @@ ### 1.1.3 | 2026-10-27 +- gravity-forms-abilities: Add an API Conventions section covering id types, not-found behavior, count keys, plain-text errors, delete confirmations, annotations and warnings. - gravity-forms-abilities: Document that submissions refuse file upload values, name inactive and trashed forms, and that the speed check does not run for API submissions. - gravity-forms-abilities: Document that API-created entries store an empty source_url. - gravity-forms-abilities: Document date_created on entries-create, the date_updated stamp on entries-update, and the warnings array for unknown field ids. diff --git a/skills/gravity-forms-abilities/SKILL.md b/skills/gravity-forms-abilities/SKILL.md index 32900e4..28c3268 100644 --- a/skills/gravity-forms-abilities/SKILL.md +++ b/skills/gravity-forms-abilities/SKILL.md @@ -406,3 +406,13 @@ For detailed field type tables, compound field suffix mappings, and form design For entry search filters, input value formatting, and submission examples, see [references/entry-operations.md](references/entry-operations.md). For conditional logic structure, operators, dependency maps, and CL modification patterns, see [references/conditional-logic.md](references/conditional-logic.md). + +## API Conventions + +- **IDs.** Form, entry and feed ids are integers. Notification and confirmation ids are strings (generated hex, or the key you supplied). Field ids are integers on the form and strings inside conditional logic rules. +- **Not found.** Every ability answers a missing form, entry, feed, notification or confirmation with the error code `gf_ability_not_found`, including the list calls when you name a specific form or entry (`entries-search` with `form_ids`, `feeds-list` with `form_id`, `notes-list`). An empty list means the record exists and has nothing in it. +- **Counts.** `entries-count` returns `count` for one form and `total` plus per-form `counts` for several; `entries-search` returns `total_count` beside the page of entries. The keys differ by shape on purpose and will not be renamed. +- **Errors are plain text.** Schedule, entry-limit and other pipeline messages arrive without HTML. +- **Permanent deletes echo the id.** `forms-delete` (title), `entries-delete`, `feeds-delete`, `notifications-delete` and `confirmations-delete` all take a `confirmation` that repeats the identifier; bulk entry deletes use the `DELETE {count} ENTRIES FROM FORM {form_id}` phrase. +- **Annotations.** Read-only tools carry `readonly: true` (including `submissions-validate`). Creates, sends and submits are writes but not `destructive`; updates and deletes are `destructive`. +- **Warnings.** `forms-create`, `forms-update`, `entries-create` and `entries-update` may return a `warnings` array for things saved differently than asked. Treat each entry as an action item. From 06e7d9a0becaec54e744b69ec8824a204375bfad Mon Sep 17 00:00:00 2001 From: Samuel Estok Date: Wed, 28 Oct 2026 08:42:27 -0700 Subject: [PATCH 16/16] docs(gravity-forms-abilities): document that a changed inputType is a replacement on forms-update --- change_log.txt | 1 + skills/gravity-forms-abilities/SKILL.md | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/change_log.txt b/change_log.txt index cbc8fb0..c745235 100644 --- a/change_log.txt +++ b/change_log.txt @@ -1,4 +1,5 @@ ### 1.1.3 | 2026-10-27 +- gravity-forms-abilities: Document that a changed inputType on forms-update is a replacement, like a changed type, so inputs from the old shape are not kept. - gravity-forms-abilities: Add an API Conventions section covering id types, not-found behavior, count keys, plain-text errors, delete confirmations, annotations and warnings. - gravity-forms-abilities: Document that submissions refuse file upload values, name inactive and trashed forms, and that the speed check does not run for API submissions. - gravity-forms-abilities: Document that API-created entries store an empty source_url. diff --git a/skills/gravity-forms-abilities/SKILL.md b/skills/gravity-forms-abilities/SKILL.md index 28c3268..02d22f5 100644 --- a/skills/gravity-forms-abilities/SKILL.md +++ b/skills/gravity-forms-abilities/SKILL.md @@ -113,7 +113,7 @@ Use `{admin_email}` for site admin, or a specific address. `{all_fields}` render 2. Modify the returned fields array (add/remove/change) 3. Call `forms-update` with the complete form object -**Which fields exist is replaced; a field's properties are merged.** A submitted field whose `id` matches a stored field of the same `type` keeps every stored property you did not resend (`inputs`, `size`, `productField`, `validateState`, ...). Send a property as an empty value (`""`, `[]`) to clear it. A field with a changed `type` is a replacement and inherits nothing. Fields without an `id` are new. +**Which fields exist is replaced; a field's properties are merged.** A submitted field whose `id` matches a stored field of the same `type` keeps every stored property you did not resend (`inputs`, `size`, `productField`, `validateState`, ...). Send a property as an empty value (`""`, `[]`) to clear it. A field with a changed `type` or `inputType` is a replacement: it inherits nothing and gets the editor defaults for its new shape (a Single Product changed to a Drop Down loses its Name/Price/Quantity `inputs`). Fields without an `id` are new. **Field IDs can be reused after a delete.** Like the form editor, Gravity Forms computes the next field ID from the highest ID currently on the form. Within one `forms-update` call new fields always get IDs above every stored ID, but if you remove the highest field in one call and add an ID-less field in a later call, the new field takes the old ID. Entry values and conditional-logic rules from the removed field then attach to the new one. To avoid it: remove and add in the same call, or give the new field an explicit `id` above the old maximum, and check `forms-analyze-logic` for rules that point at removed fields.