markform 0.1.20 → 0.1.22

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 (58) hide show
  1. package/README.md +44 -12
  2. package/dist/ai-sdk.d.mts +1 -1
  3. package/dist/ai-sdk.mjs +2 -2
  4. package/dist/{apply-DIvm1b1s.mjs → apply-C7mO7VkZ.mjs} +158 -95
  5. package/dist/apply-C7mO7VkZ.mjs.map +1 -0
  6. package/dist/bin.mjs +1 -1
  7. package/dist/{cli-FFMoEhFS.mjs → cli-C8F9yDsv.mjs} +102 -1225
  8. package/dist/cli-C8F9yDsv.mjs.map +1 -0
  9. package/dist/cli.mjs +1 -1
  10. package/dist/{coreTypes-CkxML8g2.d.mts → coreTypes-BlsJkU1w.d.mts} +28 -2
  11. package/dist/{coreTypes-CPKXf2dc.mjs → coreTypes-CTLr-NGd.mjs} +24 -3
  12. package/dist/coreTypes-CTLr-NGd.mjs.map +1 -0
  13. package/dist/fillRecord-DTl5lnK0.d.mts +345 -0
  14. package/dist/fillRecordRenderer-CruJrLkj.mjs +1256 -0
  15. package/dist/fillRecordRenderer-CruJrLkj.mjs.map +1 -0
  16. package/dist/index.d.mts +22 -342
  17. package/dist/index.mjs +5 -5
  18. package/dist/render.d.mts +74 -0
  19. package/dist/render.mjs +4 -0
  20. package/dist/{session-CK0x28RO.mjs → session-BCcltrLA.mjs} +2 -2
  21. package/dist/{session-CK0x28RO.mjs.map → session-BCcltrLA.mjs.map} +1 -1
  22. package/dist/{session-ZHBi3LVQ.mjs → session-VeSkVrck.mjs} +1 -1
  23. package/dist/{shared-DwdyWmvE.mjs → shared-CsdT2T7k.mjs} +1 -1
  24. package/dist/{shared-DwdyWmvE.mjs.map → shared-CsdT2T7k.mjs.map} +1 -1
  25. package/dist/{shared-BTR35aMz.mjs → shared-fb0nkzQi.mjs} +1 -1
  26. package/dist/{src-wR7GoftB.mjs → src-CbRnGzMK.mjs} +205 -138
  27. package/dist/src-CbRnGzMK.mjs.map +1 -0
  28. package/dist/urlFormat-lls7CsEP.mjs +71 -0
  29. package/dist/urlFormat-lls7CsEP.mjs.map +1 -0
  30. package/docs/markform-apis.md +53 -0
  31. package/examples/movie-research/movie-deep-research-mock-filled.form.md +320 -343
  32. package/examples/movie-research/movie-deep-research.form.md +273 -308
  33. package/examples/movie-research/movie-research-demo.form.md +27 -41
  34. package/examples/parallel/parallel-research.form.md +33 -29
  35. package/examples/parallel/parallel-research.mock.filled.form.md +88 -0
  36. package/examples/rejection-test/rejection-test-mock-filled.form.md +21 -16
  37. package/examples/rejection-test/rejection-test-mock-filled.schema.json +1 -1
  38. package/examples/rejection-test/rejection-test.form.md +17 -15
  39. package/examples/rejection-test/rejection-test.session.yaml +88 -60
  40. package/examples/simple/simple-mock-filled.form.md +113 -126
  41. package/examples/simple/simple-mock-filled.schema.json +2 -3
  42. package/examples/simple/simple-skipped-filled.form.md +112 -129
  43. package/examples/simple/simple-skipped-filled.report.md +8 -8
  44. package/examples/simple/simple-skipped-filled.schema.json +2 -3
  45. package/examples/simple/simple-tags-syntax.form.md +32 -0
  46. package/examples/simple/simple-with-skips.session.yaml +663 -627
  47. package/examples/simple/simple.form.md +97 -113
  48. package/examples/simple/simple.schema.json +2 -3
  49. package/examples/simple/simple.session.yaml +663 -627
  50. package/examples/startup-deep-research/startup-deep-research.form.md +191 -235
  51. package/examples/startup-research/startup-research-mock-filled.form.md +128 -147
  52. package/examples/startup-research/startup-research.form.md +90 -129
  53. package/examples/twitter-thread/twitter-thread.form.md +373 -0
  54. package/package.json +5 -1
  55. package/dist/apply-DIvm1b1s.mjs.map +0 -1
  56. package/dist/cli-FFMoEhFS.mjs.map +0 -1
  57. package/dist/coreTypes-CPKXf2dc.mjs.map +0 -1
  58. package/dist/src-wR7GoftB.mjs.map +0 -1
