@jasonbelmonti/markdown-engine 3.2.0 → 3.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (38) hide show
  1. package/CHANGELOG.md +8 -0
  2. package/README.md +25 -8
  3. package/dist/declarative-validation/assertions/evaluator.d.ts.map +1 -1
  4. package/dist/declarative-validation/assertions/evaluator.js +3 -0
  5. package/dist/declarative-validation/assertions/evaluator.js.map +1 -1
  6. package/dist/declarative-validation/assertions/selection-count.d.ts +9 -0
  7. package/dist/declarative-validation/assertions/selection-count.d.ts.map +1 -0
  8. package/dist/declarative-validation/assertions/selection-count.js +36 -0
  9. package/dist/declarative-validation/assertions/selection-count.js.map +1 -0
  10. package/dist/declarative-validation/compiler/assertion-builders.d.ts.map +1 -1
  11. package/dist/declarative-validation/compiler/assertion-builders.js +2 -1
  12. package/dist/declarative-validation/compiler/assertion-builders.js.map +1 -1
  13. package/dist/declarative-validation/compiler/assertions.d.ts.map +1 -1
  14. package/dist/declarative-validation/compiler/assertions.js +1 -0
  15. package/dist/declarative-validation/compiler/assertions.js.map +1 -1
  16. package/dist/declarative-validation/compiler/compatibility.d.ts.map +1 -1
  17. package/dist/declarative-validation/compiler/compatibility.js +1 -0
  18. package/dist/declarative-validation/compiler/compatibility.js.map +1 -1
  19. package/dist/declarative-validation/compiler/length-assertion-builders.d.ts +1 -0
  20. package/dist/declarative-validation/compiler/length-assertion-builders.d.ts.map +1 -1
  21. package/dist/declarative-validation/compiler/length-assertion-builders.js +6 -0
  22. package/dist/declarative-validation/compiler/length-assertion-builders.js.map +1 -1
  23. package/dist/declarative-validation/compiler/plan.d.ts +4 -0
  24. package/dist/declarative-validation/compiler/plan.d.ts.map +1 -1
  25. package/dist/declarative-validation/profile/assertion-schema.d.ts.map +1 -1
  26. package/dist/declarative-validation/profile/assertion-schema.js +8 -0
  27. package/dist/declarative-validation/profile/assertion-schema.js.map +1 -1
  28. package/dist/declarative-validation/profile/index.d.ts +4 -0
  29. package/dist/declarative-validation/profile/index.d.ts.map +1 -1
  30. package/dist/declarative-validation/profile/length-bound-schema.d.ts +1 -1
  31. package/dist/declarative-validation/profile/length-bound-schema.d.ts.map +1 -1
  32. package/dist/declarative-validation/profile/length-bound-schema.js.map +1 -1
  33. package/dist/internal/package-version.d.ts +1 -1
  34. package/dist/internal/package-version.js +1 -1
  35. package/dist-bundled/markdown-engine-cli.mjs +331 -274
  36. package/docs/contracts/declarative-validation.md +47 -10
  37. package/package.json +2 -2
  38. package/scripts/install-markdown-engine-cli.sh +2 -2
@@ -1,9 +1,10 @@
1
1
  # Declarative Validation Contract
2
2
 
3
3
  Status: package 3.0.0, v1 profile syntax with v2 Conditional V2, document contract 1.0.0
4
- Last updated: 2026-06-15
5
- Current v2 surface: flat-rule result/evidence shell, document `sourceLength`
6
- schema and runtime measurement, ID count-bound schema and
4
+ Last updated: 2026-08-12
5
+ Current v2 surface: flat-rule result/evidence shell, generic selector
6
+ `selectionCount` bounds, document `sourceLength` schema and runtime
7
+ measurement, ID count-bound schema and
7
8
  runtime evaluator contract, plus `tableColumnCoverage` schema, compiled-plan,
8
9
  and runtime evaluator contract, `frontmatterShape` schema, compiled-plan, and
9
10
  runtime evaluator contract, `textFormat` schema, compiled-plan, and runtime
@@ -26,7 +27,8 @@ rich IR document contract, while the profile admission path recognizes
26
27
  `severity`, `select`, and `assert`; non-recursive `anyOf` and `allOf`; and
27
28
  optional rule-level `when`. The admitted v2 path exposes the result and evidence
28
29
  shell needed to distinguish assertion, grouped, and skipped evaluation output
29
- from v1 output, plus the ID count-bound schema, compiled-plan, and runtime
30
+ from v1 output, plus generic selector `selectionCount` bounds, the ID
31
+ count-bound schema, compiled-plan, and runtime
30
32
  evaluator contract; the `tableColumnCoverage` schema, compiled-plan, and
