markform 0.1.24 → 0.1.26

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 (44) hide show
  1. package/README.md +55 -31
  2. package/dist/ai-sdk.d.mts +1 -1
  3. package/dist/ai-sdk.mjs +2 -2
  4. package/dist/bin.mjs +1 -1
  5. package/dist/{cli-B1DhFYBS.mjs → cli-BMQ9k9z7.mjs} +85 -40
  6. package/dist/cli-BMQ9k9z7.mjs.map +1 -0
  7. package/dist/cli.mjs +1 -1
  8. package/dist/{coreTypes-GxzWNXap.d.mts → coreTypes-CxpqKpBA.d.mts} +45 -2
  9. package/dist/{coreTypes-CctFK6uE.mjs → coreTypes-DIv9Aabl.mjs} +19 -5
  10. package/dist/coreTypes-DIv9Aabl.mjs.map +1 -0
  11. package/dist/{fillRecord-DeqI2pQ5.d.mts → fillRecord-V3vlyobd.d.mts} +5 -1
  12. package/dist/{fillRecordRenderer-VBQ2vwPV.mjs → fillRecordRenderer-BqRPHPmE.mjs} +47 -15
  13. package/dist/fillRecordRenderer-BqRPHPmE.mjs.map +1 -0
  14. package/dist/index.d.mts +32 -4
  15. package/dist/index.mjs +4 -4
  16. package/dist/{prompts-BCnYaH4_.mjs → prompts-4jZmkGKW.mjs} +114 -11
  17. package/dist/prompts-4jZmkGKW.mjs.map +1 -0
  18. package/dist/render.d.mts +2 -2
  19. package/dist/render.mjs +1 -1
  20. package/dist/{session-BLjN3BkJ.mjs → session-BW9jtYNV.mjs} +2 -2
  21. package/dist/{session-BLjN3BkJ.mjs.map → session-BW9jtYNV.mjs.map} +1 -1
  22. package/dist/{session-D7C7IlEv.mjs → session-DHyTMP67.mjs} +1 -1
  23. package/dist/{shared-DtorFV21.mjs → shared-BLh342F5.mjs} +1 -1
  24. package/dist/{shared-CuSRYcIB.mjs → shared-BszoSkAO.mjs} +8 -8
  25. package/dist/{shared-CuSRYcIB.mjs.map → shared-BszoSkAO.mjs.map} +1 -1
  26. package/dist/{src-C5OWf1dL.mjs → src-Dy3cDjDS.mjs} +165 -35
  27. package/dist/src-Dy3cDjDS.mjs.map +1 -0
  28. package/docs/markform-apis.md +19 -7
  29. package/docs/markform-reference.md +247 -178
  30. package/docs/markform-spec.md +81 -33
  31. package/docs/skill/SKILL.md +62 -20
  32. package/examples/markform-demo-playbook.md +342 -0
  33. package/examples/parallel/parallel-research.form.md +2 -6
  34. package/examples/simple/simple-mock-filled.report.md +2 -2
  35. package/examples/simple/simple-skipped-filled.report.md +2 -2
  36. package/examples/twitter-thread/twitter-thread.form.md +5 -5
  37. package/package.json +1 -1
  38. package/dist/cli-B1DhFYBS.mjs.map +0 -1
  39. package/dist/coreTypes-CctFK6uE.mjs.map +0 -1
  40. package/dist/fillRecordRenderer-VBQ2vwPV.mjs.map +0 -1
  41. package/dist/prompts-BCnYaH4_.mjs.map +0 -1
  42. package/dist/src-C5OWf1dL.mjs.map +0 -1
  43. package/examples/startup-research/startup-research-mock-filled.form.md +0 -297
  44. package/examples/startup-research/startup-research.form.md +0 -181
@@ -1,12 +1,12 @@
1
- <!--
2
- SPDX-License-Identifier: CC-BY-4.0
1
+ <!-- SPDX-License-Identifier: CC-BY-4.0
3
2
 
4
3
  Markform Specification - Licensed under Creative Commons Attribution 4.0 International
5
4
  https://creativecommons.org/licenses/by/4.0/
6
5
 
7
6
  You may freely implement this specification in your own software under any license.
