markform 0.1.17 → 0.1.18

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 (31) hide show
  1. package/README.md +2 -2
  2. package/dist/ai-sdk.d.mts +1 -1
  3. package/dist/ai-sdk.mjs +2 -2
  4. package/dist/{apply-DgDJBscb.mjs → apply-BYgtU64w.mjs} +29 -3
  5. package/dist/apply-BYgtU64w.mjs.map +1 -0
  6. package/dist/bin.mjs +1 -1
  7. package/dist/{cli-DAl8LQzI.mjs → cli-D9w0Bp4J.mjs} +192 -6
  8. package/dist/cli-D9w0Bp4J.mjs.map +1 -0
  9. package/dist/cli.mjs +1 -1
  10. package/dist/{coreTypes-CnEea7Kh.d.mts → coreTypes-BMEs8h_2.d.mts} +125 -2
  11. package/dist/{coreTypes-DiCddBKu.mjs → coreTypes-SDB3KRRJ.mjs} +9 -4
  12. package/dist/coreTypes-SDB3KRRJ.mjs.map +1 -0
  13. package/dist/index.d.mts +129 -2
  14. package/dist/index.mjs +5 -5
  15. package/dist/{session-B7aR6hno.mjs → session-CW9AQw6i.mjs} +1 -1
  16. package/dist/{session-XDrocA3j.mjs → session-Ci4B0Pna.mjs} +2 -2
  17. package/dist/{session-XDrocA3j.mjs.map → session-Ci4B0Pna.mjs.map} +1 -1
  18. package/dist/{src-CHVJLGKt.mjs → src-DDxi-2ne.mjs} +495 -14
  19. package/dist/src-DDxi-2ne.mjs.map +1 -0
  20. package/docs/markform-apis.md +31 -0
  21. package/docs/markform-reference.md +27 -0
  22. package/docs/markform-spec.md +115 -0
  23. package/examples/movie-research/movie-deep-research-mock-filled.form.md +1 -1
  24. package/examples/movie-research/movie-deep-research.form.md +1 -1
  25. package/examples/parallel/parallel-research.form.md +57 -0
  26. package/examples/startup-deep-research/startup-deep-research.form.md +1 -1
  27. package/package.json +1 -1
  28. package/dist/apply-DgDJBscb.mjs.map +0 -1
  29. package/dist/cli-DAl8LQzI.mjs.map +0 -1
  30. package/dist/coreTypes-DiCddBKu.mjs.map +0 -1
  31. package/dist/src-CHVJLGKt.mjs.map +0 -1
