markform 0.1.1 → 0.1.3

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 (36) hide show
  1. package/DOCS.md +546 -0
  2. package/README.md +340 -71
  3. package/SPEC.md +2779 -0
  4. package/dist/ai-sdk.d.mts +2 -2
  5. package/dist/ai-sdk.mjs +5 -3
  6. package/dist/{apply-BQdd-fdx.mjs → apply-00UmzDKL.mjs} +849 -730
  7. package/dist/bin.mjs +6 -3
  8. package/dist/{cli-pjOiHgCW.mjs → cli-D--Lel-e.mjs} +1374 -428
  9. package/dist/cli.mjs +6 -3
  10. package/dist/{coreTypes--6etkcwb.d.mts → coreTypes-BXhhz9Iq.d.mts} +1946 -794
  11. package/dist/coreTypes-Dful87E0.mjs +537 -0
  12. package/dist/index.d.mts +116 -19
  13. package/dist/index.mjs +5 -3
  14. package/dist/session-Bqnwi9wp.mjs +110 -0
  15. package/dist/session-DdAtY2Ni.mjs +4 -0
  16. package/dist/shared-D7gf27Tr.mjs +3 -0
  17. package/dist/shared-N_s1M-_K.mjs +176 -0
  18. package/dist/src-Dm8jZ5dl.mjs +7587 -0
  19. package/examples/celebrity-deep-research/celebrity-deep-research.form.md +912 -0
  20. package/examples/earnings-analysis/earnings-analysis.form.md +6 -1
  21. package/examples/earnings-analysis/earnings-analysis.valid.ts +119 -59
  22. package/examples/movie-research/movie-research-basic.form.md +164 -0
  23. package/examples/movie-research/movie-research-deep.form.md +486 -0
  24. package/examples/movie-research/movie-research-minimal.form.md +54 -0
  25. package/examples/simple/simple-mock-filled.form.md +17 -13
  26. package/examples/simple/simple-skipped-filled.form.md +32 -9
  27. package/examples/simple/simple-with-skips.session.yaml +102 -143
  28. package/examples/simple/simple.form.md +13 -13
  29. package/examples/simple/simple.session.yaml +80 -69
  30. package/examples/startup-deep-research/startup-deep-research.form.md +60 -8
  31. package/examples/startup-research/startup-research-mock-filled.form.md +1 -1
  32. package/examples/startup-research/startup-research.form.md +1 -1
  33. package/package.json +10 -14
  34. package/dist/src-Cs4_9lWP.mjs +0 -2151
  35. package/examples/political-research/political-research.form.md +0 -233
  36. package/examples/political-research/political-research.mock.lincoln.form.md +0 -355