8
- The reference implementation at https://github.com/jlevy/markform is separately
9
- licensed under AGPL-3.0-or-later. Contact the author for commercial licensing options.
7
+ The reference implementation at https://github.com/jlevy/markform is separately licensed
8
+ under AGPL-3.0-or-later.
9
+ Contact the author for commercial licensing options.
10
10
  -->
11
11
 
12
12
  # Markform Specification
@@ -145,17 +145,17 @@ markform:
145
145
  This is a hint for tooling, not enforced by the engine.
146
146
 
147
147
  - `harness` (*optional*): A map of harness configuration hints that suggest execution
148
- parameters to harness implementations. These are suggestions — a harness MAY ignore
149
- them or override them via API options.
148
+ parameters to harness implementations.
149
+ These are suggestions — a harness MAY ignore them or override them via API options.
150
150
 
151
151
  Supported keys (all values must be numbers, all keys must be `snake_case`):
152
152
 
153
- | Key | Description |
154
- | --- | --- |
155
- | `max_turns` | Suggested maximum turns before stopping |
156
- | `max_patches_per_turn` | Suggested maximum patches per turn |
157
- | `max_issues_per_turn` | Suggested maximum issues surfaced per turn |
158
- | `max_parallel_agents` | Suggested maximum concurrent agents for parallel execution |
153
+ | Key | Description |
154
+ | --- | --- |
155
+ | `max_turns` | Suggested maximum turns before stopping |
156
+ | `max_patches_per_turn` | Suggested maximum patches per turn |
157
+ | `max_issues_per_turn` | Suggested maximum issues surfaced per turn |
158
+ | `max_parallel_agents` | Suggested maximum concurrent agents for parallel execution |
159
159
 
160
160
  Unrecognized keys or non-numeric values are parse errors.
161
161
 
@@ -225,8 +225,8 @@ Markform defines its own scoping rules where option IDs are field-scoped.
225
225
 
226
226
  - Duplicate `(ref, tag)` pairs are an error
227
227
 
228
- - Multiple doc blocks can reference the same target with different tags (e.g., both `{%
229
- description ref="foo" %}` and `{% instructions ref="foo" %}` are allowed)
228
+ - Multiple doc blocks can reference the same target with different tags (e.g., both
229
+ `{% description ref="foo" %}` and `{% instructions ref="foo" %}` are allowed)
230
230
 
231
231
  - To reference an option, use qualified form: `ref="{fieldId}.{optionId}"`
232
232
 
@@ -298,8 +298,8 @@ parse error.
298
298
 
299
299
  **Nesting constraints:**
300
300
  - Field tags MUST NOT be nested inside other field tags
301
- - Nested field tags produce a parse error:
302
- `Field tags cannot be nested. Found 'inner_id' inside 'outer_id'`
301
+ - Nested field tags produce a parse error: `Field tags cannot be nested.
302
+ Found 'inner_id' inside 'outer_id'`
303
303
 
304
304
  **Example with placeholder and examples:**
305
305
  ```md
@@ -409,9 +409,11 @@ Type: `integer`, default: `-1` (require all).
409
409
  Example with partial completion allowed:
410
410
  ```md
411
411
  {% field kind="checkboxes" id="optional_tasks" label="Optional tasks" required=true minDone=1 %}
