markform 0.1.22 → 0.1.24

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 (43) hide show
  1. package/README.md +53 -16
  2. package/dist/ai-sdk.d.mts +1 -1
  3. package/dist/ai-sdk.mjs +48 -6
  4. package/dist/ai-sdk.mjs.map +1 -1
  5. package/dist/bin.mjs +1 -1
  6. package/dist/{cli-C8F9yDsv.mjs → cli-B1DhFYBS.mjs} +642 -96
  7. package/dist/cli-B1DhFYBS.mjs.map +1 -0
  8. package/dist/cli.d.mts +1 -1
  9. package/dist/cli.mjs +1 -1
  10. package/dist/{coreTypes-CTLr-NGd.mjs → coreTypes-CctFK6uE.mjs} +38 -2
  11. package/dist/coreTypes-CctFK6uE.mjs.map +1 -0
  12. package/dist/{coreTypes-BlsJkU1w.d.mts → coreTypes-GxzWNXap.d.mts} +137 -3
  13. package/dist/{fillRecord-DTl5lnK0.d.mts → fillRecord-DeqI2pQ5.d.mts} +25 -1
  14. package/dist/{fillRecordRenderer-CruJrLkj.mjs → fillRecordRenderer-VBQ2vwPV.mjs} +2 -5
  15. package/dist/fillRecordRenderer-VBQ2vwPV.mjs.map +1 -0
  16. package/dist/index.d.mts +52 -29
  17. package/dist/index.mjs +5 -5
  18. package/dist/{apply-C7mO7VkZ.mjs → prompts-BCnYaH4_.mjs} +969 -8
  19. package/dist/prompts-BCnYaH4_.mjs.map +1 -0
  20. package/dist/render.d.mts +2 -2
  21. package/dist/render.mjs +1 -1
  22. package/dist/{session-BCcltrLA.mjs → session-BLjN3BkJ.mjs} +2 -2
  23. package/dist/{session-BCcltrLA.mjs.map → session-BLjN3BkJ.mjs.map} +1 -1
  24. package/dist/{session-VeSkVrck.mjs → session-D7C7IlEv.mjs} +1 -1
  25. package/dist/{shared-CsdT2T7k.mjs → shared-CuSRYcIB.mjs} +3 -3
  26. package/dist/shared-CuSRYcIB.mjs.map +1 -0
  27. package/dist/{shared-fb0nkzQi.mjs → shared-DtorFV21.mjs} +1 -1
  28. package/dist/{src-CbRnGzMK.mjs → src-C5OWf1dL.mjs} +114 -826
  29. package/dist/src-C5OWf1dL.mjs.map +1 -0
  30. package/docs/markform-apis.md +6 -0
  31. package/docs/markform-reference.md +26 -1
  32. package/docs/markform-spec.md +11 -3
  33. package/docs/skill/SKILL.md +119 -0
  34. package/examples/rejection-test/rejection-test.session.yaml +52 -0
  35. package/examples/simple/simple-with-skips.session.yaml +78 -0
  36. package/examples/simple/simple.session.yaml +78 -0
  37. package/package.json +2 -2
  38. package/dist/apply-C7mO7VkZ.mjs.map +0 -1
  39. package/dist/cli-C8F9yDsv.mjs.map +0 -1
  40. package/dist/coreTypes-CTLr-NGd.mjs.map +0 -1
  41. package/dist/fillRecordRenderer-CruJrLkj.mjs.map +0 -1
  42. package/dist/shared-CsdT2T7k.mjs.map +0 -1
  43. package/dist/src-CbRnGzMK.mjs.map +0 -1
@@ -138,6 +138,12 @@ Each patch has an `op` and `fieldId`.
138
138
  | `set_date` | date | `{ "op": "set_date", "fieldId": "deadline", "value": "2024-06-15" }` |
139
139
  | `set_year` | year | `{ "op": "set_year", "fieldId": "founded", "value": 2015 }` |
140
140
  | `set_table` | table | `{ "op": "set_table", "fieldId": "data", "value": [{"col1": "v1"}] }` |
141
+ | `append_table` | table | `{ "op": "append_table", "fieldId": "data", "value": [{"col1": "v2"}] }` |
142
+ | `delete_table` | table | `{ "op": "delete_table", "fieldId": "data", "value": [0, 2] }` |
143
+ | `append_string_list` | string_list | `{ "op": "append_string_list", "fieldId": "tags", "value": ["c"] }` |
144
+ | `delete_string_list` | string_list | `{ "op": "delete_string_list", "fieldId": "tags", "value": ["a"] }` |
145
+ | `append_url_list` | url_list | `{ "op": "append_url_list", "fieldId": "sources", "value": ["https://new"] }` |
146
+ | `delete_url_list` | url_list | `{ "op": "delete_url_list", "fieldId": "sources", "value": ["https://old"] }` |
141
147
  | `clear_field` | any | `{ "op": "clear_field", "fieldId": "name" }` |
