flex-md 3.5.0 → 4.1.0

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 (74) hide show
  1. package/README.md +423 -39
  2. package/dist/index.cjs +62 -3
  3. package/dist/index.d.ts +1 -0
  4. package/dist/index.js +2 -0
  5. package/dist/md/parse.d.ts +1 -0
  6. package/dist/md/parse.js +12 -0
  7. package/dist/ofs/parser.js +31 -10
  8. package/dist/tokens/auto-fix.d.ts +10 -0
  9. package/dist/tokens/auto-fix.js +56 -0
  10. package/dist/tokens/cognitive-cost.d.ts +10 -0
  11. package/dist/tokens/cognitive-cost.js +205 -0
  12. package/dist/tokens/compliance.d.ts +10 -0
  13. package/dist/tokens/compliance.js +70 -0
  14. package/dist/tokens/confidence.d.ts +6 -0
  15. package/dist/tokens/confidence.js +332 -0
  16. package/dist/tokens/estimator.d.ts +12 -0
  17. package/dist/tokens/estimator.js +138 -0
  18. package/dist/tokens/improvements.d.ts +10 -0
  19. package/dist/tokens/improvements.js +697 -0
  20. package/dist/tokens/index.d.ts +24 -0
  21. package/dist/tokens/index.js +31 -0
  22. package/dist/tokens/parser.d.ts +3 -0
  23. package/dist/tokens/parser.js +97 -0
  24. package/dist/tokens/patterns.d.ts +9 -0
  25. package/dist/tokens/patterns.js +20 -0
  26. package/dist/tokens/smart-report.d.ts +10 -0
  27. package/dist/tokens/smart-report.js +187 -0
  28. package/dist/tokens/spec-estimator.d.ts +7 -0
  29. package/dist/tokens/spec-estimator.js +68 -0
  30. package/dist/tokens/types.d.ts +185 -0
  31. package/dist/tokens/validator.d.ts +16 -0
  32. package/dist/tokens/validator.js +59 -0
  33. package/docs/Recommended New Strategies for AI Request Builder.md +691 -0
  34. package/package.json +7 -3
  35. package/dist/detection/detector.d.ts +0 -6
  36. package/dist/detection/detector.js +0 -104
  37. package/dist/detection/extractor.d.ts +0 -10
  38. package/dist/detection/extractor.js +0 -54
  39. package/dist/issues/build.d.ts +0 -26
  40. package/dist/issues/build.js +0 -62
  41. package/dist/md/lists.d.ts +0 -14
  42. package/dist/md/lists.js +0 -33
  43. package/dist/md/tables.d.ts +0 -25
  44. package/dist/md/tables.js +0 -72
  45. package/dist/ofs/extractor.d.ts +0 -9
  46. package/dist/ofs/extractor.js +0 -75
  47. package/dist/ofs/issues.d.ts +0 -14
  48. package/dist/ofs/issues.js +0 -92
  49. package/dist/ofs/validator.d.ts +0 -10
  50. package/dist/ofs/validator.js +0 -91
  51. package/dist/outline/builder.d.ts +0 -10
  52. package/dist/outline/builder.js +0 -85
  53. package/dist/outline/renderer.d.ts +0 -6
  54. package/dist/outline/renderer.js +0 -23
  55. package/dist/parser.d.ts +0 -2
  56. package/dist/parser.js +0 -199
  57. package/dist/parsers/lists.d.ts +0 -6
  58. package/dist/parsers/lists.js +0 -36
  59. package/dist/parsers/tables.d.ts +0 -10
  60. package/dist/parsers/tables.js +0 -58
  61. package/dist/stringify.d.ts +0 -2
  62. package/dist/stringify.js +0 -110
  63. package/dist/test-pipeline.js +0 -53
  64. package/dist/test-runner.d.ts +0 -1
  65. package/dist/test-runner.js +0 -331
  66. package/dist/test-strictness.d.ts +0 -1
  67. package/dist/test-strictness.js +0 -213
  68. package/dist/util.d.ts +0 -5
  69. package/dist/util.js +0 -64
  70. package/dist/validate/policy.d.ts +0 -10
  71. package/dist/validate/policy.js +0 -17
  72. package/dist/validator.d.ts +0 -2
  73. package/dist/validator.js +0 -80
  74. /package/dist/{test-pipeline.d.ts → tokens/types.js} +0 -0
package/README.md CHANGED
@@ -1,17 +1,31 @@
1
- # Flex-MD (v3.0) — Markdown Output Contract
1
+ # Flex-MD (v4.0) — Markdown Output Contract with Smart Token Estimation
2
2
 