@@ -0,0 +1,373 @@
1
+ ---
2
+ markform:
3
+ spec: MF/0.1
4
+ title: Content to Twitter Thread
5
+ description: Transform raw content into an engaging Twitter/X thread through structured analysis, prioritization, and iterative refinement.
6
+ run_mode: fill
7
+ roles:
8
+ - user
9
+ - agent
10
+ role_instructions:
11
+ user: |
12
+ Provide your raw content and any context about your audience and goals.
13
+ The content can be a transcript, blog draft, notes, or any text.
14
+ Include as much detail as possible: specific examples, names, links, code.
15
+ agent: |
16
+ Transform the input into a compelling Twitter thread. Work through each stage in order—do not skip stages.
17
+
18
+ VOICE AND STYLE (CRITICAL):
19
+ - Write like a smart person talking, not a press release
20
+ - Be informal: use contractions, conversational phrasing
21
+ - Be opinionated: take strong positions, not wishy-washy hedging
22
+ - Be specific: name people, cite sources, link to things
23
+ - Be novel: each tweet should make the reader pause and think
24
+ - AVOID: generic "sounds like perfect English" corporate speak
25
+ - AVOID: vague claims like "improves quality" without showing HOW
26
+
27
+ Good example: "LLMs are, first and foremost, fuzzy subgraph matching machines"
28
+ Bad example: "LLMs have limitations in certain reasoning tasks"
29
+
30
+ Good example: "Like Katalin Karikó, for instance" (names a specific person)
31
+ Bad example: "Like many successful researchers" (generic)
32
+
33
+ STAGE 1 - CLEANUP: Edit raw content. PRESERVE specific names, examples, links, code.
34
+
35
+ STAGE 2 - EXTRACT INSIGHTS: Find CONCRETE, NOVEL insights worth sharing.
36
+ Look for:
37
+ - Specific examples with names/links (people, repos, books, episodes)
38
+ - Technical details that are precise and memorable
39
+ - Personal observations ("As a researcher, I find...")
40
+ - Contrarian or surprising claims
41
+ - Things that make you go "huh, I never thought of it that way"
42
+ AVOID: Generic claims that could be in any article on the topic
43
+
44
+ STAGE 3 - PRIORITIZE: Rank by NOVELTY and specificity.
45
+ The hook should be surprising or contrarian, not a generic claim.
46
+ Include tweets that link to specific things (repos, docs, people, books).
47
+
48
+ STAGE 4 - STRUCTURE: Plan the thread. Longer is fine (15-25 tweets) if every
49
+ tweet has real substance. Include:
50
+ - Specific examples with links
51
+ - Technical details that are precise
52
+ - Personal takes and opinions
53
+ - At least 2-3 tweets that reference specific things to click/explore
54
+
55
+ STAGE 5 - DRAFT: Write informally. Sound like a person, not a brand.
56
+ - Use contractions (I've, it's, that's)
57
+ - Use parentheticals for asides (if you're a researcher, you'll have noticed)
58
+ - Be direct and opinionated
59
+ - Include specific names, links, code when relevant
60
+
61
+ STAGE 6 - REVIEW: Check each tweet:
62
+ - Does it sound like a person talking? (not corporate)
63
+ - Is it specific? (names, examples, links)
64
+ - Is it novel? (makes you think, not just nod)
65
+ - Would someone quote-tweet this specific insight?
66
+
67
+ STAGE 7 - FINAL: Produce polished output. Every tweet should be quotable.
68
+
69
+ Key principles:
70
+ - Generic = worthless. Specific = valuable.
71
+ - Sound like yourself, not like marketing copy
72
+ - Each tweet should teach something or make someone think
73
+ - Include things to click on (links, repos, names to search)
74
+ harness_config:
75
+ max_issues_per_turn: 5
76
+ max_patches_per_turn: 15
77
+ ---
78
+ <!-- form id="twitter_thread" title="Content to Twitter Thread" -->
79
+
80
+ <!-- description ref="twitter_thread" -->
81
+ A rigorous content transformation workflow: raw text → insights → prioritization → structure → drafts → review → final thread. Each stage enforces quality through structured tables and validation.
82
+ <!-- /description -->
83
+
84
+ <!-- group id="input" title="Input: Raw Content" -->
85
+
86
+ ## Source Content
87
+
88
+ <!-- field kind="string" id="raw_content" label="Raw Content" role="user" required=true minLength=200 --><!-- /field -->
89
+
90
+ <!-- instructions ref="raw_content" -->
91
+ Paste your raw content. This can be:
92
+ - A rough transcript (talk, podcast, voice memo)
93
+ - A blog post or article draft
94
+ - Meeting notes, brainstorm, or research notes
95
+ - Any text you want to transform
96
+
97
+ Aim for at least a few paragraphs. More content = richer thread options.
98
+ <!-- /instructions -->
99
+
100
+ <!-- field kind="string" id="target_audience" label="Target Audience" role="user" maxLength=200 --><!-- /field -->
101
+
102
+ <!-- instructions ref="target_audience" -->
103
+ Who is this thread for? Examples:
104
+ - "Startup founders building AI products"
105
+ - "Developers learning system design"
106
+ - "Product managers in B2B SaaS"
107
+
108
+ Helps tailor tone, examples, and assumed knowledge level.
109
+ <!-- /instructions -->
110
+
111
+ <!-- field kind="string" id="thread_goal" label="Thread Goal" role="user" maxLength=300 --><!-- /field -->
112
+
113
+ <!-- instructions ref="thread_goal" -->
114
+ What should readers take away? Examples:
115
+ - "Understand why structured forms improve AI agent reliability"
116
+ - "Learn the 5 key principles of good API design"
117
+ - "See why this approach to X is underrated"
118
+ <!-- /instructions -->
119
+
120
+ <!-- field kind="number" id="target_length" label="Target Thread Length" role="user" min=5 max=20 integer=true --><!-- /field -->
121
+
122
+ <!-- instructions ref="target_length" -->
123
+ Desired number of tweets (5-20). Typical threads:
124
+ - 5-7 tweets: Quick insight or single concept
125
+ - 8-12 tweets: Moderate depth, multiple points
126
+ - 12-20 tweets: Deep dive, comprehensive coverage
127
+ <!-- /instructions -->
128
+
129
+ <!-- /group -->
130
+
131
+ <!-- group id="cleanup" title="Stage 1: Content Cleanup" -->
132
+
133
+ ## Cleaned Content
134
+
135
+ <!-- field kind="string" id="cleaned_content" label="Cleaned Content" role="agent" required=true minLength=100 --><!-- /field -->
136
+
137
+ <!-- instructions ref="cleaned_content" -->
138
+ Edit the raw content into clean, readable prose:
139
+ - Fix transcription errors, typos, and grammatical issues
140
+ - Remove filler words (um, uh, like, you know, basically)
141
+ - Improve sentence flow and clarity
142
+ - Preserve the author's voice and distinctive phrases
143
+ - Don't add new ideas—just clean what's there
144
+ <!-- /instructions -->
145
+
146
+ <!-- /group -->
147
+
148
+ <!-- group id="insights" title="Stage 2: Extract Insights" -->
149
+
150
+ ## Key Insights
151
+
152
+ Extract every insight, claim, or idea worth sharing.
153
+
154
+ <!-- field kind="table" id="insights_table" label="Insights" role="agent" required=true
155
+ columnIds=["insight", "why_matters", "type"]
156
+ columnLabels=["Insight/Claim", "Why It Matters", "Type"]
157
+ columnTypes=["string", "string", "string"]
158
+ minRows=5 maxRows=20 -->
159
+
160
+ | Insight/Claim | Why It Matters | Type |
161
+ |---------------|----------------|------|
162
+
163
+ <!-- /field -->
164
+
165
+ <!-- instructions ref="insights_table" -->
166
+ For each insight from the cleaned content:
167
+ - **Insight/Claim**: The core idea in one sentence
168
+ - **Why It Matters**: Why should readers care? What's the payoff?
169
+ - **Type**: categorize as one of:
170
+ - `thesis` - central argument
171
+ - `supporting` - backs up the thesis
172
+ - `example` - concrete illustration
173
+ - `context` - background/setup
174
+ - `contrarian` - challenges assumptions
175
+ - `actionable` - something readers can do
176
+
177
+ Be thorough—extract MORE than you'll use. You'll prioritize in the next stage.
178
+ <!-- /instructions -->
179
+
180
+ <!-- /group -->
181
+
182
+ <!-- group id="prioritize" title="Stage 3: Prioritize & Rank" -->
183
+
184
+ ## Prioritization
185
+
186
+ Not every insight makes the thread. Rank by impact and assign roles.
187
+
188
+ <!-- field kind="table" id="priority_table" label="Ranked Insights" role="agent" required=true
189
+ columnIds=["rank", "insight_summary", "role", "include"]
190
+ columnLabels=["Rank", "Insight (summary)", "Thread Role", "Include?"]
191
+ columnTypes=["number", "string", "string", "string"]
192
+ minRows=5 maxRows=15 -->
193
+
194
+ | Rank | Insight (summary) | Thread Role | Include? |
195
+ |------|-------------------|-------------|----------|
196
+
197
+ <!-- /field -->
198
+
199
+ <!-- instructions ref="priority_table" -->
200
+ Take insights from Stage 2 and prioritize:
201
+ - **Rank**: 1 = highest impact, most compelling
202
+ - **Insight**: Brief summary (reference the insight)
203
+ - **Thread Role**: Where it fits in the thread:
204
+ - `hook` - attention-grabbing opener (need exactly 1)
205
+ - `context` - setup/background
206
+ - `main_point` - core argument support
207
+ - `example` - concrete illustration
208
+ - `pivot` - transition or "but here's the thing"
209
+ - `summary` - ties it together
210
+ - `cta` - call to action (need exactly 1)
211
+ - **Include?**: `yes` or `no` (cut ruthlessly—not everything fits)
212
+
213
+ Total "yes" should roughly match target thread length.
214
+ <!-- /instructions -->
215
+
216
+ <!-- field kind="string" id="hook_strategy" label="Hook Strategy" role="agent" required=true maxLength=400 --><!-- /field -->
217
+
218
+ <!-- instructions ref="hook_strategy" -->
219
+ What's the hook strategy? Choose one:
220
+ - **Contrarian**: "Most people think X, but actually Y"
221
+ - **Promise**: "Here's how to do X in N steps"
222
+ - **Story**: "Last week I learned something that changed how I think about X"
223
+ - **Bold claim**: "X is the most underrated skill in Y"
224
+ - **Question**: "Why do most X fail at Y?"
225
+
226
+ Write out your specific hook angle for this thread.
227
+ <!-- /instructions -->
228
+
229
+ <!-- /group -->
230
+
231
+ <!-- group id="structure" title="Stage 4: Thread Structure" -->
232
+
233
+ ## Thread Plan
234
+
235
+ Map the prioritized insights into a tweet-by-tweet structure.
236
+
237
+ <!-- field kind="table" id="structure_table" label="Thread Structure" role="agent" required=true
238
+ columnIds=["tweet_num", "role", "content_plan", "source_insight"]
239
+ columnLabels=["#", "Role", "Content Plan", "From Insight"]
240
+ columnTypes=["number", "string", "string", "string"]
241
+ minRows=5 maxRows=20 -->
242
+
243
+ | # | Role | Content Plan | From Insight |
244
+ |---|------|--------------|--------------|
245
+
246
+ <!-- /field -->
247
+
248
+ <!-- instructions ref="structure_table" -->
249
+ Plan each tweet position:
250
+ - **#**: Tweet number (1, 2, 3...)
251
+ - **Role**: hook, context, main_point, example, pivot, summary, cta
252
+ - **Content Plan**: What this tweet will say (not the final text, just the plan)
253
+ - **From Insight**: Which insight from the priority table this uses (or "new" if synthesized)
254
+
255
+ This is your blueprint. Drafting should follow this plan.
256
+ <!-- /instructions -->
257
+
258
+ <!-- /group -->
259
+
260
+ <!-- group id="drafts" title="Stage 5: Draft Tweets" -->
261
+
262
+ ## Tweet Drafts
263
+
264
+ Write each tweet following the structure plan.
265
+
266
+ <!-- field kind="table" id="drafts_table" label="Tweet Drafts" role="agent" required=true
267
+ columnIds=["tweet_num", "draft_content", "char_count", "issues"]
268
+ columnLabels=["#", "Draft Content", "Chars", "Issues"]
269
+ columnTypes=["number", "string", "number", "string"]
270
+ minRows=5 maxRows=20 -->
271
+
272
+ | # | Draft Content | Chars | Issues |
273
+ |---|---------------|-------|--------|
274
+
275
+ <!-- /field -->
276
+
277
+ <!-- instructions ref="drafts_table" -->
278
+ Write each tweet:
279
+ - **#**: Tweet number, must include "N/" prefix in the content
280
+ - **Draft Content**: The tweet text (must be ≤280 characters)
281
+ - **Chars**: Character count (be accurate!)
282
+ - **Issues**: Note any problems: "too long", "weak hook", "unclear", "missing link to previous"
283
+
284
+ Rules:
285
+ - Hard limit: 280 characters per tweet
286
+ - Include thread number prefix (1/, 2/, etc.)
287
+ - Each tweet should make sense if quoted alone
288
+ - Line breaks within tweets are fine for readability
289
+ <!-- /instructions -->
290
+
291
+ <!-- /group -->
292
+
293
+ <!-- group id="review" title="Stage 6: Review & Refine" -->
294
+
295
+ ## Review Checklist
296
+
297
+ Verify each tweet against quality criteria.
298
+
299
+ <!-- field kind="table" id="review_table" label="Tweet Review" role="agent" required=true
300
+ columnIds=["tweet_num", "under_280", "clear", "flows", "standalone", "revision_needed"]
301
+ columnLabels=["#", "≤280?", "Clear?", "Flows?", "Standalone?", "Revision"]
302
+ columnTypes=["number", "string", "string", "string", "string", "string"]
303
+ minRows=5 maxRows=20 -->
304
+
305
+ | # | ≤280? | Clear? | Flows? | Standalone? | Revision |
306
+ |---|-------|--------|--------|-------------|----------|
307
+
308
+ <!-- /field -->
309
+
310
+ <!-- instructions ref="review_table" -->
311
+ Review each tweet:
312
+ - **≤280?**: Is it under 280 characters? (yes/no)
313
+ - **Clear?**: Is the point immediately clear? (yes/no)
314
+ - **Flows?**: Does it connect naturally from the previous tweet? (yes/no/na for #1)
315
+ - **Standalone?**: Would it make sense if someone only saw this tweet? (yes/no)
316
+ - **Revision**: What needs fixing? Leave blank if good, otherwise note the issue.
317
+
318
+ If any issues exist, address them before finalizing.
319
+ <!-- /instructions -->
320
+
321
+ <!-- field kind="string" id="revision_notes" label="Revision Notes" role="agent" maxLength=500 --><!-- /field -->
322
+
323
+ <!-- instructions ref="revision_notes" -->
324
+ If any tweets needed revision based on the review, note what you changed.
325
+ Leave blank if no revisions were needed.
326
+ <!-- /instructions -->
327
+
328
+ <!-- /group -->
329
+
330
+ <!-- group id="final" title="Stage 7: Final Thread" -->
331
+
332
+ ## Final Output
333
+
334
+ The polished, copy-paste ready thread.
335
+
336
+ <!-- field kind="string" id="final_thread" label="Final Thread" role="agent" required=true --><!-- /field -->
337
+
338
+ <!-- instructions ref="final_thread" -->
339
+ Produce the final thread in copy-paste format:
340
+
341
+ 1/ [First tweet]
342
+
343
+ 2/ [Second tweet]
344
+
345
+ 3/ [Third tweet]
346
+
347
+ ...
348
+
349
+ (Double line break between each tweet for easy copying)
350
+ <!-- /instructions -->
351
+
352
+ <!-- field kind="number" id="total_tweets" label="Total Tweet Count" role="agent" required=true min=5 max=20 integer=true --><!-- /field -->
353
+
354
+ <!-- field kind="checkboxes" id="final_checklist" label="Final Quality Checklist" role="agent" checkboxMode="simple" required=true -->
355
+
356
+ - [ ] Hook grabs attention and is specific to the content <!-- #hook_quality -->
357
+ - [ ] Every tweet is under 280 characters <!-- #char_limit -->
358
+ - [ ] Thread has clear narrative arc (setup → points → conclusion) <!-- #narrative_arc -->
359
+ - [ ] Each tweet flows naturally from the previous one <!-- #flow_quality -->
360
+ - [ ] Each tweet makes sense if read in isolation <!-- #standalone -->
361
+ - [ ] Ends with clear CTA or memorable summary <!-- #ending_quality -->
362
+ - [ ] No filler tweets—every tweet adds value <!-- #no_filler -->
363
+
364
+ <!-- /field -->
365
+
366
+ <!-- instructions ref="final_checklist" -->
367
+ Verify ALL quality criteria are met before marking complete.
368
+ Do not check a box unless you've verified it's true.
369
+ <!-- /instructions -->
370
+
371
+ <!-- /group -->
372
+
373
+ <!-- /form -->
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "markform",
3
- "version": "0.1.20",
3
+ "version": "0.1.22",
4
4
  "description": "Markdown forms for token-friendly workflows",
5
5
  "license": "AGPL-3.0-or-later",
6
6
  "author": "Joshua Levy",
@@ -40,6 +40,10 @@
40
40
  "types": "./dist/ai-sdk.d.mts",
41
41
  "default": "./dist/ai-sdk.mjs"
42
42
  },
43
+ "./render": {
44
+ "types": "./dist/render.d.mts",
45
+ "default": "./dist/render.mjs"
46
+ },
43
47
  "./package.json": "./package.json"
44
48
  },
45
49
  "bin": {