142
148
  | `skip_field` | optional | `{ "op": "skip_field", "fieldId": "notes", "reason": "Not applicable" }` |
143
149
  | `abort_field` | any | `{ "op": "abort_field", "fieldId": "data", "reason": "Unable to find" }` |
@@ -716,7 +716,22 @@ markform inspect form.md --format=json
716
716
  # Validate form (check for errors)
717
717
  markform validate form.md
718
718
 
719
- # Fill forms
719
+ # Set field values (agent-friendly, auto-coerced)
720
+ markform set form.md fieldId "value" # Set a single field
721
+ markform set form.md --values '{"name": "Alice", "age": 30}' # Batch set
722
+ markform set form.md fieldId --clear # Clear a field
723
+ markform set form.md fieldId --skip # Skip a field
724
+ markform set form.md fieldId --abort # Abort a field
725
+ markform set form.md tableId --append '[{"col": "val"}]' # Append rows
726
+ markform set form.md tableId --delete '[0, 2]' # Delete rows by index
727
+
728
+ # Get next field recommendation
729
+ markform next form.md # What field to fill next
730
+
731
+ # Apply raw typed patches (low-level)
732
+ markform patch form.md '[{"op": "set_string", "fieldId": "name", "value": "Alice"}]'
733
+
734
+ # Fill forms (harness-driven sessions)
720
735
  markform fill form.md --interactive # Interactive prompts for user fields
721
736
  markform fill form.md --roles=user --interactive # Only fill user-role fields
722
737
  markform fill form.md --model anthropic/claude-sonnet-4-5 # AI fills agent fields
@@ -783,6 +798,16 @@ markform fill template.form.md --mock --mock-source filled.form.md
783
798
 
784
799
  6. **Document thoroughly**: Use `{% instructions %}` for complex fields
785
800
 
801
+ ## Claude Code Skill Setup
802
+
803
+ Install markform as a Claude Code skill so agents know how to use it:
804
+
805
+ ```bash
806
+ markform setup --auto # Non-interactive (for agents)
807
+ markform setup --interactive # Guided setup (for humans)
808
+ markform skill # View the skill content
809
+ ```
810
+
786
811
  ## Programmatic API
787
812
 
788
813
  For TypeScript and AI SDK integration, run `markform apis` or see
@@ -2868,9 +2868,11 @@ This formula ensures:
2868
2868
  | Operation | CLI | AI SDK | MCP (MF/0.2) |
2869
2869
  | --- | --- | --- | --- |
2870
2870
  | inspect | `markform inspect` (prints YAML report) | `markform_inspect` | `markform.inspect` |
2871
- | apply | `markform apply` | `markform_apply` | `markform.apply` |
2871
+ | patch | `markform patch` (raw typed patches) | `markform_apply` | `markform.apply` |
2872
+ | set | `markform set` (auto-coerced value setting) | — | — |
2873
+ | next | `markform next` (next-field advisor) | — | — |
2872
2874
  | export | `markform export --format=json` | `markform_export` | `markform.export` |
2873
- | getMarkdown | `markform apply` (writes file) | `markform_get_markdown` | `markform.get_markdown` |
2875
+ | getMarkdown | `markform patch` (writes file) | `markform_get_markdown` | `markform.get_markdown` |
2874
2876
  | render | `markform render` (static HTML output) | — | — |
2875
2877
  | serve | `markform serve` (interactive web UI) | — | — |
2876
2878
 
@@ -2889,6 +2891,12 @@ type Patch =
2889
2891
  | { op: 'set_table'; fieldId: Id; value: PatchTableRow[] }
2890
2892
  | { op: 'set_date'; fieldId: Id; value: string | null }
2891
2893
  | { op: 'set_year'; fieldId: Id; value: number | null }
2894
+ | { op: 'append_table'; fieldId: Id; value: PatchTableRow[] }
2895
+ | { op: 'delete_table'; fieldId: Id; value: number[] }
2896
+ | { op: 'append_string_list'; fieldId: Id; value: string[] }
2897
+ | { op: 'delete_string_list'; fieldId: Id; value: string[] }
2898
+ | { op: 'append_url_list'; fieldId: Id; value: string[] }
2899
+ | { op: 'delete_url_list'; fieldId: Id; value: string[] }
2892
2900
  | { op: 'clear_field'; fieldId: Id }
2893
2901
  | { op: 'skip_field'; fieldId: Id; role: string; reason?: string }
2894
2902
  | { op: 'abort_field'; fieldId: Id; role: string; reason?: string }
@@ -3059,7 +3067,7 @@ This is the normal inspect/apply/fix workflow.
3059
3067
 
3060
3068
  **Patch conflict handling:**
3061
3069
 
3062
- - Patches are applied in array order within a single `apply` call
3070
+ - Patches are applied in array order within a single `patch`/`applyPatches()` call
3063
3071
 
3064
3072
  - Later patches to the same field overwrite earlier ones (last-write-wins)
3065
3073
 
