flex-md 3.2.0 → 4.0.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 (80) hide show
  1. package/README.md +423 -39
  2. package/dist/__tests__/structural.test.js +28 -0
  3. package/dist/cli/index.d.ts +2 -0
  4. package/dist/cli/index.js +108 -0
  5. package/dist/index.cjs +62 -3
  6. package/dist/index.d.ts +3 -0
  7. package/dist/index.js +4 -0
  8. package/dist/md/outline.d.ts +6 -3
  9. package/dist/md/outline.js +28 -50
  10. package/dist/md/parse.js +15 -4
  11. package/dist/ofs/parser.js +31 -10
  12. package/dist/tokens/auto-fix.d.ts +10 -0
  13. package/dist/tokens/auto-fix.js +56 -0
  14. package/dist/tokens/cognitive-cost.d.ts +10 -0
  15. package/dist/tokens/cognitive-cost.js +205 -0
  16. package/dist/tokens/compliance.d.ts +10 -0
  17. package/dist/tokens/compliance.js +70 -0
  18. package/dist/tokens/confidence.d.ts +6 -0
  19. package/dist/tokens/confidence.js +332 -0
  20. package/dist/tokens/estimator.d.ts +12 -0
  21. package/dist/tokens/estimator.js +138 -0
  22. package/dist/tokens/improvements.d.ts +10 -0
  23. package/dist/tokens/improvements.js +697 -0
  24. package/dist/tokens/index.d.ts +24 -0
  25. package/dist/tokens/index.js +31 -0
  26. package/dist/tokens/parser.d.ts +3 -0
  27. package/dist/tokens/parser.js +97 -0
  28. package/dist/tokens/patterns.d.ts +9 -0
  29. package/dist/tokens/patterns.js +20 -0
  30. package/dist/tokens/smart-report.d.ts +10 -0
  31. package/dist/tokens/smart-report.js +187 -0
  32. package/dist/tokens/spec-estimator.d.ts +7 -0
  33. package/dist/tokens/spec-estimator.js +68 -0
  34. package/dist/tokens/types.d.ts +185 -0
  35. package/dist/tokens/validator.d.ts +16 -0
  36. package/dist/tokens/validator.js +59 -0
  37. package/dist/validate/connection.d.ts +12 -0
  38. package/dist/validate/connection.js +44 -0
  39. package/docs/Recommended New Strategies for AI Request Builder.md +691 -0
  40. package/package.json +8 -3
  41. package/dist/detection/detector.d.ts +0 -6
  42. package/dist/detection/detector.js +0 -104
  43. package/dist/detection/extractor.d.ts +0 -10
  44. package/dist/detection/extractor.js +0 -54
  45. package/dist/issues/build.d.ts +0 -26
  46. package/dist/issues/build.js +0 -62
  47. package/dist/md/lists.d.ts +0 -14
  48. package/dist/md/lists.js +0 -33
  49. package/dist/md/tables.d.ts +0 -25
  50. package/dist/md/tables.js +0 -72
  51. package/dist/ofs/extractor.d.ts +0 -9
  52. package/dist/ofs/extractor.js +0 -75
  53. package/dist/ofs/issues.d.ts +0 -14
  54. package/dist/ofs/issues.js +0 -92
  55. package/dist/ofs/validator.d.ts +0 -10
  56. package/dist/ofs/validator.js +0 -91
  57. package/dist/outline/builder.d.ts +0 -10
  58. package/dist/outline/builder.js +0 -85
  59. package/dist/outline/renderer.d.ts +0 -6
  60. package/dist/outline/renderer.js +0 -23
  61. package/dist/parser.d.ts +0 -2
  62. package/dist/parser.js +0 -199
  63. package/dist/parsers/lists.d.ts +0 -6
  64. package/dist/parsers/lists.js +0 -36
  65. package/dist/parsers/tables.d.ts +0 -10
  66. package/dist/parsers/tables.js +0 -58
  67. package/dist/stringify.d.ts +0 -2
  68. package/dist/stringify.js +0 -110
  69. package/dist/test-pipeline.js +0 -53
  70. package/dist/test-runner.js +0 -331
  71. package/dist/test-strictness.d.ts +0 -1
  72. package/dist/test-strictness.js +0 -213
  73. package/dist/util.d.ts +0 -5
  74. package/dist/util.js +0 -64
  75. package/dist/validate/policy.d.ts +0 -10
  76. package/dist/validate/policy.js +0 -17
  77. package/dist/validator.d.ts +0 -2
  78. package/dist/validator.js +0 -80
  79. /package/dist/{test-pipeline.d.ts → __tests__/structural.test.d.ts} +0 -0
  80. /package/dist/{test-runner.d.ts → tokens/types.js} +0 -0