package/DOCS.md ADDED
@@ -0,0 +1,546 @@
1
+ # Markform Quick Reference
2
+
3
+ **Version:** MF/0.1
4
+
5
+ Markform is structured Markdown for forms.
6
+ Files combine YAML frontmatter with [Markdoc](https://markdoc.dev/) tags to define
7
+ typed, validated fields.
8
+
9
+ **More info:** [Project README](https://github.com/jlevy/markform) |
10
+ [Full Specification](https://github.com/jlevy/markform/blob/main/SPEC.md) (`markform
11
+ spec`)
12
+
13
+ ## Installation
14
+
15
+ ```bash
16
+ npm install -g markform # Global CLI
17
+ npm install markform # Project dependency
18
+ ```
19
+
20
+ Run the CLI as `npx markform` or simply `markform` if installed globally.
21
+
22
+ Requires Node.js 20+. See [README](https://github.com/jlevy/markform) for full details.
23
+
24
+ ## File Structure
25
+
26
+ ```markdown
27
+ ---
28
+ markform:
29
+ spec: MF/0.1
30
+ title: "Form Title"
31
+ description: "What this form does"
32
+ roles:
33
+ - user
34
+ - agent
35
+ role_instructions:
36
+ user: "Instructions for human users"
37
+ agent: "Instructions for AI agents"
38
+ ---
39
+
40
+ {% form id="form_id" title="Form Title" %}
41
+
42
+ {% field-group id="group_id" title="Group Title" %}
43
+
44
+ <!-- fields go here -->
45
+
46
+ {% /field-group %}
47
+
48
+ {% /form %}
49
+ ```
50
+
51
+ ## Conventions
52
+
53
+ Use `.form.md` for Markform files.
54
+ They are Markdoc syntax, which is a superset of Markdown.
55
+
56
+ ## Field Types
57
+
58
+ ### String Field
59
+
60
+ Single-line or multi-line text.
61
+
62
+ ````markdown
63
+ {% string-field id="name" label="Name" required=true minLength=2 maxLength=100 %}{% /string-field %}
64
+
65
+ {% string-field id="bio" label="Biography" pattern="^[A-Z].*" %}
66
+ ```value
67
+ Existing value here
68
+ ````
69
+ {% /string-field %}
70
+ ````
71
+
72
+ | Attribute | Type | Description |
73
+ |-----------|------|-------------|
74
+ | `minLength` | number | Minimum character count |
75
+ | `maxLength` | number | Maximum character count |
76
+ | `pattern` | string | JavaScript regex (no delimiters) |
77
+
78
+ ### Number Field
79
+
80
+ Numeric values with optional constraints.
81
+
82
+ ```markdown
83
+ {% number-field id="age" label="Age" required=true min=0 max=150 integer=true %}{% /number-field %}
84
+
85
+ {% number-field id="price" label="Price" min=0.01 max=999999.99 %}
86
+ ```value
87
+ 49.99
88
+ ````
89
+ {% /number-field %}
90
+ ````
91
+
92
+ | Attribute | Type | Description |
93
+ |-----------|------|-------------|
94
+ | `min` | number | Minimum value |
95
+ | `max` | number | Maximum value |
96
+ | `integer` | boolean | Require whole numbers |
97
+
98
+ ### String List
99
+
100
+ Array of strings, one per line.
101
+
102
+ ```markdown
103
+ {% string-list id="tags" label="Tags" required=true minItems=1 maxItems=10 uniqueItems=true %}{% /string-list %}
104
+
105
+ {% string-list id="features" label="Key Features" minItems=3 itemMinLength=10 %}
106
+ ```value
107
+ Feature one description
108
+ Feature two description
109
+ Feature three description
110
+ ````
111
+ {% /string-list %}
112
+ ````
113
+
114
+ | Attribute | Type | Description |
115
+ |-----------|------|-------------|
116
+ | `minItems` | number | Minimum items required |
117
+ | `maxItems` | number | Maximum items allowed |
118
+ | `itemMinLength` | number | Min length per item |
119
+ | `itemMaxLength` | number | Max length per item |
120
+ | `uniqueItems` | boolean | No duplicates allowed |
121
+
122
+ ### Single Select
123
+
124
+ Choose exactly one option.
125
+
126
+ ```markdown
127
+ {% single-select id="rating" label="Rating" required=true %}
128
+ - [ ] Low {% #low %}
129
+ - [ ] Medium {% #medium %}
130
+ - [x] High {% #high %}
131
+ {% /single-select %}
132
+ ````
133
+
134
+ Options use `[ ]` (unselected) or `[x]` (selected).
135
+ Each option needs `{% #id %}`.
136
+
137
+ ### Multi Select
138
+
139
+ Choose multiple options.
140
+
141
+ ```markdown
142
+ {% multi-select id="categories" label="Categories" required=true minSelections=1 maxSelections=3 %}
143
+ - [x] Frontend {% #frontend %}
144
+ - [x] Backend {% #backend %}
145
+ - [ ] Database {% #database %}
146
+ - [ ] DevOps {% #devops %}
147
+ {% /multi-select %}
148
+ ```
149
+
150
+ | Attribute | Type | Description |
151
+ | --- | --- | --- |
152
+ | `minSelections` | number | Minimum selections |
153
+ | `maxSelections` | number | Maximum selections |
154
+
155
+ ### Checkboxes
156
+
157
+ Stateful checklists with three modes.
158
+
159
+ **Multi Mode** (default) - 5 states for workflow tracking:
160
+
161
+ ```markdown
162
+ {% checkboxes id="tasks" label="Tasks" required=true checkboxMode="multi" %}
163
+ - [ ] Research {% #research %}
164
+ - [x] Design {% #design %}
165
+ - [/] Implementation {% #impl %}
166
+ - [*] Testing {% #test %}
167
+ - [-] N/A item {% #na %}
168
+ {% /checkboxes %}
169
+ ```
170
+
171
+ | Token | State | Meaning |
172
+ | --- | --- | --- |
173
+ | `[ ]` | todo | Not started |
174
+ | `[x]` | done | Completed |
175
+ | `[/]` | incomplete | Work started |
176
+ | `[*]` | active | Currently working |
177
+ | `[-]` | na | Not applicable |
178
+
179
+ **Simple Mode** - 2 states (GFM compatible):
180
+
181
+ ```markdown
182
+ {% checkboxes id="agreements" label="Agreements" checkboxMode="simple" required=true %}
183
+ - [x] I agree to terms {% #terms %}
184
+ - [ ] Subscribe to newsletter {% #news %}
185
+ {% /checkboxes %}
186
+ ```
187
+
188
+ **Explicit Mode** - Requires yes/no for each:
189
+
190
+ ```markdown
191
+ {% checkboxes id="confirmations" label="Confirmations" checkboxMode="explicit" required=true %}
192
+ - [y] Backup completed {% #backup %}
193
+ - [n] Stakeholders notified {% #notify %}
194
+ - [ ] Deployment ready {% #deploy %}
195
+ {% /checkboxes %}
196
+ ```
197
+
198
+ | Token | Value | Meaning |
199
+ | --- | --- | --- |
200
+ | `[ ]` | unfilled | Not answered (invalid) |
201
+ | `[y]` | yes | Explicit yes |
202
+ | `[n]` | no | Explicit no |
203
+
204
+ ### URL Field
205
+
206
+ Single URL with format validation.
207
+
208
+ ````markdown
209
+ {% url-field id="website" label="Website" required=true %}{% /url-field %}
210
+
211
+ {% url-field id="repo" label="Repository" %}
212
+ ```value
213
+ https://github.com/example/repo
214
+ ````
215
+ {% /url-field %}
216
+ ````
217
+
218
+ ### URL List
219
+
220
+ Array of URLs.
221
+
222
+ ```markdown
223
+ {% url-list id="sources" label="Sources" required=true minItems=1 maxItems=10 uniqueItems=true %}
224
+ ```value
225
+ https://example.com/source1
226
+ https://example.com/source2
227
+ ````
228
+ {% /url-list %}
229
+ ````
230
+
231
+ ## Common Attributes
232
+
233
+ All fields support these attributes:
234
+
235
+ | Attribute | Type | Default | Description |
236
+ |-----------|------|---------|-------------|
237
+ | `id` | string | required | Unique snake_case identifier |
238
+ | `label` | string | required | Human-readable label |
239
+ | `required` | boolean | false | Must be filled for completion |
240
+ | `role` | string | - | Target actor (`user`, `agent`) |
241
+ | `priority` | string | medium | `high`, `medium`, `low` |
242
+
243
+ ## Documentation Blocks
244
+
245
+ Add context to fields, groups, or the form.
246
+
247
+ ```markdown
248
+ {% description ref="form_id" %}
249
+ Overall form description and purpose.
250
+ {% /description %}
251
+
252
+ {% instructions ref="field_id" %}
253
+ Step-by-step guidance for filling this field.
254
+ {% /instructions %}
255
+
256
+ {% notes ref="field_id" %}
257
+ Additional context or caveats.
258
+ {% /notes %}
259
+
260
+ {% examples ref="field_id" %}
261
+ Example values: "AAPL", "GOOGL", "MSFT"
262
+ {% /examples %}
263
+ ````
264
+
265
+ Place doc blocks after the element they reference.
266
+
267
+ ## ID Conventions
268
+
269
+ - **Form/Group/Field IDs**: Globally unique, `snake_case`
270
+
271
+ - **Option IDs**: Unique within field, `snake_case`, use `{% #id %}` syntax
272
+
273
+ - **Qualified refs**: `field_id.option_id` for external references
274
+
275
+ ## Role System
276
+
277
+ Assign fields to different actors:
278
+
279
+ ```yaml
280
+ roles:
281
+ - user # Human fills these
282
+ - agent # AI fills these
283
+ ```
284
+
285
+ ```markdown
286
+ {% string-field id="query" label="Search Query" role="user" %}{% /string-field %}
287
+ {% string-field id="summary" label="AI Summary" role="agent" %}{% /string-field %}
288
+ ```
289
+
290
+ ## Value Encoding
291
+
292
+ Values use fenced code blocks with language `value`:
293
+
294
+ ````markdown
295
+ {% string-field id="name" label="Name" %}
296
+ ```value
297
+ John Smith
298
+ ````
299
+ {% /string-field %}
300
+ ````
301
+
302
+ Empty fields omit the value block entirely:
303
+
304
+ ```markdown
305
+ {% string-field id="name" label="Name" %}{% /string-field %}
306
+ ````
307
+
308
+ ## Complete Example
309
+
310
+ ```markdown
311
+ ---
312
+ markform:
313
+ spec: MF/0.1
314
+ title: Movie Research
315
+ description: Quick movie research form pulling ratings and key stats from IMDB, Rotten Tomatoes, and Metacritic.
316
+ roles:
317
+ - user
318
+ - agent
319
+ role_instructions:
320
+ user: "Enter the movie title and optionally the year for disambiguation."
321
+ agent: |
322
+ Research and fill in all fields for the specified movie.
323
+ Guidelines:
324
+ 1. WORKFLOW - Complete sections in order:
325
+ - First identify the movie title
326
+ - Then find all source URLs (verify you have the right movie on each site)
327
+ - Then fill in details (year, directors, ratings) from those sources
328
+ 2. PRIMARY SOURCES:
329
+ - IMDB (imdb.com) for ratings, runtime, and technical details
330
+ - Rotten Tomatoes (rottentomatoes.com) for Tomatometer and Audience Score
331
+ - Metacritic (metacritic.com) for Metascore
332
+ 3. Use the EXACT numeric scores from each source - don't average or interpret
333
+ 4. Skip fields if any scores are unavailable (older films may lack some metrics)
334
+ harness_config:
335
+ max_issues_per_turn: 3
336
+ max_patches_per_turn: 8
337
+ ---
338
+
339
+ {% form id="movie_research" title="Movie Research" %}
340
+
341
+ {% description ref="movie_research" %}
342
+ A focused research form for gathering ratings and key statistics for any film.
343
+ Pulls from IMDB, Rotten Tomatoes, and Metacritic.
344
+ {% /description %}
345
+
346
+ {% field-group id="movie_input" title="Movie Identification" %}
347
+
348
+ {% string-field id="movie" label="Movie" role="user" required=true minLength=1 maxLength=300 %}{% /string-field %}
349
+
350
+ {% instructions ref="movie" %}
351
+ Enter the movie title (add any details to help identify, like "Barbie 2023" or "the Batman movie with Robert Pattinson")
352
+ {% /instructions %}
353
+
354
+ {% /field-group %}
355
+
356
+ {% field-group id="title_identification" title="Title Identification" %}
357
+
358
+ {% string-field id="full_title" label="Full Title" role="agent" required=true %}{% /string-field %}
359
+
360
+ {% instructions ref="full_title" %}
361
+ Look up what film the user had in mind and fill in the official title including subtitle if any (e.g., "The Lord of the Rings: The Fellowship of the Ring").
362
+ {% /instructions %}
363
+
364
+ {% /field-group %}
365
+
366
+ {% field-group id="sources" title="Sources" %}
367
+
368
+ {% url-field id="imdb_url" label="IMDB URL" role="agent" required=true %}{% /url-field %}
369
+
370
+ {% instructions ref="imdb_url" %}
371
+ Direct link to the movie's IMDB page (e.g., https://www.imdb.com/title/tt0111161/).
372
+ {% /instructions %}
373
+
374
+ {% url-field id="rt_url" label="Rotten Tomatoes URL" role="agent" %}{% /url-field %}
375
+
376
+ {% instructions ref="rt_url" %}
377
+ Direct link to the movie's Rotten Tomatoes page.
378
+ {% /instructions %}
379
+
380
+ {% url-field id="metacritic_url" label="Metacritic URL" role="agent" %}{% /url-field %}
381
+
382
+ {% instructions ref="metacritic_url" %}
383
+ Direct link to the movie's Metacritic page.
384
+ {% /instructions %}
385
+
386
+ {% /field-group %}
387
+
388
+ {% field-group id="basic_details" title="Basic Details" %}
389
+
390
+ {% number-field id="year" label="Release Year" role="agent" required=true min=1888 max=2030 %}{% /number-field %}
391
+
392
+ {% string-list id="directors" label="Director(s)" role="agent" required=true %}{% /string-list %}
393
+
394
+ {% instructions ref="directors" %}
395
+ One director per line. Most films have one; some have two or more co-directors.
396
+ {% /instructions %}
397
+
398
+ {% number-field id="runtime_minutes" label="Runtime (minutes)" role="agent" min=1 max=1000 %}{% /number-field %}
399
+
400
+ {% single-select id="mpaa_rating" label="MPAA Rating" role="agent" %}
401
+ - [ ] G {% #g %}
402
+ - [ ] PG {% #pg %}
403
+ - [ ] PG-13 {% #pg_13 %}
404
+ - [ ] R {% #r %}
405
+ - [ ] NC-17 {% #nc_17 %}
406
+ - [ ] NR/Unrated {% #nr %}
407
+ {% /single-select %}
408
+
409
+ {% /field-group %}
410
+
411
+ {% field-group id="imdb_ratings" title="IMDB Ratings" %}
412
+
413
+ {% number-field id="imdb_rating" label="IMDB Rating" role="agent" min=1.0 max=10.0 %}{% /number-field %}
414
+
415
+ {% instructions ref="imdb_rating" %}
416
+ IMDB user rating (1.0-10.0 scale).
417
+ {% /instructions %}
418
+
419
+ {% number-field id="imdb_votes" label="IMDB Vote Count" role="agent" min=0 %}{% /number-field %}
420
+
421
+ {% instructions ref="imdb_votes" %}
422
+ Number of IMDB user votes (e.g., 2800000 for a popular film).
423
+ {% /instructions %}
424
+
425
+ {% /field-group %}
426
+
427
+ {% field-group id="rotten_tomatoes_ratings" title="Rotten Tomatoes Ratings" %}
428
+
429
+ {% number-field id="rt_critics_score" label="Tomatometer (Critics)" role="agent" min=0 max=100 %}{% /number-field %}
430
+
431
+ {% instructions ref="rt_critics_score" %}
432
+ Tomatometer percentage (0-100).
433
+ {% /instructions %}
434
+
435
+ {% number-field id="rt_critics_count" label="Critics Review Count" role="agent" min=0 %}{% /number-field %}
436
+
437
+ {% number-field id="rt_audience_score" label="Audience Score" role="agent" min=0 max=100 %}{% /number-field %}
438
+
439
+ {% instructions ref="rt_audience_score" %}
440
+ Audience Score percentage (0-100).
441
+ {% /instructions %}
442
+
443
+ {% /field-group %}
444
+
445
+ {% field-group id="metacritic_ratings" title="Metacritic Ratings" %}
446
+
447
+ {% number-field id="metacritic_score" label="Metacritic Score" role="agent" min=0 max=100 %}{% /number-field %}
448
+
449
+ {% instructions ref="metacritic_score" %}
450
+ Metascore (0-100 scale). Leave empty if not available.
451
+ {% /instructions %}
452
+
453
+ {% /field-group %}
454
+
455
+ {% field-group id="summary" title="Summary" %}
456
+
457
+ {% string-field id="logline" label="One-Line Summary" role="agent" maxLength=300 %}{% /string-field %}
458
+
459
+ {% instructions ref="logline" %}
460
+ Brief plot summary in 1-2 sentences, no spoilers.
461
+ {% /instructions %}
462
+
463
+ {% string-list id="notable_awards" label="Notable Awards" role="agent" %}{% /string-list %}
464
+
465
+ {% instructions ref="notable_awards" %}
466
+ Major awards won. One per line.
467
+ Format: Award | Category | Year
468
+ Example: "Oscar | Best Picture | 1995"
469
+ {% /instructions %}
470
+
471
+ {% /field-group %}
472
+
473
+ {% /form %}
474
+ ```
475
+
476
+ ## CLI Quick Reference
477
+
478
+ ```bash
479
+ # Inspect form structure and progress
480
+ markform inspect form.md
481
+ markform inspect form.md --format=json
482
+
483
+ # Validate form (check for errors)
484
+ markform validate form.md
485
+
486
+ # Fill forms
487
+ markform fill form.md --interactive # Interactive prompts for user fields
488
+ markform fill form.md --roles=user --interactive # Only fill user-role fields
489
+ markform fill form.md --model anthropic/claude-sonnet-4-5 # AI fills agent fields
490
+
491
+ # Export data
492
+ markform export form.md --format=json # Export values as JSON
493
+ markform export form.md --format=yaml # Export values as YAML
494
+ markform export form.md --format=markdown # Readable markdown (strips tags)
495
+
496
+ # Other commands
497
+ markform serve form.md # Web UI for browsing
498
+ markform examples # Try built-in examples
499
+ markform models # List supported AI providers
500
+ ```
501
+
502
+ ## Testing and Validation
503
+
504
+ **Inspect a form** to see structure, progress, and issues:
505
+
506
+ ```bash
507
+ markform inspect my-form.form.md
508
+ ```
509
+
510
+ **Validate** checks for constraint violations:
511
+
512
+ ```bash
513
+ markform validate my-form.form.md
514
+ ```
515
+
516
+ **Test with mock data** using a pre-filled source:
517
+
518
+ ```bash
519
+ markform fill template.form.md --mock --mock-source filled.form.md
520
+ ```
521
+
522
+ **Workflow for testing forms:**
523
+
524
+ 1. Create your `.form.md` template
525
+
526
+ 2. Run `markform validate` to check syntax and constraints
527
+
528
+ 3. Run `markform fill --interactive` to test user fields
529
+
530
+ 4. Run `markform fill --model <model>` to test agent fields
531
+
532
+ 5. Use `markform inspect` to verify progress and completion
533
+
534
+ ## Best Practices
535
+
536
+ 1. **Use descriptive IDs**: `company_revenue_m` not `rev` or `field1`
537
+
538
+ 2. **Add instructions**: Help agents understand what you want
539
+
540
+ 3. **Set constraints**: Use `min`, `max`, `minLength`, `pattern` to validate
541
+
542
+ 4. **Group logically**: Related fields in the same `field-group`
543
+
544
+ 5. **Assign roles**: Separate user input from agent research
545
+
546
+ 6. **Document thoroughly**: Use `{% instructions %}` for complex fields