@@ -0,0 +1,119 @@
1
+ ---
2
+ name: markform
3
+ description: >-
4
+ Markdown-based form system for structured data collection by AI agents and humans.
5
+ Inspect, fill, validate, and export .form.md files with typed fields and role-based workflows.
6
+ Use when working with .form.md files, filling forms, validating fields, exporting data,
7
+ or when the user mentions markform, forms, form filling, structured data, or field validation.
8
+ allowed-tools: Bash(markform:*)
9
+ ---
10
+
11
+ # Markform — Agent Skill
12
+
13
+ Markform is structured Markdown for forms. Files combine YAML frontmatter with HTML
14
+ comment tags to define typed, validated fields. Forms render cleanly on GitHub since
15
+ structure is hidden in comments.
16
+
17
+ ## What Markform Does
18
+
19
+ 1. **Structured Forms**: Define typed fields (string, number, select, table, etc.) in
20
+ Markdown with validation constraints
21
+ 2. **Role-Based Filling**: Separate fields for humans (`role="user"`) and AI agents
22
+ (`role="agent"`)
23
+ 3. **Incremental Filling**: Fill fields one at a time with immediate validation
24
+ 4. **Agent-Driven Workflows**: AI agents fill forms via CLI or programmatic API
25
+ 5. **Multi-Format Export**: Export filled data as JSON, YAML, or Markdown
26
+
27
+ ## Core CLI Commands
28
+
29
+ | Command | Purpose |
30
+ | --- | --- |
31
+ | `markform inspect <form>` | Show form structure, progress, and issues |
32
+ | `markform validate <form>` | Check for constraint violations and errors |
33
+ | `markform set <form> <field> "value"` | Set a field value (auto-coerced) |
34
+ | `markform set <form> --values '{"k":"v"}'` | Batch set multiple fields |
35
+ | `markform next <form>` | Recommend the next field to fill |
36
+ | `markform fill <form> --interactive` | Interactive prompts for user fields |
37
+ | `markform fill <form> --model <model>` | AI agent fills form fields |
38
+ | `markform export <form> --format=json` | Export values as JSON |
39
+ | `markform export <form> --format=yaml` | Export values as YAML |
40
+ | `markform schema <form>` | Export JSON Schema for form structure |
41
+ | `markform dump <form>` | Quick dump of current field values |
42
+ | `markform status <form>` | Show fill progress per role |
43
+ | `markform docs` | Show Markform syntax reference |
44
+ | `markform examples` | Copy built-in example forms |
45
+ | `markform serve <form>` | Web UI for browsing and editing |
46
+
47
+ ## Agent Workflow
48
+
49
+ When working with markform files:
50
+
51
+ 1. **Inspect first**: `markform inspect form.md` to understand the form structure,
52
+ see which fields exist, their types, constraints, and current fill progress
53
+ 2. **Check what's next**: `markform next form.md` to see which field should be
54
+ filled next (respects priority, order, and role)
55
+ 3. **Set values**: `markform set form.md field_id "value"` to fill fields one at
56
+ a time, or use `--values` for batch updates
57
+ 4. **Validate**: `markform validate form.md` to check all constraints are met
58
+ 5. **Export**: `markform export form.md --format=json` to extract filled data
59
+
60
+ ## Setting Field Values
61
+
62
+ The `set` command is the primary way to fill fields. It auto-coerces values to
63
+ the correct type:
64
+
65
+ ```bash
66
+ # String fields
67
+ markform set form.md name "Alice Smith"
68
+
69
+ # Number fields (auto-coerced from string)
70
+ markform set form.md age 30
71
+
72
+ # Single select (by option ID)
73
+ markform set form.md rating high
74
+
75
+ # Multi select (JSON array of option IDs)
76
+ markform set form.md categories '["frontend","backend"]'
77
+
78
+ # Checkboxes (JSON object of {itemId: value})
79
+ markform set form.md tasks '{"research":"done","testing":"done"}'
80
+
81
+ # Table (append rows as JSON)
82
+ markform set form.md team --append '[{"name": "Alice", "title": "Engineer"}]'
83
+
84
+ # Batch set multiple fields
85
+ markform set form.md --values '{"name": "Alice", "age": 30, "rating": "high"}'
86
+
87
+ # Special operations
88
+ markform set form.md field_id --clear # Clear a field value
89
+ markform set form.md field_id --skip # Skip (mark as skipped)
90
+ markform set form.md field_id --abort # Abort (mark as aborted)
91
+ ```
92
+
93
+ ## Global Options
94
+
95
+ All commands support:
96
+
97
+ | Option | Description |
98
+ | --- | --- |
99
+ | `--format <fmt>` | Output format: console, json, yaml, plaintext, markform, markdown |
100
+ | `--verbose` | Enable verbose/debug output |
101
+ | `--quiet` | Suppress non-essential output |
102
+ | `--dry-run` | Show what would be done without changes |
103
+ | `--overwrite` | Overwrite existing field values |
104
+
105
+ ## File Conventions
106
+
107
+ | Extension | Purpose |
108
+ | --- | --- |
109
+ | `.form.md` | Markform source and filled forms |
110
+ | `.fill.json` | Execution metadata (sidecar, auto-generated) |
111
+ | `.report.md` | Filtered human-readable output |
112
+ | `.schema.json` | JSON Schema export |
113
+
114
+ ## More Information
115
+
116
+ - Syntax reference: `markform docs`
117
+ - Full specification: `markform spec`
118
+ - API documentation: `markform apis`
119
+ - Example forms: `markform examples`
@@ -78,6 +78,19 @@ turns:
78
78
  | checkboxes | `{ op: "set_checkboxes", fieldId: "tasks", value: { "task1": "done", "task2": "todo" } }` |