3
3
  Flex-MD is a TypeScript library for building and enforcing **Markdown Output Contracts** with LLMs. It treats Markdown as a semi-structured data format, allowing you to define required sections, list types, and tables while maintaining 100% standard Markdown compatibility.
4
4
 
5
- Version 3.0 introduces the **Detect-Repair-Enforce** pipeline, ensuring LLM responses are coerced into compliant structures before being parsed.
5
+ **What's New in v4.0:**
6
+ - 🎯 **Automatic Token Estimation**: Calculate `max_tokens` directly from your spec
7
+ - 📏 **System Parts Protocol**: Standardized size hints that guide LLMs AND enable token prediction
8
+ - 🧠 **Smart Toolbox**: Cognitive cost analysis, confidence scoring, and improvement detection
9
+ - 🔧 **Auto-Fix**: Automatically improve specs with one command
6
10
 
7
11
  ## Key Features
8
12
 
13
+ ### Core (v3.0)
9
14
  - **Standard Markdown**: No proprietary tags. Pure headings, lists, and tables.
10
15
  - **Strictness Levels (L0–L3)**: From loose guidance to rigid structural enforcement.
11
16
  - **Deterministic Repair**: Auto-fixes misformatted LLM output (merged fences, missing headings, format conversion).
12
17
  - **Instructions Output Format Guidance**: Generate formal "Instructions Blocks" for LLM prompts directly from spec objects.
13
18
  - **Issues Envelope**: A structured failure format for when repairs fail, allowing safe fallbacks.
14
19
 
20
+ ### Smart Features (v4.0)
21
+ - **Token Estimation**: Automatically calculate `max_tokens` for API calls based on your spec
22
+ - **System Parts**: Structured instruction patterns (`Length: 2-3 paragraphs`, `Items: 3-5`) that guide LLMs and enable estimation
23
+ - **Compliance Checking**: Validate specs meet quality standards (L0-L3 compliance levels)
24
+ - **Cognitive Cost Analysis**: Measure how much effort your spec requires to write/maintain
25
+ - **Confidence Scoring**: Know how accurate your token estimates will be
26
+ - **Improvement Detection**: Find issues and get actionable suggestions
27
+ - **Auto-Fix**: Apply improvements automatically
28
+
15
29
  ## Installation
16
30
 
17
31
  ```bash
@@ -20,29 +34,49 @@ npm install flex-md
20
34
 
21
35
  ## Quick Start
22
36
 
23
- ### 1. Define your Output Format Spec (OFS)
37
+ ### 1. Define your Output Format Spec (OFS) with System Parts
24
38
 
25
39
  ```typescript
26
- import { parseOutputFormatSpec } from 'flex-md';
40
+ import { parseOutputFormatSpec, getMaxTokens } from 'flex-md';
27
41
 
28
42
  const spec = parseOutputFormatSpec(`
29
43
  ## Output format
30
44
  - Short answer — text (required)
45
+ Length: 1-2 sentences. Be concise and direct.
46
+
31
47
  - Reasoning — ordered list (required)
48
+ Items: 3-5. Explain your logic step by step.
49
+
32
50
  - Assumptions — list (optional)
51
+ Items: at least 2. List any key assumptions made.
33
52
 
34
53
  empty sections:
35
54
  - If a section is empty, write \`None\`.
36
55
  `);
56
+
57
+ // Automatically estimate max_tokens needed
58
+ const maxTokens = getMaxTokens(spec);
59
+ console.log(`Estimated max_tokens: ${maxTokens}`); // ~650
37
60
  ```
38
61
 
39
- ### 2. Generate Prompt Guidance
62
+ ### 2. Use in Your LLM API Call
40
63
 
41
64
  ```typescript
42
- import { buildMarkdownGuidance } from 'flex-md';
43
-
44
- const guidance = buildMarkdownGuidance(spec, { level: 1 });
45
- // Output: "Reply in Markdown. Include these headings... If a section is empty, write 'None'."
65
+ const response = await fetch('https://api.anthropic.com/v1/messages', {
66
+ method: 'POST',
67
+ headers: {
68
+ 'Content-Type': 'application/json',
69
+ 'x-api-key': API_KEY
70
+ },
71
+ body: JSON.stringify({
72
+ model: 'claude-sonnet-4-20250514',
73
+ max_tokens: maxTokens, // Automatically calculated!
74
+ messages: [{
75
+ role: 'user',
76
+ content: yourPrompt + '\n\n' + buildMarkdownGuidance(spec)
77
+ }]
78
+ })
79
+ });
46
80
  ```
47
81
 
48
82
  ### 3. Enforce the Contract
@@ -50,47 +84,201 @@ const guidance = buildMarkdownGuidance(spec, { level: 1 });
50
84
  ```typescript