@@ -0,0 +1,24 @@
1
+ import type { OutputFormatSpec } from '../types.js';
2
+ export * from './types.js';
3
+ export * from './parser.js';
4
+ export * from './estimator.js';
5
+ export * from './spec-estimator.js';
6
+ export * from './validator.js';
7
+ export * from './compliance.js';
8
+ export * from './cognitive-cost.js';
9
+ export * from './confidence.js';
10
+ export * from './smart-report.js';
11
+ export * from './improvements.js';
12
+ export * from './auto-fix.js';
13
+ /**
14
+ * Convenience function: estimate max_tokens from spec
15
+ *
16
+ * @param spec - OutputFormatSpec object or markdown string
17
+ * @param options - Estimation options
18
+ * @returns Estimated max_tokens value
19
+ */
20
+ export declare function getMaxTokens(spec: OutputFormatSpec | string | null | undefined, options?: {
21
+ includeOptional?: boolean;
22
+ safetyMultiplier?: number;
23
+ strategy?: 'conservative' | 'average' | 'generous';
24
+ }): number;
@@ -0,0 +1,31 @@
1
+ import { parseOutputFormatSpec } from '../ofs/parser.js';
2
+ import { estimateSpecTokens } from './spec-estimator.js';
3
+ export * from './types.js';
4
+ export * from './parser.js';
5
+ export * from './estimator.js';
6
+ export * from './spec-estimator.js';
7
+ export * from './validator.js';
8
+ export * from './compliance.js';
9
+ export * from './cognitive-cost.js';
10
+ export * from './confidence.js';
11
+ export * from './smart-report.js';
12
+ export * from './improvements.js';
13
+ export * from './auto-fix.js';
14
+ /**
15
+ * Convenience function: estimate max_tokens from spec
16
+ *
17
+ * @param spec - OutputFormatSpec object or markdown string
18
+ * @param options - Estimation options
19
+ * @returns Estimated max_tokens value
20
+ */
21
+ export function getMaxTokens(spec, options) {
22
+ if (!spec)
23
+ return 0;
24
+ const parsedSpec = typeof spec === 'string'
25
+ ? parseOutputFormatSpec(spec)
26
+ : spec;
27
+ if (!parsedSpec)
28
+ return 0;
29
+ const estimate = estimateSpecTokens(parsedSpec, options);
30
+ return estimate.total.estimated;
31
+ }
@@ -0,0 +1,3 @@
1
+ import type { SystemPart } from './types.js';
2
+ import type { SectionKind } from '../types.js';
3
+ export declare function parseSystemPart(instruction: string | undefined, kind: SectionKind | 'code'): SystemPart | null;
@@ -0,0 +1,97 @@
1
+ import { SYSTEM_PART_PATTERNS, INSTRUCTION_SPLIT } from './patterns.js';
2
+ export function parseSystemPart(instruction, kind // Allow 'code' as a special case if needed
3
+ ) {
4
+ if (!instruction)
5
+ return null;
6
+ const pattern = SYSTEM_PART_PATTERNS[kind];
7
+ if (!pattern)
8
+ return null;
9
+ const match = instruction.match(pattern);
10
+ if (!match)
11
+ return null;
12
+ // Split into system and guidance parts
13
+ const parts = instruction.split(INSTRUCTION_SPLIT);
14
+ const raw = parts[0];
15
+ const guidance = parts.slice(1).join('. ') || null;
16
+ const parsed = parseMatchByKind(kind, match);
17
+ if (!parsed)
18
+ return null;
19
+ return { raw, guidance, parsed };
20
+ }
21
+ function parseMatchByKind(kind, match) {
22
+ switch (kind) {
23
+ case 'text':
24
+ return parseTextMatch(match);
25
+ case 'list':
26
+ case 'ordered_list':
27
+ return parseItemsMatch(match);
28
+ case 'table':
29
+ case 'ordered_table':
30
+ return parseTableMatch(match);
31
+ case 'code':
32
+ return parseCodeMatch(match);
33
+ default:
34
+ return null;
35
+ }
36
+ }
37
+ function parseTextMatch(match) {
38
+ const raw = match[1].toLowerCase().replace(/\s+/g, ' ');
39
+ // Map to canonical LengthValue
40
+ const lengthMap = {
41
+ '1 sentence': '1 sentence',
42
+ '1-2 sentences': '1-2 sentences',
43
+ '1 paragraph': '1 paragraph',
44
+ '2-3 paragraphs': '2-3 paragraphs',
45
+ 'brief': 'brief',
46
+ 'moderate': 'moderate',
47
+ 'detailed': 'detailed',
48
+ 'extensive': 'extensive'
49
+ };
50
+ const value = lengthMap[raw] || 'moderate';
51
+ return { type: 'length', value };
52
+ }
53
+ function parseItemsMatch(match) {
54
+ // match[1] = "at least" (optional)
55
+ // match[2] = min number
56
+ // match[3] = max number (optional)
57
+ return {
58
+ type: 'items',
59
+ min: parseInt(match[2]),
60
+ max: match[3] ? parseInt(match[3]) : null,
61
+ atLeast: !!match[1]
62
+ };
63
+ }
64
+ function parseTableMatch(match) {
65
+ // match[1] = rows "at least" (optional)
66
+ // match[2] = rows min
67
+ // match[3] = rows max (optional)
68
+ // match[4] = columns "at least" (optional)
69
+ // match[5] = columns min
70
+ // match[6] = columns max (optional)
71
+ return {
72
+ type: 'table',
73
+ rows: {
74
+ min: parseInt(match[2]),
75
+ max: match[3] ? parseInt(match[3]) : null,
76
+ atLeast: !!match[1],
77
+ approximate: false
78
+ },
79
+ columns: {
80
+ min: parseInt(match[5]),
81
+ max: match[6] ? parseInt(match[6]) : null,
82
+ atLeast: !!match[4],
83
+ approximate: false
84
+ }
85
+ };
86
+ }
87
+ function parseCodeMatch(match) {
88
+ // match[1] = "~" (optional)
89
+ // match[2] = min number
90
+ // match[3] = max number (optional)
91
+ return {
92
+ type: 'lines',
93
+ min: parseInt(match[2]),
94
+ max: match[3] ? parseInt(match[3]) : null,
95
+ approximate: !!match[1]
96
+ };
97
+ }
@@ -0,0 +1,9 @@
1
+ export declare const SYSTEM_PART_PATTERNS: {
2
+ readonly text: RegExp;
3
+ readonly list: RegExp;
4
+ readonly ordered_list: RegExp;
5
+ readonly table: RegExp;
6
+ readonly ordered_table: RegExp;
7
+ readonly code: RegExp;
8
+ };
9
+ export declare const INSTRUCTION_SPLIT: RegExp;
@@ -0,0 +1,20 @@
1
+ // patterns.ts
2
+ export const SYSTEM_PART_PATTERNS = {
3
+ // TEXT: Enumerated literal strings only
4
+ text: /^Length:\s*(1\s+sentence|1-2\s+sentences|1\s+paragraph|2-3\s+paragraphs|brief|moderate|detailed|extensive)/i,
5
+ // LIST/ORDERED-LIST: [optional "at least"] + number + [optional range]
6
+ // Matches: "3" | "3-5" | "at least 3"
7
+ list: /^Items:\s*(?:(at least)\s+)?(\d+)(?:-(\d+))?/i,
8
+ ordered_list: /^Items:\s*(?:(at least)\s+)?(\d+)(?:-(\d+))?/i,
9
+ // TABLE: Two numeric patterns (rows and columns)
10
+ // Matches: "Rows: 3, Columns: 5" | "Rows: 3-5, Columns: at least 2"
11
+ table: /^Rows:\s*(?:(at least)\s+)?(\d+)(?:-(\d+))?,\s*Columns:\s*(?:(at least)\s+)?(\d+)(?:-(\d+))?/i,
12
+ ordered_table: /^Rows:\s*(?:(at least)\s+)?(\d+)(?:-(\d+))?,\s*Columns:\s*(?:(at least)\s+)?(\d+)(?:-(\d+))?/i,
13
+ // CODE: [optional "~"] + number + [optional range]
14
+ // Matches: "10" | "10-20" | "~50"
15
+ // Note: SectionKind doesn't include 'code' currently, but we might handle it if it's added.
16
+ // For now, let's keep it but expect SectionKind to match.
17
+ code: /^Lines:\s*(~)?(\d+)(?:-(\d+))?/i
18
+ };
19
+ // Separator for splitting system part from guidance
20
+ export const INSTRUCTION_SPLIT = /\.\s+/;
@@ -0,0 +1,10 @@
1
+ import type { SmartAnalysis, ComplianceLevel } from './types.js';
2
+ import type { OutputFormatSpec } from '../types.js';
3
+ /**
4
+ * Comprehensive smart analysis of spec
5
+ */
6
+ export declare function analyzeSpec(spec: OutputFormatSpec, targetLevel?: ComplianceLevel): SmartAnalysis;
7
+ /**
8
+ * Format comprehensive smart report
9
+ */
10
+ export declare function formatSmartReport(analysis: SmartAnalysis): string;
@@ -0,0 +1,187 @@
1
+ import { checkSpecCompliance } from './compliance.js';
2
+ import { calculateCognitiveCost } from './cognitive-cost.js';
3
+ import { calculateConfidence } from './confidence.js';
4
+ import { estimateSpecTokens } from './spec-estimator.js';
5
+ /**
6
+ * Comprehensive smart analysis of spec
7
+ */
8
+ export function analyzeSpec(spec, targetLevel = 2) {
9
+ const compliance = checkSpecCompliance(spec, targetLevel);
10
+ const cognitiveCost = calculateCognitiveCost(spec);
11
+ const confidence = calculateConfidence(spec);
12
+ const tokenEstimate = estimateSpecTokens(spec);
13
+ const recommendations = generateSmartRecommendations(compliance, cognitiveCost, confidence, tokenEstimate);
14
+ return {
15
+ spec,
16
+ compliance,
17
+ cognitiveCost,
18
+ confidence,
19
+ tokenEstimate,
20
+ recommendations
21
+ };
22
+ }
23
+ function generateSmartRecommendations(compliance, cost, confidence, estimate) {
24
+ const recs = [];
25
+ // High priority: Compliance issues
26
+ if (!compliance.compliant && compliance.violations.length > 0) {
27
+ recs.push({
28
+ priority: 'high',
29
+ category: 'quality',
30
+ message: `${compliance.violations.length} sections don't meet L${compliance.level} compliance`,
31
+ action: 'Add or upgrade system parts in flagged sections'
32
+ });
33
+ }
34
+ // High priority: Low confidence
35
+ if (confidence.overall < 70) {
36
+ recs.push({
37
+ priority: 'high',
38
+ category: 'confidence',
39
+ message: `Token estimation confidence is ${confidence.grade} (${confidence.overall.toFixed(0)}%)`,
40
+ action: confidence.recommendations[0]
41
+ });
42
+ }
43
+ // Medium priority: High cognitive cost
44
+ if (cost.totalCost > 60) {
45
+ recs.push({
46
+ priority: 'medium',
47
+ category: 'cost',
48
+ message: `Cognitive cost is high (${cost.totalCost.toFixed(0)}/100)`,
49
+ action: 'Consider reducing some sections to L2 or L1'
50
+ });
51
+ }
52
+ // Medium priority: Unreasonable token estimate
53
+ if (estimate.total.estimated > 4000) {
54
+ recs.push({
55
+ priority: 'medium',
56
+ category: 'quality',
57
+ message: `Estimated ${estimate.total.estimated} tokens - may be too large`,
58
+ action: 'Consider reducing scope or splitting into multiple prompts'
59
+ });
60
+ }
61
+ // Low priority: Optimization opportunities
62
+ if (confidence.overall >= 70 && confidence.overall < 90) {
63
+ recs.push({
64
+ priority: 'low',
65
+ category: 'confidence',
66
+ message: 'Good confidence, but can be improved',
67
+ action: 'Upgrade a few sections to L3 for better precision'
68
+ });
69
+ }
70
+ // Low priority: Cost optimization
71
+ if (cost.totalCost < 30 && confidence.overall > 80) {
72
+ recs.push({
73
+ priority: 'low',
74
+ category: 'cost',
75
+ message: 'Excellent balance of cost and confidence',
76
+ action: 'No changes needed'
77
+ });
78
+ }
79
+ return recs;
80
+ }
81
+ /**
82
+ * Format comprehensive smart report
83
+ */
84
+ export function formatSmartReport(analysis) {
85
+ const lines = [];
86
+ lines.push('╔═══════════════════════════════════════════════════╗');
87
+ lines.push('║ FLEX-MD SMART ANALYSIS REPORT ║');
88
+ lines.push('╚═══════════════════════════════════════════════════╝');
89
+ lines.push('');
90
+ // Summary Dashboard
91
+ lines.push('📊 SUMMARY DASHBOARD');
92
+ lines.push('─'.repeat(50));
93
+ lines.push(`Compliance: ${analysis.compliance.compliant ? '✓' : '✗'} L${analysis.compliance.level} ${analysis.compliance.compliant ? 'PASS' : 'FAIL'}`);
94
+ lines.push(`Confidence: ${analysis.confidence.grade} (${analysis.confidence.overall.toFixed(0)}%)`);
95
+ lines.push(`Cognitive Cost: ${analysis.cognitiveCost.totalCost.toFixed(0)}/100`);
96
+ lines.push(`Token Estimate: ${analysis.tokenEstimate.total.estimated} tokens`);
97
+ lines.push('');
98
+ // Key Metrics
99
+ lines.push('📈 KEY METRICS');
100
+ lines.push('─'.repeat(50));
101
+ lines.push(`Total Sections: ${analysis.spec.sections.length}`);
102
+ lines.push(`With System Parts: ${analysis.compliance.summary.compliantSections}`);
103
+ lines.push(`Coverage: ${analysis.confidence.bySection.filter(s => s.hasSystemPart).length}/${analysis.spec.sections.length} (${((analysis.confidence.bySection.filter(s => s.hasSystemPart).length / (analysis.spec.sections.length || 1)) * 100).toFixed(0)}%)`);
104
+ lines.push(`Average Compliance Level: L${(analysis.compliance.summary.averageLevel || 0).toFixed(1)}`);
105
+ lines.push('');
106
+ // Recommendations
107
+ if (analysis.recommendations.length > 0) {
108
+ lines.push('💡 RECOMMENDATIONS');
109
+ lines.push('─'.repeat(50));
110
+ const highPriority = analysis.recommendations.filter(r => r.priority === 'high');
111
+ const mediumPriority = analysis.recommendations.filter(r => r.priority === 'medium');
112
+ const lowPriority = analysis.recommendations.filter(r => r.priority === 'low');
113
+ if (highPriority.length > 0) {
114
+ lines.push('🔴 High Priority:');
115
+ highPriority.forEach(r => {
116
+ lines.push(` • ${r.message}`);
117
+ if (r.action)
118
+ lines.push(` → ${r.action}`);
119
+ });
120
+ lines.push('');
121
+ }
122
+ if (mediumPriority.length > 0) {
123
+ lines.push('🟡 Medium Priority:');
124
+ mediumPriority.forEach(r => {
125
+ lines.push(` • ${r.message}`);
126
+ if (r.action)
127
+ lines.push(` → ${r.action}`);
128
+ });
129
+ lines.push('');
130
+ }
131
+ if (lowPriority.length > 0) {
132
+ lines.push('🟢 Low Priority:');
133
+ lowPriority.forEach(r => {
134
+ lines.push(` • ${r.message}`);
135
+ if (r.action)
136
+ lines.push(` → ${r.action}`);
137
+ });
138
+ lines.push('');
139
+ }
140
+ }
141
+ // Section Breakdown
142
+ lines.push('📋 SECTION BREAKDOWN');
143
+ lines.push('─'.repeat(50));
144
+ lines.push('Section Level Confidence Cost Tokens');
145
+ lines.push('─'.repeat(50));
146
+ analysis.confidence.bySection.forEach((conf, i) => {
147
+ const cost = analysis.cognitiveCost.perSection[i];
148
+ const tokens = analysis.tokenEstimate.bySectionName[conf.sectionName];
149
+ const level = conf.level !== null ? `L${conf.level}` : 'L0';
150
+ const confStr = `${conf.confidence.toFixed(0)}%`;
151
+ const costStr = cost ? `${cost.cost.toFixed(1)}` : '0.0';
152
+ const tokenStr = tokens ? `~${tokens.estimated}` : 'N/A';
153
+ const name = conf.sectionName.length > 24 ? conf.sectionName.slice(0, 21) + '...' : conf.sectionName.padEnd(24);
154
+ lines.push(`${name} ${level.padEnd(5)} ${confStr.padEnd(10)} ${costStr.padEnd(4)} ${tokenStr}`);
155
+ });
156
+ lines.push('');
157
+ // Confidence Factors
158
+ if (analysis.confidence.factors.length > 0) {
159
+ lines.push('🎯 CONFIDENCE FACTORS');
160
+ lines.push('─'.repeat(50));
161
+ analysis.confidence.factors.forEach(factor => {
162
+ const icon = factor.impact === 'positive' ? '✓' : factor.impact === 'negative' ? '✗' : '○';
163
+ const sign = factor.score >= 0 ? '+' : '';
164
+ lines.push(`${icon} ${factor.factor}: ${sign}${factor.score}`);
165
+ lines.push(` ${factor.description}`);
166
+ });
167
+ lines.push('');
168
+ }
169
+ // Cost Breakdown
170
+ lines.push('💰 COGNITIVE COST BREAKDOWN');
171
+ lines.push('─'.repeat(50));
172
+ lines.push(`Base Cost: ${analysis.cognitiveCost.breakdown.baseCost.toFixed(1)}`);
173
+ lines.push(`Complexity Cost: ${analysis.cognitiveCost.breakdown.complexityCost.toFixed(1)}`);
174
+ lines.push(`Decision Cost: ${analysis.cognitiveCost.breakdown.decisionCost.toFixed(1)}`);
175
+ lines.push(`Total Cost: ${analysis.cognitiveCost.totalCost.toFixed(1)}/100`);
176
+ lines.push(`Assessment: ${analysis.cognitiveCost.recommendation}`);
177
+ lines.push('');
178
+ // Token Estimate
179
+ lines.push('🔢 TOKEN ESTIMATE');
180
+ lines.push('─'.repeat(50));
181
+ lines.push(`Estimated: ${analysis.tokenEstimate.total.estimated} tokens`);
182
+ lines.push(`Range: ${analysis.tokenEstimate.total.min} - ${analysis.tokenEstimate.total.max} tokens`);
183
+ lines.push(`Overhead: ${analysis.tokenEstimate.overhead} tokens`);
184
+ lines.push(`Confidence: ${analysis.confidence.grade}`);
185
+ lines.push('');
186
+ return lines.join('\n');
187
+ }
@@ -0,0 +1,7 @@
1
+ import type { SpecTokenEstimate } from './types.js';
2
+ import type { OutputFormatSpec } from '../types.js';
3
+ export declare function estimateSpecTokens(spec: OutputFormatSpec, options?: {
4
+ includeOptional?: boolean;
5
+ safetyMultiplier?: number;
6
+ strategy?: 'conservative' | 'average' | 'generous';
7
+ }): SpecTokenEstimate;
@@ -0,0 +1,68 @@
1
+ import { parseSystemPart } from './parser.js';
2
+ import { estimateTokens, getFallbackEstimate, TOKEN_CONSTANTS } from './estimator.js';
3
+ export function estimateSpecTokens(spec, options = {}) {
4
+ const { includeOptional = true, safetyMultiplier = 1.2, strategy = 'average' } = options;
5
+ const bySectionName = {};
6
+ let totalEstimated = 0;
7
+ let totalMin = 0;
8
+ let totalMax = 0;
9
+ for (const section of spec.sections) {
10
+ // Skip optional sections if requested
11
+ const isRequired = section.required !== false; // Default to required if not explicitly false
12
+ if (!includeOptional && !isRequired)
13
+ continue;
14
+ const kind = section.kind || 'text';
15
+ const systemPart = parseSystemPart(section.instruction, kind);
16
+ let estimate;
17
+ if (systemPart) {
18
+ estimate = estimateTokens(systemPart);
19
+ }
20
+ else {
21
+ estimate = getFallbackEstimate(kind, isRequired);
22
+ }
23
+ // Apply optional section discount
24
+ if (!isRequired) {
25
+ estimate = {
26
+ estimated: Math.round(estimate.estimated * 0.6),
27
+ min: Math.round(estimate.min * 0.5),
28
+ max: Math.round(estimate.max * 0.7),
29
+ confidence: 'low'
30
+ };
31
+ }
32
+ bySectionName[section.name] = estimate;
33
+ totalEstimated += estimate.estimated;
34
+ totalMin += estimate.min;
35
+ totalMax += estimate.max;
36
+ }
37
+ // Add overhead
38
+ const overhead = TOKEN_CONSTANTS.baseOverhead +
39
+ (spec.sections.length * TOKEN_CONSTANTS.headingOverhead);
40
+ totalEstimated += overhead;
41
+ totalMin += overhead;
42
+ totalMax += overhead;
43
+ // Apply strategy
44
+ let finalEstimate;
45
+ switch (strategy) {
46
+ case 'conservative':
47
+ finalEstimate = totalMin;
48
+ break;
49
+ case 'generous':
50
+ finalEstimate = totalMax;
51
+ break;
52
+ case 'average':
53
+ default:
54
+ finalEstimate = totalEstimated;
55
+ }
56
+ // Apply safety multiplier
57
+ finalEstimate = Math.ceil(finalEstimate * safetyMultiplier);
58
+ return {
59
+ total: {
60
+ estimated: finalEstimate,
61
+ min: Math.ceil(totalMin * safetyMultiplier),
62
+ max: Math.ceil(totalMax * safetyMultiplier),
63
+ confidence: 'medium'
64
+ },
65
+ bySectionName,
66
+ overhead
67
+ };
68
+ }
@@ -0,0 +1,185 @@
1
+ import type { SectionKind, OutputFormatSpec as RealOutputFormatSpec } from "../types.js";
2
+ export type ComplianceLevel = 0 | 1 | 2 | 3;
3
+ export type LengthValue = '1 sentence' | '1-2 sentences' | '1 paragraph' | '2-3 paragraphs' | 'brief' | 'moderate' | 'detailed' | 'extensive';
4
+ export interface NumericSpec {
5
+ min: number;
6
+ max: number | null;
7
+ atLeast: boolean;
8
+ approximate: boolean;
9
+ }
10
+ export type ParsedSystemPart = {
11
+ type: 'length';
12
+ value: LengthValue;
13
+ } | {
14
+ type: 'items';
15
+ min: number;
16
+ max: number | null;
17
+ atLeast: boolean;
18
+ } | {
19
+ type: 'table';
20
+ rows: NumericSpec;
21
+ columns: NumericSpec;
22
+ } | {
23
+ type: 'lines';
24
+ min: number;
25
+ max: number | null;
26
+ approximate: boolean;
27
+ };
28
+ export interface SystemPart {
29
+ raw: string;
30
+ guidance: string | null;
31
+ parsed: ParsedSystemPart;
32
+ }
33
+ export interface TokenEstimate {
34
+ estimated: number;
35
+ min: number;
36
+ max: number;
37
+ confidence: 'high' | 'medium' | 'low';
38
+ }
39
+ export interface SpecTokenEstimate {
40
+ total: TokenEstimate;
41
+ bySectionName: Record<string, TokenEstimate>;
42
+ overhead: number;
43
+ }
44
+ export interface ComplianceViolation {
45
+ sectionName: string;
46
+ kind: SectionKind;
47
+ level: ComplianceLevel;
48
+ message: string;
49
+ }
50
+ export interface ComplianceReport {
51
+ compliant: boolean;
52
+ level: ComplianceLevel;
53
+ violations: ComplianceViolation[];
54
+ summary: {
55
+ totalSections: number;
56
+ compliantSections: number;
57
+ averageLevel: number;
58
+ };
59
+ }
60
+ export interface CostFactor {
61
+ factor: string;
62
+ impact: number;
63
+ description: string;
64
+ }
65
+ export interface CostBreakdown {
66
+ baseCost: number;
67
+ complexityCost: number;
68
+ decisionCost: number;
69
+ totalSections: number;
70
+ }
71
+ export interface SectionCost {
72
+ sectionName: string;
73
+ cost: number;
74
+ level: ComplianceLevel | null;
75
+ factors: CostFactor[];
76
+ }
77
+ export interface CognitiveCost {
78
+ totalCost: number;
79
+ perSection: SectionCost[];
80
+ breakdown: CostBreakdown;
81
+ recommendation: string;
82
+ }
83
+ export interface LevelCostComparison {
84
+ byLevel: Record<ComplianceLevel, number>;
85
+ recommendation: string;
86
+ }
87
+ export interface ConfidenceFactor {
88
+ factor: string;
89
+ impact: 'positive' | 'negative' | 'neutral';
90
+ score: number;
91
+ description: string;
92
+ }
93
+ export interface SectionConfidence {
94
+ sectionName: string;
95
+ confidence: number;
96
+ hasSystemPart: boolean;
97
+ level: ComplianceLevel | null;
98
+ estimateQuality: 'excellent' | 'good' | 'fair' | 'poor' | 'none';
99
+ }
100
+ export interface ConfidenceScore {
101
+ overall: number;
102
+ grade: 'A' | 'B' | 'C' | 'D' | 'F';
103
+ bySection: SectionConfidence[];
104
+ factors: ConfidenceFactor[];
105
+ recommendations: string[];
106
+ }
107
+ export interface SmartRecommendation {
108
+ priority: 'high' | 'medium' | 'low';
109
+ category: 'quality' | 'cost' | 'confidence';
110
+ message: string;
111
+ action?: string;
112
+ }
113
+ export interface SmartAnalysis {
114
+ spec: RealOutputFormatSpec;
115
+ compliance: ComplianceReport;
116
+ cognitiveCost: CognitiveCost;
117
+ confidence: ConfidenceScore;
118
+ tokenEstimate: SpecTokenEstimate;
119
+ recommendations: SmartRecommendation[];
120
+ }
121
+ export interface ImprovementImpact {
122
+ confidenceGain: number;
123
+ cognitiveLoadChange: number;
124
+ estimateAccuracyGain: number;
125
+ description: string;
126
+ }
127
+ export interface Improvement {
128
+ sectionName: string;
129
+ priority: 'critical' | 'high' | 'medium' | 'low';
130
+ category: 'missing' | 'vague' | 'upgrade' | 'fix' | 'optimize';
131
+ issue: string;
132
+ impact: ImprovementImpact;
133
+ suggestion: string;
134
+ before: string;
135
+ after: string;
136
+ effort: 'trivial' | 'easy' | 'moderate' | 'hard';
137
+ autoFixable: boolean;
138
+ }
139
+ export interface AntiPattern {
140
+ sectionName: string;
141
+ pattern: string;
142
+ severity: 'error' | 'warning' | 'info';
143
+ why: string;
144
+ fix: string;
145
+ example: string;
146
+ }
147
+ export interface Optimization {
148
+ type: 'consolidate' | 'simplify' | 'rebalance' | 'split';
149
+ scope: 'section' | 'spec';
150
+ description: string;
151
+ benefit: string;
152
+ effort: 'trivial' | 'easy' | 'moderate' | 'hard';
153
+ sections?: string[];
154
+ }
155
+ export interface ImprovementSummary {
156
+ totalImprovements: number;
157
+ criticalCount: number;
158
+ potentialConfidenceGain: number;
159
+ quickWinCount: number;
160
+ estimatedEffort: string;
161
+ }
162
+ export interface ImprovementAnalysis {
163
+ improvements: Improvement[];
164
+ quickWins: Improvement[];
165
+ antiPatterns: AntiPattern[];
166
+ optimizations: Optimization[];
167
+ summary: ImprovementSummary;
168
+ }
169
+ export interface AppliedFix {
170
+ sectionName: string;
171
+ improvement: string;
172
+ before: string;
173
+ after: string;
174
+ }
175
+ export interface SkippedFix {
176
+ sectionName: string;
177
+ reason: string;
178
+ manualActionNeeded: string;
179
+ }
180
+ export interface AutoFixResult {
181
+ fixed: RealOutputFormatSpec;
182
+ appliedFixes: AppliedFix[];
183
+ skippedFixes: SkippedFix[];
184
+ summary: string;
185
+ }
@@ -0,0 +1,16 @@
1
+ import type { OutputFormatSpec } from '../types.js';
2
+ export interface ValidationError {
3
+ sectionName: string;
4
+ message: string;
5
+ instruction: string;
6
+ }
7
+ export interface ValidationWarning {
8
+ sectionName: string;
9
+ message: string;
10
+ }
11
+ export interface TokenValidationResult {
12
+ valid: boolean;
13
+ errors: ValidationError[];
14
+ warnings: ValidationWarning[];
15
+ }
16
+ export declare function validateSystemParts(spec: OutputFormatSpec): TokenValidationResult;