79
79
  | table | `{ op: "set_table", fieldId: "team", value: [{ "name": "Alice", "role": "Engineer" }] }` |
80
80
 
81
+ ## Incremental Operations (for collections)
82
+
83
+ Use these to add/remove items without replacing the entire collection:
84
+
85
+ | Type | Example |
86
+ |------|---------|
87
+ | append_table | `{ op: "append_table", fieldId: "team", value: [{ "name": "Bob", "role": "PM" }] }` |
88
+ | append_string_list | `{ op: "append_string_list", fieldId: "tags", value: ["new_tag"] }` |
89
+ | append_url_list | `{ op: "append_url_list", fieldId: "sources", value: ["https://new.com"] }` |
90
+ | delete_table | `{ op: "delete_table", fieldId: "team", value: 0 }` (0-based row index) |
91
+ | delete_string_list | `{ op: "delete_string_list", fieldId: "tags", value: 0 }` (0-based item index) |
92
+ | delete_url_list | `{ op: "delete_url_list", fieldId: "sources", value: 0 }` (0-based item index) |
93
+
81
94
  ## Important: checkboxes vs multi_select
82
95
 
83
96
  These two types look similar but have DIFFERENT value formats:
@@ -201,6 +214,19 @@ turns:
201
214
  | checkboxes | `{ op: "set_checkboxes", fieldId: "tasks", value: { "task1": "done", "task2": "todo" } }` |
202
215
  | table | `{ op: "set_table", fieldId: "team", value: [{ "name": "Alice", "role": "Engineer" }] }` |
203
216
 
217
+ ## Incremental Operations (for collections)
218
+
219
+ Use these to add/remove items without replacing the entire collection:
220
+
221
+ | Type | Example |
222
+ |------|---------|
223
+ | append_table | `{ op: "append_table", fieldId: "team", value: [{ "name": "Bob", "role": "PM" }] }` |
224
+ | append_string_list | `{ op: "append_string_list", fieldId: "tags", value: ["new_tag"] }` |
225
+ | append_url_list | `{ op: "append_url_list", fieldId: "sources", value: ["https://new.com"] }` |
226
+ | delete_table | `{ op: "delete_table", fieldId: "team", value: 0 }` (0-based row index) |
227
+ | delete_string_list | `{ op: "delete_string_list", fieldId: "tags", value: 0 }` (0-based item index) |
228
+ | delete_url_list | `{ op: "delete_url_list", fieldId: "sources", value: 0 }` (0-based item index) |
229
+
204
230
  ## Important: checkboxes vs multi_select
205
231
 
206
232
  These two types look similar but have DIFFERENT value formats:
@@ -381,6 +407,19 @@ turns:
381
407
  | checkboxes | `{ op: "set_checkboxes", fieldId: "tasks", value: { "task1": "done", "task2": "todo" } }` |
382
408
  | table | `{ op: "set_table", fieldId: "team", value: [{ "name": "Alice", "role": "Engineer" }] }` |
383
409
 
410
+ ## Incremental Operations (for collections)
411
+
412
+ Use these to add/remove items without replacing the entire collection:
413
+
414
+ | Type | Example |
415
+ |------|---------|
416
+ | append_table | `{ op: "append_table", fieldId: "team", value: [{ "name": "Bob", "role": "PM" }] }` |
417
+ | append_string_list | `{ op: "append_string_list", fieldId: "tags", value: ["new_tag"] }` |
418
+ | append_url_list | `{ op: "append_url_list", fieldId: "sources", value: ["https://new.com"] }` |
419
+ | delete_table | `{ op: "delete_table", fieldId: "team", value: 0 }` (0-based row index) |
420
+ | delete_string_list | `{ op: "delete_string_list", fieldId: "tags", value: 0 }` (0-based item index) |
421
+ | delete_url_list | `{ op: "delete_url_list", fieldId: "sources", value: 0 }` (0-based item index) |
422
+
384
423
  ## Important: checkboxes vs multi_select
385
424
 
386
425
  These two types look similar but have DIFFERENT value formats:
@@ -510,6 +549,19 @@ turns:
510
549
  | checkboxes | `{ op: "set_checkboxes", fieldId: "tasks", value: { "task1": "done", "task2": "todo" } }` |
511
550
  | table | `{ op: "set_table", fieldId: "team", value: [{ "name": "Alice", "role": "Engineer" }] }` |
512
551
 
552
+ ## Incremental Operations (for collections)
553
+
554
+ Use these to add/remove items without replacing the entire collection:
555
+
556
+ | Type | Example |
557
+ |------|---------|
558
+ | append_table | `{ op: "append_table", fieldId: "team", value: [{ "name": "Bob", "role": "PM" }] }` |
559
+ | append_string_list | `{ op: "append_string_list", fieldId: "tags", value: ["new_tag"] }` |
560
+ | append_url_list | `{ op: "append_url_list", fieldId: "sources", value: ["https://new.com"] }` |
561
+ | delete_table | `{ op: "delete_table", fieldId: "team", value: 0 }` (0-based row index) |
562
+ | delete_string_list | `{ op: "delete_string_list", fieldId: "tags", value: 0 }` (0-based item index) |
563
+ | delete_url_list | `{ op: "delete_url_list", fieldId: "sources", value: 0 }` (0-based item index) |
564
+
513
565
  ## Important: checkboxes vs multi_select
514
566
 
515
567
  These two types look similar but have DIFFERENT value formats:
@@ -151,6 +151,19 @@ turns:
151
151
  | checkboxes | `{ op: "set_checkboxes", fieldId: "tasks", value: { "task1": "done", "task2": "todo" } }` |
152
152
  | table | `{ op: "set_table", fieldId: "team", value: [{ "name": "Alice", "role": "Engineer" }] }` |
153
153
 
154
+ ## Incremental Operations (for collections)
155
+
156
+ Use these to add/remove items without replacing the entire collection:
157
+
158
+ | Type | Example |
159
+ |------|---------|
160
+ | append_table | `{ op: "append_table", fieldId: "team", value: [{ "name": "Bob", "role": "PM" }] }` |
161
+ | append_string_list | `{ op: "append_string_list", fieldId: "tags", value: ["new_tag"] }` |
162
+ | append_url_list | `{ op: "append_url_list", fieldId: "sources", value: ["https://new.com"] }` |
163
+ | delete_table | `{ op: "delete_table", fieldId: "team", value: 0 }` (0-based row index) |
164
+ | delete_string_list | `{ op: "delete_string_list", fieldId: "tags", value: 0 }` (0-based item index) |
165
+ | delete_url_list | `{ op: "delete_url_list", fieldId: "sources", value: 0 }` (0-based item index) |
166
+
154
167
  ## Important: checkboxes vs multi_select
155
168
 
156
169
  These two types look similar but have DIFFERENT value formats:
@@ -477,6 +490,19 @@ turns:
477
490
  | checkboxes | `{ op: "set_checkboxes", fieldId: "tasks", value: { "task1": "done", "task2": "todo" } }` |
478
491
  | table | `{ op: "set_table", fieldId: "team", value: [{ "name": "Alice", "role": "Engineer" }] }` |
479
492
 
493
+ ## Incremental Operations (for collections)
494
+
495
+ Use these to add/remove items without replacing the entire collection:
496
+
497
+ | Type | Example |
498
+ |------|---------|
499
+ | append_table | `{ op: "append_table", fieldId: "team", value: [{ "name": "Bob", "role": "PM" }] }` |
500
+ | append_string_list | `{ op: "append_string_list", fieldId: "tags", value: ["new_tag"] }` |
501
+ | append_url_list | `{ op: "append_url_list", fieldId: "sources", value: ["https://new.com"] }` |
502
+ | delete_table | `{ op: "delete_table", fieldId: "team", value: 0 }` (0-based row index) |
503
+ | delete_string_list | `{ op: "delete_string_list", fieldId: "tags", value: 0 }` (0-based item index) |
504
+ | delete_url_list | `{ op: "delete_url_list", fieldId: "sources", value: 0 }` (0-based item index) |
505
+
480
506
  ## Important: checkboxes vs multi_select
481
507
 
482
508
  These two types look similar but have DIFFERENT value formats:
@@ -979,6 +1005,19 @@ turns:
979
1005
  | checkboxes | `{ op: "set_checkboxes", fieldId: "tasks", value: { "task1": "done", "task2": "todo" } }` |
980
1006
  | table | `{ op: "set_table", fieldId: "team", value: [{ "name": "Alice", "role": "Engineer" }] }` |
981
1007
 