412
+
412
413
  - [ ] Task A {% #task_a %}
413
414
  - [ ] Task B {% #task_b %}
414
415
  - [ ] Task C {% #task_c %}
416
+
415
417
  {% /field %}
416
418
  ```
417
419
 
@@ -456,7 +458,7 @@ type.
456
458
  | --- | --- | --- | --- |
457
459
  | `columnIds` | string[] | Yes | Array of snake_case column identifiers |
458
460
  | `columnLabels` | string[] | No | Array of display labels (backfilled from table header row if omitted) |
459
- | `columnTypes` | string[] | No | Array of column types (defaults to all `'string'`) |
461
+ | `columnTypes` | (string \| object)[] | No | Array of column types with optional constraints (defaults to all `'string'`) |
460
462
  | `minRows` | number | No | Minimum row count (default: 0) |
461
463
  | `maxRows` | number | No | Maximum row count (default: unlimited) |
462
464
 
@@ -464,23 +466,50 @@ type.
464
466
 
465
467
  | Type | Description | Validation |
466
468
  | --- | --- | --- |
467
- | `string` | Any text value | None |
469
+ | `string` | Any text value | None (unless constraints specified) |
468
470
  | `number` | Numeric value | Integer or float |
469
471
  | `url` | URL value | Valid URL format |
470
472
  | `date` | Date value | ISO 8601 format (YYYY-MM-DD) |
471
473
  | `year` | Year value | Integer (1000-9999) |
472
474
 
473
- **Per-column required setting:** Column types can optionally specify a `required` flag:
475
+ **Per-column required setting and constraints:** Column types can be specified as a
476
+ simple type name or an object with type, required flag, and optional constraints:
474
477
  ```md
475
478
  columnTypes=[{type: "string", required: true}, "number", "url"]
476
479
  ```
477
480
 
481
+ **Per-column constraints by type:**
482
+
483
+ | Constraint | Applies to | Description |
484
+ | --- | --- | --- |
485
+ | `required` | all types | Cell must have a value |
486
+ | `minLength` | `string` | Minimum string length |
487
+ | `maxLength` | `string` | Maximum string length |
488
+ | `pattern` | `string` | Regex pattern the value must match |
489
+ | `enum` | `string` | Array of allowed values (controlled vocabulary) |
490
+ | `min` | `number`, `year`, `date` | Minimum value (number for number/year, ISO date string for date) |
491
+ | `max` | `number`, `year`, `date` | Maximum value |
492
+ | `integer` | `number` | Value must be an integer |
493
+
494
+ **Example with per-column constraints:**
495
+ ```md
496
+ {% field kind="table" id="priority_table" label="Ranked Insights"
497
+ columnIds=["rank", "summary", "role"]
498
+ columnTypes=[{"type": "number", "min": 1, "integer": true}, "string", {"type": "string", "enum": ["hook", "context", "example", "summary"]}]
499
+ minRows=3 maxRows=15 %}
500
+ | Rank | Summary | Role |
501
+ |------|---------|------|
502
+
503
+ {% /field %}
504
+ ```
505
+
478
506
  **Basic table-field (columnLabels backfilled from header row):**
479
507
  ```md
480
508
  {% field kind="table" id="team" label="Team Members"
481
509
  columnIds=["name", "title", "department"] %}
482
510
  | Name | Title | Department |
483
511
  |------|-------|------------|
512
+
484
513
  {% /field %}
485
514
  ```
486
515
 
@@ -492,6 +521,7 @@ columnTypes=[{type: "string", required: true}, "number", "url"]
492
521
  columnTypes=["string", "string", "string"] %}
493
522
  | Full Name | Job Title | Department |
494
523
  |-----------|-----------|------------|
524
+
495
525
  {% /field %}
496
526
  ```
497
527
 
@@ -506,6 +536,7 @@ columnTypes=[{type: "string", required: true}, "number", "url"]
506
536
  |------|-------|----------|-----------------|
507
537
  | 2023 | Barbie | 88 | 1441.8 |
508
538
  | 2019 | Once Upon a Time in Hollywood | 85 | 374.3 |
539
+
509
540
  {% /field %}
510
541
  ```
511
542
 
@@ -564,11 +595,11 @@ without filtering out nested doc blocks.
564
595
 
565
596
  - Doc blocks do not have their own IDs
566
597
 
567
- - *required:* `(ref, tag)` combination must be unique (e.g., only one `{% instructions
568
- ref="foo" %}`)
598
+ - *required:* `(ref, tag)` combination must be unique (e.g., only one
599
+ `{% instructions ref="foo" %}`)
569
600
 
570
- - Multiple doc blocks with different tags can reference the same target (e.g., both `{%
571
- description ref="foo" %}` and `{% instructions ref="foo" %}` are allowed)
601
+ - Multiple doc blocks with different tags can reference the same target (e.g., both
602
+ `{% description ref="foo" %}` and `{% instructions ref="foo" %}` are allowed)
572
603
 
573
604
  #### Field Values
574
605
 
@@ -614,9 +645,11 @@ Values are encoded **inline** via `[x]` marker—at most one option may be selec
614
645
  `required=true`, exactly one must be selected):
615
646
  ```md
616
647
  {% field kind="single_select" id="rating" label="Rating" %}
648
+
617
649
  - [ ] Bullish {% #bullish %}
618
650
  - [x] Neutral {% #neutral %}
619
651
  - [ ] Bearish {% #bearish %}
652
+
620
653
  {% /field %}
621
654
  ````
622
655
 
@@ -627,9 +660,11 @@ Option IDs are scoped to the field—reference as `rating.bullish`, `rating.neut
627
660
  Values are encoded **inline** via `[x]` markers—no separate value fence:
628
661
  ```md
629
662
  {% field kind="multi_select" id="categories" label="Categories" %}
663
+
630
664
  - [x] Technology {% #tech %}
631
665
  - [ ] Healthcare {% #health %}
632
666
  - [x] Finance {% #finance %}
667
+
633
668
  {% /field %}
634
669
  ```
635
670
 
@@ -638,28 +673,34 @@ Values are encoded **inline** via `[x]` markers—no separate value fence:
638
673
  Values are encoded **inline** via state markers—no separate value fence:
639
674
  ```md
640
675
  {% field kind="checkboxes" id="tasks" label="Tasks" %}
676
+
641
677
  - [x] Review docs {% #review %}
642
678
  - [/] Write tests {% #tests %}
643
679
  - [*] Run CI {% #ci %}
644
680
  - [ ] Deploy {% #deploy %}
645
681
  - [-] Manual QA {% #manual_qa %}
682
+
646
683
  {% /field %}
647
684
  ```
648
685
 
649
686
  For simple two-state checkboxes:
650
687
  ```md
651
688
  {% field kind="checkboxes" id="agreements" label="Agreements" checkboxMode="simple" %}
689
+
652
690
  - [x] I agree to terms {% #terms %}
653
691
  - [ ] Subscribe to newsletter {% #newsletter %}
692
+
654
693
  {% /field %}
655
694
  ```
656
695
 
657
696
  For explicit yes/no checkboxes (requires answer for each):
658
697
  ```md
659
698
  {% field kind="checkboxes" id="risk_factors" label="Risk Assessment" checkboxMode="explicit" required=true %}
699
+
660
700
  - [y] Market volatility risk assessed {% #market %}
661
701
  - [n] Regulatory risk assessed {% #regulatory %}
662
702
  - [ ] Currency risk assessed {% #currency %}
703
+
663
704
  {% /field %}
664
705
  ```
665
706
 
@@ -669,8 +710,8 @@ answers.
669
710
 
670
711
  ##### Implicit Checkboxes (Plan Documents)
671
712
 
672
- Forms designed as task lists or plans can omit explicit field wrappers. When a form
673
- contains:
713
+ Forms designed as task lists or plans can omit explicit field wrappers.
714
+ When a form contains:
674
715
  - A `{% form %}` wrapper (or `<!-- form ... -->`)
675
716
  - No explicit `{% field %}` tags
676
717
  - Standard markdown checkboxes with ID annotations
@@ -882,7 +923,7 @@ Analysis completed with partial data due to API limitations.
882
923
  ```value
883
924
  %SKIP% (Not applicable for this analysis type)
884
925
  ````
885
- {% /field %} {% /group %}
926
+ {% /field %}{% /group %}
886
927
 
887
928
  {% note id="n1" ref="quarterly_earnings" role="agent" %} Analysis completed with partial
888
929
  data due to API limitations.
@@ -961,10 +1002,12 @@ Prepare an earnings-call brief by extracting key financials and writing a thesis
961
1002
 
962
1003
  {% group id="source_docs" title="Source Documents" %}
963
1004
  {% field kind="checkboxes" id="docs_reviewed" label="Documents reviewed" required=true %}
1005
+
964
1006
  - [ ] 10-K {% #ten_k %}
965
1007
  - [ ] 10-Q {% #ten_q %}
966
1008
  - [ ] Earnings release {% #earnings_release %}
967
1009
  - [ ] Earnings call transcript {% #call_transcript %}
1010
+
968
1011
  {% /field %}
969
1012
  {% /group %}
970
1013
 
@@ -976,9 +1019,11 @@ Prepare an earnings-call brief by extracting key financials and writing a thesis
976
1019
 
977
1020
  {% group id="analysis" title="Analysis" %}
978
1021
  {% field kind="single_select" id="rating" label="Overall rating" required=true %}
1022
+
979
1023
  - [ ] Bullish {% #bullish %}
980
1024
  - [ ] Neutral {% #neutral %}
981
1025
  - [ ] Bearish {% #bearish %}
1026
+
982
1027
  {% /field %}
983
1028
  {% field kind="string" id="thesis" label="Investment thesis" required=true %}{% /field %}
984
1029
  {% /group %}
@@ -998,15 +1043,16 @@ Hand-authored forms only need the `spec` field.
998
1043
  ```value
999
1044
  ACME Corp
1000
1045
  ````
1001
- {% /field %} {% field kind="string" id="ticker" label="Ticker" required=true %}
1046
+ {% /field %}{% field kind="string" id="ticker" label="Ticker" required=true %}
1002
1047
  ```value
1003
1048
  ACME
1004
1049
  ```
1005
- {% /field %} {% field kind="string" id="fiscal_period" label="Fiscal period"
1006
- required=true %}{% /field %} {% /group %}
1050
+ {% /field %}
1051
+ {% field kind="string" id="fiscal_period" label="Fiscal period" required=true %}{% /field %}
1052
+ {% /group %}
1007
1053
 
1008
- {% group id="source_docs" title="Source Documents" %} {% checkboxes id="docs_reviewed"
1009
- label="Documents reviewed" required=true %}
1054
+ {% group id="source_docs" title="Source Documents" %}
1055
+ {% checkboxes id="docs_reviewed" label="Documents reviewed" required=true %}
1010
1056
 
1011
1057
  - [x] 10-K {% #ten_k %}
1012
1058
 
@@ -1014,7 +1060,7 @@ label="Documents reviewed" required=true %}
1014
1060
 
1015
1061
  - [/] Earnings release {% #earnings_release %}
1016
1062
 
1017
- - [ ] Earnings call transcript {% #call_transcript %} {% /field %} {% /group %}
1063
+ - [ ] Earnings call transcript {% #call_transcript %}{% /field %}{% /group %}
1018
1064
  ````
1019
1065
 
1020
1066
  Notes:
@@ -1268,9 +1314,11 @@ markform:
1268
1314
  <!-- group id="ratings" -->
1269
1315
 
1270
1316
  <!-- field kind="single_select" id="quality" label="Quality Rating" -->
1317
+
1271
1318
  - [ ] Excellent <!-- #excellent -->
1272
1319
  - [ ] Good <!-- #good -->
1273
1320
  - [ ] Fair <!-- #fair -->
1321
+
1274
1322
  <!-- /field -->
1275
1323
 
1276
1324
  <!-- /group -->
@@ -1368,7 +1416,7 @@ classification) and **data types** (the underlying value representation).
1368
1416
  | **Data Type** | TypeScript/JSON type of the value. | `string`, `number`, `string[]` |
1369
1417
  | **Value Type** | Complete type expression including nullability. | `string \| null`, `OptionId[]` |
1370
1418
  | **Scalar Type** | Single atomic value (optionally format-constrained). | `string`, `url`, `date` |
1371
- | **Column Type** | Type of a cell in a table field (subset of scalar types). | `string`, `number`, `url` |
1419
+ | **Column Type** | Type of a cell in a table field (subset of scalar types). Supports per-column constraints (minLength, maxLength, pattern, enum, min, max, integer). | `string`, `number`, `url` |
1372
1420
 
1373
1421
  ##### Data Type Taxonomy
1374
1422
 
@@ -7,22 +7,61 @@ description: >-
7
7
  or when the user mentions markform, forms, form filling, structured data, or field validation.
8
8
  allowed-tools: Bash(markform:*)
9
9
  ---
10
+ # Markform Agent Skill
10
11
 
11
- # Markform Agent Skill
12
+ Markform is structured Markdown for forms.
13
+ Files combine YAML frontmatter with HTML comment tags to define typed, validated fields.
14
+ Forms render cleanly on GitHub since structure is hidden in comments.
12
15
 
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
+ ## Getting Started
17
+
18
+ There are three ways to help a user get started with Markform:
19
+
20
+ 1. **Run an example automatically:** `markform examples` copies bundled forms, then
21
+ `markform run <form>` fills one end-to-end with an LLM. Quickest demo.
22
+ 2. **Agent-guided example tour:** Walk the user through a specific bundled example step
23
+ by step—copy it, inspect the structure, fill fields, validate, and export.
24
+ Use `markform examples --list` to pick an example, then `--name <id>` to copy it.
25
+ 3. **End-to-end walkthrough playbook:** Follow `examples/markform-demo-playbook.md` to
26
+ design a research form from scratch, fill it with real data, validate, export, and
27
+ browse. The most thorough tour of all Markform features.
28
+
29
+ ### API Key Setup
30
+
31
+ Automated filling (`markform fill --model`, `markform run`) requires an LLM API key.
32
+ Set one of these environment variables (or add to `.env`):
33
+
34
+ - `OPENAI_API_KEY` — for OpenAI models (e.g., `openai/gpt-4o`)
35
+ - `ANTHROPIC_API_KEY` — for Anthropic models (e.g.,
36
+ `anthropic/claude-sonnet-4-5-20250929`)
37
+
38
+ Run `markform models` to see available providers and configured keys.
39
+
40
+ ### Bundled Examples
41
+
42
+ | Example | Type | Description |
43
+ | --- | --- | --- |
44
+ | `movie-research-demo` | research | Quick movie ratings lookup (IMDB, Rotten Tomatoes) |
45
+ | `simple` | fill | Interactive demo of all field types |
46
+ | `twitter-thread` | fill | Multi-stage content-to-Twitter-thread transformation |
47
+ | `movie-deep-research` | research | Comprehensive movie analysis with multiple sources |
48
+ | `startup-deep-research` | research | Startup intelligence: funding, team, market, press |
49
+
50
+ ```bash
51
+ markform examples --list # See all examples
52
+ markform examples --list --format=json # Structured output for agents
53
+ markform examples --name <id> --forms-dir ./ # Copy a specific example
54
+ ```
16
55
 
17
56
  ## What Markform Does
18
57
 
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
58
+ 1. **Structured Forms:** Define typed fields (string, number, select, table, etc.)
59
+ in Markdown with validation constraints
60
+ 2. **Role-Based Filling:** Separate fields for humans (`role="user"`) and AI agents
22
61
  (`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
62
+ 3. **Incremental Filling:** Fill fields one at a time with immediate validation
63
+ 4. **Agent-Driven Workflows:** AI agents fill forms via CLI or programmatic API
64
+ 5. **Multi-Format Export:** Export filled data as JSON, YAML, or Markdown
26
65
 
27
66
  ## Core CLI Commands
28
67
 
@@ -37,6 +76,8 @@ structure is hidden in comments.
37
76
  | `markform fill <form> --model <model>` | AI agent fills form fields |
38
77
  | `markform export <form> --format=json` | Export values as JSON |
39
78
  | `markform export <form> --format=yaml` | Export values as YAML |
79
+ | `markform export <form> --format=markdown` | Full rendered markdown (includes instructions) |
80
+ | `markform report <form>` | Clean report markdown (values only, no instructions) |
40
81
  | `markform schema <form>` | Export JSON Schema for form structure |
41
82
  | `markform dump <form>` | Quick dump of current field values |
42
83
  | `markform status <form>` | Show fill progress per role |
@@ -48,19 +89,19 @@ structure is hidden in comments.
48
89
 
49
90
  When working with markform files:
50
91
 
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
92
+ 1. **Inspect first:** `markform inspect form.md` to understand the form structure, see
93
+ which fields exist, their types, constraints, and current fill progress
94
+ 2. **Check whats next:** `markform next form.md` to see which field should be filled
95
+ next (respects priority, order, and role)
96
+ 3. **Set values:** `markform set form.md field_id "value"` to fill fields one at a time,
97
+ or use `--values` for batch updates
98
+ 4. **Validate:** `markform validate form.md` to check all constraints are met
99
+ 5. **Export:** `markform export form.md --format=json` to extract filled data
59
100
 
60
101
  ## Setting Field Values
61
102
 
62
- The `set` command is the primary way to fill fields. It auto-coerces values to
63
- the correct type:
103
+ The `set` command is the primary way to fill fields.
104
+ It auto-coerces values to the correct type:
64
105
 
65
106
  ```bash
66
107
  # String fields
@@ -117,3 +158,4 @@ All commands support:
117
158
  - Full specification: `markform spec`
118
159
  - API documentation: `markform apis`
119
160
  - Example forms: `markform examples`
161
+ - End-to-end walkthrough: `examples/markform-demo-playbook.md`