flex-md 4.5.3 → 4.5.5
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/dist/__tests__/diagnostics.test.js +47 -45
- package/dist/__tests__/ofs.test.js +30 -28
- package/dist/__tests__/structural.test.js +21 -19
- package/dist/__tests__/validate.test.js +29 -27
- package/dist/cli/index.js +15 -13
- package/dist/detect/json/detectIntent.js +4 -1
- package/dist/detect/json/detectMarkdown.js +35 -29
- package/dist/detect/json/detectPresence.js +6 -2
- package/dist/detect/json/index.js +31 -10
- package/dist/detect/json/types.js +2 -1
- package/dist/extract/extract.js +14 -11
- package/dist/extract/types.js +2 -1
- package/dist/index.js +67 -22
- package/dist/logger.js +6 -3
- package/dist/md/match.js +4 -1
- package/dist/md/normalize.js +4 -1
- package/dist/md/outline.js +8 -4
- package/dist/md/parse.js +20 -11
- package/dist/ofs/adapter.js +49 -45
- package/dist/ofs/enricher.js +8 -3
- package/dist/ofs/infer.js +7 -4
- package/dist/ofs/issuesEnvelope.js +10 -5
- package/dist/ofs/memory.js +10 -6
- package/dist/ofs/parser.js +8 -4
- package/dist/ofs/stringify.js +4 -1
- package/dist/pipeline/enforce.js +15 -12
- package/dist/pipeline/kind.js +6 -3
- package/dist/pipeline/repair.js +11 -8
- package/dist/strictness/container.js +4 -1
- package/dist/strictness/processor.js +10 -7
- package/dist/strictness/types.js +4 -1
- package/dist/tokens/auto-fix.js +4 -1
- package/dist/tokens/cognitive-cost.js +10 -6
- package/dist/tokens/compliance.js +8 -4
- package/dist/tokens/confidence.js +9 -6
- package/dist/tokens/estimator.js +23 -18
- package/dist/tokens/improvements.js +16 -12
- package/dist/tokens/index.js +33 -16
- package/dist/tokens/parser.js +7 -4
- package/dist/tokens/patterns.js +5 -2
- package/dist/tokens/smart-report.js +14 -10
- package/dist/tokens/spec-estimator.js +11 -8
- package/dist/tokens/types.js +2 -1
- package/dist/tokens/validator.js +6 -3
- package/dist/types.js +2 -1
- package/dist/validate/compliance.js +6 -2
- package/dist/validate/connection.js +8 -5
- package/dist/validate/types.js +2 -1
- package/dist/validate/validate.js +19 -16
- package/package.json +3 -3
package/dist/ofs/enricher.js
CHANGED
|
@@ -1,8 +1,13 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.buildMarkdownGuidance = buildMarkdownGuidance;
|
|
4
|
+
exports.enrichInstructions = enrichInstructions;
|
|
5
|
+
exports.enrichInstructionsWithFlexMd = enrichInstructionsWithFlexMd;
|
|
1
6
|
/**
|
|
2
7
|
* Generates Markdown guidance instructions for the LLM based on the OFS and contract level.
|
|
3
8
|
* Strictly avoids the word "flex-md" and remains "tax-aware" by only including relevant rules.
|
|
4
9
|
*/
|
|
5
|
-
|
|
10
|
+
function buildMarkdownGuidance(spec, strict, opts) {
|
|
6
11
|
const level = strict.level ?? 0;
|
|
7
12
|
const fence = opts?.containerFence === "flexmd" ? "```flexmd" : "```markdown";
|
|
8
13
|
// L0 - Minimal Markdown
|
|
@@ -80,14 +85,14 @@ export function buildMarkdownGuidance(spec, strict, opts) {
|
|
|
80
85
|
/**
|
|
81
86
|
* @deprecated Use buildMarkdownGuidance
|
|
82
87
|
*/
|
|
83
|
-
|
|
88
|
+
function enrichInstructions(spec, strict) {
|
|
84
89
|
return buildMarkdownGuidance(spec, strict);
|
|
85
90
|
}
|
|
86
91
|
/**
|
|
87
92
|
* Enrich instructions with flex-md compliance guidance.
|
|
88
93
|
* Returns detailed information about what was changed.
|
|
89
94
|
*/
|
|
90
|
-
|
|
95
|
+
async function enrichInstructionsWithFlexMd(instructions, strictnessLevel, spec // Optional spec, if provided will include section guidance
|
|
91
96
|
) {
|
|
92
97
|
const originalLength = instructions.length;
|
|
93
98
|
const level = parseInt(strictnessLevel.slice(1));
|
package/dist/ofs/infer.js
CHANGED
|
@@ -1,8 +1,11 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.inferOfsFromMarkdown = inferOfsFromMarkdown;
|
|
4
|
+
const parse_js_1 = require("../md/parse.js");
|
|
2
5
|
/**
|
|
3
6
|
* Infers an OutputFormatSpec from a Markdown string.
|
|
4
7
|
*/
|
|
5
|
-
|
|
8
|
+
function inferOfsFromMarkdown(md) {
|
|
6
9
|
// Collect all bullet names that look like headers ("- Name")
|
|
7
10
|
const lines = md.split("\n");
|
|
8
11
|
const bulletNames = [];
|
|
@@ -13,13 +16,13 @@ export function inferOfsFromMarkdown(md) {
|
|
|
13
16
|
bulletNames.push(m[1].trim());
|
|
14
17
|
}
|
|
15
18
|
}
|
|
16
|
-
const sections = parseHeadingsAndSections(md, { bulletNames });
|
|
19
|
+
const sections = (0, parse_js_1.parseHeadingsAndSections)(md, { bulletNames });
|
|
17
20
|
const specSections = [];
|
|
18
21
|
for (const sec of sections) {
|
|
19
22
|
const name = sec.heading.name;
|
|
20
23
|
const body = sec.body.trim();
|
|
21
24
|
// 1. Detect list
|
|
22
|
-
const bullets = extractBullets(body);
|
|
25
|
+
const bullets = (0, parse_js_1.extractBullets)(body);
|
|
23
26
|
if (bullets.length > 0) {
|
|
24
27
|
specSections.push({
|
|
25
28
|
name,
|
|
@@ -1,8 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.parseIssuesEnvelope = parseIssuesEnvelope;
|
|
4
|
+
exports.buildIssuesEnvelope = buildIssuesEnvelope;
|
|
5
|
+
exports.buildIssuesEnvelopeAuto = buildIssuesEnvelopeAuto;
|
|
6
|
+
const parse_js_1 = require("../md/parse.js");
|
|
7
|
+
function parseIssuesEnvelope(md) {
|
|
8
|
+
return (0, parse_js_1.isIssuesEnvelopeCheck)(md);
|
|
4
9
|
}
|
|
5
|
-
|
|
10
|
+
function buildIssuesEnvelope(args) {
|
|
6
11
|
const issues = args.validation.issues
|
|
7
12
|
.filter(i => i.severity === "warn" || i.severity === "error")
|
|
8
13
|
.map(i => `- ${i.message}`);
|
|
@@ -27,7 +32,7 @@ export function buildIssuesEnvelope(args) {
|
|
|
27
32
|
"",
|
|
28
33
|
].join("\n");
|
|
29
34
|
}
|
|
30
|
-
|
|
35
|
+
function buildIssuesEnvelopeAuto(args) {
|
|
31
36
|
const v = args.validation;
|
|
32
37
|
const expected = [];
|
|
33
38
|
const found = [];
|
package/dist/ofs/memory.js
CHANGED
|
@@ -1,22 +1,26 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.remember = remember;
|
|
4
|
+
exports.recall = recall;
|
|
5
|
+
const parser_js_1 = require("./parser.js");
|
|
6
|
+
const node_crypto_1 = require("node:crypto");
|
|
3
7
|
const specMemory = new Map();
|
|
4
8
|
/**
|
|
5
9
|
* Parses Flex-MD instructions and "remembers" the Output Format Spec.
|
|
6
10
|
* Returns a unique recallId that can be used later.
|
|
7
11
|
*/
|
|
8
|
-
|
|
9
|
-
const spec = parseOutputFormatSpec(instructions);
|
|
12
|
+
function remember(instructions) {
|
|
13
|
+
const spec = (0, parser_js_1.parseOutputFormatSpec)(instructions);
|
|
10
14
|
if (!spec) {
|
|
11
15
|
throw new Error("No valid Output Format Spec found in instructions.");
|
|
12
16
|
}
|
|
13
|
-
const id = randomUUID();
|
|
17
|
+
const id = (0, node_crypto_1.randomUUID)();
|
|
14
18
|
specMemory.set(id, spec);
|
|
15
19
|
return id;
|
|
16
20
|
}
|
|
17
21
|
/**
|
|
18
22
|
* Recalls a previously remembered Output Format Spec.
|
|
19
23
|
*/
|
|
20
|
-
|
|
24
|
+
function recall(id) {
|
|
21
25
|
return specMemory.get(id);
|
|
22
26
|
}
|
package/dist/ofs/parser.js
CHANGED
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.validateFormat = validateFormat;
|
|
4
|
+
exports.parseOutputFormatSpec = parseOutputFormatSpec;
|
|
5
|
+
const parse_js_1 = require("../md/parse.js");
|
|
2
6
|
/**
|
|
3
7
|
* Validate a format specification.
|
|
4
8
|
* Returns detailed validation results.
|
|
5
9
|
*/
|
|
6
|
-
|
|
10
|
+
async function validateFormat(formatSpec, formatType = "flex-md") {
|
|
7
11
|
const issues = [];
|
|
8
12
|
const suggestions = [];
|
|
9
13
|
if (formatType === "json-schema") {
|
|
@@ -69,7 +73,7 @@ export async function validateFormat(formatSpec, formatType = "flex-md") {
|
|
|
69
73
|
}
|
|
70
74
|
};
|
|
71
75
|
}
|
|
72
|
-
|
|
76
|
+
function parseOutputFormatSpec(md, opts = {}) {
|
|
73
77
|
const headingRx = opts.headingRegex ?? /^##\s*Output format\b/i;
|
|
74
78
|
const lines = md.split("\n");
|
|
75
79
|
// find OFS start
|
|
@@ -144,7 +148,7 @@ export function parseOutputFormatSpec(md, opts = {}) {
|
|
|
144
148
|
if (headingMatch) {
|
|
145
149
|
const name = headingMatch[1].trim();
|
|
146
150
|
// Don't re-parse "Output format" itself if it somehow gets in here
|
|
147
|
-
if (normalizeName(name) !== "output format") {
|
|
151
|
+
if ((0, parse_js_1.normalizeName)(name) !== "output format") {
|
|
148
152
|
const s = { name, kind: "text" };
|
|
149
153
|
sections.push(s);
|
|
150
154
|
currentSection = s;
|
package/dist/ofs/stringify.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.stringifyOutputFormatSpec = stringifyOutputFormatSpec;
|
|
1
4
|
/**
|
|
2
5
|
* Convert an OutputFormatSpec to a formal "Instructions Output Format Block".
|
|
3
6
|
*/
|
|
4
|
-
|
|
7
|
+
function stringifyOutputFormatSpec(spec) {
|
|
5
8
|
const lines = [];
|
|
6
9
|
lines.push(`## Output format (Markdown)`);
|
|
7
10
|
if (spec.description) {
|
package/dist/pipeline/enforce.js
CHANGED
|
@@ -1,20 +1,23 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
4
|
-
|
|
5
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.enforceFlexMd = enforceFlexMd;
|
|
4
|
+
const types_js_1 = require("../strictness/types.js");
|
|
5
|
+
const kind_js_1 = require("./kind.js");
|
|
6
|
+
const repair_js_1 = require("./repair.js");
|
|
7
|
+
const processor_js_1 = require("../strictness/processor.js");
|
|
8
|
+
const issuesEnvelope_js_1 = require("../ofs/issuesEnvelope.js");
|
|
6
9
|
/**
|
|
7
10
|
* Main pipeline: detect, optionally repair, and enforce Markdown contract constraints.
|
|
8
11
|
*/
|
|
9
|
-
|
|
12
|
+
function enforceFlexMd(text, spec, strictInput = {}, options = {}) {
|
|
10
13
|
const level = strictInput.level ?? 0;
|
|
11
|
-
const strict = { ...strictnessDefaults(level), ...strictInput };
|
|
14
|
+
const strict = { ...(0, types_js_1.strictnessDefaults)(level), ...strictInput };
|
|
12
15
|
const autoFix = options.autoFix ?? true;
|
|
13
16
|
// 1. Kind detection
|
|
14
|
-
const detected = detectResponseKind(text, spec);
|
|
17
|
+
const detected = (0, kind_js_1.detectResponseKind)(text, spec);
|
|
15
18
|
if (detected.kind === "issues") {
|
|
16
19
|
return {
|
|
17
|
-
...processResponseMarkdown(text, spec, strict),
|
|
20
|
+
...(0, processor_js_1.processResponseMarkdown)(text, spec, strict),
|
|
18
21
|
kind: "issues",
|
|
19
22
|
outputText: text
|
|
20
23
|
};
|
|
@@ -23,15 +26,15 @@ export function enforceFlexMd(text, spec, strictInput = {}, options = {}) {
|
|
|
23
26
|
let currentText = text;
|
|
24
27
|
let repairedInfo;
|
|
25
28
|
if (autoFix) {
|
|
26
|
-
repairedInfo = repairToMarkdownLevel(currentText, spec, level);
|
|
29
|
+
repairedInfo = (0, repair_js_1.repairToMarkdownLevel)(currentText, spec, level);
|
|
27
30
|
currentText = repairedInfo.output;
|
|
28
31
|
}
|
|
29
32
|
// 3. Enforce
|
|
30
|
-
const result = processResponseMarkdown(currentText, spec, strict);
|
|
33
|
+
const result = (0, processor_js_1.processResponseMarkdown)(currentText, spec, strict);
|
|
31
34
|
// 4. Mode B Fallback
|
|
32
35
|
let outputText = currentText;
|
|
33
36
|
if (!result.ok && level >= 1) {
|
|
34
|
-
outputText = buildIssuesEnvelopeAuto({
|
|
37
|
+
outputText = (0, issuesEnvelope_js_1.buildIssuesEnvelopeAuto)({
|
|
35
38
|
validation: result.validation,
|
|
36
39
|
level,
|
|
37
40
|
requiredSectionNames: spec.sections.filter(s => s.required !== false).map(s => s.name)
|
package/dist/pipeline/kind.js
CHANGED
|
@@ -1,6 +1,9 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.detectResponseKind = detectResponseKind;
|
|
4
|
+
const parse_js_1 = require("../md/parse.js");
|
|
5
|
+
function detectResponseKind(text, spec) {
|
|
6
|
+
const issuesResult = (0, parse_js_1.isIssuesEnvelopeCheck)(text);
|
|
4
7
|
const hasIssues = issuesResult.isIssuesEnvelope;
|
|
5
8
|
// Use more robust detection: check for both #+ Name and ===Name
|
|
6
9
|
const hasSections = spec.sections.some(s => {
|
package/dist/pipeline/repair.js
CHANGED
|
@@ -1,19 +1,22 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.repairToMarkdownLevel = repairToMarkdownLevel;
|
|
4
|
+
const parse_js_1 = require("../md/parse.js");
|
|
2
5
|
/**
|
|
3
6
|
* Deterministic 9-step repair plan to transform input into the required Markdown structure.
|
|
4
7
|
*/
|
|
5
|
-
|
|
8
|
+
function repairToMarkdownLevel(input, spec, level, opts) {
|
|
6
9
|
const applied = [];
|
|
7
10
|
const noneValue = opts?.noneValue ?? spec.emptySectionValue ?? "None";
|
|
8
11
|
const preferHeadingLevel = opts?.preferHeadingLevel ?? 2;
|
|
9
12
|
// Step 0 — If Issues envelope, return as-is
|
|
10
|
-
if (isIssuesEnvelopeCheck(input).isIssuesEnvelope) {
|
|
13
|
+
if ((0, parse_js_1.isIssuesEnvelopeCheck)(input).isIssuesEnvelope) {
|
|
11
14
|
return { output: input, applied: [] };
|
|
12
15
|
}
|
|
13
16
|
// Step 1 — Normalize container (L2+ only)
|
|
14
17
|
let workingMd = input;
|
|
15
18
|
if (level >= 2) {
|
|
16
|
-
const fences = extractFencedBlocks(workingMd);
|
|
19
|
+
const fences = (0, parse_js_1.extractFencedBlocks)(workingMd);
|
|
17
20
|
if (fences.length === 0) {
|
|
18
21
|
workingMd = `\`\`\`markdown\n${workingMd.trim()}\n\`\`\`\n`;
|
|
19
22
|
applied.push("CONTAINER_WRAPPED");
|
|
@@ -41,7 +44,7 @@ export function repairToMarkdownLevel(input, spec, level, opts) {
|
|
|
41
44
|
let contentToRepair = workingMd;
|
|
42
45
|
let isWrapped = false;
|
|
43
46
|
if (level >= 2) {
|
|
44
|
-
const fences = extractFencedBlocks(workingMd);
|
|
47
|
+
const fences = (0, parse_js_1.extractFencedBlocks)(workingMd);
|
|
45
48
|
if (fences.length === 1) {
|
|
46
49
|
contentToRepair = fences[0].content;
|
|
47
50
|
isWrapped = true;
|
|
@@ -60,14 +63,14 @@ export function repairToMarkdownLevel(input, spec, level, opts) {
|
|
|
60
63
|
catch (e) { }
|
|
61
64
|
}
|
|
62
65
|
// Step 4 — Ensure required section headings exist (L1+)
|
|
63
|
-
let sections = parseHeadingsAndSections(contentToRepair);
|
|
66
|
+
let sections = (0, parse_js_1.parseHeadingsAndSections)(contentToRepair);
|
|
64
67
|
const existingNorms = new Set(sections.map(s => s.heading.norm));
|
|
65
68
|
for (const sSpec of spec.sections) {
|
|
66
|
-
if (sSpec.required !== false && !existingNorms.has(normalizeName(sSpec.name))) {
|
|
69
|
+
if (sSpec.required !== false && !existingNorms.has((0, parse_js_1.normalizeName)(sSpec.name))) {
|
|
67
70
|
const hashes = "#".repeat(preferHeadingLevel);
|
|
68
71
|
contentToRepair = contentToRepair.trim() + `\n\n${hashes} ${sSpec.name}\n${noneValue}\n`;
|
|
69
72
|
applied.push(`SECTION_ADDED:${sSpec.name}`);
|
|
70
|
-
existingNorms.add(normalizeName(sSpec.name));
|
|
73
|
+
existingNorms.add((0, parse_js_1.normalizeName)(sSpec.name));
|
|
71
74
|
}
|
|
72
75
|
}
|
|
73
76
|
// Step 5 — Move stray content (L1+)
|
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.extractSingleFence = extractSingleFence;
|
|
1
4
|
/**
|
|
2
5
|
* Extracts content from exactly one fenced block of the specified language.
|
|
3
6
|
*/
|
|
4
|
-
|
|
7
|
+
function extractSingleFence(text, fenceLang) {
|
|
5
8
|
const issues = [];
|
|
6
9
|
// Find first occurrence of opening fence
|
|
7
10
|
const startMarker = "```" + fenceLang;
|
|
@@ -1,13 +1,16 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
3
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.processResponseMarkdown = processResponseMarkdown;
|
|
4
|
+
const validate_js_1 = require("../validate/validate.js");
|
|
5
|
+
const extract_js_1 = require("../extract/extract.js");
|
|
6
|
+
const issuesEnvelope_js_1 = require("../ofs/issuesEnvelope.js");
|
|
4
7
|
/**
|
|
5
8
|
* Unified entry point for processing a response against an OFS.
|
|
6
9
|
*/
|
|
7
|
-
|
|
10
|
+
function processResponseMarkdown(text, spec, strict // StrictnessOptions
|
|
8
11
|
) {
|
|
9
12
|
const level = strict.level ?? 0;
|
|
10
|
-
const validation = validateMarkdownAgainstOfs(text, spec, level, strict.policy);
|
|
13
|
+
const validation = (0, validate_js_1.validateMarkdownAgainstOfs)(text, spec, level, strict.policy);
|
|
11
14
|
const result = {
|
|
12
15
|
ok: validation.ok,
|
|
13
16
|
strictness: strict,
|
|
@@ -17,10 +20,10 @@ export function processResponseMarkdown(text, spec, strict // StrictnessOptions
|
|
|
17
20
|
issues: validation.issues,
|
|
18
21
|
};
|
|
19
22
|
if (validation.ok) {
|
|
20
|
-
result.extracted = extractFromMarkdown(text, spec);
|
|
23
|
+
result.extracted = (0, extract_js_1.extractFromMarkdown)(text, spec);
|
|
21
24
|
}
|
|
22
25
|
else {
|
|
23
|
-
const issuesEnv = parseIssuesEnvelope(text);
|
|
26
|
+
const issuesEnv = (0, issuesEnvelope_js_1.parseIssuesEnvelope)(text);
|
|
24
27
|
if (issuesEnv.isIssuesEnvelope) {
|
|
25
28
|
result.issuesEnvelope = issuesEnv;
|
|
26
29
|
}
|
package/dist/strictness/types.js
CHANGED
|
@@ -1,4 +1,7 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.strictnessDefaults = strictnessDefaults;
|
|
4
|
+
function strictnessDefaults(level) {
|
|
2
5
|
const common = {
|
|
3
6
|
tablesGuidance: "auto",
|
|
4
7
|
listsGuidance: "auto",
|
package/dist/tokens/auto-fix.js
CHANGED
|
@@ -1,7 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.autoFix = autoFix;
|
|
1
4
|
/**
|
|
2
5
|
* Automatically apply fixable improvements
|
|
3
6
|
*/
|
|
4
|
-
|
|
7
|
+
function autoFix(spec, improvements, options = {}) {
|
|
5
8
|
const { applyQuickWinsOnly = false, maxPriority = 'low', skipManual = true } = options;
|
|
6
9
|
const priorityOrder = { critical: 0, high: 1, medium: 2, low: 3 };
|
|
7
10
|
const maxPriorityLevel = priorityOrder[maxPriority] ?? 3;
|
|
@@ -1,9 +1,13 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.calculateCognitiveCost = calculateCognitiveCost;
|
|
4
|
+
exports.compareLevelCosts = compareLevelCosts;
|
|
5
|
+
const parser_js_1 = require("./parser.js");
|
|
6
|
+
const compliance_js_1 = require("./compliance.js");
|
|
3
7
|
/**
|
|
4
8
|
* Calculate cognitive cost of creating/maintaining spec
|
|
5
9
|
*/
|
|
6
|
-
|
|
10
|
+
function calculateCognitiveCost(spec) {
|
|
7
11
|
const perSection = [];
|
|
8
12
|
let totalCost = 0;
|
|
9
13
|
let complexityCost = 0;
|
|
@@ -34,8 +38,8 @@ export function calculateCognitiveCost(spec) {
|
|
|
34
38
|
*/
|
|
35
39
|
function calculateSectionCost(section) {
|
|
36
40
|
const kind = section.kind || 'text';
|
|
37
|
-
const systemPart = parseSystemPart(section.instruction, kind);
|
|
38
|
-
const level = systemPart ? detectSystemPartLevel(systemPart, kind) : null;
|
|
41
|
+
const systemPart = (0, parser_js_1.parseSystemPart)(section.instruction, kind);
|
|
42
|
+
const level = systemPart ? (0, compliance_js_1.detectSystemPartLevel)(systemPart, kind) : null;
|
|
39
43
|
const factors = [];
|
|
40
44
|
let cost = 0;
|
|
41
45
|
// Base cost by level
|
|
@@ -166,7 +170,7 @@ function generateCostRecommendation(totalCost, sectionCount) {
|
|
|
166
170
|
/**
|
|
167
171
|
* Compare cognitive cost across different compliance levels
|
|
168
172
|
*/
|
|
169
|
-
|
|
173
|
+
function compareLevelCosts(spec) {
|
|
170
174
|
const costs = { 0: 0, 1: 0, 2: 0, 3: 0 };
|
|
171
175
|
// Simulate cost at each level
|
|
172
176
|
for (let level = 0; level <= 3; level++) {
|
|
@@ -1,8 +1,12 @@
|
|
|
1
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.detectSystemPartLevel = detectSystemPartLevel;
|
|
4
|
+
exports.checkSpecCompliance = checkSpecCompliance;
|
|
5
|
+
const parser_js_1 = require("./parser.js");
|
|
2
6
|
/**
|
|
3
7
|
* Detect the compliance level of a system part
|
|
4
8
|
*/
|
|
5
|
-
|
|
9
|
+
function detectSystemPartLevel(systemPart, kind) {
|
|
6
10
|
const { parsed } = systemPart;
|
|
7
11
|
switch (parsed.type) {
|
|
8
12
|
case 'length':
|
|
@@ -31,13 +35,13 @@ export function detectSystemPartLevel(systemPart, kind) {
|
|
|
31
35
|
/**
|
|
32
36
|
* Check if a spec complies with a target level
|
|
33
37
|
*/
|
|
34
|
-
|
|
38
|
+
function checkSpecCompliance(spec, targetLevel = 2) {
|
|
35
39
|
const violations = [];
|
|
36
40
|
let totalLevel = 0;
|
|
37
41
|
let compliantCount = 0;
|
|
38
42
|
for (const section of spec.sections) {
|
|
39
43
|
const kind = section.kind || 'text';
|
|
40
|
-
const systemPart = parseSystemPart(section.instruction, kind);
|
|
44
|
+
const systemPart = (0, parser_js_1.parseSystemPart)(section.instruction, kind);
|
|
41
45
|
const level = systemPart ? detectSystemPartLevel(systemPart, kind) : 0;
|
|
42
46
|
totalLevel += level;
|
|
43
47
|
if (level >= targetLevel) {
|
|
@@ -1,9 +1,12 @@
|
|
|
1
|
-
|
|
2
|
-
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.calculateConfidence = calculateConfidence;
|
|
4
|
+
const parser_js_1 = require("./parser.js");
|
|
5
|
+
const compliance_js_1 = require("./compliance.js");
|
|
3
6
|
/**
|
|
4
7
|
* Calculate confidence in token estimation
|
|
5
8
|
*/
|
|
6
|
-
|
|
9
|
+
function calculateConfidence(spec) {
|
|
7
10
|
const bySection = [];
|
|
8
11
|
const factors = [];
|
|
9
12
|
let totalConfidence = 0;
|
|
@@ -49,9 +52,9 @@ export function calculateConfidence(spec) {
|
|
|
49
52
|
*/
|
|
50
53
|
function analyzeSectionConfidence(section) {
|
|
51
54
|
const kind = section.kind || 'text';
|
|
52
|
-
const systemPart = parseSystemPart(section.instruction, kind);
|
|
55
|
+
const systemPart = (0, parser_js_1.parseSystemPart)(section.instruction, kind);
|
|
53
56
|
const hasSystemPart = systemPart !== null;
|
|
54
|
-
const level = systemPart ? detectSystemPartLevel(systemPart, kind) : null;
|
|
57
|
+
const level = systemPart ? (0, compliance_js_1.detectSystemPartLevel)(systemPart, kind) : null;
|
|
55
58
|
let confidence = 0;
|
|
56
59
|
let quality = 'none';
|
|
57
60
|
if (systemPart && level !== null) {
|
|
@@ -137,7 +140,7 @@ function getConfidenceAdjustment(systemPart, _section) {
|
|
|
137
140
|
*/
|
|
138
141
|
function calculateCoverageFactor(spec) {
|
|
139
142
|
const total = spec.sections.length;
|
|
140
|
-
const withSystemParts = spec.sections.filter(s => parseSystemPart(s.instruction, s.kind || 'text') !== null).length;
|
|
143
|
+
const withSystemParts = spec.sections.filter(s => (0, parser_js_1.parseSystemPart)(s.instruction, s.kind || 'text') !== null).length;
|
|
141
144
|
const coverage = total > 0 ? (withSystemParts / total) * 100 : 0;
|
|
142
145
|
let score = 0;
|
|
143
146
|
let impact = 'neutral';
|
package/dist/tokens/estimator.js
CHANGED
|
@@ -1,5 +1,10 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
3
|
+
exports.TOKEN_CONSTANTS = void 0;
|
|
4
|
+
exports.estimateTokens = estimateTokens;
|
|
5
|
+
exports.getFallbackEstimate = getFallbackEstimate;
|
|
1
6
|
// Calibrated token constants
|
|
2
|
-
|
|
7
|
+
exports.TOKEN_CONSTANTS = {
|
|
3
8
|
// Text lengths (enumerated)
|
|
4
9
|
lengths: {
|
|
5
10
|
'1 sentence': 25,
|
|
@@ -19,7 +24,7 @@ export const TOKEN_CONSTANTS = {
|
|
|
19
24
|
headingOverhead: 10,
|
|
20
25
|
baseOverhead: 50
|
|
21
26
|
};
|
|
22
|
-
|
|
27
|
+
function estimateTokens(systemPart) {
|
|
23
28
|
const { parsed } = systemPart;
|
|
24
29
|
switch (parsed.type) {
|
|
25
30
|
case 'length':
|
|
@@ -33,7 +38,7 @@ export function estimateTokens(systemPart) {
|
|
|
33
38
|
}
|
|
34
39
|
}
|
|
35
40
|
function estimateTextLength(value) {
|
|
36
|
-
const estimated = TOKEN_CONSTANTS.lengths[value];
|
|
41
|
+
const estimated = exports.TOKEN_CONSTANTS.lengths[value];
|
|
37
42
|
return {
|
|
38
43
|
estimated,
|
|
39
44
|
min: Math.floor(estimated * 0.7),
|
|
@@ -46,26 +51,26 @@ function estimateItems(parsed) {
|
|
|
46
51
|
if (max !== null) {
|
|
47
52
|
// Range: "3-5" → use average
|
|
48
53
|
const avg = (min + max) / 2;
|
|
49
|
-
const estimated = Math.round(avg * TOKEN_CONSTANTS.perItem);
|
|
54
|
+
const estimated = Math.round(avg * exports.TOKEN_CONSTANTS.perItem);
|
|
50
55
|
return {
|
|
51
56
|
estimated,
|
|
52
|
-
min: min * TOKEN_CONSTANTS.perItem,
|
|
53
|
-
max: max * TOKEN_CONSTANTS.perItem,
|
|
57
|
+
min: min * exports.TOKEN_CONSTANTS.perItem,
|
|
58
|
+
max: max * exports.TOKEN_CONSTANTS.perItem,
|
|
54
59
|
confidence: 'high'
|
|
55
60
|
};
|
|
56
61
|
}
|
|
57
62
|
if (atLeast) {
|
|
58
63
|
// "at least 3" → estimate at min + 50%
|
|
59
|
-
const estimated = Math.round(min * 1.5 * TOKEN_CONSTANTS.perItem);
|
|
64
|
+
const estimated = Math.round(min * 1.5 * exports.TOKEN_CONSTANTS.perItem);
|
|
60
65
|
return {
|
|
61
66
|
estimated,
|
|
62
|
-
min: min * TOKEN_CONSTANTS.perItem,
|
|
63
|
-
max: min * 3 * TOKEN_CONSTANTS.perItem,
|
|
67
|
+
min: min * exports.TOKEN_CONSTANTS.perItem,
|
|
68
|
+
max: min * 3 * exports.TOKEN_CONSTANTS.perItem,
|
|
64
69
|
confidence: 'medium'
|
|
65
70
|
};
|
|
66
71
|
}
|
|
67
72
|
// Exact: "3" → use exact value
|
|
68
|
-
const estimated = min * TOKEN_CONSTANTS.perItem;
|
|
73
|
+
const estimated = min * exports.TOKEN_CONSTANTS.perItem;
|
|
69
74
|
return {
|
|
70
75
|
estimated,
|
|
71
76
|
min: Math.floor(estimated * 0.8),
|
|
@@ -84,15 +89,15 @@ function estimateTable(parsed) {
|
|
|
84
89
|
: parsed.columns.atLeast
|
|
85
90
|
? parsed.columns.min * 1.5
|
|
86
91
|
: parsed.columns.min;
|
|
87
|
-
const estimated = Math.round(rowAvg * colAvg * TOKEN_CONSTANTS.perTableCell);
|
|
92
|
+
const estimated = Math.round(rowAvg * colAvg * exports.TOKEN_CONSTANTS.perTableCell);
|
|
88
93
|
const minCells = parsed.rows.min * parsed.columns.min;
|
|
89
94
|
const maxRows = parsed.rows.max || (parsed.rows.atLeast ? parsed.rows.min * 2 : parsed.rows.min);
|
|
90
95
|
const maxCols = parsed.columns.max || (parsed.columns.atLeast ? parsed.columns.min * 2 : parsed.columns.min);
|
|
91
96
|
const maxCells = maxRows * maxCols;
|
|
92
97
|
return {
|
|
93
98
|
estimated,
|
|
94
|
-
min: minCells * TOKEN_CONSTANTS.perTableCell,
|
|
95
|
-
max: maxCells * TOKEN_CONSTANTS.perTableCell,
|
|
99
|
+
min: minCells * exports.TOKEN_CONSTANTS.perTableCell,
|
|
100
|
+
max: maxCells * exports.TOKEN_CONSTANTS.perTableCell,
|
|
96
101
|
confidence: (parsed.rows.max && parsed.columns.max) ? 'high' : 'medium'
|
|
97
102
|
};
|
|
98
103
|
}
|
|
@@ -101,16 +106,16 @@ function estimateCodeLines(parsed) {
|
|
|
101
106
|
if (max !== null) {
|
|
102
107
|
// Range: "10-20"
|
|
103
108
|
const avg = (min + max) / 2;
|
|
104
|
-
const estimated = Math.round(avg * TOKEN_CONSTANTS.perCodeLine);
|
|
109
|
+
const estimated = Math.round(avg * exports.TOKEN_CONSTANTS.perCodeLine);
|
|
105
110
|
return {
|
|
106
111
|
estimated,
|
|
107
|
-
min: min * TOKEN_CONSTANTS.perCodeLine,
|
|
108
|
-
max: max * TOKEN_CONSTANTS.perCodeLine,
|
|
112
|
+
min: min * exports.TOKEN_CONSTANTS.perCodeLine,
|
|
113
|
+
max: max * exports.TOKEN_CONSTANTS.perCodeLine,
|
|
109
114
|
confidence: 'high'
|
|
110
115
|
};
|
|
111
116
|
}
|
|
112
117
|
// Exact or approximate: "10" or "~10"
|
|
113
|
-
const estimated = min * TOKEN_CONSTANTS.perCodeLine;
|
|
118
|
+
const estimated = min * exports.TOKEN_CONSTANTS.perCodeLine;
|
|
114
119
|
const variance = approximate ? 0.3 : 0.15;
|
|
115
120
|
return {
|
|
116
121
|
estimated,
|
|
@@ -120,7 +125,7 @@ function estimateCodeLines(parsed) {
|
|
|
120
125
|
};
|
|
121
126
|
}
|
|
122
127
|
// Fallback for sections without system parts
|
|
123
|
-
|
|
128
|
+
function getFallbackEstimate(kind, required) {
|
|
124
129
|
const fallbacks = {
|
|
125
130
|
text: 150,
|
|
126
131
|
list: 200,
|