51
85
  import { enforceFlexMd } from 'flex-md';
52
86
 
53
- const llmResponse = "I think... ## Short answer \n Yes. ## Reasoning \n 1. Logic";
54
- const result = enforceFlexMd(llmResponse, spec, { level: 1 });
87
+ const llmResponse = await response.json();
88
+ const result = enforceFlexMd(llmResponse.content[0].text, spec, { level: 2 });
55
89
 
56
90
  if (result.ok) {
57
91
  console.log(result.extracted.sectionsByName["Short answer"].md);
92
+ console.log(result.extracted.sectionsByName["Reasoning"].md);
58
93
  } else {
59
- // result.outputText will contain the Issues Envelope if strictness level >= 1
60
- console.log(result.outputText);
94
+ console.log(result.outputText); // Issues Envelope
61
95
  }
62
96
  ```
63
97
 
64
- ### 4. Dynamic Instructions Output Format Blocks
98
+ ## System Parts Protocol
65
99
 
66
- You can also define your spec as a plain JavaScript object and generate the formal "Instructions Block" for your LLM prompts.
100
+ System Parts are structured prefixes in section instructions that serve dual purposes:
101
+ 1. **Guide the LLM** on expected output size
102
+ 2. **Enable token estimation** for `max_tokens` calculation
103
+
104
+ ### Syntax
105
+
106
+ ```
107
+ [SYSTEM_PART]. [OPTIONAL_GUIDANCE]
108
+ ```
67
109
 
110
+ **Examples:**
68
111
  ```typescript
69
- import { stringifyOutputFormatSpec } from 'flex-md';
112
+ // Text sections
113
+ "Length: 2-3 paragraphs. Provide detailed analysis."
114
+ "Length: brief. Keep it short."
70
115
 
71
- const spec = {
72
- description: "Standard report format for technical analysis.",
73
- sections: [
74
- {
75
- name: "Summary",
76
- kind: "text",
77
- required: true,
78
- description: "A brief summary of the topic."
79
- },
80
- {
81
- name: "Key Points",
82
- kind: "list",
83
- required: false,
84
- instruction: "Include at least 3 bullet points."
85
- }
86
- ]
87
- };
116
+ // Lists
117
+ "Items: 3-5. Focus on key insights."
118
+ "Items: at least 3. Be comprehensive."
88
119
 
