shortcuts-playground 1.2.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (68) hide show
  1. package/README.md +54 -0
  2. package/agents/shortcut-builder.md +172 -0
  3. package/agents/shortcut-remixer.md +239 -0
  4. package/commands/build-shortcut.md +32 -0
  5. package/commands/remix-shortcut.md +34 -0
  6. package/opencode.json +30 -0
  7. package/package.json +47 -0
  8. package/plugin/validator.ts +179 -0
  9. package/skills/shortcuts-playground/ACTIONS.md +713 -0
  10. package/skills/shortcuts-playground/APPINTENTS.md +2760 -0
  11. package/skills/shortcuts-playground/AUTOMATION_TRIGGERS.md +133 -0
  12. package/skills/shortcuts-playground/BEST_PRACTICES.md +357 -0
  13. package/skills/shortcuts-playground/CHANGELOG.md +585 -0
  14. package/skills/shortcuts-playground/CONTROL_FLOW.md +777 -0
  15. package/skills/shortcuts-playground/DATE_TIME.md +75 -0
  16. package/skills/shortcuts-playground/EXAMPLES.md +738 -0
  17. package/skills/shortcuts-playground/FILTERS.md +697 -0
  18. package/skills/shortcuts-playground/HEALTHKIT.md +317 -0
  19. package/skills/shortcuts-playground/ICONS_AND_COLORS.md +89 -0
  20. package/skills/shortcuts-playground/JAVASCRIPT_WEBPAGE.md +51 -0
  21. package/skills/shortcuts-playground/PARAMETER_TYPES.md +1117 -0
  22. package/skills/shortcuts-playground/PLIST_FORMAT.md +296 -0
  23. package/skills/shortcuts-playground/README.md +77 -0
  24. package/skills/shortcuts-playground/SKILL.md +459 -0
  25. package/skills/shortcuts-playground/THIRD_PARTY_ACTIONS.md +77 -0
  26. package/skills/shortcuts-playground/TOOLKIT_SNAPSHOT.md +62 -0
  27. package/skills/shortcuts-playground/URL_SCHEMES.md +59 -0
  28. package/skills/shortcuts-playground/VARIABLES.md +569 -0
  29. package/skills/shortcuts-playground/assets/shortcuts-small.svg +14 -0
  30. package/skills/shortcuts-playground/assets/shortcuts.png +0 -0
  31. package/skills/shortcuts-playground/data/healthkit-ios26.2-reference.json +2603 -0
  32. package/skills/shortcuts-playground/data/macos27-shortpy-grounding.json +4085 -0
  33. package/skills/shortcuts-playground/data/macos27-workflow-trigger-samples.json +1 -0
  34. package/skills/shortcuts-playground/data/shortcuts-glyph-synonyms.json +5102 -0
  35. package/skills/shortcuts-playground/data/shortcuts-icon-colors.json +107 -0
  36. package/skills/shortcuts-playground/data/shortcuts-official-glyph-mapping.json +509 -0
  37. package/skills/shortcuts-playground/data/toolkit-v63-tool-ids.json +1806 -0
  38. package/skills/shortcuts-playground/data/toolkit-v78-first-party-enum-cases.json +1 -0
  39. package/skills/shortcuts-playground/data/toolkit-v78-first-party-parameter-keys.json +1 -0
  40. package/skills/shortcuts-playground/data/toolkit-v78-ios27-tool-ids.json +1222 -0
  41. package/skills/shortcuts-playground/data/toolkit-v78-tool-ids.json +2745 -0
  42. package/skills/shortcuts-playground/data/toolkit-v78-trigger-parameter-keys.json +1051 -0
  43. package/skills/shortcuts-playground/golden-shortcuts/index.jsonl +19 -0
  44. package/skills/shortcuts-playground/golden-shortcuts/xml/1be4dde95b794253bf82438e201b33e7.xml +174 -0
  45. package/skills/shortcuts-playground/golden-shortcuts/xml/2e0fb675e45948aaacee7e534f910492.xml +1016 -0
  46. package/skills/shortcuts-playground/golden-shortcuts/xml/332c12a0060043b388b22b806be7ab58.xml +1924 -0
  47. package/skills/shortcuts-playground/golden-shortcuts/xml/3dd4ee24e43f464f92adaa70a0311eaa.xml +1177 -0
  48. package/skills/shortcuts-playground/golden-shortcuts/xml/4d102301c6e646faa7a8a221f4f4ec98.xml +321 -0
  49. package/skills/shortcuts-playground/golden-shortcuts/xml/51cc4e26d1044893a0c3f2f3630cf2d2.xml +1933 -0
  50. package/skills/shortcuts-playground/golden-shortcuts/xml/623e7f1ca5f948e2bd53811fec63e544.xml +136 -0
  51. package/skills/shortcuts-playground/golden-shortcuts/xml/6a18b76843ac45c384ac3400f3740997.xml +1791 -0
  52. package/skills/shortcuts-playground/golden-shortcuts/xml/71f0cacb0f604b399b76c5dcb7286e7c.xml +2228 -0
  53. package/skills/shortcuts-playground/golden-shortcuts/xml/807525ed9f974829bc8494defac923a8.xml +259 -0
  54. package/skills/shortcuts-playground/golden-shortcuts/xml/8ab0d39826ab4249be58672763caa3ba.xml +420 -0
  55. package/skills/shortcuts-playground/golden-shortcuts/xml/91c45fd3fd3b427897d9ba485efb1227.xml +800 -0
  56. package/skills/shortcuts-playground/golden-shortcuts/xml/97be626bb25c41709d175646a7f6d8f2.xml +424 -0
  57. package/skills/shortcuts-playground/golden-shortcuts/xml/ae59e10d409348f9bd33894f03f9beb4.xml +568 -0
  58. package/skills/shortcuts-playground/golden-shortcuts/xml/afa83b6be811483b9c32189c41eb9312.xml +391 -0
  59. package/skills/shortcuts-playground/golden-shortcuts/xml/cfdb083b857e4ac189629fa386d27cdc.xml +193 -0
  60. package/skills/shortcuts-playground/golden-shortcuts/xml/e01cebe192d64b2fbca80204d03d92ab.xml +111 -0
  61. package/skills/shortcuts-playground/golden-shortcuts/xml/ef669bcf8bad489d9ef4b88bfaf5772f.xml +780 -0
  62. package/skills/shortcuts-playground/golden-shortcuts/xml/f44f5caf5e3e48d4817e73af450c4404.xml +570 -0
  63. package/skills/shortcuts-playground/scripts/generate_healthkit_reference.py +394 -0
  64. package/skills/shortcuts-playground/scripts/lookup_action_grounding.py +1164 -0
  65. package/skills/shortcuts-playground/scripts/select_shortcut_icon_color.py +597 -0
  66. package/skills/shortcuts-playground/scripts/test_random_mixed_shortcuts.py +1067 -0
  67. package/skills/shortcuts-playground/scripts/test_wiring_regressions.py +2247 -0
  68. package/skills/shortcuts-playground/scripts/validate_shortcut.py +4526 -0
