flex-md 4.7.2 → 4.7.4

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 (104) hide show
  1. package/README.md +1 -1
  2. package/dist/__tests__/diagnostics.test.js +45 -47
  3. package/dist/__tests__/ofs.test.js +28 -30
  4. package/dist/__tests__/structural.test.js +19 -21
  5. package/dist/__tests__/validate.test.js +27 -29
  6. package/dist/cli/index.js +13 -15
  7. package/dist/detect/json/detectIntent.js +1 -4
  8. package/dist/detect/json/detectMarkdown.js +29 -35
  9. package/dist/detect/json/detectPresence.js +2 -6
  10. package/dist/detect/json/index.js +10 -31
  11. package/dist/detect/json/types.js +1 -2
  12. package/dist/extract/extract.js +11 -14
  13. package/dist/extract/types.js +1 -2
  14. package/dist/index.js +22 -69
  15. package/dist/logger.js +3 -6
  16. package/dist/md/match.js +1 -4
  17. package/dist/md/normalize.js +1 -4
  18. package/dist/md/outline.js +4 -8
  19. package/dist/md/parse.js +11 -20
  20. package/dist/ofs/adapter.js +45 -49
  21. package/dist/ofs/enricher.js +3 -8
  22. package/dist/ofs/infer.js +4 -7
  23. package/dist/ofs/issuesEnvelope.js +5 -10
  24. package/dist/ofs/memory.js +6 -10
  25. package/dist/ofs/parser.js +7 -13
  26. package/dist/ofs/stringify.js +1 -4
  27. package/dist/pipeline/enforce.js +12 -15
  28. package/dist/pipeline/kind.js +3 -6
  29. package/dist/pipeline/repair.js +8 -11
  30. package/dist/strictness/container.js +1 -4
  31. package/dist/strictness/processor.js +7 -10
  32. package/dist/strictness/types.js +1 -4
  33. package/dist/tokens/auto-fix.js +1 -4
  34. package/dist/tokens/cognitive-cost.js +6 -10
  35. package/dist/tokens/compliance.js +4 -8
  36. package/dist/tokens/confidence.js +6 -9
  37. package/dist/tokens/estimator.js +20 -26
  38. package/dist/tokens/improvements.js +12 -16
  39. package/dist/tokens/index.js +22 -40
  40. package/dist/tokens/parser.js +4 -7
  41. package/dist/tokens/patterns.js +2 -5
  42. package/dist/tokens/runtime-estimator.js +9 -12
  43. package/dist/tokens/smart-report.js +10 -14
  44. package/dist/tokens/spec-estimator.js +10 -15
  45. package/dist/tokens/types.js +1 -2
  46. package/dist/tokens/validator.js +3 -6
  47. package/dist/types.js +1 -2
  48. package/dist/validate/compliance.js +4 -8
  49. package/dist/validate/connection.js +5 -8
  50. package/dist/validate/types.js +1 -2
  51. package/dist/validate/validate.js +16 -19
  52. package/dist-cjs/__tests__/diagnostics.test.cjs +61 -0
  53. package/dist-cjs/__tests__/ofs.test.cjs +53 -0
  54. package/dist-cjs/__tests__/structural.test.cjs +30 -0
  55. package/dist-cjs/__tests__/validate.test.cjs +110 -0
  56. package/dist-cjs/cli/index.cjs +110 -0
  57. package/dist-cjs/detect/json/detectIntent.cjs +82 -0
  58. package/dist-cjs/detect/json/detectMarkdown.cjs +304 -0
  59. package/dist-cjs/detect/json/detectPresence.cjs +195 -0
  60. package/dist-cjs/detect/json/index.cjs +34 -0
  61. package/dist-cjs/detect/json/types.cjs +2 -0
  62. package/dist-cjs/extract/extract.cjs +72 -0
  63. package/dist-cjs/extract/types.cjs +2 -0
  64. package/dist-cjs/flex-md-loader.cjs +102 -0
  65. package/dist-cjs/index.cjs +79 -0
  66. package/dist-cjs/logger.cjs +22 -0
  67. package/dist-cjs/md/match.cjs +47 -0
  68. package/dist-cjs/md/normalize.cjs +13 -0
  69. package/dist-cjs/md/outline.cjs +49 -0
  70. package/dist-cjs/md/parse.cjs +199 -0
  71. package/dist-cjs/ofs/adapter.cjs +195 -0
  72. package/dist-cjs/ofs/enricher.cjs +151 -0
  73. package/dist-cjs/ofs/infer.cjs +63 -0
  74. package/dist-cjs/ofs/issuesEnvelope.cjs +76 -0
  75. package/dist-cjs/ofs/memory.cjs +26 -0
  76. package/dist-cjs/ofs/parser.cjs +373 -0
  77. package/dist-cjs/ofs/stringify.cjs +45 -0
  78. package/dist-cjs/pipeline/enforce.cjs +49 -0
  79. package/dist-cjs/pipeline/kind.cjs +30 -0
  80. package/dist-cjs/pipeline/repair.cjs +115 -0
  81. package/dist-cjs/strictness/container.cjs +49 -0
  82. package/dist-cjs/strictness/processor.cjs +32 -0
  83. package/dist-cjs/strictness/types.cjs +109 -0
  84. package/dist-cjs/tokens/auto-fix.cjs +59 -0
  85. package/dist-cjs/tokens/cognitive-cost.cjs +209 -0
  86. package/dist-cjs/tokens/compliance.cjs +74 -0
  87. package/dist-cjs/tokens/confidence.cjs +335 -0
  88. package/dist-cjs/tokens/estimator.cjs +157 -0
  89. package/dist-cjs/tokens/improvements.cjs +701 -0
  90. package/dist-cjs/tokens/index.cjs +74 -0
  91. package/dist-cjs/tokens/parser.cjs +100 -0
  92. package/dist-cjs/tokens/patterns.cjs +23 -0
  93. package/dist-cjs/tokens/runtime-estimator.cjs +74 -0
  94. package/dist-cjs/tokens/smart-report.cjs +191 -0
  95. package/dist-cjs/tokens/spec-estimator.cjs +125 -0
  96. package/dist-cjs/tokens/types.cjs +2 -0
  97. package/dist-cjs/tokens/validator.cjs +62 -0
  98. package/dist-cjs/types.cjs +2 -0
  99. package/dist-cjs/validate/compliance.cjs +103 -0
  100. package/dist-cjs/validate/connection.cjs +47 -0
  101. package/dist-cjs/validate/types.cjs +2 -0
  102. package/dist-cjs/validate/validate.cjs +319 -0
  103. package/docs/consumption.md +1 -1
  104. package/package.json +14 -8