31
33
  runtime evaluator contract; the `frontmatterShape` schema, private
32
34
  compiled-plan, and runtime evaluator contract; the `textFormat` schema,
@@ -99,8 +101,9 @@ syntaxVersion: markdown-engine.validation@v2
99
101
  ```
100
102
 
101
103
  This release recognizes v2 as a distinct syntax version at profile admission,
102
- admits ID count bounds at the schema, compiled-plan, and runtime evaluator
103
- layers, admits `tableColumnCoverage` at the schema, internal compiled-plan, and
104
+ admits `selectionCount` and ID count bounds at the schema, compiled-plan, and
105
+ runtime evaluator layers, admits `tableColumnCoverage` at the schema, internal
106
+ compiled-plan, and
104
107
  runtime evaluator layers, admits `frontmatterShape` at the schema, internal
105
108
  compiled-plan, and runtime evaluator layers, admits `textFormat` at the schema,
106
109
  internal compiled-plan, and runtime evaluator layers, admits non-recursive
@@ -293,6 +296,10 @@ Supported assertion members are:
293
296
  ```ts
294
297
  interface DeclarativeAssertion {
295
298
  exists?: true;
299
+ selectionCount?: {
300
+ min?: number;
301
+ max?: number;
302
+ };
296
303
  sectionsRequired?: {
297
304
  headings: readonly string[];
298
305
  order?: "none" | "strict";
@@ -371,6 +378,7 @@ Selector/assertion compatibility is part of the public contract:
371
378
  | Assertion | Compatible selector targets |
372
379
  | --- | --- |
373
380
  | `exists` | all supported selector targets |
381
+ | `selectionCount` | all supported selector targets |
374
382
  | `sectionsRequired` | `document` |
375
383
  | `tableColumnsRequired` | `table` |
376
384
  | `ids` | all supported selector targets |
@@ -391,6 +399,16 @@ Incompatible supported selector/assertion pairs emit
391
399
  target and fails with `profile.validation.emptySelection` when the selector
392
400
  resolves zero targets.
393
401
 
402
+ For v2 profiles, `selectionCount` must include `min`, `max`, or both. Bounds
403
+ are inclusive non-negative integers, and `min` must be less than or equal to
404
+ `max` when both are present. It evaluates the number of targets resolved by the
405
+ rule selector and is compatible with every supported selector target. An empty
406
+ selection is count zero, so `max: 0` passes and `min: 1` fails with
407
+ `profile.validation.assertionFailed`; `selectionCount` does not replace its
408
+ result with `profile.validation.emptySelection`. Maximum-bound failures use the
409
+ first excess selected target as source evidence when available. Minimum-bound
410
+ failures at zero omit source location rather than fabricating one.
411
+
394
412
  `sectionsRequired.order` defaults to `none`. `strict` checks that configured
395
413
  headings appear as an ordered subsequence in the normalized section tree
396
414
  flattened in source order.
@@ -483,9 +501,10 @@ profile-supplied regular expressions, call `Date.parse`, perform locale
483
501
  parsing, or implement date ordering.
484
502
 
485
503
  Empty selector results produce `profile.validation.emptySelection` for exists,
486
- table, ID, reference, text, occurrence, text-length, and text-format
487
- assertions. Document-scoped required-section, required-frontmatter, and
488
- frontmatter-shape assertions evaluate against the document.
504
+ table, ID, reference, text, occurrence, text-length, and text-format assertions.
505
+ `selectionCount` instead evaluates the empty selection as zero. Document-scoped
506
+ required-section, required-frontmatter, and frontmatter-shape assertions
507
+ evaluate against the document.
489
508
 
490
509
  ## Diagnostics
491
510
 
@@ -517,7 +536,7 @@ an unproven pass.
517
536
  | `profile.compile.unsupportedAssertion` | `error` | Parsed YAML or JSON-safe `assert` input contains an unsupported first-level assertion member that does not have unsupported-key precedence. |
518
537
  | `profile.compile.incompatibleSelectorAssertion` | `error` | A supported selector target is paired with an incompatible supported assertion. |
519
538
  | `profile.validation.emptySelection` | Rule severity | A rule cannot evaluate because its selector matches no applicable target. |
520
- | `profile.validation.assertionFailed` | Rule severity | A supported assertion evaluates and fails without a more specific diagnostic code, including missing table columns, exact occurrence-count mismatches, text-length bound failures, and text-format `isoDate` failures. |
539
+ | `profile.validation.assertionFailed` | Rule severity | A supported assertion evaluates and fails without a more specific diagnostic code, including selector-count bound failures, missing table columns, exact occurrence-count mismatches, text-length bound failures, and text-format `isoDate` failures. |
521
540
  | `profile.validation.duplicateId` | Rule severity | An `ids.unique` assertion finds repeated IDs. |
522
541
  | `profile.validation.frontmatterForbidden` | Rule severity | A `frontmatterShape` assertion with `presence: "forbidden"` finds present frontmatter. |
523
542
  | `profile.validation.frontmatterFieldEmpty` | Rule severity | A frontmatter field configured with `nonEmpty: true` is not a non-empty string. |
@@ -919,6 +938,24 @@ rules:
919
938
  exists: true
920
939
  ```
921
940
 
941
+ V2 selector cardinality profile:
942
+
943
+ ```yaml
944
+ syntaxVersion: markdown-engine.validation@v2
945
+ rules:
946
+ - id: actions.table.exactly-one
947
+ select:
948
+ target: table
949
+ section: Execution Actions
950
+ header:
951
+ - Step ID
952
+ - Action
953
+ assert:
954
+ selectionCount:
955
+ min: 1
956
+ max: 1
957
+ ```
958
+
922
959
  ### OKF v0.1 Hard-Validation Profile Composition
923
960
 
924
961
  `markdown-engine` does not ship a built-in OKF validator. Consumers that want to
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jasonbelmonti/markdown-engine",
3
- "version": "3.2.0",
3
+ "version": "3.3.0",
4
4
  "description": "Deterministic Markdown parsing and validation engine package.",
5
5
  "license": "MIT",
6
6
  "type": "module",
@@ -71,7 +71,7 @@
71
71
  "test:validation:profile": "npm run build && vitest run tests/declarative-validation-profile.test.ts \"--exclude=.worktrees/**\"",
72
72
  "test:validation:compiler": "npm run build && vitest run tests/declarative-validation-compiler.test.ts \"--exclude=.worktrees/**\"",
73
73
  "test:validation:selectors": "npm run build && vitest run tests/declarative-validation-selectors.test.ts \"--exclude=.worktrees/**\"",
74
- "test:validation:assertions": "npm run build && vitest run tests/declarative-validation-assertions.test.ts tests/declarative-validation-frontmatter-shape-assertions.test.ts tests/declarative-validation-table-column-coverage-fixtures.test.ts tests/declarative-validation-source-assertion-coverage.test.ts tests/declarative-validation-source-length.test.ts tests/declarative-validation-normalized-source-ranges.test.ts tests/declarative-validation-grouped-rules-fixtures.test.ts tests/declarative-validation-when-skipped-rules-fixtures.test.ts \"--exclude=.worktrees/**\"",
74
+ "test:validation:assertions": "npm run build && vitest run tests/declarative-validation-assertions.test.ts tests/declarative-validation-frontmatter-shape-assertions.test.ts tests/declarative-validation-table-column-coverage-fixtures.test.ts tests/declarative-validation-source-assertion-coverage.test.ts tests/declarative-validation-source-length.test.ts tests/declarative-validation-selection-count.test.ts tests/declarative-validation-normalized-source-ranges.test.ts tests/declarative-validation-grouped-rules-fixtures.test.ts tests/declarative-validation-when-skipped-rules-fixtures.test.ts \"--exclude=.worktrees/**\"",
75
75
  "test:validation:diagnostics": "npm run build && vitest run tests/declarative-validation-diagnostics.test.ts \"--exclude=.worktrees/**\"",
76
76
  "test:validation:cli": "npm run build && vitest run tests/declarative-validation-cli.test.ts \"--exclude=.worktrees/**\"",
77
77
  "test:validation:examples": "npm run build && vitest run tests/declarative-validation-examples.test.ts \"--exclude=.worktrees/**\"",
@@ -1,9 +1,9 @@
1
1
  #!/usr/bin/env sh
2
2
  set -eu
3
3
 
4
- VERSION="3.2.0"
4
+ VERSION="3.3.0"
5
5
  PACKAGE="@jasonbelmonti/markdown-engine"
6
- EXPECTED_SHA256="5033d08160fcd3f44b11498dc29d01db73d7aff2a55eb3257fd9a1c14e29c3f6"
6
+ EXPECTED_SHA256="367455824fde63074afe896510fd2133690bb3c06222257e579e575d59105768"
7
7
  DEFAULT_DATA_HOME="${XDG_DATA_HOME:-$HOME/.local/share}"
8
8
  MARKDOWN_ENGINE_HOME="${MARKDOWN_ENGINE_HOME:-$DEFAULT_DATA_HOME/markdown-engine}"
9
9
  MARKDOWN_ENGINE_BIN_DIR="${MARKDOWN_ENGINE_BIN_DIR:-$HOME/.local/bin}"