markform 0.1.16 → 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.
- package/LICENSE +369 -0
- package/README.md +154 -214
- package/dist/ai-sdk.d.mts +1 -1
- package/dist/ai-sdk.mjs +2 -2
- package/dist/{apply-CXsI5N9x.mjs → apply-BYgtU64w.mjs} +203 -16
- package/dist/apply-BYgtU64w.mjs.map +1 -0
- package/dist/bin.mjs +1 -1
- package/dist/{cli-BsFessUW.mjs → cli-D9w0Bp4J.mjs} +199 -13
- package/dist/cli-D9w0Bp4J.mjs.map +1 -0
- package/dist/cli.mjs +1 -1
- package/dist/{coreTypes-DE6Giau5.d.mts → coreTypes-BMEs8h_2.d.mts} +165 -2
- package/dist/{coreTypes-DiCddBKu.mjs → coreTypes-SDB3KRRJ.mjs} +9 -4
- package/dist/coreTypes-SDB3KRRJ.mjs.map +1 -0
- package/dist/index.d.mts +266 -2
- package/dist/index.mjs +5 -5
- package/dist/{session-B7aR6hno.mjs → session-CW9AQw6i.mjs} +1 -1
- package/dist/{session-XDrocA3j.mjs → session-Ci4B0Pna.mjs} +2 -2
- package/dist/{session-XDrocA3j.mjs.map → session-Ci4B0Pna.mjs.map} +1 -1
- package/dist/{src-Dv3IZSQU.mjs → src-DDxi-2ne.mjs} +966 -32
- package/dist/src-DDxi-2ne.mjs.map +1 -0
- package/docs/markform-apis.md +110 -0
- package/docs/markform-reference.md +58 -0
- package/docs/markform-spec.md +204 -9
- package/examples/movie-research/movie-deep-research-mock-filled.form.md +1 -1
- package/examples/movie-research/movie-deep-research.form.md +1 -1
- package/examples/parallel/parallel-research.form.md +57 -0
- package/examples/plan-document/plan-document-markdoc.form.md +35 -0
- package/examples/plan-document/plan-document-progress.form.md +47 -0
- package/examples/plan-document/plan-document.form.md +47 -0
- package/examples/startup-deep-research/startup-deep-research.form.md +1 -1
- package/package.json +2 -2
- package/dist/apply-CXsI5N9x.mjs.map +0 -1
- package/dist/cli-BsFessUW.mjs.map +0 -1
- package/dist/coreTypes-DiCddBKu.mjs.map +0 -1
- package/dist/src-Dv3IZSQU.mjs.map +0 -1
package/docs/markform-apis.md
CHANGED
|
@@ -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:
|
|
@@ -355,6 +386,85 @@ Run a research session on a research-type form.
|
|
|
355
386
|
|
|
356
387
|
See [runResearch.ts](../packages/markform/src/research/runResearch.ts) for full details.
|
|
357
388
|
|
|
389
|
+
## Markdown Utilities
|
|
390
|
+
|
|
391
|
+
Utilities for working with markdown content, particularly for plan documents with
|
|
392
|
+
implicit checkboxes.
|
|
393
|
+
|
|
394
|
+
```typescript
|
|
395
|
+
import {
|
|
396
|
+
findAllHeadings,
|
|
397
|
+
findEnclosingHeadings,
|
|
398
|
+
findAllCheckboxes,
|
|
399
|
+
injectCheckboxIds,
|
|
400
|
+
injectHeaderIds,
|
|
401
|
+
} from 'markform';
|
|
402
|
+
```
|
|
403
|
+
|
|
404
|
+
### findAllHeadings(markdown: string): HeadingInfo[]
|
|
405
|
+
|
|
406
|
+
Find all headings in a markdown document, returned in document order.
|
|
407
|
+
|
|
408
|
+
```typescript
|
|
409
|
+
interface HeadingInfo {
|
|
410
|
+
level: number; // 1-6 for h1-h6
|
|
411
|
+
title: string; // Heading text (without # prefix)
|
|
412
|
+
line: number; // Line number (1-indexed)
|
|
413
|
+
position: SourceRange;
|
|
414
|
+
}
|
|
415
|
+
```
|
|
416
|
+
|
|
417
|
+
### findEnclosingHeadings(markdown: string, line: number): HeadingInfo[]
|
|
418
|
+
|
|
419
|
+
Find all headings that enclose a given line position. Returns headings from innermost
|
|
420
|
+
(most specific) to outermost (least specific).
|
|
421
|
+
|
|
422
|
+
A heading "encloses" a line if the heading appears before the line and no heading of
|
|
423
|
+
equal or higher level appears between them.
|
|
424
|
+
|
|
425
|
+
### findAllCheckboxes(markdown: string): CheckboxInfo[]
|
|
426
|
+
|
|
427
|
+
Find all checkboxes in a markdown document with their enclosing heading context.
|
|
428
|
+
|
|
429
|
+
```typescript
|
|
430
|
+
interface CheckboxInfo {
|
|
431
|
+
id?: string; // Existing ID from annotation
|
|
432
|
+
label: string; // Checkbox label text
|
|
433
|
+
state: CheckboxValue; // Current state (todo, done, etc.)
|
|
434
|
+
position: SourceRange; // Source position
|
|
435
|
+
enclosingHeadings: HeadingInfo[]; // Innermost first
|
|
436
|
+
}
|
|
437
|
+
```
|
|
438
|
+
|
|
439
|
+
### injectCheckboxIds(markdown: string, options): InjectIdsResult
|
|
440
|
+
|
|
441
|
+
Inject ID annotations into checkboxes that lack them.
|
|
442
|
+
|
|
443
|
+
```typescript
|
|
444
|
+
interface InjectCheckboxIdsOptions {
|
|
445
|
+
generator: (info: CheckboxInfo, index: number) => string;
|
|
446
|
+
onlyMissing?: boolean; // Default: true
|
|
447
|
+
}
|
|
448
|
+
|
|
449
|
+
interface InjectIdsResult {
|
|
450
|
+
markdown: string; // Modified markdown
|
|
451
|
+
injectedCount: number; // Number of IDs added
|
|
452
|
+
injectedIds: Map<string, string>; // label -> generated ID
|
|
453
|
+
}
|
|
454
|
+
```
|
|
455
|
+
|
|
456
|
+
### injectHeaderIds(markdown: string, options): InjectIdsResult
|
|
457
|
+
|
|
458
|
+
Inject ID annotations into markdown headings.
|
|
459
|
+
|
|
460
|
+
```typescript
|
|
461
|
+
interface InjectHeaderIdsOptions {
|
|
462
|
+
generator: (info: HeadingInfo, index: number) => string;
|
|
463
|
+
onlyMissing?: boolean; // Default: true
|
|
464
|
+
levels?: number[]; // Default: [1, 2, 3, 4, 5, 6]
|
|
465
|
+
}
|
|
466
|
+
```
|
|
467
|
+
|
|
358
468
|
## Type Exports
|
|
359
469
|
|
|
360
470
|
All Zod schemas and TypeScript types are exported from the main package:
|
|
@@ -256,6 +256,37 @@ Stateful checklists with three modes.
|
|
|
256
256
|
| `[y]` | yes | Explicit yes |
|
|
257
257
|
| `[n]` | no | Explicit no |
|
|
258
258
|
|
|
259
|
+
### Implicit Checkboxes (Plan Documents)
|
|
260
|
+
|
|
261
|
+
Forms designed as task lists can omit explicit field wrappers. When a form has a
|
|
262
|
+
`{% form %}` tag but no `{% field %}` tags, checkboxes are automatically wrapped in
|
|
263
|
+
an implicit checkboxes field.
|
|
264
|
+
|
|
265
|
+
```markdown
|
|
266
|
+
---
|
|
267
|
+
markform:
|
|
268
|
+
spec: MF/0.1
|
|
269
|
+
---
|
|
270
|
+
{% form id="plan" title="Project Plan" %}
|
|
271
|
+
|
|
272
|
+
## Phase 1: Research
|
|
273
|
+
- [ ] Literature review {% #lit_review %}
|
|
274
|
+
- [ ] Competitive analysis {% #comp %}
|
|
275
|
+
|
|
276
|
+
## Phase 2: Design
|
|
277
|
+
- [x] Architecture doc {% #arch %}
|
|
278
|
+
- [/] API design {% #api %}
|
|
279
|
+
|
|
280
|
+
{% /form %}
|
|
281
|
+
```
|
|
282
|
+
|
|
283
|
+
**Requirements:**
|
|
284
|
+
- Each checkbox MUST have an ID annotation (`{% #id %}` or `<!-- #id -->`)
|
|
285
|
+
- IDs must be unique (same rules as explicit checkboxes fields)
|
|
286
|
+
- The implicit field uses ID `checkboxes` (reserved)
|
|
287
|
+
- Always uses `checkboxMode="multi"` (5-state)
|
|
288
|
+
- Mixing explicit fields with checkboxes outside fields is an error
|
|
289
|
+
|
|
259
290
|
### URL Field
|
|
260
291
|
|
|
261
292
|
Single URL with format validation.
|
|
@@ -385,6 +416,8 @@ All fields support these attributes:
|
|
|
385
416
|
| `required` | boolean | false | Must be filled for completion |
|
|
386
417
|
| `role` | string | - | Target actor (`user`, `agent`) |
|
|
387
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. |
|
|
388
421
|
|
|
389
422
|
**Text-entry fields only** (string, number, string-list, url, url-list):
|
|
390
423
|
|
|
@@ -401,6 +434,31 @@ All fields support these attributes:
|
|
|
401
434
|
Note: `placeholder` and `examples` are NOT valid on chooser fields (single-select,
|
|
402
435
|
multi-select, checkboxes).
|
|
403
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
|
+
|
|
404
462
|
## Documentation Blocks
|
|
405
463
|
|
|
406
464
|
Add context to fields, groups, or the form.
|
package/docs/markform-spec.md
CHANGED
|
@@ -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.
|
|
@@ -270,6 +296,11 @@ These attributes are only valid on text-entry field kinds.
|
|
|
270
296
|
Using them on chooser fields (single-select, multi-select, checkboxes) will result in a
|
|
271
297
|
parse error.
|
|
272
298
|
|
|
299
|
+
**Nesting constraints:**
|
|
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'`
|
|
303
|
+
|
|
273
304
|
**Example with placeholder and examples:**
|
|
274
305
|
```md
|
|
275
306
|
{% field kind="string" id="company_name" label="Company name" placeholder="Enter company name" examples=["ACME Corp", "Globex Inc"] %}{% /field %}
|
|
@@ -636,6 +667,60 @@ In this example, `risk_factors.currency` is unfilled (`[ ]`) and will fail valid
|
|
|
636
667
|
because `checkboxMode="explicit"` requires all options to have explicit `[y]` or `[n]`
|
|
637
668
|
answers.
|
|
638
669
|
|
|
670
|
+
##### Implicit Checkboxes (Plan Documents)
|
|
671
|
+
|
|
672
|
+
Forms designed as task lists or plans can omit explicit field wrappers. When a form
|
|
673
|
+
contains:
|
|
674
|
+
- A `{% form %}` wrapper (or `<!-- form ... -->`)
|
|
675
|
+
- No explicit `{% field %}` tags
|
|
676
|
+
- Standard markdown checkboxes with ID annotations
|
|
677
|
+
|
|
678
|
+
The parser automatically creates an implicit checkboxes field:
|
|
679
|
+
|
|
680
|
+
| Property | Value |
|
|
681
|
+
| --- | --- |
|
|
682
|
+
| ID | `checkboxes` (reserved) |
|
|
683
|
+
| Label | `Checkboxes` |
|
|
684
|
+
| Mode | `multi` (always) |
|
|
685
|
+
| Options | All checkboxes in document order |
|
|
686
|
+
| Implicit | `true` |
|
|
687
|
+
|
|
688
|
+
**Example:**
|
|
689
|
+
```md
|
|
690
|
+
---
|
|
691
|
+
markform:
|
|
692
|
+
spec: MF/0.1
|
|
693
|
+
---
|
|
694
|
+
{% form id="plan" title="Project Plan" %}
|
|
695
|
+
|
|
696
|
+
## Phase 1: Research
|
|
697
|
+
- [ ] Literature review {% #lit_review %}
|
|
698
|
+
- [ ] Competitive analysis {% #comp %}
|
|
699
|
+
|
|
700
|
+
## Phase 2: Design
|
|
701
|
+
- [x] Architecture doc {% #arch %}
|
|
702
|
+
- [/] API design {% #api %}
|
|
703
|
+
|
|
704
|
+
{% /form %}
|
|
705
|
+
```
|
|
706
|
+
|
|
707
|
+
The above form parses to a schema with a single implicit checkboxes field containing
|
|
708
|
+
four options: `lit_review`, `comp`, `arch`, and `api`.
|
|
709
|
+
|
|
710
|
+
**Requirements:**
|
|
711
|
+
- Standard option ID rules apply (see [Identifiers](#identifiers)):
|
|
712
|
+
- Each checkbox MUST have an ID annotation (`{% #id %}` or `<!-- #id -->`)
|
|
713
|
+
- IDs MUST be unique within the implicit field
|
|
714
|
+
- Recommended: use `snake_case` slugified from label
|
|
715
|
+
- ID `checkboxes` is reserved and MUST NOT be used for explicit fields
|
|
716
|
+
- Nested checkboxes (indented list items) are collected as separate options
|
|
717
|
+
|
|
718
|
+
**Error conditions:**
|
|
719
|
+
- Checkbox without ID annotation: Parse error (same as explicit checkboxes fields)
|
|
720
|
+
- Duplicate checkbox ID: Parse error (same as explicit checkboxes fields)
|
|
721
|
+
- Mixed mode (explicit fields AND checkboxes outside fields): Parse error
|
|
722
|
+
- Explicit field with ID `checkboxes`: Parse error (reserved ID)
|
|
723
|
+
|
|
639
724
|
##### String-List Fields
|
|
640
725
|
|
|
641
726
|
String-list fields represent open-ended arrays of user-provided strings.
|
|
@@ -974,17 +1059,24 @@ Markform files may contain content outside of Markform tags. This content is han
|
|
|
974
1059
|
|
|
975
1060
|
| Content Type | Policy |
|
|
976
1061
|
|--------------|--------|
|
|
977
|
-
|
|
|
1062
|
+
| Markdown content (headings, paragraphs, lists, etc.) | Preserved; structure must be equivalent after round-trip |
|
|
1063
|
+
| HTML comments (`<!-- ... -->`) | Preserved verbatim on round-trip |
|
|
1064
|
+
| Arbitrary Markdoc tags (non-Markform) | Parse warning, ignored (not preserved) |
|
|
978
1065
|
|
|
979
|
-
|
|
1066
|
+
**Content preservation semantics (*required*):**
|
|
1067
|
+
|
|
1068
|
+
- *required:* All markdown content outside of Markform tags MUST be preserved on
|
|
1069
|
+
canonical serialization
|
|
1070
|
+
|
|
1071
|
+
- *required:* The markdown structure MUST be equivalent after round-trip (same headings,
|
|
1072
|
+
paragraphs, lists, code blocks, etc.)
|
|
980
1073
|
|
|
981
|
-
|
|
982
|
-
| Markdown headings/text between groups | Allowed, but NOT preserved on canonical serialize |
|
|
983
|
-
| Arbitrary Markdoc tags (non-Markform) | Parse warning, ignored |
|
|
1074
|
+
- *recommended:* Visual appearance SHOULD be preserved (same rendering output)
|
|
984
1075
|
|
|
985
|
-
|
|
986
|
-
|
|
987
|
-
|
|
1076
|
+
- Superficial adjustments are permitted: line wrapping, whitespace normalization,
|
|
1077
|
+
stylistic conventions for Markform tag formatting (attribute ordering, spacing)
|
|
1078
|
+
|
|
1079
|
+
- The semantic content and document structure must remain intact
|
|
988
1080
|
|
|
989
1081
|
#### Serialization Strategy
|
|
990
1082
|
|
|
@@ -993,7 +1085,9 @@ requirements beyond what it provides—see [Formatting][markdoc-format]):
|
|
|
993
1085
|
|
|
994
1086
|
**MF/0.1 content restrictions for canonical serialization (*required*):**
|
|
995
1087
|
|
|
996
|
-
|
|
1088
|
+
The following restrictions apply to content *within* Markform elements to ensure
|
|
1089
|
+
deterministic parsing and validation. General markdown content outside of Markform
|
|
1090
|
+
tags is preserved via raw slicing (retaining the original text):
|
|
997
1091
|
|
|
998
1092
|
| Content type | Restriction |
|
|
999
1093
|
|--------------|-------------|
|
|
@@ -1191,6 +1285,59 @@ On GitHub, all `<!-- ... -->` comments are hidden, leaving only the visible cont
|
|
|
1191
1285
|
**Constraint:** Values containing the literal string `-->` require escaping or should
|
|
1192
1286
|
use the tag syntax to avoid prematurely closing the comment.
|
|
1193
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
|
+
|
|
1194
1341
|
* * *
|
|
1195
1342
|
|
|
1196
1343
|
## Layer 2: Form Data Model
|
|
@@ -1374,6 +1521,8 @@ interface FieldGroup {
|
|
|
1374
1521
|
// Note: `required` on groups is not supported in MF/0.1 (ignored with warning)
|
|
1375
1522
|
validate?: ValidatorRef[]; // validator references (string IDs or parameterized objects)
|
|
1376
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.
|
|
1377
1526
|
}
|
|
1378
1527
|
|
|
1379
1528
|
type FieldPriorityLevel = 'high' | 'medium' | 'low';
|
|
@@ -1384,6 +1533,8 @@ interface FieldBase {
|
|
|
1384
1533
|
required: boolean; // explicit: parser defaults to false if not specified
|
|
1385
1534
|
priority: FieldPriorityLevel; // explicit: parser defaults to 'medium' if not specified
|
|
1386
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.
|
|
1387
1538
|
}
|
|
1388
1539
|
|
|
1389
1540
|
// NOTE: `required` and `priority` are explicit (not optional) in the data model.
|
|
@@ -1420,7 +1571,9 @@ interface Option {
|
|
|
1420
1571
|
id: Id;
|
|
1421
1572
|
label: string;
|
|
1422
1573
|
}
|
|
1574
|
+
```
|
|
1423
1575
|
|
|
1576
|
+
```typescript
|
|
1424
1577
|
type CheckboxMode = 'multi' | 'simple' | 'explicit';
|
|
1425
1578
|
|
|
1426
1579
|
interface CheckboxesField extends FieldBase {
|
|
@@ -1966,6 +2119,16 @@ YAML keys use snake_case for readability and consistency with common YAML conven
|
|
|
1966
2119
|
| `tag` | `DocumentationBlock` | `DocumentationTag` values | Identifies doc block type |
|
|
1967
2120
|
| `nodeType` | `IdIndexEntry` | `'form' \| 'group' \| 'field'` | Identifies structural element type |
|
|
1968
2121
|
|
|
2122
|
+
**Special IDs:**
|
|
2123
|
+
|
|
2124
|
+
These IDs have special meaning but can also be used explicitly. When used explicitly, uniqueness
|
|
2125
|
+
is still enforced (only one field or group with each ID).
|
|
2126
|
+
|
|
2127
|
+
| Special ID | Purpose | Explicit Use |
|
|
2128
|
+
| --- | --- | --- |
|
|
2129
|
+
| `default` | Implicit group for ungrouped fields | When explicit, ungrouped fields merge into it |
|
|
2130
|
+
| `checkboxes` | Implicit checkboxes field for plan documents | When explicit, used instead of implicit creation |
|
|
2131
|
+
|
|
1969
2132
|
##### Field Kind Mappings
|
|
1970
2133
|
|
|
1971
2134
|
**`string-field`** — Single string value
|
|
@@ -2584,6 +2747,38 @@ isRetryableError(error) // LLM error with retryable=true
|
|
|
2584
2747
|
`ParseError` is exported as an alias for `MarkformParseError` for backward compatibility.
|
|
2585
2748
|
Use `MarkformParseError` in new code.
|
|
2586
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
|
+
|
|
2587
2782
|
* * *
|
|
2588
2783
|
|
|
2589
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
|
-
|
|
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
|
-
|
|
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 %}
|
|
@@ -0,0 +1,35 @@
|
|
|
1
|
+
---
|
|
2
|
+
markform:
|
|
3
|
+
spec: MF/0.1
|
|
4
|
+
title: Sprint Tasks
|
|
5
|
+
description: "Plan document example using Markdoc syntax instead of HTML comments."
|
|
6
|
+
roles:
|
|
7
|
+
- user
|
|
8
|
+
role_instructions:
|
|
9
|
+
user: "Update task status as you complete work."
|
|
10
|
+
---
|
|
11
|
+
{% form id="sprint_tasks" title="Sprint Tasks" %}
|
|
12
|
+
|
|
13
|
+
{% description ref="sprint_tasks" %}
|
|
14
|
+
A sprint task list using Markdoc tag syntax. Both Markdoc (`{% %}`) and
|
|
15
|
+
HTML comment (`<!-- -->`) syntaxes are equivalent in Markform.
|
|
16
|
+
{% /description %}
|
|
17
|
+
|
|
18
|
+
## Backend
|
|
19
|
+
|
|
20
|
+
- [ ] Implement user authentication {% #auth %}
|
|
21
|
+
- [ ] Add rate limiting {% #rate_limit %}
|
|
22
|
+
- [ ] Set up database migrations {% #db_migrations %}
|
|
23
|
+
|
|
24
|
+
## Frontend
|
|
25
|
+
|
|
26
|
+
- [ ] Create login page {% #login_page %}
|
|
27
|
+
- [ ] Add form validation {% #form_validation %}
|
|
28
|
+
- [ ] Implement dark mode {% #dark_mode %}
|
|
29
|
+
|
|
30
|
+
## DevOps
|
|
31
|
+
|
|
32
|
+
- [ ] Configure CI/CD pipeline {% #cicd %}
|
|
33
|
+
- [ ] Set up monitoring {% #monitoring %}
|
|
34
|
+
|
|
35
|
+
{% /form %}
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
---
|
|
2
|
+
markform:
|
|
3
|
+
spec: MF/0.1
|
|
4
|
+
title: Project Plan
|
|
5
|
+
description: "Example plan document using implicit checkboxes - no explicit field wrappers needed."
|
|
6
|
+
roles:
|
|
7
|
+
- user
|
|
8
|
+
- agent
|
|
9
|
+
role_instructions:
|
|
10
|
+
user: "Review the plan and update task status as work progresses."
|
|
11
|
+
agent: "Track task completion and update checkbox states."
|
|
12
|
+
---
|
|
13
|
+
<!-- form id="project_plan" title="Project Plan" -->
|
|
14
|
+
|
|
15
|
+
<!-- description ref="project_plan" -->
|
|
16
|
+
A project plan demonstrating Markform's implicit checkboxes feature.
|
|
17
|
+
When a form has no explicit field tags, checkboxes are automatically
|
|
18
|
+
collected into an implicit `checkboxes` field.
|
|
19
|
+
<!-- /description -->
|
|
20
|
+
|
|
21
|
+
## Phase 1: Research
|
|
22
|
+
|
|
23
|
+
- [x] Review existing documentation <!-- #review_docs -->
|
|
24
|
+
- [x] Analyze competitor solutions <!-- #competitor_analysis -->
|
|
25
|
+
- [x] Interview stakeholders <!-- #stakeholder_interviews -->
|
|
26
|
+
|
|
27
|
+
## Phase 2: Design
|
|
28
|
+
|
|
29
|
+
- [x] Create architecture document <!-- #arch_doc -->
|
|
30
|
+
- [x] Design API specification <!-- #api_spec -->
|
|
31
|
+
- [/] Review design with team <!-- #design_review -->
|
|
32
|
+
|
|
33
|
+
## Phase 3: Implementation
|
|
34
|
+
|
|
35
|
+
- [*] Set up development environment <!-- #dev_setup -->
|
|
36
|
+
- [ ] Implement core functionality <!-- #core_impl -->
|
|
37
|
+
- [ ] Add unit tests <!-- #unit_tests -->
|
|
38
|
+
- [ ] Add integration tests <!-- #integration_tests -->
|
|
39
|
+
|
|
40
|
+
## Phase 4: Release
|
|
41
|
+
|
|
42
|
+
- [ ] Write user documentation <!-- #user_docs -->
|
|
43
|
+
- [ ] Perform security audit <!-- #security_audit -->
|
|
44
|
+
- [-] Deploy to staging <!-- #staging_deploy -->
|
|
45
|
+
- [ ] Deploy to production <!-- #prod_deploy -->
|
|
46
|
+
|
|
47
|
+
<!-- /form -->
|