package/README.md CHANGED
@@ -36,7 +36,7 @@ npm install flex-md
36
36
 
37
37
  ## Runtime Compatibility
38
38
 
39
- - Node LTS baseline: `>=18 <22` (see `engines` in `package.json`).
39
+ - Node LTS baseline: `>=18` (see `engines` in `package.json`).
40
40
  - Dual-surface consumption guidance for library authors is documented in [docs/consumption.md](./docs/consumption.md).
41
41
 
42
42
  ## Quick Start
@@ -1,61 +1,59 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const vitest_1 = require("vitest");
4
- const index_js_1 = require("../index.js");
5
- (0, vitest_1.describe)("Diagnostics", () => {
6
- (0, vitest_1.describe)("checkCompliance", () => {
7
- (0, vitest_1.it)("should return meetsCompliance: true for L0 if Markdown is mentioned", async () => {
8
- const res = await (0, index_js_1.checkCompliance)("Reply in Markdown.", "L0");
9
- (0, vitest_1.expect)(res.meetsCompliance).toBe(true);
10
- (0, vitest_1.expect)(res.issues).toHaveLength(0);
11
- });
12
- (0, vitest_1.it)("should return issues for L2 if container is missing", async () => {
13
- const res = await (0, index_js_1.checkCompliance)("Reply in Markdown. Include headings.", "L2");
14
- (0, vitest_1.expect)(res.meetsCompliance).toBe(false);
15
- (0, vitest_1.expect)(res.issues.some(i => i.type === "missing-container")).toBe(true);
16
- });
17
- (0, vitest_1.it)("should return false for hasFlexMdContract if requirements not met", async () => {
18
- const ok = await (0, index_js_1.hasFlexMdContract)("Hello", "L0");
19
- (0, vitest_1.expect)(ok).toBe(false);
1
+ import { describe, it, expect } from "vitest";
2
+ import { checkCompliance, hasFlexMdContract, enrichInstructionsWithFlexMd, validateFormat } from "../index.js";
3
+ describe("Diagnostics", () => {
4
+ describe("checkCompliance", () => {
5
+ it("should return meetsCompliance: true for L0 if Markdown is mentioned", async () => {
6
+ const res = await checkCompliance("Reply in Markdown.", "L0");
7
+ expect(res.meetsCompliance).toBe(true);
8
+ expect(res.issues).toHaveLength(0);
9
+ });
10
+ it("should return issues for L2 if container is missing", async () => {
11
+ const res = await checkCompliance("Reply in Markdown. Include headings.", "L2");
12
+ expect(res.meetsCompliance).toBe(false);
13
+ expect(res.issues.some(i => i.type === "missing-container")).toBe(true);
14
+ });
15
+ it("should return false for hasFlexMdContract if requirements not met", async () => {
16
+ const ok = await hasFlexMdContract("Hello", "L0");
17
+ expect(ok).toBe(false);
20
18
  });
21
19
  });
22
- (0, vitest_1.describe)("enrichInstructionsWithFlexMd", () => {
23
- (0, vitest_1.it)("should append guidance to existing instructions", async () => {
24
- const res = await (0, index_js_1.enrichInstructionsWithFlexMd)("Do a good job.", "L0");
25
- (0, vitest_1.expect)(res.enriched).toContain("Do a good job.");
26
- (0, vitest_1.expect)(res.enriched).toContain("Reply in Markdown.");
27
- (0, vitest_1.expect)(res.changes).toHaveLength(1);
28
- (0, vitest_1.expect)(res.metadata?.guidanceAdded).toBe(true);
29
- });
30
- (0, vitest_1.it)("should track container addition for L2", async () => {
31
- const res = await (0, index_js_1.enrichInstructionsWithFlexMd)("Do a good job.", "L2");
32
- (0, vitest_1.expect)(res.changes.some(c => c.type === "added-container")).toBe(true);
33
- (0, vitest_1.expect)(res.metadata?.containerAdded).toBe(true);
20
+ describe("enrichInstructionsWithFlexMd", () => {
21
+ it("should append guidance to existing instructions", async () => {
22
+ const res = await enrichInstructionsWithFlexMd("Do a good job.", "L0");
23
+ expect(res.enriched).toContain("Do a good job.");
24
+ expect(res.enriched).toContain("Reply in Markdown.");
25
+ expect(res.changes).toHaveLength(1);
26
+ expect(res.metadata?.guidanceAdded).toBe(true);
27
+ });
28
+ it("should track container addition for L2", async () => {
29
+ const res = await enrichInstructionsWithFlexMd("Do a good job.", "L2");
30
+ expect(res.changes.some(c => c.type === "added-container")).toBe(true);
31
+ expect(res.metadata?.containerAdded).toBe(true);
34
32
  });
35
33
  });
36
- (0, vitest_1.describe)("validateFormat", () => {
37
- (0, vitest_1.it)("should validate a correct flex-md OFS", async () => {
34
+ describe("validateFormat", () => {
35
+ it("should validate a correct flex-md OFS", async () => {
38
36
  const ofs = `## Output format\n- Summary — prose\n- Actions — list`;
39
- const res = await (0, index_js_1.validateFormat)(ofs);
40
- (0, vitest_1.expect)(res.valid).toBe(true);
41
- (0, vitest_1.expect)(res.metadata?.sectionCount).toBe(2);
37
+ const res = await validateFormat(ofs);
38
+ expect(res.valid).toBe(true);
39
+ expect(res.metadata?.sectionCount).toBe(2);
42
40
  });
43
- (0, vitest_1.it)("should return errors for missing heading", async () => {
41
+ it("should return errors for missing heading", async () => {
44
42
  const ofs = `- Summary — prose`;
45
- const res = await (0, index_js_1.validateFormat)(ofs);
46
- (0, vitest_1.expect)(res.valid).toBe(false);
47
- (0, vitest_1.expect)(res.issues.some(i => i.type === "missing-heading")).toBe(true);
43
+ const res = await validateFormat(ofs);
44
+ expect(res.valid).toBe(false);
45
+ expect(res.issues.some(i => i.type === "missing-heading")).toBe(true);
48
46
  });
49
- (0, vitest_1.it)("should validate JSON schema", async () => {
47
+ it("should validate JSON schema", async () => {
50
48
  const schema = `{"type": "object"}`;
51
- const res = await (0, index_js_1.validateFormat)(schema, "json-schema");
52
- (0, vitest_1.expect)(res.valid).toBe(true);
49
+ const res = await validateFormat(schema, "json-schema");
50
+ expect(res.valid).toBe(true);
53
51
  });
54
- (0, vitest_1.it)("should fail on invalid JSON schema", async () => {
52
+ it("should fail on invalid JSON schema", async () => {
55
53
  const schema = `{"type": "object"`;
56
- const res = await (0, index_js_1.validateFormat)(schema, "json-schema");
57
- (0, vitest_1.expect)(res.valid).toBe(false);
58
- (0, vitest_1.expect)(res.issues[0].type).toBe("syntax-error");
54
+ const res = await validateFormat(schema, "json-schema");
55
+ expect(res.valid).toBe(false);
56
+ expect(res.issues[0].type).toBe("syntax-error");
59
57
  });
60
58
  });
61
59
  });
@@ -1,9 +1,7 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const vitest_1 = require("vitest");
4
- const stringify_js_1 = require("../ofs/stringify.js");
5
- const enricher_js_1 = require("../ofs/enricher.js");
6
- (0, vitest_1.describe)("Instructions Output Format Block Generation", () => {
1
+ import { describe, it, expect } from "vitest";
2
+ import { stringifyOutputFormatSpec } from "../ofs/stringify.js";
3
+ import { buildMarkdownGuidance } from "../ofs/enricher.js";
4
+ describe("Instructions Output Format Block Generation", () => {
7
5
  const spec = {
8
6
  description: "Standard report format for technical analysis.",
9
7
  sections: [
@@ -23,31 +21,31 @@ const enricher_js_1 = require("../ofs/enricher.js");
23
21
  ],
24
22
  emptySectionValue: "N/A"
25
23
  };
26
- (0, vitest_1.it)("should stringify an OFS object correctly", () => {
27
- const md = (0, stringify_js_1.stringifyOutputFormatSpec)(spec);
28
- (0, vitest_1.expect)(md).toContain("## Output format (Markdown)");
29
- (0, vitest_1.expect)(md).toContain("Standard report format for technical analysis.");
30
- (0, vitest_1.expect)(md).toContain("- Summary — text (required)");
31
- (0, vitest_1.expect)(md).toContain("Description: A brief summary of the topic.");
32
- (0, vitest_1.expect)(md).toContain("Instruction: Keep it under 3 sentences.");
33
- (0, vitest_1.expect)(md).toContain("- Key Points — list (optional)");
34
- (0, vitest_1.expect)(md).toContain("Description: Important takeaways.");
35
- (0, vitest_1.expect)(md).toContain("If a section is empty, write `N/A`.");
24
+ it("should stringify an OFS object correctly", () => {
25
+ const md = stringifyOutputFormatSpec(spec);
26
+ expect(md).toContain("## Output format (Markdown)");
27
+ expect(md).toContain("Standard report format for technical analysis.");
28
+ expect(md).toContain("- Summary — text (required)");
29
+ expect(md).toContain("Description: A brief summary of the topic.");
30
+ expect(md).toContain("Instruction: Keep it under 3 sentences.");
31
+ expect(md).toContain("- Key Points — list (optional)");
32
+ expect(md).toContain("Description: Important takeaways.");
33
+ expect(md).toContain("If a section is empty, write `N/A`.");
36
34
  });
37
- (0, vitest_1.it)("should build markdown guidance (L1) correctly", () => {
38
- const guidance = (0, enricher_js_1.buildMarkdownGuidance)(spec, { level: 1 });
39
- (0, vitest_1.expect)(guidance).toContain("Include these section headings somewhere");
40
- (0, vitest_1.expect)(guidance).toContain("- Summary");
41
- (0, vitest_1.expect)(guidance).toContain("Description: A brief summary of the topic.");
42
- (0, vitest_1.expect)(guidance).toContain("Instruction: Keep it under 3 sentences.");
43
- (0, vitest_1.expect)(guidance).toContain("- Key Points");
44
- (0, vitest_1.expect)(guidance).toContain("Description: Important takeaways.");
35
+ it("should build markdown guidance (L1) correctly", () => {
36
+ const guidance = buildMarkdownGuidance(spec, { level: 1 });
37
+ expect(guidance).toContain("Include these section headings somewhere");
38
+ expect(guidance).toContain("- Summary");
39
+ expect(guidance).toContain("Description: A brief summary of the topic.");
40
+ expect(guidance).toContain("Instruction: Keep it under 3 sentences.");
41
+ expect(guidance).toContain("- Key Points");
42
+ expect(guidance).toContain("Description: Important takeaways.");
45
43
  });
46
- (0, vitest_1.it)("should build markdown guidance (L3) correctly", () => {
47
- const guidance = (0, enricher_js_1.buildMarkdownGuidance)(spec, { level: 3 });
48
- (0, vitest_1.expect)(guidance).toContain("Return your entire answer inside a single ```markdown fenced block");
49
- (0, vitest_1.expect)(guidance).toContain("- Summary");
50
- (0, vitest_1.expect)(guidance).toContain("- Key Points (list)");
51
- (0, vitest_1.expect)(guidance).toContain("Do not return JSON");
44
+ it("should build markdown guidance (L3) correctly", () => {
45
+ const guidance = buildMarkdownGuidance(spec, { level: 3 });
46
+ expect(guidance).toContain("Return your entire answer inside a single ```markdown fenced block");
47
+ expect(guidance).toContain("- Summary");
48
+ expect(guidance).toContain("- Key Points (list)");
49
+ expect(guidance).toContain("Do not return JSON");
52
50
  });
53
51
  });
@@ -1,30 +1,28 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const vitest_1 = require("vitest");
4
- const index_js_1 = require("../index.js");
5
- (0, vitest_1.describe)("Structural Diagnostics", () => {
6
- (0, vitest_1.describe)("===key support", () => {
7
- (0, vitest_1.it)("should parse ===key as a top-level section", () => {
1
+ import { describe, it, expect } from "vitest";
2
+ import { buildOutline, checkConnection } from "../index.js";
3
+ describe("Structural Diagnostics", () => {
4
+ describe("===key support", () => {
5
+ it("should parse ===key as a top-level section", () => {
8
6
  const md = `===skills\nThis is the skills section.\n\n## Subskill\nDetails.`;
9
- const outline = (0, index_js_1.buildOutline)(md);
10
- (0, vitest_1.expect)(outline.nodes).toHaveLength(1);
11
- (0, vitest_1.expect)(outline.nodes[0].title).toBe("skills");
12
- (0, vitest_1.expect)(outline.nodes[0].children).toHaveLength(1);
13
- (0, vitest_1.expect)(outline.nodes[0].children[0].title).toBe("Subskill");
7
+ const outline = buildOutline(md);
8
+ expect(outline.nodes).toHaveLength(1);
9
+ expect(outline.nodes[0].title).toBe("skills");
10
+ expect(outline.nodes[0].children).toHaveLength(1);
11
+ expect(outline.nodes[0].children[0].title).toBe("Subskill");
14
12
  });
15
13
  });
16
- (0, vitest_1.describe)("checkConnection", () => {
17
- (0, vitest_1.it)("should find a section by name", () => {
14
+ describe("checkConnection", () => {
15
+ it("should find a section by name", () => {
18
16
  const md = `# Overview\n## Details\n===skills\nContent.`;
19
- const res = (0, index_js_1.checkConnection)(md, "skills");
20
- (0, vitest_1.expect)(res.connected).toBe(true);
21
- (0, vitest_1.expect)(res.path).toContain("skills");
17
+ const res = checkConnection(md, "skills");
18
+ expect(res.connected).toBe(true);
19
+ expect(res.path).toContain("skills");
22
20
  });
23
- (0, vitest_1.it)("should fail gracefully for missing sections", () => {
21
+ it("should fail gracefully for missing sections", () => {
24
22
  const md = `# Overview`;
25
- const res = (0, index_js_1.checkConnection)(md, "missing");
26
- (0, vitest_1.expect)(res.connected).toBe(false);
27
- (0, vitest_1.expect)(res.suggestion).toContain("Overview");
23
+ const res = checkConnection(md, "missing");
24
+ expect(res.connected).toBe(false);
25
+ expect(res.suggestion).toContain("Overview");
28
26
  });
29
27
  });
30
28
  });
@@ -1,8 +1,6 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- const vitest_1 = require("vitest");
4
- const validate_js_1 = require("../validate/validate.js");
5
- const issuesEnvelope_js_1 = require("../ofs/issuesEnvelope.js");
1
+ import { describe, it, expect } from "vitest";
2
+ import { validateMarkdownAgainstOfs } from "../validate/validate.js";
3
+ import { parseIssuesEnvelope } from "../ofs/issuesEnvelope.js";
6
4
  const SPEC = {
7
5
  emptySectionValue: "None",
8
6
  sections: [
@@ -32,8 +30,8 @@ function mdL1Good() {
32
30
  "- U",
33
31
  ].join("\n");
34
32
  }
35
- (0, vitest_1.describe)("parseIssuesEnvelope()", () => {
36
- (0, vitest_1.it)("detects envelope and extracts bullets", () => {
33
+ describe("parseIssuesEnvelope()", () => {
34
+ it("detects envelope and extracts bullets", () => {
37
35
  const env = [
38
36
  "## Status",
39
37
  "Non-compliant output (cannot be repaired to the required format).",
@@ -50,17 +48,17 @@ function mdL1Good() {
50
48
  "## How to fix",
51
49
  "- Do X",
52
50
  ].join("\n");
53
- const parsed = (0, issuesEnvelope_js_1.parseIssuesEnvelope)(env);
54
- (0, vitest_1.expect)(parsed.isIssuesEnvelope).toBe(true);
55
- (0, vitest_1.expect)(parsed.sections["issues"].bullets[0]).toContain("Missing required section");
51
+ const parsed = parseIssuesEnvelope(env);
52
+ expect(parsed.isIssuesEnvelope).toBe(true);
53
+ expect(parsed.sections["issues"].bullets[0]).toContain("Missing required section");
56
54
  });
57
55
  });
58
- (0, vitest_1.describe)("validateMarkdownAgainstOfs()", () => {
59
- (0, vitest_1.it)("L0 accepts anything", () => {
60
- const r = (0, validate_js_1.validateMarkdownAgainstOfs)("whatever", SPEC, 0);
61
- (0, vitest_1.expect)(r.ok).toBe(true);
56
+ describe("validateMarkdownAgainstOfs()", () => {
57
+ it("L0 accepts anything", () => {
58
+ const r = validateMarkdownAgainstOfs("whatever", SPEC, 0);
59
+ expect(r.ok).toBe(true);
62
60
  });
63
- (0, vitest_1.it)("L1 fails when required section missing", () => {
61
+ it("L1 fails when required section missing", () => {
64
62
  const md = [
65
63
  "## Short answer",
66
64
  "Yes.",
@@ -68,21 +66,21 @@ function mdL1Good() {
68
66
  "## Reasoning",
69
67
  "1. A",
70
68
  ].join("\n");
71
- const r = (0, validate_js_1.validateMarkdownAgainstOfs)(md, SPEC, 1);
72
- (0, vitest_1.expect)(r.ok).toBe(false);
73
- (0, vitest_1.expect)(r.issues.some(i => i.code === "MISSING_SECTION")).toBe(true);
69
+ const r = validateMarkdownAgainstOfs(md, SPEC, 1);
70
+ expect(r.ok).toBe(false);
71
+ expect(r.issues.some(i => i.code === "MISSING_SECTION")).toBe(true);
74
72
  });
75
- (0, vitest_1.it)("L2 requires a single fenced markdown block", () => {
76
- const r = (0, validate_js_1.validateMarkdownAgainstOfs)(mdL1Good(), SPEC, 2);
77
- (0, vitest_1.expect)(r.ok).toBe(false);
78
- (0, vitest_1.expect)(r.issues.some(i => i.code === "CONTAINER_MISSING")).toBe(true);
73
+ it("L2 requires a single fenced markdown block", () => {
74
+ const r = validateMarkdownAgainstOfs(mdL1Good(), SPEC, 2);
75
+ expect(r.ok).toBe(false);
76
+ expect(r.issues.some(i => i.code === "CONTAINER_MISSING")).toBe(true);
79
77
  });
80
- (0, vitest_1.it)("L2 passes with one fence containing valid L1", () => {
78
+ it("L2 passes with one fence containing valid L1", () => {
81
79
  const md = ["```markdown", mdL1Good(), "```"].join("\n");
82
- const r = (0, validate_js_1.validateMarkdownAgainstOfs)(md, SPEC, 2);
83
- (0, vitest_1.expect)(r.ok).toBe(true);
80
+ const r = validateMarkdownAgainstOfs(md, SPEC, 2);
81
+ expect(r.ok).toBe(true);
84
82
  });
85
- (0, vitest_1.it)("L3 enforces section kinds (Reasoning must be ordered list)", () => {
83
+ it("L3 enforces section kinds (Reasoning must be ordered list)", () => {
86
84
  const bad = [
87
85
  "```markdown",
88
86
  [
@@ -103,8 +101,8 @@ function mdL1Good() {
103
101
  ].join("\n"),
104
102
  "```",
105
103
  ].join("\n");
106
- const r = (0, validate_js_1.validateMarkdownAgainstOfs)(bad, SPEC, 3);
107
- (0, vitest_1.expect)(r.ok).toBe(false);
108
- (0, vitest_1.expect)(r.issues.some(i => i.code === "WRONG_SECTION_KIND")).toBe(true);
104
+ const r = validateMarkdownAgainstOfs(bad, SPEC, 3);
105
+ expect(r.ok).toBe(false);
106
+ expect(r.issues.some(i => i.code === "WRONG_SECTION_KIND")).toBe(true);
109
107
  });
110
108
  });
package/dist/cli/index.js CHANGED
@@ -1,9 +1,7 @@
1
1
  #!/usr/bin/env node
2
- "use strict";
3
- Object.defineProperty(exports, "__esModule", { value: true });
4
- const fs_1 = require("fs");
5
- const path_1 = require("path");
6
- const index_js_1 = require("../index.js");
2
+ import { readFileSync, writeFileSync, existsSync } from "fs";
3
+ import { resolve } from "path";
4
+ import { checkCompliance, checkConnection } from "../index.js";
7
5
  const [, , command, ...args] = process.argv;
8
6
  async function main() {
9
7
  if (!command || command === "--help" || command === "-h") {
@@ -57,8 +55,8 @@ async function handleCheck(args) {
57
55
  if (!file)
58
56
  throw new Error("Missing file argument.");
59
57
  const level = (args.includes("--level") ? args[args.indexOf("--level") + 1] : "L2");
60
- const content = (0, fs_1.readFileSync)((0, path_1.resolve)(file), "utf-8");
61
- const result = await (0, index_js_1.checkCompliance)(content, level);
58
+ const content = readFileSync(resolve(file), "utf-8");
59
+ const result = await checkCompliance(content, level);
62
60
  if (result.meetsCompliance) {
63
61
  console.log("✅ Content meets compliance.");
64
62
  }
@@ -74,10 +72,10 @@ async function handleDiagnose(args) {
74
72
  const key = args[1];
75
73
  if (!file || !key)
76
74
  throw new Error("Usage: flex-md diagnose <file> <key>");
77
- if (!(0, fs_1.existsSync)(file))
75
+ if (!existsSync(file))
78
76
  throw new Error(`File not found: ${file}`);
79
- const content = (0, fs_1.readFileSync)((0, path_1.resolve)(file), "utf-8");
80
- const result = (0, index_js_1.checkConnection)(content, key);
77
+ const content = readFileSync(resolve(file), "utf-8");
78
+ const result = checkConnection(content, key);
81
79
  if (result.connected) {
82
80
  console.log(`✅ Key "${key}" found at path: ${result.path?.join(" -> ")}`);
83
81
  }
@@ -91,9 +89,9 @@ async function handleCreate(args) {
91
89
  const key = args[1];
92
90
  if (!file || !key)
93
91
  throw new Error("Usage: flex-md create <file> <key>");
94
- const content = (0, fs_1.existsSync)(file) ? (0, fs_1.readFileSync)(file, "utf-8") : "";
92
+ const content = existsSync(file) ? readFileSync(file, "utf-8") : "";
95
93
  const newContent = content + `\n\n## ${key}\n\n[Content for ${key}]\n`;
96
- (0, fs_1.writeFileSync)(file, newContent);
94
+ writeFileSync(file, newContent);
97
95
  console.log(`✅ Section "${key}" created in ${file}`);
98
96
  }
99
97
  async function handleSync(args) {
@@ -101,10 +99,10 @@ async function handleSync(args) {
101
99
  const target = args[1];
102
100
  if (!source || !target)
103
101
  throw new Error("Usage: flex-md sync <source> <target>");
104
- if (!(0, fs_1.existsSync)(source))
102
+ if (!existsSync(source))
105
103
  throw new Error(`Source file not found: ${source}`);
106
- const content = (0, fs_1.readFileSync)(source, "utf-8");
107
- (0, fs_1.writeFileSync)(target, content);
104
+ const content = readFileSync(source, "utf-8");
105
+ writeFileSync(target, content);
108
106
  console.log(`✅ Content synced from ${source} to ${target}`);
109
107
  }
110
108
  main();
@@ -1,6 +1,3 @@
1
- "use strict";
2
- Object.defineProperty(exports, "__esModule", { value: true });
3
- exports.detectJsonIntent = detectJsonIntent;
4
1
  const HARD_PATTERNS = [
5
2
  /\breturn\s+only\s+json\b/i,
6
3
  /\boutput\s+only\s+json\b/i,
@@ -28,7 +25,7 @@ const TOOLING_PATTERNS = [
28
25
  /\btool\s+call\b/i,
29
26
  /\barguments\b.*\bjson\b/i,
30
27
  ];
31
- function detectJsonIntent(text) {
28
+ export function detectJsonIntent(text) {
32
29
  const signals = [];
33
30
  const add = (rx, strength, idx, len) => {
34
31
  signals.push({
@@ -1,4 +1,3 @@
1
- "use strict";
2
1
  /**
3
2
  * Helpers for "framed vs frameless" Markdown handling before Flex-MD.
4
3
  *
@@ -9,29 +8,24 @@
9
8
  * Notes:
10
9
  * - This is heuristic by design; tune thresholds as you learn your data.
11
10
  */
12
- Object.defineProperty(exports, "__esModule", { value: true });
13
- exports.detectMarkdown = detectMarkdown;
14
- exports.stripSingleFence = stripSingleFence;
15
- exports.forceWrapAsMarkdown = forceWrapAsMarkdown;
16
- exports.normalizeForFlexMd = normalizeForFlexMd;
17
- const logger_js_1 = require("../../logger.js");
11
+ import { logger } from "../../logger.js";
18
12
  const SINGLE_FENCE_BLOCK_RE = /^```([a-zA-Z0-9_-]+)?([^\n]*)\n([\s\S]*?)\n```$/;
19
13
  const FENCE_OPEN_RE = /(^|\n)```/g;
20
- function detectMarkdown(text) {
21
- logger_js_1.logger.debug("Starting markdown detection", {
14
+ export function detectMarkdown(text) {
15
+ logger.debug("Starting markdown detection", {
22
16
  inputType: typeof text,
23
17
  inputLength: typeof text === "string" ? text.length : JSON.stringify(text ?? "").length
24
18
  });
25
19
  const reasons = [];
26
20
  const raw = typeof text === "string" ? text : JSON.stringify(text ?? "");
27
21
  const s = raw.replace(/\r\n/g, "\n");
28
- logger_js_1.logger.verbose("Input normalized for processing", {
22
+ logger.verbose("Input normalized for processing", {
29
23
  originalType: typeof text,
30
24
  normalizedLength: s.length,
31
25
  hasNewlines: s.includes('\n')
32
26
  });
33
27
  const codeFences = [...s.matchAll(FENCE_OPEN_RE)].length;
34
- logger_js_1.logger.debug("Code fence analysis", {
28
+ logger.debug("Code fence analysis", {
35
29
  totalFences: codeFences,
36
30
  fenceRegex: FENCE_OPEN_RE.source
37
31
  });
@@ -39,7 +33,7 @@ function detectMarkdown(text) {
39
33
  const m = s.match(SINGLE_FENCE_BLOCK_RE);
40
34
  const isFramed = !!m && codeFences === 2;
41
35
  const frameLanguage = isFramed ? (m?.[1] ?? null) : null;
42
- logger_js_1.logger.debug("Framed markdown detection", {
36
+ logger.debug("Framed markdown detection", {
43
37
  regexMatch: !!m,
44
38
  expectedFences: 2,
45
39
  actualFences: codeFences,
@@ -53,24 +47,24 @@ function detectMarkdown(text) {
53
47
  });
54
48
  if (isFramed) {
55
49
  reasons.push("Single fenced code block detected (framed payload).");
56
- logger_js_1.logger.info("Detected framed markdown", { language: frameLanguage });
50
+ logger.info("Detected framed markdown", { language: frameLanguage });
57
51
  }
58
52
  else if (codeFences > 2) {
59
53
  reasons.push("Multiple fenced code blocks detected.");
60
- logger_js_1.logger.debug("Multiple fences detected, not treating as single framed block", { fenceCount: codeFences });
54
+ logger.debug("Multiple fences detected, not treating as single framed block", { fenceCount: codeFences });
61
55
  }
62
56
  else if (codeFences === 1) {
63
57
  reasons.push("Single fence marker found but not properly framed.");
64
- logger_js_1.logger.debug("Single fence found but regex didn't match", {
58
+ logger.debug("Single fence found but regex didn't match", {
65
59
  regex: SINGLE_FENCE_BLOCK_RE.source,
66
60
  hasMatch: !!m
67
61
  });
68
62
  }
69
63
  else {
70
- logger_js_1.logger.debug("No fence markers detected");
64
+ logger.debug("No fence markers detected");
71
65
  }
72
66
  const lines = s.split("\n");
73
- logger_js_1.logger.verbose("Line-by-line analysis started", { totalLines: lines.length });
67
+ logger.verbose("Line-by-line analysis started", { totalLines: lines.length });
74
68
  const atxHeadings = lines.filter((l) => /^#{1,6}\s+\S/.test(l.trim())).length;
75
69
  let setextHeadings = 0;
76
70
  for (let i = 0; i < lines.length - 1; i++) {
@@ -95,7 +89,7 @@ function detectMarkdown(text) {
95
89
  (s.match(/__[^_\n]+__/g) ?? []).length +
96
90
  (s.match(/(^|[^*])\*[^*\n]+\*([^*]|$)/g) ?? []).length +
97
91
  (s.match(/(^|[^_])_[^_\n]+_([^_]|$)/g) ?? []).length;
98
- logger_js_1.logger.debug("Markdown structure analysis", {
92
+ logger.debug("Markdown structure analysis", {
99
93
  atxHeadings,
100
94
  setextHeadings,
101
95
  totalHeadings: headings,
@@ -110,7 +104,7 @@ function detectMarkdown(text) {
110
104
  const hasList = unorderedListLines + orderedListLines >= 2;
111
105
  const hasTable = tableRows >= 2;
112
106
  const hasOtherSignals = inlineCodeSpans + mdLinks + emphasisTokens >= 2;
113
- logger_js_1.logger.debug("Heuristic analysis", {
107
+ logger.debug("Heuristic analysis", {
114
108
  hasList,
115
109
  hasTable,
116
110
  hasOtherSignals,
@@ -121,17 +115,17 @@ function detectMarkdown(text) {
121
115
  let isMarkdownLikely = false;
122
116
  if (isFramed) {
123
117
  isMarkdownLikely = true;
124
- logger_js_1.logger.debug("Markdown likelihood determined: framed content is always considered markdown");
118
+ logger.debug("Markdown likelihood determined: framed content is always considered markdown");
125
119
  }
126
120
  else if (headings >= 2) {
127
121
  isMarkdownLikely = true;
128
122
  reasons.push(`Detected ${headings} markdown heading(s) (>=2).`);
129
- logger_js_1.logger.debug("Markdown likelihood: sufficient headings detected", { headingCount: headings });
123
+ logger.debug("Markdown likelihood: sufficient headings detected", { headingCount: headings });
130
124
  }
131
125
  else if (headings >= 1 && (hasList || hasTable)) {
132
126
  isMarkdownLikely = true;
133
127
  reasons.push(`Detected heading(s) plus ${hasList ? "list" : "table"} structure.`);
134
- logger_js_1.logger.debug("Markdown likelihood: heading plus structural element", {
128
+ logger.debug("Markdown likelihood: heading plus structural element", {
135
129
  hasHeading: headings >= 1,
136
130
  hasList,
137
131
  hasTable
@@ -140,7 +134,7 @@ function detectMarkdown(text) {
140
134
  else if ((hasList && hasTable) || (hasTable && hasOtherSignals) || (hasList && hasOtherSignals)) {
141
135
  isMarkdownLikely = true;
142
136
  reasons.push("Detected multiple markdown structural signals (lists/tables/links/code/emphasis).");
143
- logger_js_1.logger.debug("Markdown likelihood: multiple structural signals", {
137
+ logger.debug("Markdown likelihood: multiple structural signals", {
144
138
  listAndTable: hasList && hasTable,
145
139
  tableAndOther: hasTable && hasOtherSignals,
146
140
  listAndOther: hasList && hasOtherSignals
@@ -148,7 +142,7 @@ function detectMarkdown(text) {
148
142
  }
149
143
  else {
150
144
  reasons.push("Insufficient markdown structure signals; treating as plain text.");
151
- logger_js_1.logger.debug("Markdown likelihood: insufficient signals, treating as plain text", {
145
+ logger.debug("Markdown likelihood: insufficient signals, treating as plain text", {
152
146
  headings,
153
147
  hasList,
154
148
  hasTable,
@@ -158,7 +152,7 @@ function detectMarkdown(text) {
158
152
  if (/^\s*#{1,6}\s+\S/.test(lines[0] ?? "")) {
159
153
  reasons.push("Text starts with an ATX heading (#...).");
160
154
  isMarkdownLikely = true;
161
- logger_js_1.logger.debug("Additional check: starts with heading, upgrading to markdown");
155
+ logger.debug("Additional check: starts with heading, upgrading to markdown");
162
156
  }
163
157
  return {
164
158
  isMarkdownLikely,
@@ -185,7 +179,7 @@ function detectMarkdown(text) {
185
179
  *
186
180
  * - Also handles ```md / ```markdown / ```json etc.
187
181
  */
188
- function stripSingleFence(input) {
182
+ export function stripSingleFence(input) {
189
183
  const s = input.replace(/\r\n/g, "\n").trim();
190
184
  const fenceCount = [...s.matchAll(FENCE_OPEN_RE)].length;
191
185
  if (fenceCount !== 2) {
@@ -205,7 +199,7 @@ function stripSingleFence(input) {
205
199
  * Choose a heading that exists in your OFS to maximize alignment.
206
200
  * Default: "Full Answer" (common sink section).
207
201
  */
208
- function forceWrapAsMarkdown(plainText, opts) {
202
+ export function forceWrapAsMarkdown(plainText, opts) {
209
203
  const heading = opts?.heading ?? "Full Answer";
210
204
  const level = opts?.level ?? 3;
211
205
  const hashes = "#".repeat(level);
@@ -221,15 +215,15 @@ function forceWrapAsMarkdown(plainText, opts) {
221
215
  * - Else: if markdown-likely: keep as-is
222
216
  * - Else: wrap as markdown under a chosen heading
223
217
  */
224
- function normalizeForFlexMd(input, opts) {
225
- logger_js_1.logger.info("Starting Flex-MD normalization", {
218
+ export function normalizeForFlexMd(input, opts) {
219
+ logger.info("Starting Flex-MD normalization", {
226
220
  inputType: typeof input,
227
221
  inputLength: typeof input === "string" ? input.length : JSON.stringify(input ?? "").length,
228
222
  options: opts
229
223
  });
230
224
  const raw = typeof input === "string" ? input : JSON.stringify(input ?? "");
231
225
  const detection = detectMarkdown(raw);
232
- logger_js_1.logger.debug("Detection completed", {
226
+ logger.debug("Detection completed", {
233
227
  isFramed: detection.isFramed,
234
228
  isMarkdownLikely: detection.isMarkdownLikely,
235
229
  frameLanguage: detection.frameLanguage,
@@ -237,14 +231,14 @@ function normalizeForFlexMd(input, opts) {
237
231
  });
238
232
  // 1) Strip if framed
239
233
  const { stripped, wasFramed, language } = stripSingleFence(raw);
240
- logger_js_1.logger.debug("Strip fence check", {
234
+ logger.debug("Strip fence check", {
241
235
  wasFramed,
242
236
  language,
243
237
  strippedLength: stripped.length,
244
238
  originalLength: raw.length
245
239
  });
246
240
  if (wasFramed) {
247
- logger_js_1.logger.info("Normalization: stripped framed markdown", {
241
+ logger.info("Normalization: stripped framed markdown", {
248
242
  language,
249
243
  contentLength: stripped.length
250
244
  });
@@ -258,7 +252,7 @@ function normalizeForFlexMd(input, opts) {
258
252
  }
259
253
  // 2) Keep if markdown-likely
260
254
  if (detection.isMarkdownLikely) {
261
- logger_js_1.logger.info("Normalization: keeping as-is (markdown-likely)", {
255
+ logger.info("Normalization: keeping as-is (markdown-likely)", {
262
256
  reasons: detection.reasons
263
257
  });
264
258
  return {
@@ -272,7 +266,7 @@ function normalizeForFlexMd(input, opts) {
272
266
  // 3) Wrap if not markdown-likely
273
267
  const fallbackHeading = opts?.fallbackHeading ?? "Full Answer";
274
268
  const fallbackLevel = opts?.fallbackHeadingLevel ?? 3;
275
- logger_js_1.logger.info("Normalization: wrapping as markdown", {
269
+ logger.info("Normalization: wrapping as markdown", {
276
270
  fallbackHeading,
277
271
  fallbackLevel,
278
272
  reasons: detection.reasons
@@ -281,7 +275,7 @@ function normalizeForFlexMd(input, opts) {
281
275
  heading: fallbackHeading,
282
276
  level: fallbackLevel,
283
277
  });
284
- logger_js_1.logger.debug("Wrapping completed", {
278
+ logger.debug("Wrapping completed", {
285
279
  wrappedLength: wrapped.length,
286
280
  originalLength: raw.length
287
281
  });