1008
+ ## Incremental Operations (for collections)
1009
+
1010
+ Use these to add/remove items without replacing the entire collection:
1011
+
1012
+ | Type | Example |
1013
+ |------|---------|
1014
+ | append_table | `{ op: "append_table", fieldId: "team", value: [{ "name": "Bob", "role": "PM" }] }` |
1015
+ | append_string_list | `{ op: "append_string_list", fieldId: "tags", value: ["new_tag"] }` |
1016
+ | append_url_list | `{ op: "append_url_list", fieldId: "sources", value: ["https://new.com"] }` |
1017
+ | delete_table | `{ op: "delete_table", fieldId: "team", value: 0 }` (0-based row index) |
1018
+ | delete_string_list | `{ op: "delete_string_list", fieldId: "tags", value: 0 }` (0-based item index) |
1019
+ | delete_url_list | `{ op: "delete_url_list", fieldId: "sources", value: 0 }` (0-based item index) |
1020
+
982
1021
  ## Important: checkboxes vs multi_select
983
1022
 
984
1023
  These two types look similar but have DIFFERENT value formats:
@@ -1328,6 +1367,19 @@ turns:
1328
1367
  | checkboxes | `{ op: "set_checkboxes", fieldId: "tasks", value: { "task1": "done", "task2": "todo" } }` |
1329
1368
  | table | `{ op: "set_table", fieldId: "team", value: [{ "name": "Alice", "role": "Engineer" }] }` |
1330
1369
 
1370
+ ## Incremental Operations (for collections)
1371
+
1372
+ Use these to add/remove items without replacing the entire collection:
1373
+
1374
+ | Type | Example |
1375
+ |------|---------|
1376
+ | append_table | `{ op: "append_table", fieldId: "team", value: [{ "name": "Bob", "role": "PM" }] }` |
1377
+ | append_string_list | `{ op: "append_string_list", fieldId: "tags", value: ["new_tag"] }` |
1378
+ | append_url_list | `{ op: "append_url_list", fieldId: "sources", value: ["https://new.com"] }` |
1379
+ | delete_table | `{ op: "delete_table", fieldId: "team", value: 0 }` (0-based row index) |
1380
+ | delete_string_list | `{ op: "delete_string_list", fieldId: "tags", value: 0 }` (0-based item index) |
1381
+ | delete_url_list | `{ op: "delete_url_list", fieldId: "sources", value: 0 }` (0-based item index) |
1382
+
1331
1383
  ## Important: checkboxes vs multi_select
1332
1384
 
1333
1385
  These two types look similar but have DIFFERENT value formats:
@@ -1763,6 +1815,19 @@ turns:
1763
1815
  | checkboxes | `{ op: "set_checkboxes", fieldId: "tasks", value: { "task1": "done", "task2": "todo" } }` |
1764
1816
  | table | `{ op: "set_table", fieldId: "team", value: [{ "name": "Alice", "role": "Engineer" }] }` |
1765
1817
 
1818
+ ## Incremental Operations (for collections)
1819
+
1820
+ Use these to add/remove items without replacing the entire collection:
1821
+
1822
+ | Type | Example |
1823
+ |------|---------|
1824
+ | append_table | `{ op: "append_table", fieldId: "team", value: [{ "name": "Bob", "role": "PM" }] }` |
1825
+ | append_string_list | `{ op: "append_string_list", fieldId: "tags", value: ["new_tag"] }` |
1826
+ | append_url_list | `{ op: "append_url_list", fieldId: "sources", value: ["https://new.com"] }` |
1827
+ | delete_table | `{ op: "delete_table", fieldId: "team", value: 0 }` (0-based row index) |
1828
+ | delete_string_list | `{ op: "delete_string_list", fieldId: "tags", value: 0 }` (0-based item index) |
1829
+ | delete_url_list | `{ op: "delete_url_list", fieldId: "sources", value: 0 }` (0-based item index) |
1830
+
1766
1831
  ## Important: checkboxes vs multi_select
1767
1832
 
1768
1833
  These two types look similar but have DIFFERENT value formats:
@@ -2085,6 +2150,19 @@ turns:
2085
2150
  | checkboxes | `{ op: "set_checkboxes", fieldId: "tasks", value: { "task1": "done", "task2": "todo" } }` |
2086
2151
  | table | `{ op: "set_table", fieldId: "team", value: [{ "name": "Alice", "role": "Engineer" }] }` |
2087
2152
 
2153
+ ## Incremental Operations (for collections)
2154
+
2155
+ Use these to add/remove items without replacing the entire collection:
2156
+
2157
+ | Type | Example |
2158
+ |------|---------|
2159
+ | append_table | `{ op: "append_table", fieldId: "team", value: [{ "name": "Bob", "role": "PM" }] }` |
2160
+ | append_string_list | `{ op: "append_string_list", fieldId: "tags", value: ["new_tag"] }` |
2161
+ | append_url_list | `{ op: "append_url_list", fieldId: "sources", value: ["https://new.com"] }` |
2162
+ | delete_table | `{ op: "delete_table", fieldId: "team", value: 0 }` (0-based row index) |
2163
+ | delete_string_list | `{ op: "delete_string_list", fieldId: "tags", value: 0 }` (0-based item index) |
2164
+ | delete_url_list | `{ op: "delete_url_list", fieldId: "sources", value: 0 }` (0-based item index) |
2165
+
2088
2166
  ## Important: checkboxes vs multi_select