@@ -202,10 +202,41 @@ const result = await fillForm({
202
202
  | `maxStepsPerTurn` | `number` | `20` | Maximum AI SDK steps (tool call rounds) per turn |
203
203
  | `targetRoles` | `string[]` | `['agent']` | Roles to fill |
204
204
  | `fillMode` | `FillMode` | `'continue'` | `'continue'` or `'overwrite'` |
205
+ | `enableParallel` | `boolean` | `false` | Enable parallel execution for forms with `parallel` batches |
206
+ | `maxParallelAgents` | `number` | `4` | Max concurrent agents for parallel batches |
205
207
  | `callbacks` | `FillCallbacks` | `undefined` | Progress callbacks |
206
208
  | `signal` | `AbortSignal` | `undefined` | Cancellation signal |
207
209
  | `additionalTools` | `Record<string, Tool>` | `undefined` | Custom tools for agent |
208
210
 
211
+ ### Parallel Execution
212
+
213
+ When a form uses `parallel` attributes on groups, you can enable concurrent execution:
214
+
215
+ ```typescript
216
+ const result = await fillForm({
217
+ form: formMarkdown,
218
+ model: 'anthropic/claude-sonnet-4-5',
219
+ enableWebSearch: true,
220
+ captureWireFormat: false,
221
+ enableParallel: true,
222
+ maxParallelAgents: 4,
223
+ callbacks: {
224
+ onOrderLevelStart: ({ order }) => console.log(`Order ${order} starting`),
225
+ onBatchStart: ({ batchId }) => console.log(`Batch ${batchId} starting`),
226
+ onBatchComplete: ({ batchId, patchesApplied }) =>
227
+ console.log(`Batch ${batchId}: ${patchesApplied} patches`),
228
+ },
229
+ });
230
+ ```
231
+
232
+ **Behavior:**
233
+ - `enableParallel: false` (default): All fields filled serially, `parallel` attributes
234
+ ignored. The `order` attribute still controls issue filtering.
235
+ - `enableParallel: true`: Batch items run concurrently (up to `maxParallelAgents`).
236
+ Each agent runs a multi-turn loop with rejection feedback, same as the serial path.
237
+ - If the form has no `parallel` batches, falls back to serial automatically.
238
+ - `FillResult` shape is identical regardless of serial or parallel execution.
239
+
209
240
  ### FillStatus
210
241
 
211
242
  The `status` field in `FillResult` indicates success or failure:
@@ -416,6 +416,8 @@ All fields support these attributes:
416
416
  | `required` | boolean | false | Must be filled for completion |
417
417
  | `role` | string | - | Target actor (`user`, `agent`) |
418
418
  | `priority` | string | medium | `high`, `medium`, `low` |
419
+ | `order` | number | `0` | Fill order. Lower values filled first. Different order levels are filled in separate turns. |
420
+ | `parallel` | string | - | Parallel batch identifier. Items with the same value may execute concurrently. Top-level only. |
419
421
 
420
422
  **Text-entry fields only** (string, number, string-list, url, url-list):
421
423
 
@@ -432,6 +434,31 @@ All fields support these attributes:
432
434
  Note: `placeholder` and `examples` are NOT valid on chooser fields (single-select,
433
435
  multi-select, checkboxes).
434
436
 
437
+ ## Harness Configuration
438
+
439
+ Optional harness hints can be set in YAML frontmatter under `markform.harness`.
440
+ All keys must be `snake_case` and all values must be numbers.
441
+ These are suggestions — a harness may ignore or override them via API options.
442
+
443
+ | Key | Type | Description |
444
+ | --- | --- | --- |
445
+ | `max_turns` | number | Maximum turns before stopping |
446
+ | `max_patches_per_turn` | number | Maximum patches per turn |
447
+ | `max_issues_per_turn` | number | Maximum issues surfaced per turn |
448
+ | `max_parallel_agents` | number | Maximum concurrent agents for parallel execution |
449
+
450
+ ```yaml
451
+ markform:
452
+ spec: MF/0.1
453
+ harness:
454
+ max_turns: 50
455
+ max_issues_per_turn: 5
456
+ max_patches_per_turn: 10
457
+ max_parallel_agents: 4
458
+ ```
459
+
460
+ Unrecognized keys or non-numeric values cause parse errors.
461
+
435
462
  ## Documentation Blocks
436
463
 
437
464
  Add context to fields, groups, or the form.
@@ -144,6 +144,30 @@ markform:
144
144
  When omitted, tools may infer from field roles or require explicit selection.
145
145
  This is a hint for tooling, not enforced by the engine.
146
146
 
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.
150
+
151
+ Supported keys (all values must be numbers, all keys must be `snake_case`):
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 |
159
+
160
+ Unrecognized keys or non-numeric values are parse errors.
161
+
162
+ Example:
163
+ ```yaml
164
+ markform:
165
+ spec: MF/0.1
166
+ harness:
167
+ max_turns: 50
168
+ max_parallel_agents: 4
169
+ ```
170
+
147
171
  **Behavioral rules (*required*):**
148
172
 
149
173
  - *required:* `form_summary`, `form_progress`, and `form_state` are derived,
@@ -255,6 +279,8 @@ Example: `pattern="^[A-Z]{1,5}$"` for a ticker symbol.
255
279
  | `label` | string | Required. Human-readable field name |
256
280
  | `required` | boolean | Whether field must be filled for form completion |
257
281
  | `role` | string | Target actor (e.g., `"user"`, `"agent"`). See role-filtered completion |
282
+ | `parallel` | string | Parallel batch identifier. Top-level fields/groups only. See [Parallel Execution Hints](#parallel-execution-hints) |
283
+ | `order` | number | Fill order (default: `0`). Lower values filled first. See [Fill Order](#fill-order) |
258
284
 
259
285
  The `role` attribute enables multi-actor workflows where different fields are assigned
260
286
  to different actors.
@@ -1259,6 +1285,59 @@ On GitHub, all `<!-- ... -->` comments are hidden, leaving only the visible cont
1259
1285
  **Constraint:** Values containing the literal string `-->` require escaping or should
1260
1286
  use the tag syntax to avoid prematurely closing the comment.
1261
1287
 
1288
+ ##### Parallel Execution Hints
1289
+
1290
+ Top-level fields and groups MAY include a `parallel` attribute to indicate that they
1291
+ can be filled concurrently with other items sharing the same value.
1292
+
1293
+ ```markdown
1294
+ <!-- field kind="string" id="a" label="A" parallel="batch_1" --><!-- /field -->
1295
+ <!-- field kind="string" id="b" label="B" parallel="batch_1" --><!-- /field -->
1296
+ ```
1297
+
1298
+ **Rules:**
1299
+ - `parallel` value is an arbitrary string identifier (recommended: `snake_case`)
1300
+ - Items with the same `parallel` value form a *parallel batch*
1301
+ - Items without `parallel` remain in loose-serial mode (single agent, no enforced
1302
+ ordering) — identical to current behavior
1303
+ - `parallel` MUST NOT appear on fields inside groups (parse error) — only on
1304
+ top-level fields and groups
1305
+ - All items in a parallel batch MUST have the same effective `role` (parse error)
1306
+ - `parallel` is a hint — a harness MAY ignore it and fill everything in
1307
+ loose-serial mode
1308
+
1309
+ **Execution model:**
1310
+ ```
1311
+ Without parallel: All items filled by one agent in loose-serial mode (current behavior).
1312
+
1313
+ With parallel: Items are partitioned into two pools:
1314
+ 1. Loose-serial pool: items without `parallel`, filled by primary agent
1315
+ 2. Parallel batches: items with `parallel`, each item filled by a separate agent
1316
+ All agents (primary + parallel) run concurrently. No barriers between them.
1317
+ ```
1318
+
1319
+ ##### Fill Order
1320
+
1321
+ Fields and groups MAY include an `order` attribute (numeric) that controls the
1322
+ sequence in which the harness presents fields to the agent.
1323
+
1324
+ ```markdown
1325
+ <!-- field kind="string" id="details" label="Details" --><!-- /field -->
1326
+ <!-- field kind="string" id="summary" label="Summary" order=99 --><!-- /field -->
1327
+ ```
1328
+
1329
+ **Rules:**
1330
+ - `order` is a number (integer or float). Default: `0`.
1331
+ - Lower `order` values are filled first. Fields at the same order level are
1332
+ filled in loose-serial order (agent chooses).
1333
+ - The harness MUST NOT surface issues for `order=N` fields until all fields at
1334
+ `order<N` are complete (answered, skipped, or aborted).
1335
+ - Fields at different order levels are always filled in separate agent turns.
1336
+ - A field inside a group with `order` MUST NOT specify a different `order`
1337
+ (parse error). Use separate groups for different order levels.
1338
+ - `order` composes with `parallel`: all items in a parallel batch MUST have the
1339
+ same effective `order` value (parse error otherwise).
1340
+
1262
1341
  * * *
1263
1342
 
1264
1343
  ## Layer 2: Form Data Model
@@ -1442,6 +1521,8 @@ interface FieldGroup {
1442
1521
  // Note: `required` on groups is not supported in MF/0.1 (ignored with warning)
1443
1522
  validate?: ValidatorRef[]; // validator references (string IDs or parameterized objects)
1444
1523
  children: Field[]; // MF/0.1/0.2: fields only; nested groups deferred (future)
1524
+ parallel?: string; // Parallel batch identifier
1525
+ order?: number; // Fill order (default: 0). Applies to all child fields.
1445
1526
  }
1446
1527
 
1447
1528
  type FieldPriorityLevel = 'high' | 'medium' | 'low';
@@ -1452,6 +1533,8 @@ interface FieldBase {
1452
1533
  required: boolean; // explicit: parser defaults to false if not specified
1453
1534
  priority: FieldPriorityLevel; // explicit: parser defaults to 'medium' if not specified
1454
1535
  validate?: ValidatorRef[]; // validator references (string IDs or parameterized objects)
1536
+ parallel?: string; // Parallel batch identifier (top-level only)
1537
+ order?: number; // Fill order (default: 0). Lower = filled first.
1455
1538
  }
1456
1539
 
1457
1540
  // NOTE: `required` and `priority` are explicit (not optional) in the data model.
@@ -2664,6 +2747,38 @@ isRetryableError(error) // LLM error with retryable=true
2664
2747
  `ParseError` is exported as an alias for `MarkformParseError` for backward compatibility.
2665
2748
  Use `MarkformParseError` in new code.
2666
2749
 
2750
+ #### Execution Plan
2751
+
2752
+ An **execution plan** partitions top-level form items into a loose-serial pool and
2753
+ zero or more parallel batches:
2754
+
2755
+ ```typescript
2756
+ interface ExecutionPlan {
2757
+ /** Items without `parallel` — filled by primary agent in loose-serial mode */
2758
+ looseSerial: Array<{ itemId: Id; itemType: 'field' | 'group' }>;
2759
+
2760
+ /** Parallel batches — each item filled by a separate concurrent agent */
2761
+ parallelBatches: Array<{
2762
+ batchId: string;
2763
+ items: Array<{ itemId: Id; itemType: 'field' | 'group' }>;
2764
+ }>;
2765
+ }
2766
+ ```
2767
+
2768
+ **Computation:** Walk top-level items (fields and groups) in document order:
2769
+ - If item has no `parallel`: add to the loose-serial pool
2770
+ - If item has `parallel`: add to the batch with that ID (create batch if new)
2771
+
2772
+ **Execution:** The primary agent fills loose-serial items. For each parallel batch,
2773
+ one agent per item is spawned. All agents (primary + batch agents) run concurrently.
2774
+ When all complete, patches are merged and validation runs.
2775
+
2776
+ **Order-based filtering:** The harness partitions items by their effective `order`
2777
+ value (default `0`). Issues for fields at `order=N` are only surfaced after all fields
2778
+ at `order<N` are complete (answered, skipped, or aborted). This ensures fields at
2779
+ different order levels are always filled in separate agent turns, so higher-order fields
2780
+ see completed lower-order field values in the form markdown.
2781
+
2667
2782
  * * *
2668
2783
 
2669
2784
  ## Layer 4: Tool API & Interfaces
@@ -35,7 +35,7 @@ markform:
35
35
  - Skip fields if data unavailable (older films may lack some metrics)
36
36
  - For box office, use millions (e.g., 100.5 for $100.5M)
37
37
  - Add notes for any missing, confusing, or unclear information
38
- harness_config:
38
+ harness:
39
39
  max_issues_per_turn: 5
40
40
  max_patches_per_turn: 15
41
41
  ---
@@ -35,7 +35,7 @@ markform:
35
35
  - Skip fields if data unavailable (older films may lack some metrics)
36
36
  - For box office, use millions (e.g., 100.5 for $100.5M)
37
37
  - Add notes for any missing, confusing, or unclear information
38
- harness_config:
38
+ harness:
39
39
  max_issues_per_turn: 5
40
40
  max_patches_per_turn: 15
41
41
  ---
@@ -0,0 +1,57 @@
1
+ ---
2
+ markform:
3
+ spec: MF/0.1
4
+ title: Company Research (Parallel)
5
+ description: "Demonstrates parallel and order attributes for concurrent form filling."
6
+ roles:
7
+ - agent
8
+ role_instructions:
9
+ agent: "Research the company and fill in all fields."
10
+ harness:
11
+ max_turns: 10
12
+ max_parallel_agents: 4
13
+ ---
14
+ {% form id="company_research" title="Company Research (Parallel)" %}
15
+
16
+ {% description ref="company_research" %}
17
+ A company research form that uses `parallel` for concurrent deep research
18
+ and `order` to sequence synthesis after data gathering.
19
+ {% /description %}
20
+
21
+ {% group id="overview" order=0 %}
22
+
23
+ {% field kind="string" id="company_name" label="Company Name" role="agent" required=true %}{% /field %}
24
+
25
+ {% field kind="string" id="company_overview" label="Company Overview" role="agent" %}{% /field %}
26
+
27
+ {% /group %}
28
+
29
+ {% group id="financials" parallel="deep_research" order=0 %}
30
+
31
+ {% field kind="string" id="revenue" label="Annual Revenue" role="agent" %}{% /field %}
32
+
33
+ {% field kind="string" id="margins" label="Margin Analysis" role="agent" %}{% /field %}
34
+
35
+ {% /group %}
36
+
37
+ {% group id="team" parallel="deep_research" order=0 %}
38
+
39
+ {% field kind="string" id="leadership" label="Team & Leadership" role="agent" %}{% /field %}
40
+
41
+ {% /group %}
42
+
43
+ {% group id="market" parallel="deep_research" order=0 %}
44
+
45
+ {% field kind="string" id="tam" label="TAM" role="agent" %}{% /field %}
46
+
47
+ {% field kind="string" id="competitors" label="Competitors" role="agent" %}{% /field %}
48
+
49
+ {% /group %}
50
+
51
+ {% group id="synthesis" order=10 %}
52
+
53
+ {% field kind="string" id="overall" label="Overall Assessment" role="agent" required=true %}{% /field %}
54
+
55
+ {% /group %}
56
+
57
+ {% /form %}
@@ -21,7 +21,7 @@ markform:
21
21
  7. Include source URLs for every piece of information
22
22
  8. Leave unknown fields empty - don't guess or fabricate
23
23
  9. Keep descriptions concise (50-150 words max)
24
- harness_config:
24
+ harness:
25
25
  max_issues_per_turn: 5
26
26
  max_patches_per_turn: 10
27
27
  ---
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "markform",
3
- "version": "0.1.17",
3
+ "version": "0.1.18",
4
4
  "description": "Markdown forms for token-friendly workflows",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "author": "Joshua Levy",