89
- const instructionsBlock = stringifyOutputFormatSpec(spec);
90
- // Output will include the ## Output format (Markdown) header, descriptions, and instructions.
120
+ // Tables
121
+ "Rows: 5-7, Columns: 3. Include metrics."
122
+
123
+ // Code
124
+ "Lines: 20-30. Include error handling."
125
+ "Lines: ~50. Provide complete example."
91
126
  ```
92
127
 
93
- ## Strictness Levels
128
+ ### Allowed Values
129
+
130
+ | Section Type | System Part Pattern | Examples |
131
+ |--------------|-------------------|----------|
132
+ | **text** | `Length: <value>` | `brief`, `moderate`, `detailed`, `extensive`, `1-2 sentences`, `2-3 paragraphs` |
133
+ | **list** | `Items: <value>` | `3`, `3-5`, `at least 3` |
134
+ | **table** | `Rows: <value>, Columns: <value>` | `Rows: 5, Columns: 3`, `Rows: 3-5, Columns: 4` |
135
+ | **code** | `Lines: <value>` | `20`, `15-25`, `~50` |
136
+
137
+ See [System Parts Guide](./docs/system-parts.md) for complete reference.
138
+
139
+ ## Compliance Levels (for Spec Authors)
140
+
141
+ Compliance levels measure how much detail you provide in system parts:
142
+
143
+ | Level | Detail | Cognitive Load | Token Estimation Accuracy |
144
+ |-------|--------|---------------|--------------------------|
145
+ | **L0** | No system parts | None | Fallback (~±40%) |
146
+ | **L1** | Simple values | Minimal | Basic (~±30%) |
147
+ | **L2** | Ranges allowed | Low | Good (~±20%) |
148
+ | **L3** | Full spec with "at least", "~" | Medium | Precise (~±10%) |
149
+
150
+ **L2 is recommended** for most use cases - good balance of effort and accuracy.
151
+
152
+ ### Examples by Level
153
+
154
+ ```typescript
155
+ // L0 - No system parts (fallback estimation)
156
+ "Just provide a summary."
157
+
158
+ // L1 - Simple values
159
+ "Length: brief. Provide a summary."
160
+ "Items: 3. List the main points."
161
+
162
+ // L2 - Ranges
163
+ "Length: 2-3 paragraphs. Provide detailed analysis."
164
+ "Items: 3-5. List key insights."
165
+
166
+ // L3 - Full specification
167
+ "Items: at least 5. Include all relevant factors."
168
+ "Lines: ~50. Provide a complete working example."
169
+ ```
170
+
171
+ ## Smart Toolbox
172
+
173
+ ### Token Estimation
174
+
175
+ ```typescript
176
+ import { getMaxTokens, estimateSpecTokens } from 'flex-md';
177
+
178
+ // Quick estimate
179
+ const maxTokens = getMaxTokens(spec);
180
+
181
+ // Detailed estimate with options
182
+ const estimate = estimateSpecTokens(spec, {
183
+ includeOptional: true,
184
+ safetyMultiplier: 1.3,
185
+ strategy: 'average' // 'conservative' | 'average' | 'generous'
186
+ });
187
+
188
+ console.log(estimate);
189
+ // {
190
+ // total: { estimated: 650, min: 520, max: 780, confidence: 'high' },
191
+ // bySectionName: { ... },
192
+ // overhead: 60
193
+ // }
194
+ ```
195
+
196
+ ### Compliance Checking
197
+
198
+ ```typescript
199
+ import { checkCompliance, formatComplianceReport } from 'flex-md';
200
+
201
+ const report = checkCompliance(spec, 2); // Check if meets L2
202
+
203
+ console.log(formatComplianceReport(report));
204
+ // Shows which sections need improvement to meet target level
205
+ ```
206
+
207
+ ### Confidence Scoring
208
+
209
+ ```typescript
210
+ import { calculateConfidence } from 'flex-md';
211
+
212
+ const confidence = calculateConfidence(spec);
213
+
214
+ console.log(`Confidence: ${confidence.grade} (${confidence.overall}%)`);
215
+ console.log('Recommendations:', confidence.recommendations);
216
+ // Grade: B (82%)
217
+ // Recommendations: ["Good confidence, but can be improved", ...]
218
+ ```
219
+
220
+ ### Cognitive Cost Analysis
221
+
222
+ ```typescript
223
+ import { calculateCognitiveCost } from 'flex-md';
224
+
225
+ const cost = calculateCognitiveCost(spec);
226
+
227
+ console.log(`Cost: ${cost.totalCost}/100`);
228
+ console.log(`Assessment: ${cost.recommendation}`);
229
+ // Cost: 28/100
230
+ // Assessment: "Moderate cognitive load - reasonable effort required"
231
+ ```
232
+
233
+ ### Improvement Detection
234
+
235
+ ```typescript
236
+ import { detectImprovements, formatImprovementReport, autoFix } from 'flex-md';
237
+
238
+ // Detect issues and opportunities
239
+ const analysis = detectImprovements(spec, 2);
240
+ console.log(formatImprovementReport(analysis));
241
+
242
+ // Auto-fix quick wins
243
+ const fixResult = autoFix(spec, analysis.improvements, {
244
+ applyQuickWinsOnly: true
245
+ });
246
+
247
+ console.log(fixResult.summary);
248
+ // "Applied 4 fixes, skipped 1"
249
+ ```
250
+
251
+ ### Complete Smart Analysis
252
+
253
+ ```typescript
254
+ import { analyzeSpec, formatSmartReport } from 'flex-md';
255
+
256
+ const analysis = analyzeSpec(spec, 2);
257
+ console.log(formatSmartReport(analysis));
258
+ ```
259
+
260
+ **Output:**
261
+ ```
262
+ ╔═══════════════════════════════════════════════════╗
263
+ ║ FLEX-MD SMART ANALYSIS REPORT ║
264
+ ╚═══════════════════════════════════════════════════╝
265
+
266
+ 📊 SUMMARY DASHBOARD
267
+ ──────────────────────────────────────────────────
268
+ Compliance: ✓ L2 PASS
269
+ Confidence: B (82%)
270
+ Cognitive Cost: 28/100
271
+ Token Estimate: 650 tokens
272
+
273
+ 💡 RECOMMENDATIONS
274
+ ──────────────────────────────────────────────────
275
+ 🟢 Low Priority:
276
+ • Good confidence, but can be improved
277
+ → Upgrade a few sections to L3 for better precision
278
+ ...
279
+ ```
280
+
281
+ ## Strictness Levels (for LLM Output Enforcement)
94
282
 
95
283
  | Level | Goal | Guidance | Enforcement |
96
284
  | :--- | :--- | :--- | :--- |
@@ -99,6 +287,8 @@ const instructionsBlock = stringifyOutputFormatSpec(spec);
99
287
  | **L2** | Fenced Container | "Return inside a single block..." | Exactly one fenced block. |
100
288
  | **L3** | Typed Structure | "Reasoning is an ordered list..." | Enforce list/table kinds. |
101
289
 
290
+ *Note: These are different from Compliance Levels (which measure spec quality) - Strictness Levels control how strictly Flex-MD enforces the contract on LLM output.*
291
+
102
292
  ## The Repair Pipeline
103
293
 
104
294
  Flex-MD doesn't just validate; it **repairs**. Our deterministic 9-step plan handles:
@@ -108,12 +298,206 @@ Flex-MD doesn't just validate; it **repairs**. Our deterministic 9-step plan han
108
298
  4. **Stray Content**: Moving text outside headings into a default section.
109
299
  5. **Format Conversion**: Transforming bullets to numbered lists (and vice-versa) based on spec.
110
300
 
301
+ ## Real-World Example
302
+
303
+ ```typescript
304
+ import {
305
+ parseOutputFormatSpec,
306
+ getMaxTokens,
307
+ analyzeSpec,
308
+ enforceFlexMd
309
+ } from 'flex-md';
310
+
311
+ // 1. Define spec with system parts
312
+ const spec = parseOutputFormatSpec(`
313
+ ## Output format
314
+ - Executive Summary — text (required)
315
+ Length: 2-3 paragraphs. Summarize findings and recommendations.
316
+
317
+ - Key Metrics — table (required)
318
+ Rows: 5-7, Columns: 3. Include: Metric, Current, Target.
319
+
320
+ - Action Items — ordered list (required)
321
+ Items: 5-10. Prioritize by impact.
322
+
323
+ - Technical Details — code (optional)
324
+ Lines: 20-30. Include implementation examples.
325
+ `);
326
+
327
+ // 2. Analyze spec quality
328
+ const analysis = analyzeSpec(spec, 2);
329
+ console.log(`Confidence: ${analysis.confidence.grade}`);
330
+ console.log(`Max tokens: ${analysis.tokenEstimate.total.estimated}`);
331
+
332
+ // 3. Use in API call
333
+ const response = await anthropic.messages.create({
334
+ model: 'claude-sonnet-4-20250514',
335
+ max_tokens: getMaxTokens(spec, { safetyMultiplier: 1.3 }),
336
+ messages: [{
337
+ role: 'user',
338
+ content: `Analyze Q4 performance.\n\n${buildMarkdownGuidance(spec)}`
339
+ }]
340
+ });
341
+
342
+ // 4. Enforce and extract
343
+ const result = enforceFlexMd(response.content[0].text, spec, { level: 2 });
344
+
345
+ if (result.ok) {
346
+ const summary = result.extracted.sectionsByName["Executive Summary"].md;
347
+ const metrics = result.extracted.sectionsByName["Key Metrics"].md;
348
+ // Use structured output...
349
+ }
350
+ ```
351
+
352
+ ## Advanced Usage
353
+
354
+ ### Custom Token Estimation
355
+
356
+ ```typescript
357
+ const estimate = estimateSpecTokens(spec, {
358
+ includeOptional: false, // Skip optional sections
359
+ safetyMultiplier: 1.5, // Extra headroom
360
+ strategy: 'conservative' // Use minimum estimates
361
+ });
362
+ ```
363
+
364
+ ### CI/CD Integration
365
+
366
+ ```typescript
367
+ // validate-specs.ts
368
+ import { analyzeSpec } from 'flex-md';
369
+
370
+ const analysis = analyzeSpec(spec, 2);
371
+
372
+ const highPriorityIssues = analysis.recommendations
373
+ .filter(r => r.priority === 'high');
374
+
375
+ if (highPriorityIssues.length > 0) {
376
+ console.error('High priority issues found');
377
+ process.exit(1);
378
+ }
379
+ ```
380
+
381
+ ### Progressive Enhancement
382
+
383
+ Start simple and upgrade as needed:
384
+
385
+ ```typescript
386
+ // Version 1: No system parts (works, but fallback estimation)
387
+ const v1 = `
388
+ ## Output format
389
+ - Summary — text (required)
390
+ Write a summary.
391
+ `;
392
+
393
+ // Version 2: Add L1 system parts (better)
394
+ const v2 = `
395
+ ## Output format
396
+ - Summary — text (required)
397
+ Length: brief. Write a summary.
398
+ `;
399
+
400
+ // Version 3: Upgrade to L2 (best balance)
401
+ const v3 = `
402
+ ## Output format
403
+ - Summary — text (required)
404
+ Length: 2-3 sentences. Write a summary.
405
+ `;
406
+ ```
407
+
408
+ ## API Reference
409
+
410
+ ### Core Functions
411
+ - `parseOutputFormatSpec(markdown)` - Parse spec from markdown
412
+ - `stringifyOutputFormatSpec(spec)` - Convert spec to markdown
413
+ - `buildMarkdownGuidance(spec, options)` - Generate LLM instructions
414
+ - `enforceFlexMd(text, spec, options)` - Validate and repair LLM output
415
+
416
+ ### Token Estimation (v4.0)
417
+ - `getMaxTokens(spec, options?)` - Get estimated max_tokens
418
+ - `estimateSpecTokens(spec, options?)` - Detailed token estimate
419
+ - `parseSystemPart(instruction, kind)` - Parse system part from instruction
420
+ - `estimateTokens(systemPart)` - Estimate tokens for system part
421
+
422
+ ### Smart Toolbox (v4.0)
423
+ - `checkCompliance(spec, level)` - Validate compliance level
424
+ - `calculateConfidence(spec)` - Score estimation confidence
425
+ - `calculateCognitiveCost(spec)` - Measure spec complexity
426
+ - `detectImprovements(spec, level?)` - Find issues and suggestions
427
+ - `autoFix(spec, improvements, options?)` - Apply automatic fixes
428
+ - `analyzeSpec(spec, level?)` - Complete smart analysis
429
+
430
+ ### Reporting (v4.0)
431
+ - `formatComplianceReport(report)` - Format compliance check
432
+ - `formatImprovementReport(analysis)` - Format improvements
433
+ - `formatSmartReport(analysis)` - Format complete analysis
434
+
111
435
  ## Documentation
112
436
 
113
- Detailed guides and specs can be found in the [docs](./docs) folder:
114
- - [MDFlex Compliance Spec](./docs/mdflex-compliance.md)
115
- - [OFS Syntax Guide](./SPEC.md)
437
+ Detailed guides can be found in the [docs](./docs) folder:
438
+ - [System Parts Guide](./docs/system-parts.md) - Complete protocol reference
439
+ - [Token Estimation Guide](./docs/token-estimation.md) - How estimation works
440
+ - [Smart Toolbox Guide](./docs/smart-toolbox.md) - Using analysis features
441
+ - [MDFlex Compliance Spec](./docs/mdflex-compliance.md) - Output enforcement
442
+ - [OFS Syntax Guide](./SPEC.md) - Output Format Spec syntax
443
+
444
+ ## Migration from v3.0
445
+
446
+ v4.0 is **100% backwards compatible** with v3.0. All existing code continues to work.
447
+
448
+ To adopt v4.0 features:
449
+
450
+ 1. **Add system parts** to your spec instructions:
451
+ ```diff
452
+ - Summary — text (required)
453
+ - Provide a brief overview.
454
+ + Summary — text (required)
455
+ + Length: 2-3 sentences. Provide a brief overview.
456
+ ```
457
+
458
+ 2. **Use token estimation**:
459
+ ```typescript
460
+ const maxTokens = getMaxTokens(spec);
461
+ ```
462
+
463
+ 3. **Analyze and improve** your specs:
464
+ ```typescript
465
+ const analysis = analyzeSpec(spec);
466
+ console.log(formatSmartReport(analysis));
467
+ ```
468
+
469
+ ## Why Flex-MD v4.0?
470
+
471
+ ### Before v4.0
472
+ ```typescript
473
+ // Guessing max_tokens
474
+ const response = await api.create({
475
+ max_tokens: 2000, // 🤷 Is this enough? Too much?
476
+ ...
477
+ });
478
+ ```
479
+
480
+ ### After v4.0
481
+ ```typescript
482
+ // Precise estimation
483
+ const maxTokens = getMaxTokens(spec); // ✓ 650 tokens (±20%)
484
+ const response = await api.create({
485
+ max_tokens, // 🎯 Right-sized
486
+ ...
487
+ });
488
+ ```
489
+
490
+ ### Benefits
491
+ - ⚡ **Faster responses**: Right-sized tokens mean lower latency
492
+ - 💰 **Lower costs**: Don't overpay for unused tokens
493
+ - 🎯 **Better accuracy**: Clear size expectations guide LLMs
494
+ - 🔍 **Quality insights**: Know your spec's strengths/weaknesses
495
+ - 🛠️ **Easy maintenance**: Auto-detect and fix issues
116
496
 
117
497
  ## License
118
498
 
119
499
  MIT
500
+
501
+ ---
502
+
503
+ **Flex-MD v4.0** - Smart Markdown contracts for production LLM applications.
package/dist/index.cjs CHANGED
@@ -1,3 +1,62 @@
1
- // Auto-generated CJS bridge for flex-md
2
- const m = await import('./index.js');
3
- module.exports = m;
1
+ "use strict";
2
+ var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
3
+ if (k2 === undefined) k2 = k;
4
+ var desc = Object.getOwnPropertyDescriptor(m, k);
5
+ if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
6
+ desc = { enumerable: true, get: function() { return m[k]; } };
7
+ }
8
+ Object.defineProperty(o, k2, desc);
9
+ }) : (function(o, m, k, k2) {
10
+ if (k2 === undefined) k2 = k;
11
+ o[k2] = m[k];
12
+ }));
13
+ var __exportStar = (this && this.__exportStar) || function(m, exports) {
14
+ for (var p in m) if (p !== "default" && !Object.prototype.hasOwnProperty.call(exports, p)) __createBinding(exports, m, p);
15
+ };
16
+ Object.defineProperty(exports, "__esModule", { value: true });
17
+ exports.enforceFlexMd = exports.repairToMarkdownLevel = exports.detectResponseKind = exports.buildIssuesEnvelopeAuto = exports.buildIssuesEnvelope = exports.parseIssuesEnvelope = exports.processResponseMarkdown = exports.extractFromMarkdown = exports.checkConnection = exports.hasFlexMdContract = exports.checkCompliance = exports.validateMarkdownAgainstOfs = exports.enrichInstructionsWithFlexMd = exports.enrichInstructions = exports.buildMarkdownGuidance = exports.stringifyOutputFormatSpec = exports.validateFormat = exports.parseOutputFormatSpec = exports.buildOutline = void 0;
18
+ // Core SFMD Types
19
+ __exportStar(require("./types.js"), exports);
20
+ __exportStar(require("./strictness/types.js"), exports);
21
+ // Shared MD Parsing
22
+ __exportStar(require("./md/parse.js"), exports);
23
+ var outline_js_1 = require("./md/outline.js");
24
+ Object.defineProperty(exports, "buildOutline", { enumerable: true, get: function () { return outline_js_1.buildOutline; } });
25
+ // Output Format Spec (OFS)
26
+ var parser_js_1 = require("./ofs/parser.js");
27
+ Object.defineProperty(exports, "parseOutputFormatSpec", { enumerable: true, get: function () { return parser_js_1.parseOutputFormatSpec; } });
28
+ Object.defineProperty(exports, "validateFormat", { enumerable: true, get: function () { return parser_js_1.validateFormat; } });
29
+ var stringify_js_1 = require("./ofs/stringify.js");
30
+ Object.defineProperty(exports, "stringifyOutputFormatSpec", { enumerable: true, get: function () { return stringify_js_1.stringifyOutputFormatSpec; } });
31
+ var enricher_js_1 = require("./ofs/enricher.js");
32
+ Object.defineProperty(exports, "buildMarkdownGuidance", { enumerable: true, get: function () { return enricher_js_1.buildMarkdownGuidance; } });
33
+ Object.defineProperty(exports, "enrichInstructions", { enumerable: true, get: function () { return enricher_js_1.enrichInstructions; } });
34
+ Object.defineProperty(exports, "enrichInstructionsWithFlexMd", { enumerable: true, get: function () { return enricher_js_1.enrichInstructionsWithFlexMd; } });
35
+ // Validation & Extraction
36
+ var validate_js_1 = require("./validate/validate.js");
37
+ Object.defineProperty(exports, "validateMarkdownAgainstOfs", { enumerable: true, get: function () { return validate_js_1.validateMarkdownAgainstOfs; } });
38
+ var compliance_js_1 = require("./validate/compliance.js");
39
+ Object.defineProperty(exports, "checkCompliance", { enumerable: true, get: function () { return compliance_js_1.checkCompliance; } });
40
+ Object.defineProperty(exports, "hasFlexMdContract", { enumerable: true, get: function () { return compliance_js_1.hasFlexMdContract; } });
41
+ var connection_js_1 = require("./validate/connection.js");
42
+ Object.defineProperty(exports, "checkConnection", { enumerable: true, get: function () { return connection_js_1.checkConnection; } });
43
+ var extract_js_1 = require("./extract/extract.js");
44
+ Object.defineProperty(exports, "extractFromMarkdown", { enumerable: true, get: function () { return extract_js_1.extractFromMarkdown; } });
45
+ // Processor & Fallback
46
+ var processor_js_1 = require("./strictness/processor.js");
47
+ Object.defineProperty(exports, "processResponseMarkdown", { enumerable: true, get: function () { return processor_js_1.processResponseMarkdown; } });
48
+ var issuesEnvelope_js_1 = require("./ofs/issuesEnvelope.js");
49
+ Object.defineProperty(exports, "parseIssuesEnvelope", { enumerable: true, get: function () { return issuesEnvelope_js_1.parseIssuesEnvelope; } });
50
+ Object.defineProperty(exports, "buildIssuesEnvelope", { enumerable: true, get: function () { return issuesEnvelope_js_1.buildIssuesEnvelope; } });
51
+ Object.defineProperty(exports, "buildIssuesEnvelopeAuto", { enumerable: true, get: function () { return issuesEnvelope_js_1.buildIssuesEnvelopeAuto; } });
52
+ // Pipeline
53
+ var kind_js_1 = require("./pipeline/kind.js");
54
+ Object.defineProperty(exports, "detectResponseKind", { enumerable: true, get: function () { return kind_js_1.detectResponseKind; } });
55
+ var repair_js_1 = require("./pipeline/repair.js");
56
+ Object.defineProperty(exports, "repairToMarkdownLevel", { enumerable: true, get: function () { return repair_js_1.repairToMarkdownLevel; } });
57
+ var enforce_js_1 = require("./pipeline/enforce.js");
58
+ Object.defineProperty(exports, "enforceFlexMd", { enumerable: true, get: function () { return enforce_js_1.enforceFlexMd; } });
59
+ // JSON Detection
60
+ __exportStar(require("./detect/json/index.js"), exports);
61
+ // Token Estimation
62
+ __exportStar(require("./tokens/index.js"), exports);
package/dist/index.d.ts CHANGED
@@ -15,3 +15,4 @@ export { detectResponseKind } from "./pipeline/kind.js";
15
15
  export { repairToMarkdownLevel } from "./pipeline/repair.js";
16
16
  export { enforceFlexMd } from "./pipeline/enforce.js";
17
17
  export * from "./detect/json/index.js";
18
+ export * from "./tokens/index.js";
package/dist/index.js CHANGED
@@ -22,3 +22,5 @@ export { repairToMarkdownLevel } from "./pipeline/repair.js";
22
22
  export { enforceFlexMd } from "./pipeline/enforce.js";
23
23
  // JSON Detection
24
24
  export * from "./detect/json/index.js";
25
+ // Token Estimation
26
+ export * from "./tokens/index.js";
@@ -27,3 +27,4 @@ export interface ParsedSection {
27
27
  export declare function parseHeadingsAndSections(md: string): ParsedSection[];
28
28
  export declare function extractBullets(body: string): string[];
29
29
  export declare function isIssuesEnvelopeCheck(md: string): IssuesEnvelope;
30
+ export declare function markdownToJson(md: string): Record<string, any>;
package/dist/md/parse.js CHANGED
@@ -1,3 +1,4 @@
1
+ import { toCamelCase } from "nx-helpers";
1
2
  export function normalizeName(s) {
2
3
  return s.trim().replace(/\s+/g, " ").toLowerCase();
3
4
  }
@@ -114,3 +115,14 @@ export function isIssuesEnvelopeCheck(md) {
114
115
  }
115
116
  return { isIssuesEnvelope: ok, sections };
116
117
  }
118
+ export function markdownToJson(md) {
119
+ // Robustly handle both actual newlines and literal \n (common in LLM JSON outputs)
120
+ const normalizedMd = (md || "").replace(/\\n/g, "\n");
121
+ const sections = parseHeadingsAndSections(normalizedMd);
122
+ const result = {};
123
+ for (const sec of sections) {
124
+ const key = toCamelCase(sec.heading.name);
125
+ result[key] = sec.body.trim();
126
+ }
127
+ return result;
128
+ }