@@ -0,0 +1,1117 @@
1
+ # Parameter Types Reference
2
+
3
+ Complete documentation of all parameter value types used in iOS Shortcuts.
4
+
5
+ Based on analysis of 200 real-world shortcuts containing 338 unique actions and 543 parameter keys.
6
+
7
+ ---
8
+
9
+ ## Serialization Types
10
+
11
+ These are the `WFSerializationType` values that indicate how complex values are encoded:
12
+
13
+ | Serialization Type | Description | Use Case |
14
+ |--------------------|-------------|----------|
15
+ | `WFTextTokenString` | Text with embedded variable references | Text fields that can contain variables |
16
+ | `WFTextTokenAttachment` | Single variable reference | Input parameters referencing other actions |
17
+ | `WFDictionaryFieldValue` | Dictionary with key-value pairs | HTTP headers, JSON bodies |
18
+ | `WFContentPredicateTableTemplate` | Filter conditions | Find/Filter actions |
19
+ | `WFQuantityFieldValue` | Measurement with unit | Duration, file size, etc. |
20
+ | `WFContactFieldValue` | Contact field reference | Contact properties |
21
+ | `WFTimeOffsetValue` | Time offset/duration | Time adjustments |
22
+
23
+ ---
24
+
25
+ ## Basic Value Types
26
+
27
+ ### String
28
+ Simple text value:
29
+ ```xml
30
+ <key>WFMenuPrompt</key>
31
+ <string>Choose an option</string>
32
+ ```
33
+
34
+ ### Integer
35
+ Whole number:
36
+ ```xml
37
+ <key>WFControlFlowMode</key>
38
+ <integer>0</integer>
39
+ ```
40
+
41
+ ### Number (Float)
42
+ Decimal number:
43
+ ```xml
44
+ <key>WFNumberActionNumber</key>
45
+ <real>30.0</real>
46
+ ```
47
+
48
+ ### Boolean
49
+ True/false (CRITICAL: always use `<true/>` or `<false/>`, never strings or integers):
50
+ ```xml
51
+ <key>WFShowWorkflow</key>
52
+ <true/>
53
+ ```
54
+
55
+ or
56
+
57
+ ```xml
58
+ <key>WFShowWorkflow</key>
59
+ <false/>
60
+ ```
61
+
62
+ **Important:** Never use `<string>true</string>` or `<integer>1</integer>` for boolean values.
63
+
64
+ ### Array
65
+ List of values:
66
+ ```xml
67
+ <key>WFMenuItems</key>
68
+ <array>
69
+ <string>Option 1</string>
70
+ <string>Option 2</string>
71
+ </array>
72
+ ```
73
+
74
+ ### Data
75
+ Binary data (base64 in XML):
76
+ ```xml
77
+ <key>WFData</key>
78
+ <data>BASE64_ENCODED_DATA</data>
79
+ ```
80
+
81
+ ---
82
+
83
+ ## Date and Time Format Styles
84
+
85
+ ### WFDateFormatStyle
86
+
87
+ Used by Format Date action to specify the date format:
88
+
89
+ | Value | Description |
90
+ |-------|-------------|
91
+ | `Custom` | Use a custom format string |
92
+ | `Short` | Short format (e.g., "3/24/26") |
93
+ | `Medium` | Medium format (e.g., "Mar 24, 2026") |
94
+ | `Long` | Long format (e.g., "March 24, 2026") |
95
+ | `None` | No date component (time only) |
96
+
97
+ For `is.workflow.actions.format.date` custom formats, set `WFDateFormatStyle=Custom`, set `WFDateFormat=Custom`, and put the custom pattern in `WFDateFormatString` (for example, `MMMM d, yyyy`, `yyyy-MM-dd`, or `yyyy-MM-dd'T'HH:mm:ssXXXXX`). Custom patterns use Unicode Technical Standard #35 date field symbols; see `DATE_TIME.md`.
98
+
99
+ ### WFTimeFormatStyle
100
+
101
+ Used for time-only formatting:
102
+
103
+ | Value | Description |
104
+ |-------|-------------|
105
+ | `Short` | Short time format (e.g., "2:30 PM") |
106
+ | `Medium` | Medium time format (e.g., "2:30:45 PM") |
107
+ | `Long` | Long time format with timezone |
108
+ | `None` | No time component (date only) |
109
+
110
+ ---
111
+
112
+ ## Variable Reference Types
113
+
114
+ ### WFTextTokenAttachment (Single Variable Reference)
115
+
116
+ Used when a parameter accepts a single variable/output reference:
117
+
118
+ ```xml
119
+ <key>WFInput</key>
120
+ <dict>
121
+ <key>Value</key>
122
+ <dict>
123
+ <key>OutputName</key>
124
+ <string>Photos</string>
125
+ <key>OutputUUID</key>
126
+ <string>F2BEAE11-3F38-40C3-AD1F-FD48D90F9FE2</string>
127
+ <key>Type</key>
128
+ <string>ActionOutput</string>
129
+ </dict>
130
+ <key>WFSerializationType</key>
131
+ <string>WFTextTokenAttachment</string>
132
+ </dict>
133
+ ```
134
+
135
+ ### WFTextTokenString (Text with Variables)
136
+
137
+ Used for text fields that can contain embedded variables:
138
+
139
+ ```xml
140
+ <key>Text</key>
141
+ <dict>
142
+ <key>Value</key>
143
+ <dict>
144
+ <key>attachmentsByRange</key>
145
+ <dict>
146
+ <key>{0, 1}</key>
147
+ <dict>
148
+ <key>OutputName</key>
149
+ <string>Text</string>
150
+ <key>OutputUUID</key>
151
+ <string>A1B2C3D4-E5F6-7890-ABCD-EF1234567890</string>
152
+ <key>Type</key>
153
+ <string>ActionOutput</string>
154
+ </dict>
155
+ </dict>
156
+ <key>string</key>
157
+ <string></string>
158
+ </dict>
159
+ <key>WFSerializationType</key>
160
+ <string>WFTextTokenString</string>
161
+ </dict>
162
+ ```
163
+
164
+ Key points:
165
+ - `` (U+FFFC) is the placeholder character
166
+ - `{0, 1}` means "at position 0, length 1"
167
+ - Multiple variables: `"Hello , you have  messages"` with `{6, 1}` and `{22, 1}`
168
+
169
+ **When to use WFTextTokenString vs WFTextTokenAttachment (runtime-verified):**
170
+
171
+ | Context | Use This | Why |
172
+ |---------|----------|-----|
173
+ | Display parameter with variable (Show Alert message, Notification body, Show Result text) | `WFTextTokenString` | Runtime requires `` + `attachmentsByRange` for UI display fields |
174
+ | Text containing mixed literals and variables | `WFTextTokenString` | Multiple insertion points need position-mapped placeholders |
175
+ | Single variable as data input (WFInput, WFDate, etc.) | `WFTextTokenAttachment` | Simpler structure for non-display data flow |
176
+ | Action input parameter IS a variable | `WFTextTokenAttachment` | Parameter is purely a variable reference |
177
+
178
+ ---
179
+
180
+ ## Dictionary Field Value
181
+
182
+ Used for HTTP headers, JSON bodies, and form data:
183
+
184
+ ```xml
185
+ <key>WFHTTPHeaders</key>
186
+ <dict>
187
+ <key>Value</key>
188
+ <dict>
189
+ <key>WFDictionaryFieldValueItems</key>
190
+ <array>
191
+ <dict>
192
+ <key>WFItemType</key>
193
+ <integer>0</integer>
194
+ <key>WFKey</key>
195
+ <dict>
196
+ <key>Value</key>
197
+ <dict>
198
+ <key>string</key>
199
+ <string>Content-Type</string>
200
+ </dict>
201
+ <key>WFSerializationType</key>
202
+ <string>WFTextTokenString</string>
203
+ </dict>
204
+ <key>WFValue</key>
205
+ <dict>
206
+ <key>Value</key>
207
+ <dict>
208
+ <key>string</key>
209
+ <string>application/json</string>
210
+ </dict>
211
+ <key>WFSerializationType</key>
212
+ <string>WFTextTokenString</string>
213
+ </dict>
214
+ </dict>
215
+ </array>
216
+ </dict>
217
+ <key>WFSerializationType</key>
218
+ <string>WFDictionaryFieldValue</string>
219
+ </dict>
220
+ ```
221
+
222
+ ### WFItemType Values
223
+
224
+ | Value | Type |
225
+ |-------|------|
226
+ | 0 | Text/String |
227
+ | 1 | Number |
228
+ | 2 | Array |
229
+ | 3 | Dictionary |
230
+ | 4 | Boolean |
231
+
232
+ ---
233
+
234
+ ### Arrays in WFDictionaryFieldValue
235
+
236
+ When `WFItemType = 2` (Array), `WFValue` uses `WFArrayParameterState` with a list of items. Do not encode arrays as dictionaries with numeric keys; it can crash imports.
237
+
238
+ ```xml
239
+ <dict>
240
+ <key>WFItemType</key>
241
+ <integer>2</integer>
242
+ <key>WFKey</key>
243
+ <dict>
244
+ <key>Value</key>
245
+ <dict>
246
+ <key>string</key>
247
+ <string>labels</string>
248
+ </dict>
249
+ <key>WFSerializationType</key>
250
+ <string>WFTextTokenString</string>
251
+ </dict>
252
+ <key>WFValue</key>
253
+ <dict>
254
+ <key>Value</key>
255
+ <array>
256
+ <dict>
257
+ <key>WFItemType</key>
258
+ <integer>0</integer>
259
+ <key>WFValue</key>
260
+ <dict>
261
+ <key>Value</key>
262
+ <dict>
263
+ <key>string</key>
264
+ <string>example</string>
265
+ </dict>
266
+ <key>WFSerializationType</key>
267
+ <string>WFTextTokenString</string>
268
+ </dict>
269
+ </dict>
270
+ </array>
271
+ <key>WFSerializationType</key>
272
+ <string>WFArrayParameterState</string>
273
+ </dict>
274
+ </dict>
275
+ ```
276
+
277
+ ---
278
+
279
+ ## Content Filter (WFContentPredicateTableTemplate)
280
+
281
+ Used by all Find/Filter actions. See [FILTERS.md](./FILTERS.md) for complete documentation.
282
+
283
+ For `is.workflow.actions.filter.health.quantity`, the Health sample type is a locked content predicate row: `Property` `Type`, `Operator` `4`, `Bounded` true, `Removable` false, and `Values.Enumeration` set to a `WFStringSubstitutableState` whose `Value` is the Find Health Samples picker label such as `Steps`, `Sleep`, or `Exercise Minutes`. Do not emit top-level `WFHealthQuantityType`; it imports as an inert field. Do not use `Property` `Value` plus `Values.String`; it imports as an editable text filter instead of the Health type picker.
284
+
285
+ Actions that use content filters:
286
+ - `is.workflow.actions.filter.photos`
287
+ - `is.workflow.actions.filter.files`
288
+ - `is.workflow.actions.filter.reminders`
289
+ - `is.workflow.actions.filter.calendarevents`
290
+ - `is.workflow.actions.filter.contacts`
291
+ - `is.workflow.actions.filter.notes`
292
+ - `is.workflow.actions.filter.music`
293
+ - `is.workflow.actions.filter.articles`
294
+ - `is.workflow.actions.filter.apps`
295
+ - `is.workflow.actions.filter.health.quantity`
296
+ - `is.workflow.actions.conditional` (via `WFConditions`)
297
+
298
+ ---
299
+
300
+ ## Quantity Field Value
301
+
302
+ Used for measurements with units (duration, file size, etc.):
303
+
304
+ ```xml
305
+ <key>WFDuration</key>
306
+ <dict>
307
+ <key>Value</key>
308
+ <dict>
309
+ <key>Magnitude</key>
310
+ <real>5.0</real>
311
+ <key>Unit</key>
312
+ <string>min</string>
313
+ </dict>
314
+ <key>WFSerializationType</key>
315
+ <string>WFQuantityFieldValue</string>
316
+ </dict>
317
+ ```
318
+
319
+ ### Common Units
320
+
321
+ | Category | Units |
322
+ |----------|-------|
323
+ | Time | `sec`, `min`, `hr`, `days` |
324
+ | Data | `bytes`, `KB`, `MB`, `GB` |
325
+ | Length | `m`, `km`, `ft`, `mi` |
326
+
327
+ ### HealthKit Quantity Fields
328
+
329
+ Verified from bundled anonymized iOS Shortcuts XML examples and ActionKit `WFHealthKitConstants.plist`.
330
+
331
+ For **Log Health Sample**, the main value uses `WFQuantitySampleQuantity`:
332
+
333
+ ```xml
334
+ <key>WFQuantitySampleQuantity</key>
335
+ <dict>
336
+ <key>Value</key>
337
+ <dict>
338
+ <key>Magnitude</key>
339
+ <string>120</string>
340
+ <key>Unit</key>
341
+ <string>mg</string>
342
+ </dict>
343
+ <key>WFSerializationType</key>
344
+ <string>WFQuantityFieldValue</string>
345
+ </dict>
346
+ ```
347
+
348
+ The bundled Caffeine, Bloating, and Cervical Mucus Quality XML examples also include `WFQuantitySampleAdditionalQuantity`; it can be unit-only:
349
+
350
+ ```xml
351
+ <key>WFQuantitySampleAdditionalQuantity</key>
352
+ <dict>
353
+ <key>Value</key>
354
+ <dict>
355
+ <key>Unit</key>
356
+ <string>mg</string>
357
+ </dict>
358
+ <key>WFSerializationType</key>
359
+ <string>WFQuantityFieldValue</string>
360
+ </dict>
361
+ ```
362
+
363
+ Category values can additionally include `WFCategorySampleEnumeration`:
364
+
365
+ ```xml
366
+ <key>WFQuantitySampleType</key>
367
+ <string>Cervical Mucus Quality</string>
368
+ <key>WFCategorySampleEnumeration</key>
369
+ <string>Dry</string>
370
+ ```
371
+
372
+ Health date fields such as `WFQuantitySampleDate`, `WFSampleEndDate`, and `WFWorkoutDate` accept token attachments; `{Type: CurrentDate}` is valid:
373
+
374
+ ```xml
375
+ <key>WFQuantitySampleDate</key>
376
+ <dict>
377
+ <key>Value</key>
378
+ <dict>
379
+ <key>Type</key>
380
+ <string>CurrentDate</string>
381
+ </dict>
382
+ <key>WFSerializationType</key>
383
+ <string>WFTextTokenAttachment</string>
384
+ </dict>
385
+ ```
386
+
387
+ ActionKit Health unit strings currently covered by the regression suite:
388
+
389
+ `g`, `m`, `L`, `Pa`, `s`, `J`, `K`, `S`, `mg`, `kg`, `mm`, `km`, `mL`, `kPa`, `ms`, `kJ`, `kK`, `mS`, `kS`, `oz`, `lb`, `st`, `in`, `ft`, `mi`, `mmHg`, `cmAq`, `atm`, `fl_oz_us`, `fl_oz_imp`, `pt_us`, `pt_imp`, `min`, `hr`, `d`, `cal`, `kcal`, `degC`, `degF`, `count`, `%`, `count/min`, `mg/dl`, `J/s`, `m/s^2`, `m/s`.
390
+
391
+ ---
392
+
393
+ ## Named Variable Reference
394
+
395
+ For accessing named variables (not action outputs):
396
+
397
+ ```xml
398
+ <key>WFVariable</key>
399
+ <dict>
400
+ <key>Value</key>
401
+ <dict>
402
+ <key>Type</key>
403
+ <string>Variable</string>
404
+ <key>VariableName</key>
405
+ <string>myVariable</string>
406
+ </dict>
407
+ <key>WFSerializationType</key>
408
+ <string>WFTextTokenAttachment</string>
409
+ </dict>
410
+ ```
411
+
412
+ ---
413
+
414
+ ## Special Input Types
415
+
416
+ ### Magic Variable (Shortcut Input)
417
+
418
+ Reference the shortcut's input:
419
+ ```xml
420
+ <key>WFInput</key>
421
+ <dict>
422
+ <key>Value</key>
423
+ <dict>
424
+ <key>Type</key>
425
+ <string>ExtensionInput</string>
426
+ </dict>
427
+ <key>WFSerializationType</key>
428
+ <string>WFTextTokenAttachment</string>
429
+ </dict>
430
+ ```
431
+
432
+ ### Current Date
433
+
434
+ ```xml
435
+ <key>WFDate</key>
436
+ <dict>
437
+ <key>Value</key>
438
+ <dict>
439
+ <key>Type</key>
440
+ <string>CurrentDate</string>
441
+ </dict>
442
+ <key>WFSerializationType</key>
443
+ <string>WFTextTokenAttachment</string>
444
+ </dict>
445
+ ```
446
+
447
+ ### Clipboard
448
+
449
+ ```xml
450
+ <key>WFInput</key>
451
+ <dict>
452
+ <key>Value</key>
453
+ <dict>
454
+ <key>Type</key>
455
+ <string>Clipboard</string>
456
+ </dict>
457
+ <key>WFSerializationType</key>
458
+ <string>WFTextTokenAttachment</string>
459
+ </dict>
460
+ ```
461
+
462
+ ### Current App
463
+
464
+ Reference the currently active application:
465
+ ```xml
466
+ <key>WFInput</key>
467
+ <dict>
468
+ <key>Value</key>
469
+ <dict>
470
+ <key>Type</key>
471
+ <string>CurrentApp</string>
472
+ </dict>
473
+ <key>WFSerializationType</key>
474
+ <string>WFTextTokenAttachment</string>
475
+ </dict>
476
+ ```
477
+
478
+ Note: Returns app metadata. Use `WFPropertyVariableAggrandizement` to access specific properties like name or bundle ID.
479
+
480
+ ---
481
+
482
+ ## App Identifier
483
+
484
+ For actions that reference apps:
485
+
486
+ ```xml
487
+ <key>WFAppIdentifier</key>
488
+ <string>com.apple.safari</string>
489
+ ```
490
+
491
+ Or with full app info:
492
+ ```xml
493
+ <key>WFApp</key>
494
+ <dict>
495
+ <key>BundleIdentifier</key>
496
+ <string>com.apple.mobilesafari</string>
497
+ <key>Name</key>
498
+ <string>Safari</string>
499
+ <key>TeamIdentifier</key>
500
+ <string>0000000000</string>
501
+ </dict>
502
+ ```
503
+
504
+ ---
505
+
506
+ ## Parameter Patterns by Action Type
507
+
508
+ ### Text Actions
509
+ | Parameter | Type |
510
+ |-----------|------|
511
+ | `WFTextActionText` | string or WFTextTokenString |
512
+ | `Text` | string or WFTextTokenString |
513
+
514
+ ### Control Flow Actions
515
+ | Parameter | Type |
516
+ |-----------|------|
517
+ | `GroupingIdentifier` | string (UUID) |
518
+ | `WFControlFlowMode` | integer (0=start, 1=middle, 2=end) |
519
+
520
+ ### Input Parameters
521
+ | Parameter | Type |
522
+ |-----------|------|
523
+ | `WFInput` | WFTextTokenAttachment |
524
+ | `WFVariable` | WFTextTokenAttachment (named variable) |
525
+
526
+ **Count action note**: For `is.workflow.actions.count`, set both `WFInput` and `Input` to the same variable so the UI shows the selected list.
527
+
528
+ ### Photo Actions
529
+ | Parameter | Type | Notes |
530
+ |-----------|------|-------|
531
+ | `WFContentItemFilter` | WFContentPredicateTableTemplate | Filter conditions |
532
+ | `photos` | WFTextTokenAttachment | **DeletePhotos uses lowercase `photos`!** |
533
+ | `WFPhotoCount` | integer | Number of photos |
534
+
535
+ ### HTTP Actions
536
+ | Parameter | Type |
537
+ |-----------|------|
538
+ | `WFURL` | string, WFTextTokenString, or WFTextTokenAttachment |
539
+ | `WFHTTPMethod` | string (`GET`, `POST`, `PUT`, `DELETE`) |
540
+ | `WFHTTPBodyType` | string (`JSON`, `Form`, `File`) |
541
+ | `WFHTTPHeaders` | WFDictionaryFieldValue |
542
+ | `WFJSONValues` | WFDictionaryFieldValue |
543
+ | `WFFormValues` | WFDictionaryFieldValue |
544
+
545
+ ---
546
+
547
+ #### HTTP Notes
548
+
549
+ - **WFURL variables**: For `WFURL` parameters (especially `downloadurl`), prefer `WFTextTokenString` with `` placeholders even when the URL is entirely a variable. `WFTextTokenAttachment` is rare for `WFURL` and can crash imports.
550
+ - **JSON bodies**: When `WFHTTPBodyType = JSON`, build the payload as `WFJSONValues` (structured `WFDictionaryFieldValue`). If the body contains arrays of objects or deep nesting and renders incorrectly, use a JSON Text action, set `WFHTTPBodyType = File`, and pass it via `WFRequestVariable` with `Content-Type: application/json`.
551
+ - **File body requests**: When `WFHTTPBodyType = File`, include an empty `WFFormValues` dictionary to match system exports.
552
+ - **Form file fields**: For `WFHTTPBodyType = Form` and `WFItemType = 5`, wrap the file reference like this so the UI shows the connected file:
553
+
554
+ ```xml
555
+ <dict>
556
+ <key>WFItemType</key>
557
+ <integer>5</integer>
558
+ <key>WFKey</key>
559
+ <dict>
560
+ <key>Value</key>
561
+ <dict>
562
+ <key>string</key>
563
+ <string>file</string>
564
+ </dict>
565
+ <key>WFSerializationType</key>
566
+ <string>WFTextTokenString</string>
567
+ </dict>
568
+ <key>WFValue</key>
569
+ <dict>
570
+ <key>Value</key>
571
+ <dict>
572
+ <key>Value</key>
573
+ <dict>
574
+ <key>Type</key>
575
+ <string>Variable</string>
576
+ <key>VariableName</key>
577
+ <string>Repeat Item</string>
578
+ </dict>
579
+ <key>WFSerializationType</key>
580
+ <string>WFTextTokenAttachment</string>
581
+ </dict>
582
+ <key>WFSerializationType</key>
583
+ <string>WFTokenAttachmentParameterState</string>
584
+ </dict>
585
+ </dict>
586
+ ```
587
+ - **Multipart file uploads**: For `WFHTTPBodyType = Form`, the file field must be a file item, not text. Use `WFItemType = 5` and `WFTokenAttachmentParameterState` for the file value. Also set `WFRequestVariable` to the file variable.
588
+
589
+ ## Common Parameter Keys Across Actions
590
+
591
+ These parameters appear in many different actions:
592
+
593
+ | Parameter | Count | Type | Description |
594
+ |-----------|-------|------|-------------|
595
+ | `UUID` | all | string | Action's unique identifier |
596
+ | `WFInput` | 306 | variable_ref | Input from previous action |
597
+ | `GroupingIdentifier` | ~100 | string | Links control flow actions |
598
+ | `WFControlFlowMode` | ~100 | integer | Control flow position |
599
+ | `CustomOutputName` | ~50 | string | Custom name for output |
600
+ | `WFShowWorkflow` | ~30 | boolean | Show in workflow view |
601
+
602
+ ---
603
+
604
+ ## Type Coercion (Aggrandizements)
605
+
606
+ When you need to access a property or coerce a type:
607
+
608
+ ```xml
609
+ <key>WFInput</key>
610
+ <dict>
611
+ <key>Value</key>
612
+ <dict>
613
+ <key>Aggrandizements</key>
614
+ <array>
615
+ <dict>
616
+ <key>CoercionItemClass</key>
617
+ <string>WFStringContentItem</string>
618
+ <key>Type</key>
619
+ <string>WFCoercionVariableAggrandizement</string>
620
+ </dict>
621
+ </array>
622
+ <key>OutputName</key>
623
+ <string>Model Response</string>
624
+ <key>OutputUUID</key>
625
+ <string>LLM-UUID</string>
626
+ <key>Type</key>
627
+ <string>ActionOutput</string>
628
+ </dict>
629
+ <key>WFSerializationType</key>
630
+ <string>WFTextTokenAttachment</string>
631
+ </dict>
632
+ ```
633
+
634
+ ### Common Coercion Classes
635
+
636
+ | Class | Description |
637
+ |-------|-------------|
638
+ | `WFStringContentItem` | Coerce to text |
639
+ | `WFNumberContentItem` | Coerce to number |
640
+ | `WFBooleanContentItem` | Coerce to boolean |
641
+ | `WFDictionaryContentItem` | Coerce to dictionary |
642
+ | `WFURLContentItem` | Coerce to URL |
643
+ | `WFImageContentItem` | Coerce to image |
644
+ | `WFFileContentItem` | Coerce to file |
645
+
646
+ ---
647
+
648
+ ## Math and Counting Operations
649
+
650
+ ### WFMathOperation Values (verified against Shortcuts app output, 2026)
651
+
652
+ | Operation | WFMathOperation value | Codepoint | Notes |
653
+ |-----------|----------------------|-----------|-------|
654
+ | **Addition** | **OMIT the key entirely** | — | No `WFMathOperation` key at all. Defaults to addition. |
655
+ | Subtraction | `-` | U+002D (ASCII) | Standard ASCII minus |
656
+ | Multiplication | `×` | **U+00D7** | Unicode MULTIPLICATION SIGN |
657
+ | Division | `÷` | **U+00F7** | Unicode DIVISION SIGN |
658
+ | Scientific (Modulus, Power, etc.) | `…` | U+2026 | Placeholder — real op in `WFScientificMathOperation` |
659
+
660
+ **⚠️ CRITICAL — DO NOT SUBSTITUTE ASCII CHARACTERS:**
661
+ - **NEVER** use `*` (asterisk, U+002A) for multiplication — use `×` (U+00D7)
662
+ - **NEVER** use `/` (forward slash, U+002F) for division — use `÷` (U+00F7)
663
+ - **NEVER** set `WFMathOperation='+'` for addition — **OMIT the key entirely**
664
+
665
+ **Why this matters**: Shortcuts silently mis-handles wrong math operators. `WFMathOperation='/'` renders in the Shortcuts UI as **addition (`+`)**, producing wrong results with no error. This caused hours of debugging on Apple Frames 4 proportional scaling. Every generated shortcut had `/` where it needed `÷`, causing the min-finding logic to compute `height + physicalHeight` instead of `height ÷ physicalHeight`, producing astronomical target widths that made `image.resize` output Zero KB files.
666
+
667
+ ### WFMathOperand format (literal numbers)
668
+
669
+ When the second operand is a literal number, use a **plain string** — not a wrapped value dict:
670
+
671
+ ```python
672
+ # CORRECT — how the Shortcuts app writes it
673
+ mk('is.workflow.actions.math',
674
+ WFInput=action_ref('Number', uid_prev),
675
+ WFMathOperand='10') # plain string
676
+ # (WFMathOperation omitted → addition)
677
+
678
+ mk('is.workflow.actions.math',
679
+ WFMathOperation='-', # ASCII minus
680
+ WFInput=action_ref('Calculation Result', uid_prev),
681
+ WFMathOperand='2')
682
+
683
+ mk('is.workflow.actions.math',
684
+ WFMathOperation='×', # U+00D7
685
+ WFInput=action_ref('Calculation Result', uid_prev),
686
+ WFMathOperand='3')
687
+
688
+ mk('is.workflow.actions.math',
689
+ WFMathOperation='÷', # U+00F7
690
+ WFInput=action_ref('Calculation Result', uid_prev),
691
+ WFMathOperand='2')
692
+ ```
693
+
694
+ When the operand is a variable or action output, use the standard `WFTextTokenAttachment` wrapper:
695
+
696
+ ```python
697
+ mk('is.workflow.actions.math',
698
+ WFMathOperation='÷',
699
+ WFInput=action_ref('Details of Images', uid_height),
700
+ WFMathOperand=var_ref('Min PxPerMm')) # variable reference
701
+ ```
702
+
703
+ ### WFNumberActionNumber format (for `is.workflow.actions.number`)
704
+
705
+ For literal numbers, use a **plain string**:
706
+
707
+ ```python
708
+ mk('is.workflow.actions.number',
709
+ UUID=uid, WFNumberActionNumber='1') # plain string, NOT int
710
+ ```
711
+
712
+ When the source is a variable or action output, use the standard wrapper:
713
+
714
+ ```python
715
+ mk('is.workflow.actions.number',
716
+ UUID=uid, WFNumberActionNumber=action_ref('Name', uid_getname))
717
+ ```
718
+
719
+ ### Scientific Math Operations
720
+
721
+ For scientific mode (Modulus, Power, Square Root, etc.), the structure is different:
722
+
723
+ ```python
724
+ mk('is.workflow.actions.math',
725
+ WFMathOperation='…', # U+2026 placeholder indicating scientific mode
726
+ WFInput=action_ref('Calculation Result', uid_prev),
727
+ WFScientificMathOperation='Modulus', # the actual operation
728
+ WFScientificMathOperand='1') # the operand for scientific ops
729
+ ```
730
+
731
+ Known `WFScientificMathOperation` values: `Modulus`, `Power`, `Square Root`, `Cube Root`, `Nth Root`, `Natural Logarithm`, `Common Logarithm`, `Logarithm`, `Exponent`, `Factorial`, `Sine`, `Cosine`, `Tangent`, `Arcsine`, `Arccosine`, `Arctangent`.
732
+
733
+ ### Character ordinals for math operations
734
+
735
+ The correct Unicode characters for math operations (verified):
736
+ - `ord('×')` = 215 ✓ (multiplication — U+00D7)
737
+ - `ord('÷')` = 247 ✓ (division — U+00F7)
738
+ - `ord('-')` = 45 ✓ (ASCII minus — U+002D)
739
+ - `ord('…')` = 8230 ✓ (scientific placeholder — U+2026)
740
+ - `ord('/')` = 47 ✗ (ASCII slash — silently rendered as `+` by the Shortcuts app)
741
+ - `ord('*')` = 42 ✗ (ASCII asterisk — not valid)
742
+
743
+ ### WFCountType Values
744
+
745
+ | Value | Description |
746
+ |-------|-------------|
747
+ | `Items` | Count array items |
748
+ | `Characters` | Count characters in text |
749
+ | `Words` | Count words in text |
750
+ | `Sentences` | Count sentences in text |
751
+ | `Lines` | Count lines in text |
752
+
753
+ ### WFAdjustOperation Values (for Adjust Date)
754
+
755
+ | Value | Description |
756
+ |-------|-------------|
757
+ | `Add` | Add time duration |
758
+ | `Subtract` | Subtract time duration |
759
+
760
+ ### WFInputType (for Ask for Input)
761
+
762
+ | Value | Description |
763
+ |-------|-------------|
764
+ | `Text` | Plain text input |
765
+ | `Number` | Numeric input |
766
+ | `URL` | URL input |
767
+ | `Date` | Date picker (date only) |
768
+ | `Date and Time` | Date and time picker |
769
+
770
+ ### Duration Units (WFQuantityFieldValue)
771
+
772
+ Duration units used in time-related actions:
773
+
774
+ | Unit | Description |
775
+ |------|-------------|
776
+ | `sec` | Seconds |
777
+ | `min` | Minutes |
778
+ | `hr` | Hours |
779
+ | `days` | Days |
780
+ | `wk` | Weeks |
781
+ | `mon` | Months |
782
+ | `yr` | Years |
783
+
784
+ ### Property Access (Dictionary Values)
785
+
786
+ ```xml
787
+ <key>Aggrandizements</key>
788
+ <array>
789
+ <dict>
790
+ <key>DictionaryKey</key>
791
+ <string>fieldName</string>
792
+ <key>Type</key>
793
+ <string>WFDictionaryValueVariableAggrandizement</string>
794
+ </dict>
795
+ </array>
796
+ ```
797
+
798
+ ### Date Format Aggrandizement
799
+
800
+ Format a date variable inline without a separate Format Date action:
801
+ ```xml
802
+ <key>Aggrandizements</key>
803
+ <array>
804
+ <dict>
805
+ <key>DateFormat</key>
806
+ <string>Short</string>
807
+ <key>Type</key>
808
+ <string>WFDateFormatVariableAggrandizement</string>
809
+ </dict>
810
+ </array>
811
+ ```
812
+
813
+ ### Unit Aggrandizement
814
+
815
+ Extract numeric value or unit string from a measurement variable:
816
+ ```xml
817
+ <key>Aggrandizements</key>
818
+ <array>
819
+ <dict>
820
+ <key>PropertyName</key>
821
+ <string>Value</string>
822
+ <key>Type</key>
823
+ <string>WFUnitVariableAggrandizement</string>
824
+ </dict>
825
+ </array>
826
+ ```
827
+
828
+ ## Reminders — Filter & Setter Schemas (DEFINITIVE)
829
+
830
+ Verified against an Apple-built sample shortcut titled "Reminder Edits" that exercises `is.workflow.actions.filter.reminders` with date operators plus `is.workflow.actions.setters.reminders` applied to every common Reminders property. Treat this section as canonical — do NOT invent alternative parameter keys.
831
+
832
+ ### Find Reminders (`is.workflow.actions.filter.reminders`)
833
+
834
+ The filter action uses a `WFContentItemFilter` dict wrapping a `WFContentPredicateTableTemplate`. Each filter **row** is a dict inside `WFActionParameterFilterTemplates`, structured differently from an If conditional's template:
835
+
836
+ | Field | Purpose |
837
+ |-------|---------|
838
+ | `Operator` (integer) | Operator code (see table below) |
839
+ | `Property` (string) | Apple-UI property name: `"List"`, `"Due Date"`, `"Is Completed"`, `"Priority"`, `"Title"`, etc. |
840
+ | `Removable` (bool) | Apple sets this `true` for user-removable rows; `<true/>` is fine |
841
+ | `Values` (dict) | Operator-specific value block (see table) |
842
+
843
+ **Filter-level fields:**
844
+ - `WFActionParameterFilterPrefix` (integer): `0` = Any are true (OR), `1` = All are true (AND). Same semantic as multi-condition If.
845
+ - `WFContentPredicateBoundedDate` (bool): `<false/>` unless the filter operates on a bounded date range.
846
+ - `WFSerializationType`: `"WFContentPredicateTableTemplate"` at the `WFContentItemFilter` level.
847
+
848
+ **Operator ↔ Values schema for Reminders (verified from the sample):**
849
+
850
+ | `Operator` | UI label | `Property` example | `Values` content |
851
+ |-----------|----------|---------------------|------------------|
852
+ | `4` | is (enumeration match) | `"List"` | `Values.Enumeration = { Value: "Reminders", WFSerializationType: "WFStringSubstitutableState" }` |
853
+ | `1002` | is today (date) | `"Due Date"` | **empty** `<dict/>` — the operator code itself means "today"; no value is required |
854
+ | `1003` | is between (date) | `"Due Date"` | `Values.Date` = ISO8601 `<date>` (lower bound, literal); `Values.AnotherDate` = token-attachment dict wrapping `{ Value: { Type: "CurrentDate" }, WFSerializationType: "WFTextTokenAttachment" }` (upper bound, literal or variable like Current Date) |
855
+
856
+ ⚠️ **Filter date operator ≠ If numeric operator.** Filter row `1003` ("is between") uses `Values.Date` + `Values.AnotherDate`. The If conditional `WFCondition=1003` ("is between") uses `WFNumberValue` + `WFAnotherNumber`. Do NOT copy one structure to the other.
857
+
858
+ **Boolean filter rows for Reminders** (`Is Completed`, `Is Flagged`): use `Operator = 4` and `Values = { Bool: <true/false> }`. No `Unit` field — that's a Photos-specific requirement that does NOT apply to Reminders. See [FILTERS.md → Reminders Boolean filter](FILTERS.md#reminders-wfremindercontentitem) for verbatim templates for "Is Completed = Yes" and "Is Completed = No".
859
+
860
+ **"Find Reminders" vs "Filter Reminders"** are the same action identifier — add `WFContentItemInputParameter` wrapping a previous action's `ActionOutput` (with `OutputName = "Reminders"`) to turn a Find into a chained Filter. See [FILTERS.md → Find vs Filter](FILTERS.md#find-vs-filter-wfcontentiteminputparameter).
861
+
862
+ **Verbatim template (Find Reminders where List is Reminders, AND Due Date is between today and Current Date — Any-are-true in the sample):**
863
+
864
+ ```xml
865
+ <dict>
866
+ <key>WFWorkflowActionIdentifier</key>
867
+ <string>is.workflow.actions.filter.reminders</string>
868
+ <key>WFWorkflowActionParameters</key>
869
+ <dict>
870
+ <key>UUID</key>
871
+ <string>FILTER-UUID</string>
872
+ <key>WFContentItemFilter</key>
873
+ <dict>
874
+ <key>Value</key>
875
+ <dict>
876
+ <key>WFActionParameterFilterPrefix</key>
877
+ <integer>0</integer>
878
+ <key>WFActionParameterFilterTemplates</key>
879
+ <array>
880
+ <dict>
881
+ <key>Operator</key>
882
+ <integer>4</integer>
883
+ <key>Property</key>
884
+ <string>List</string>
885
+ <key>Removable</key>
886
+ <true/>
887
+ <key>Values</key>
888
+ <dict>
889
+ <key>Enumeration</key>
890
+ <dict>
891
+ <key>Value</key>
892
+ <string>Reminders</string>
893
+ <key>WFSerializationType</key>
894
+ <string>WFStringSubstitutableState</string>
895
+ </dict>
896
+ </dict>
897
+ </dict>
898
+ <dict>
899
+ <key>Operator</key>
900
+ <integer>1002</integer>
901
+ <key>Property</key>
902
+ <string>Due Date</string>
903
+ <key>Removable</key>
904
+ <true/>
905
+ <key>Values</key>
906
+ <dict/>
907
+ </dict>
908
+ <dict>
909
+ <key>Operator</key>
910
+ <integer>1003</integer>
911
+ <key>Property</key>
912
+ <string>Due Date</string>
913
+ <key>Removable</key>
914
+ <true/>
915
+ <key>Values</key>
916
+ <dict>
917
+ <key>Date</key>
918
+ <date>2026-04-13T09:54:12Z</date>
919
+ <key>AnotherDate</key>
920
+ <dict>
921
+ <key>Value</key>
922
+ <dict>
923
+ <key>Type</key>
924
+ <string>CurrentDate</string>
925
+ </dict>
926
+ <key>WFSerializationType</key>
927
+ <string>WFTextTokenAttachment</string>
928
+ </dict>
929
+ </dict>
930
+ </dict>
931
+ </array>
932
+ <key>WFContentPredicateBoundedDate</key>
933
+ <false/>
934
+ </dict>
935
+ <key>WFSerializationType</key>
936
+ <string>WFContentPredicateTableTemplate</string>
937
+ </dict>
938
+ </dict>
939
+ </dict>
940
+ ```
941
+
942
+ ### Edit Reminder (`is.workflow.actions.setters.reminders`)
943
+
944
+ The setter action mutates **one property** of an existing Reminder per action. To change multiple properties on the same reminder, chain multiple setter actions — each subsequent setter's `WFInput` points at the previous setter's `ActionOutput` (`OutputName="Edited Reminder"`) so the "Edited Reminder" variable propagates down the chain.
945
+
946
+ **Required on every setter:**
947
+
948
+ | Field | Value | Notes |
949
+ |-------|-------|-------|
950
+ | `Mode` | `"Set"` | String literal. (Apple also appears to support other modes like `"Clear"` but only `"Set"` is in the reference sample — stick with `"Set"` unless the user asks otherwise.) |
951
+ | `UUID` | new uppercase UUID | Standard action UUID |
952
+ | `WFContentItemPropertyName` | string, e.g. `"Due Date"`, `"Title"` | Drives which value key the action expects — must match exactly (case + spaces). See table below. |
953
+ | `WFInput` | `WFTextTokenAttachment` wrapping the previous setter's `ActionOutput` with `OutputName="Edited Reminder"` | **Omit only on the first setter acting on a Find Reminders output** — that setter inherits the filter's output implicitly. Every subsequent setter needs an explicit chained `WFInput` or the "Edited Reminder" variable breaks. |
954
+
955
+ **Per-property value key** (add alongside `WFInput` when you want to set a non-default value):
956
+
957
+ | `WFContentItemPropertyName` | Value key | Value serialization | Notes |
958
+ |-----------------------------|-----------|---------------------|-------|
959
+ | `Due Date` | `WFReminderContentItemDueDate` | `WFTextTokenString` with a date token attachment (`{Type: "CurrentDate"}` or a literal ISO date) | Use `` + `attachmentsByRange` for inline date variables |
960
+ | `Title` | `WFReminderContentItemTitle` | `WFTextTokenString` | Text with optional attachments (Clipboard, Variable, etc.) |
961
+ | `Parent Reminder` | `WFReminderContentItemParentReminder` | `WFTextTokenAttachment` | Must reference another reminder (usually another "Edited Reminder" from an earlier setter chain) |
962
+ | `Subtasks` | `WFReminderContentItemSubtasks` | `WFTextTokenAttachment` | Token reference to a List variable (e.g. the output of a `list` action or a split/built list) |
963
+ | `URL` | `WFReminderContentItemURL` | `WFTextTokenString` | Plain text URL with optional attachments |
964
+ | `Notes` | `WFReminderContentItemNotes` | `WFTextTokenString` | Multiline-capable; same pattern as Title |
965
+ | `Tags` | `WFReminderContentItemTags` | `WFTextTokenString` | Apple's new Tags field; comma-separated in the text |
966
+ | `When Messaging Person` | `WFReminderContentItemWhenMessagingPerson` | `WFContactFieldValue` wrapping a `WFContactFieldValues` array of dicts with `WFContactData` (base64-encoded vCard), `WFContactMultivalue`, `WFContactProperty` | Contact-picker field. Use only when the user explicitly names a contact. |
967
+ | `Images` | `WFReminderContentItemImages` | `WFTextTokenAttachment` to an image/list variable | Attaches images to the reminder |
968
+ | `Priority` | `WFReminderContentItemPriority` | Apple UI shows a picker (None / Low / Medium / High); exact on-disk encoding varies — leave blank unless the user explicitly asks for a priority |
969
+ | `Is Completed` | `WFReminderContentItemIsCompleted` | boolean / `WFEnumerationTokenAttachment` (`"Yes"`/`"No"`) | The sample shows an unpopulated slot — when set, expect a Yes/No enumeration |
970
+ | `Is Flagged` | `WFReminderContentItemIsFlagged` | same as Is Completed | Yes/No enumeration |
971
+ | `List` | `WFReminderContentItemList` | **plain string** (list name, e.g. `"Reminders"`) — NOT a token attachment | Only property that takes a bare string value |
972
+
973
+ **Verbatim template (edit an existing reminder's Due Date to Current Date, then set Title from Clipboard, chaining both):**
974
+
975
+ ```xml
976
+ <!-- First setter works on a Find Reminders output implicitly (no WFInput). -->
977
+ <dict>
978
+ <key>WFWorkflowActionIdentifier</key>
979
+ <string>is.workflow.actions.setters.reminders</string>
980
+ <key>WFWorkflowActionParameters</key>
981
+ <dict>
982
+ <key>UUID</key>
983
+ <string>SETTER1-UUID</string>
984
+ <key>Mode</key>
985
+ <string>Set</string>
986
+ <key>WFContentItemPropertyName</key>
987
+ <string>Due Date</string>
988
+ <key>WFReminderContentItemDueDate</key>
989
+ <dict>
990
+ <key>Value</key>
991
+ <dict>
992
+ <key>attachmentsByRange</key>
993
+ <dict>
994
+ <key>{0, 1}</key>
995
+ <dict>
996
+ <key>Type</key>
997
+ <string>CurrentDate</string>
998
+ </dict>
999
+ </dict>
1000
+ <key>string</key>
1001
+ <string></string>
1002
+ </dict>
1003
+ <key>WFSerializationType</key>
1004
+ <string>WFTextTokenString</string>
1005
+ </dict>
1006
+ </dict>
1007
+ </dict>
1008
+
1009
+ <!-- Second setter chains via WFInput = previous setter's ActionOutput (OutputName "Edited Reminder"). -->
1010
+ <dict>
1011
+ <key>WFWorkflowActionIdentifier</key>
1012
+ <string>is.workflow.actions.setters.reminders</string>
1013
+ <key>WFWorkflowActionParameters</key>
1014
+ <dict>
1015
+ <key>UUID</key>
1016
+ <string>SETTER2-UUID</string>
1017
+ <key>Mode</key>
1018
+ <string>Set</string>
1019
+ <key>WFContentItemPropertyName</key>
1020
+ <string>Title</string>
1021
+ <key>WFInput</key>
1022
+ <dict>
1023
+ <key>Value</key>
1024
+ <dict>
1025
+ <key>OutputName</key>
1026
+ <string>Edited Reminder</string>
1027
+ <key>OutputUUID</key>
1028
+ <string>SETTER1-UUID</string>
1029
+ <key>Type</key>
1030
+ <string>ActionOutput</string>
1031
+ </dict>
1032
+ <key>WFSerializationType</key>
1033
+ <string>WFTextTokenAttachment</string>
1034
+ </dict>
1035
+ <key>WFReminderContentItemTitle</key>
1036
+ <dict>
1037
+ <key>Value</key>
1038
+ <dict>
1039
+ <key>attachmentsByRange</key>
1040
+ <dict>
1041
+ <key>{0, 1}</key>
1042
+ <dict>
1043
+ <key>Type</key>
1044
+ <string>Clipboard</string>
1045
+ </dict>
1046
+ </dict>
1047
+ <key>string</key>
1048
+ <string></string>
1049
+ </dict>
1050
+ <key>WFSerializationType</key>
1051
+ <string>WFTextTokenString</string>
1052
+ </dict>
1053
+ </dict>
1054
+ </dict>
1055
+ ```
1056
+
1057
+ ### Reschedule pattern (common, copy-paste safe)
1058
+
1059
+ The most common Reminders task is "reschedule a reminder to a new date." It's a single setter on `Due Date`, where the value comes from an `Ask for Input` (Date and Time) action earlier in the shortcut:
1060
+
1061
+ ```xml
1062
+ <dict>
1063
+ <key>WFWorkflowActionIdentifier</key>
1064
+ <string>is.workflow.actions.setters.reminders</string>
1065
+ <key>WFWorkflowActionParameters</key>
1066
+ <dict>
1067
+ <key>UUID</key>
1068
+ <string>RESCHEDULE-SETTER-UUID</string>
1069
+ <key>Mode</key>
1070
+ <string>Set</string>
1071
+ <key>WFContentItemPropertyName</key>
1072
+ <string>Due Date</string>
1073
+ <key>WFInput</key>
1074
+ <dict>
1075
+ <!-- Reminder to reschedule: chain from the filter or a Repeat Item -->
1076
+ <key>Value</key>
1077
+ <dict>
1078
+ <key>Type</key>
1079
+ <string>Variable</string>
1080
+ <key>VariableName</key>
1081
+ <string>Repeat Item</string>
1082
+ </dict>
1083
+ <key>WFSerializationType</key>
1084
+ <string>WFTextTokenAttachment</string>
1085
+ </dict>
1086
+ <key>WFReminderContentItemDueDate</key>
1087
+ <dict>
1088
+ <key>Value</key>
1089
+ <dict>
1090
+ <key>attachmentsByRange</key>
1091
+ <dict>
1092
+ <key>{0, 1}</key>
1093
+ <dict>
1094
+ <key>OutputName</key>
1095
+ <string>Provided Input</string>
1096
+ <key>OutputUUID</key>
1097
+ <string>ASK-FOR-INPUT-UUID</string>
1098
+ <key>Type</key>
1099
+ <string>ActionOutput</string>
1100
+ </dict>
1101
+ </dict>
1102
+ <key>string</key>
1103
+ <string></string>
1104
+ </dict>
1105
+ <key>WFSerializationType</key>
1106
+ <string>WFTextTokenString</string>
1107
+ </dict>
1108
+ </dict>
1109
+ </dict>
1110
+ ```
1111
+
1112
+ ### What you never do with Reminders
1113
+
1114
+ - **Never use `com.apple.reminders.UpdateReminderAppIntent`** for editing reminder properties. The identifier is allowlisted but its parameter schema is not published by Apple and changes between OS releases. The WF-classic path (`is.workflow.actions.setters.reminders`) is documented above, verified, and stable — always prefer it for editing existing reminders.
1115
+ - **Never chain setters without `WFInput`.** The first setter acting directly on a Find Reminders output can omit `WFInput` (implicit from the preceding filter). Every subsequent setter needs an explicit `WFInput` token attachment pointing at the previous setter's `ActionOutput` (`OutputName="Edited Reminder"`) or the chain breaks and every downstream setter edits the wrong reminder.
1116
+ - **Never put `WFReminderContentItemList` inside a token attachment dict.** It's the one property that takes a plain string — `<string>Reminders</string>`, not a wrapper.
1117
+ - **Never use filter operator `1003` with `WFNumberValue`/`WFAnotherNumber`.** Date filters use `Values.Date` + `Values.AnotherDate`. That's different from If conditional `1003`.