2089
2167
 
2090
2168
  These two types look similar but have DIFFERENT value formats:
@@ -152,6 +152,19 @@ turns:
152
152
  | checkboxes | `{ op: "set_checkboxes", fieldId: "tasks", value: { "task1": "done", "task2": "todo" } }` |
153
153
  | table | `{ op: "set_table", fieldId: "team", value: [{ "name": "Alice", "role": "Engineer" }] }` |
154
154
 
155
+ ## Incremental Operations (for collections)
156
+
157
+ Use these to add/remove items without replacing the entire collection:
158
+
159
+ | Type | Example |
160
+ |------|---------|
161
+ | append_table | `{ op: "append_table", fieldId: "team", value: [{ "name": "Bob", "role": "PM" }] }` |
162
+ | append_string_list | `{ op: "append_string_list", fieldId: "tags", value: ["new_tag"] }` |
163
+ | append_url_list | `{ op: "append_url_list", fieldId: "sources", value: ["https://new.com"] }` |
164
+ | delete_table | `{ op: "delete_table", fieldId: "team", value: 0 }` (0-based row index) |
165
+ | delete_string_list | `{ op: "delete_string_list", fieldId: "tags", value: 0 }` (0-based item index) |
166
+ | delete_url_list | `{ op: "delete_url_list", fieldId: "sources", value: 0 }` (0-based item index) |
167
+
155
168
  ## Important: checkboxes vs multi_select
156
169
 
157
170
  These two types look similar but have DIFFERENT value formats:
@@ -478,6 +491,19 @@ turns:
478
491
  | checkboxes | `{ op: "set_checkboxes", fieldId: "tasks", value: { "task1": "done", "task2": "todo" } }` |
479
492
  | table | `{ op: "set_table", fieldId: "team", value: [{ "name": "Alice", "role": "Engineer" }] }` |
480
493
 
494
+ ## Incremental Operations (for collections)
495
+
496
+ Use these to add/remove items without replacing the entire collection:
497
+
498
+ | Type | Example |
499
+ |------|---------|
500
+ | append_table | `{ op: "append_table", fieldId: "team", value: [{ "name": "Bob", "role": "PM" }] }` |
501
+ | append_string_list | `{ op: "append_string_list", fieldId: "tags", value: ["new_tag"] }` |
502
+ | append_url_list | `{ op: "append_url_list", fieldId: "sources", value: ["https://new.com"] }` |
503
+ | delete_table | `{ op: "delete_table", fieldId: "team", value: 0 }` (0-based row index) |
504
+ | delete_string_list | `{ op: "delete_string_list", fieldId: "tags", value: 0 }` (0-based item index) |
505
+ | delete_url_list | `{ op: "delete_url_list", fieldId: "sources", value: 0 }` (0-based item index) |
506
+
481
507
  ## Important: checkboxes vs multi_select
482
508
 
483
509
  These two types look similar but have DIFFERENT value formats:
@@ -980,6 +1006,19 @@ turns:
980
1006
  | checkboxes | `{ op: "set_checkboxes", fieldId: "tasks", value: { "task1": "done", "task2": "todo" } }` |
981
1007
  | table | `{ op: "set_table", fieldId: "team", value: [{ "name": "Alice", "role": "Engineer" }] }` |
982
1008
 
1009
+ ## Incremental Operations (for collections)
1010
+
1011
+ Use these to add/remove items without replacing the entire collection:
1012
+
1013
+ | Type | Example |
1014
+ |------|---------|
1015
+ | append_table | `{ op: "append_table", fieldId: "team", value: [{ "name": "Bob", "role": "PM" }] }` |
1016
+ | append_string_list | `{ op: "append_string_list", fieldId: "tags", value: ["new_tag"] }` |
1017
+ | append_url_list | `{ op: "append_url_list", fieldId: "sources", value: ["https://new.com"] }` |
1018
+ | delete_table | `{ op: "delete_table", fieldId: "team", value: 0 }` (0-based row index) |
1019
+ | delete_string_list | `{ op: "delete_string_list", fieldId: "tags", value: 0 }` (0-based item index) |
1020
+ | delete_url_list | `{ op: "delete_url_list", fieldId: "sources", value: 0 }` (0-based item index) |
1021
+
983
1022
  ## Important: checkboxes vs multi_select
984
1023
 
985
1024
  These two types look similar but have DIFFERENT value formats:
@@ -1330,6 +1369,19 @@ turns:
1330
1369
  | checkboxes | `{ op: "set_checkboxes", fieldId: "tasks", value: { "task1": "done", "task2": "todo" } }` |
1331
1370
  | table | `{ op: "set_table", fieldId: "team", value: [{ "name": "Alice", "role": "Engineer" }] }` |
1332
1371
 
