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.
- package/README.md +423 -39
- package/dist/__tests__/structural.test.js +28 -0
- package/dist/cli/index.d.ts +2 -0
- package/dist/cli/index.js +108 -0
- package/dist/index.cjs +62 -3
- package/dist/index.d.ts +3 -0
- package/dist/index.js +4 -0
- package/dist/md/outline.d.ts +6 -3
- package/dist/md/outline.js +28 -50
- package/dist/md/parse.js +15 -4
- package/dist/ofs/parser.js +31 -10
- package/dist/tokens/auto-fix.d.ts +10 -0
- package/dist/tokens/auto-fix.js +56 -0
- package/dist/tokens/cognitive-cost.d.ts +10 -0
- package/dist/tokens/cognitive-cost.js +205 -0
- package/dist/tokens/compliance.d.ts +10 -0
- package/dist/tokens/compliance.js +70 -0
- package/dist/tokens/confidence.d.ts +6 -0
- package/dist/tokens/confidence.js +332 -0
- package/dist/tokens/estimator.d.ts +12 -0
- package/dist/tokens/estimator.js +138 -0
- package/dist/tokens/improvements.d.ts +10 -0
- package/dist/tokens/improvements.js +697 -0
- package/dist/tokens/index.d.ts +24 -0
- package/dist/tokens/index.js +31 -0
- package/dist/tokens/parser.d.ts +3 -0
- package/dist/tokens/parser.js +97 -0
- package/dist/tokens/patterns.d.ts +9 -0
- package/dist/tokens/patterns.js +20 -0
- package/dist/tokens/smart-report.d.ts +10 -0
- package/dist/tokens/smart-report.js +187 -0
- package/dist/tokens/spec-estimator.d.ts +7 -0
- package/dist/tokens/spec-estimator.js +68 -0
- package/dist/tokens/types.d.ts +185 -0
- package/dist/tokens/validator.d.ts +16 -0
- package/dist/tokens/validator.js +59 -0
- package/dist/validate/connection.d.ts +12 -0
- package/dist/validate/connection.js +44 -0
- package/docs/Recommended New Strategies for AI Request Builder.md +691 -0
- package/package.json +8 -3
- package/dist/detection/detector.d.ts +0 -6
- package/dist/detection/detector.js +0 -104
- package/dist/detection/extractor.d.ts +0 -10
- package/dist/detection/extractor.js +0 -54
- package/dist/issues/build.d.ts +0 -26
- package/dist/issues/build.js +0 -62
- package/dist/md/lists.d.ts +0 -14
- package/dist/md/lists.js +0 -33
- package/dist/md/tables.d.ts +0 -25
- package/dist/md/tables.js +0 -72
- package/dist/ofs/extractor.d.ts +0 -9
- package/dist/ofs/extractor.js +0 -75
- package/dist/ofs/issues.d.ts +0 -14
- package/dist/ofs/issues.js +0 -92
- package/dist/ofs/validator.d.ts +0 -10
- package/dist/ofs/validator.js +0 -91
- package/dist/outline/builder.d.ts +0 -10
- package/dist/outline/builder.js +0 -85
- package/dist/outline/renderer.d.ts +0 -6
- package/dist/outline/renderer.js +0 -23
- package/dist/parser.d.ts +0 -2
- package/dist/parser.js +0 -199
- package/dist/parsers/lists.d.ts +0 -6
- package/dist/parsers/lists.js +0 -36
- package/dist/parsers/tables.d.ts +0 -10
- package/dist/parsers/tables.js +0 -58
- package/dist/stringify.d.ts +0 -2
- package/dist/stringify.js +0 -110
- package/dist/test-pipeline.js +0 -53
- package/dist/test-runner.js +0 -331
- package/dist/test-strictness.d.ts +0 -1
- package/dist/test-strictness.js +0 -213
- package/dist/util.d.ts +0 -5
- package/dist/util.js +0 -64
- package/dist/validate/policy.d.ts +0 -10
- package/dist/validate/policy.js +0 -17
- package/dist/validator.d.ts +0 -2
- package/dist/validator.js +0 -80
- /package/dist/{test-pipeline.d.ts → __tests__/structural.test.d.ts} +0 -0
- /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,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;
|