1372
+ ## Incremental Operations (for collections)
1373
+
1374
+ Use these to add/remove items without replacing the entire collection:
1375
+
1376
+ | Type | Example |
1377
+ |------|---------|
1378
+ | append_table | `{ op: "append_table", fieldId: "team", value: [{ "name": "Bob", "role": "PM" }] }` |
1379
+ | append_string_list | `{ op: "append_string_list", fieldId: "tags", value: ["new_tag"] }` |
1380
+ | append_url_list | `{ op: "append_url_list", fieldId: "sources", value: ["https://new.com"] }` |
1381
+ | delete_table | `{ op: "delete_table", fieldId: "team", value: 0 }` (0-based row index) |
1382
+ | delete_string_list | `{ op: "delete_string_list", fieldId: "tags", value: 0 }` (0-based item index) |
1383
+ | delete_url_list | `{ op: "delete_url_list", fieldId: "sources", value: 0 }` (0-based item index) |
1384
+
1333
1385
  ## Important: checkboxes vs multi_select
1334
1386
 
1335
1387
  These two types look similar but have DIFFERENT value formats:
@@ -1770,6 +1822,19 @@ turns:
1770
1822
  | checkboxes | `{ op: "set_checkboxes", fieldId: "tasks", value: { "task1": "done", "task2": "todo" } }` |
1771
1823
  | table | `{ op: "set_table", fieldId: "team", value: [{ "name": "Alice", "role": "Engineer" }] }` |
1772
1824
 
1825
+ ## Incremental Operations (for collections)
1826
+
1827
+ Use these to add/remove items without replacing the entire collection:
1828
+
1829
+ | Type | Example |
1830
+ |------|---------|
1831
+ | append_table | `{ op: "append_table", fieldId: "team", value: [{ "name": "Bob", "role": "PM" }] }` |
1832
+ | append_string_list | `{ op: "append_string_list", fieldId: "tags", value: ["new_tag"] }` |
1833
+ | append_url_list | `{ op: "append_url_list", fieldId: "sources", value: ["https://new.com"] }` |
1834
+ | delete_table | `{ op: "delete_table", fieldId: "team", value: 0 }` (0-based row index) |
1835
+ | delete_string_list | `{ op: "delete_string_list", fieldId: "tags", value: 0 }` (0-based item index) |
1836
+ | delete_url_list | `{ op: "delete_url_list", fieldId: "sources", value: 0 }` (0-based item index) |
1837
+
1773
1838
  ## Important: checkboxes vs multi_select
1774
1839
 
1775
1840
  These two types look similar but have DIFFERENT value formats:
@@ -2095,6 +2160,19 @@ turns:
2095
2160
  | checkboxes | `{ op: "set_checkboxes", fieldId: "tasks", value: { "task1": "done", "task2": "todo" } }` |
2096
2161
  | table | `{ op: "set_table", fieldId: "team", value: [{ "name": "Alice", "role": "Engineer" }] }` |
2097
2162
 
2163
+ ## Incremental Operations (for collections)
2164
+
2165
+ Use these to add/remove items without replacing the entire collection:
2166
+
2167
+ | Type | Example |
2168
+ |------|---------|
2169
+ | append_table | `{ op: "append_table", fieldId: "team", value: [{ "name": "Bob", "role": "PM" }] }` |
2170
+ | append_string_list | `{ op: "append_string_list", fieldId: "tags", value: ["new_tag"] }` |
2171
+ | append_url_list | `{ op: "append_url_list", fieldId: "sources", value: ["https://new.com"] }` |
2172
+ | delete_table | `{ op: "delete_table", fieldId: "team", value: 0 }` (0-based row index) |
2173
+ | delete_string_list | `{ op: "delete_string_list", fieldId: "tags", value: 0 }` (0-based item index) |
2174
+ | delete_url_list | `{ op: "delete_url_list", fieldId: "sources", value: 0 }` (0-based item index) |
2175
+
2098
2176
  ## Important: checkboxes vs multi_select
2099
2177
 
2100
2178
  These two types look similar but have DIFFERENT value formats:
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "markform",
3
- "version": "0.1.22",
3
+ "version": "0.1.24",
4
4
  "description": "Markdown forms for token-friendly workflows",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "author": "Joshua Levy",
@@ -92,7 +92,7 @@
92
92
  "vitest": "^4.0.18"
93
93
  },
94
94
  "scripts": {
95
- "copy-docs": "cp ../../README.md . && mkdir -p docs && cp ../../docs/markform-spec.md docs/ && cp ../../docs/markform-reference.md docs/ && cp ../../docs/markform-apis.md docs/",
95
+ "copy-docs": "cp ../../README.md . && mkdir -p docs docs/skill && cp ../../docs/markform-spec.md docs/ && cp ../../docs/markform-reference.md docs/ && cp ../../docs/markform-apis.md docs/ && cp ../../docs/skill/SKILL.md docs/skill/",
96
96
  "build": "pnpm run copy-docs && tsdown",
97
97
  "dev": "tsdown --watch",
98
98
  "typecheck": "tsc -p tsconfig.json --noEmit",