@jasonbelmonti/markdown-engine 3.2.0 → 3.4.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/CHANGELOG.md +17 -0
- package/README.md +27 -10
- package/dist/declarative-validation/assertions/evaluator.d.ts.map +1 -1
- package/dist/declarative-validation/assertions/evaluator.js +6 -0
- package/dist/declarative-validation/assertions/evaluator.js.map +1 -1
- package/dist/declarative-validation/assertions/selection-count.d.ts +9 -0
- package/dist/declarative-validation/assertions/selection-count.d.ts.map +1 -0
- package/dist/declarative-validation/assertions/selection-count.js +36 -0
- package/dist/declarative-validation/assertions/selection-count.js.map +1 -0
- package/dist/declarative-validation/assertions/table-columns-exact.d.ts +9 -0
- package/dist/declarative-validation/assertions/table-columns-exact.d.ts.map +1 -0
- package/dist/declarative-validation/assertions/table-columns-exact.js +44 -0
- package/dist/declarative-validation/assertions/table-columns-exact.js.map +1 -0
- package/dist/declarative-validation/compiler/assertion-builders.d.ts.map +1 -1
- package/dist/declarative-validation/compiler/assertion-builders.js +20 -1
- package/dist/declarative-validation/compiler/assertion-builders.js.map +1 -1
- package/dist/declarative-validation/compiler/assertions.d.ts.map +1 -1
- package/dist/declarative-validation/compiler/assertions.js +2 -0
- package/dist/declarative-validation/compiler/assertions.js.map +1 -1
- package/dist/declarative-validation/compiler/compatibility.d.ts.map +1 -1
- package/dist/declarative-validation/compiler/compatibility.js +2 -0
- package/dist/declarative-validation/compiler/compatibility.js.map +1 -1
- package/dist/declarative-validation/compiler/length-assertion-builders.d.ts +1 -0
- package/dist/declarative-validation/compiler/length-assertion-builders.d.ts.map +1 -1
- package/dist/declarative-validation/compiler/length-assertion-builders.js +6 -0
- package/dist/declarative-validation/compiler/length-assertion-builders.js.map +1 -1
- package/dist/declarative-validation/compiler/plan.d.ts +7 -0
- package/dist/declarative-validation/compiler/plan.d.ts.map +1 -1
- package/dist/declarative-validation/profile/assertion-schema.d.ts.map +1 -1
- package/dist/declarative-validation/profile/assertion-schema.js +28 -0
- package/dist/declarative-validation/profile/assertion-schema.js.map +1 -1
- package/dist/declarative-validation/profile/index.d.ts +7 -0
- package/dist/declarative-validation/profile/index.d.ts.map +1 -1
- package/dist/declarative-validation/profile/length-bound-schema.d.ts +1 -1
- package/dist/declarative-validation/profile/length-bound-schema.d.ts.map +1 -1
- package/dist/declarative-validation/profile/length-bound-schema.js.map +1 -1
- package/dist/internal/package-version.d.ts +1 -1
- package/dist/internal/package-version.js +1 -1
- package/dist-bundled/markdown-engine-cli.mjs +439 -276
- package/docs/contracts/declarative-validation.md +88 -12
- package/package.json +2 -2
- 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-
|
|
5
|
-
Current v2 surface: flat-rule result/evidence shell,
|
|
6
|
-
|
|
4
|
+
Last updated: 2026-08-15
|
|
5
|
+
Current v2 surface: flat-rule result/evidence shell, generic selector
|
|
6
|
+
`selectionCount` bounds, document `sourceLength` schema and runtime
|
|
7
|
+
measurement, exact normalized table-header `tableColumnsExact` assertions, 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
|
|
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,11 +101,13 @@ 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
|
|
103
|
-
layers, admits `tableColumnCoverage` at the schema, internal
|
|
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
|
-
internal compiled-plan, and runtime evaluator layers, admits
|
|
109
|
+
internal compiled-plan, and runtime evaluator layers, admits `tableColumnsExact`
|
|
110
|
+
at the schema, internal compiled-plan, and runtime evaluator layers, admits non-recursive
|
|
107
111
|
grouped rules at the schema, compiled-plan, and runtime evaluator layers, and
|
|
108
112
|
admits optional rule-level `when` at the schema, internal compiled-plan, and
|
|
109
113
|
matcher layers.
|
|
@@ -233,7 +237,7 @@ emit `profile.config.invalidShape`.
|
|
|
233
237
|
Rule-level `when` is allowed only on v2 rules. Branch-level `when` remains
|
|
234
238
|
unsupported. V1 profiles preserve the original flat rule authoring contract;
|
|
235
239
|
grouped `anyOf` / `allOf`, ID count bounds, `tableColumnCoverage`,
|
|
236
|
-
`frontmatterShape`, `textFormat`, and rule-level `when` are v2 additions.
|
|
240
|
+
`tableColumnsExact`, `frontmatterShape`, `textFormat`, and rule-level `when` are v2 additions.
|
|
237
241
|
|
|
238
242
|
Profile values must be JSON-safe data properties after YAML materialization.
|
|
239
243
|
Functions, accessors, proxies, cyclic structures, sparse arrays, `undefined`
|
|
@@ -293,6 +297,10 @@ Supported assertion members are:
|
|
|
293
297
|
```ts
|
|
294
298
|
interface DeclarativeAssertion {
|
|
295
299
|
exists?: true;
|
|
300
|
+
selectionCount?: {
|
|
301
|
+
min?: number;
|
|
302
|
+
max?: number;
|
|
303
|
+
};
|
|
296
304
|
sectionsRequired?: {
|
|
297
305
|
headings: readonly string[];
|
|
298
306
|
order?: "none" | "strict";
|
|
@@ -300,6 +308,9 @@ interface DeclarativeAssertion {
|
|
|
300
308
|
tableColumnsRequired?: {
|
|
301
309
|
columns: readonly string[];
|
|
302
310
|
};
|
|
311
|
+
tableColumnsExact?: {
|
|
312
|
+
columns: readonly string[];
|
|
313
|
+
};
|
|
303
314
|
ids?: {
|
|
304
315
|
prefix?: string;
|
|
305
316
|
unique?: boolean;
|
|
@@ -371,8 +382,10 @@ Selector/assertion compatibility is part of the public contract:
|
|
|
371
382
|
| Assertion | Compatible selector targets |
|
|
372
383
|
| --- | --- |
|
|
373
384
|
| `exists` | all supported selector targets |
|
|
385
|
+
| `selectionCount` | all supported selector targets |
|
|
374
386
|
| `sectionsRequired` | `document` |
|
|
375
387
|
| `tableColumnsRequired` | `table` |
|
|
388
|
+
| `tableColumnsExact` | `table` |
|
|
376
389
|
| `ids` | all supported selector targets |
|
|
377
390
|
| `references` | `document` |
|
|
378
391
|
| `tableColumnCoverage` | `document` |
|
|
@@ -391,6 +404,29 @@ Incompatible supported selector/assertion pairs emit
|
|
|
391
404
|
target and fails with `profile.validation.emptySelection` when the selector
|
|
392
405
|
resolves zero targets.
|
|
393
406
|
|
|
407
|
+
For v2 profiles, `selectionCount` must include `min`, `max`, or both. Bounds
|
|
408
|
+
are inclusive non-negative integers, and `min` must be less than or equal to
|
|
409
|
+
`max` when both are present. It evaluates the number of targets resolved by the
|
|
410
|
+
rule selector and is compatible with every supported selector target. An empty
|
|
411
|
+
selection is count zero, so `max: 0` passes and `min: 1` fails with
|
|
412
|
+
`profile.validation.assertionFailed`; `selectionCount` does not replace its
|
|
413
|
+
result with `profile.validation.emptySelection`. Maximum-bound failures use the
|
|
414
|
+
first excess selected target as source evidence when available. Minimum-bound
|
|
415
|
+
failures at zero omit source location rather than fabricating one.
|
|
416
|
+
|
|
417
|
+
For v2 profiles, `tableColumnsExact` requires a non-empty `columns` array of
|
|
418
|
+
non-empty strings and is compatible only with a `table` selector. It compares
|
|
419
|
+
the complete normalized header sequence from the selected `EngineTable` exactly:
|
|
420
|
+
count, order, text, and duplicate occurrences must all match. Additional
|
|
421
|
+
columns before, between, or after configured columns, and missing, reordered,
|
|
422
|
+
renamed, or duplicated columns fail with
|
|
423
|
+
`profile.validation.assertionFailed`. The deterministic diagnostic includes the
|
|
424
|
+
expected and actual header sequences. When an actual header first mismatches or
|
|
425
|
+
is excess, its header-cell source range is attached when available; otherwise
|
|
426
|
+
the normal selected-table source evidence is retained. This assertion does not
|
|
427
|
+
change the ordered-subsequence behavior of `tableColumnsRequired` or table
|
|
428
|
+
selector `header` / `tableHeader` matching.
|
|
429
|
+
|
|
394
430
|
`sectionsRequired.order` defaults to `none`. `strict` checks that configured
|
|
395
431
|
headings appear as an ordered subsequence in the normalized section tree
|
|
396
432
|
flattened in source order.
|
|
@@ -483,9 +519,11 @@ profile-supplied regular expressions, call `Date.parse`, perform locale
|
|
|
483
519
|
parsing, or implement date ordering.
|
|
484
520
|
|
|
485
521
|
Empty selector results produce `profile.validation.emptySelection` for exists,
|
|
486
|
-
table, ID, reference, text, occurrence, text-length,
|
|
487
|
-
assertions.
|
|
488
|
-
|
|
522
|
+
table, ID, reference, text, occurrence, text-length, text-format, and
|
|
523
|
+
tableColumnsExact assertions.
|
|
524
|
+
`selectionCount` instead evaluates the empty selection as zero. Document-scoped
|
|
525
|
+
required-section, required-frontmatter, and frontmatter-shape assertions
|
|
526
|
+
evaluate against the document.
|
|
489
527
|
|
|
490
528
|
## Diagnostics
|
|
491
529
|
|
|
@@ -517,7 +555,7 @@ an unproven pass.
|
|
|
517
555
|
| `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
556
|
| `profile.compile.incompatibleSelectorAssertion` | `error` | A supported selector target is paired with an incompatible supported assertion. |
|
|
519
557
|
| `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. |
|
|
558
|
+
| `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 table-header mismatches, exact occurrence-count mismatches, text-length bound failures, and text-format `isoDate` failures. |
|
|
521
559
|
| `profile.validation.duplicateId` | Rule severity | An `ids.unique` assertion finds repeated IDs. |
|
|
522
560
|
| `profile.validation.frontmatterForbidden` | Rule severity | A `frontmatterShape` assertion with `presence: "forbidden"` finds present frontmatter. |
|
|
523
561
|
| `profile.validation.frontmatterFieldEmpty` | Rule severity | A frontmatter field configured with `nonEmpty: true` is not a non-empty string. |
|
|
@@ -919,6 +957,44 @@ rules:
|
|
|
919
957
|
exists: true
|
|
920
958
|
```
|
|
921
959
|
|
|
960
|
+
V2 selector cardinality profile:
|
|
961
|
+
|
|
962
|
+
```yaml
|
|
963
|
+
syntaxVersion: markdown-engine.validation@v2
|
|
964
|
+
rules:
|
|
965
|
+
- id: actions.table.exactly-one
|
|
966
|
+
select:
|
|
967
|
+
target: table
|
|
968
|
+
section: Execution Actions
|
|
969
|
+
header:
|
|
970
|
+
- Step ID
|
|
971
|
+
- Action
|
|
972
|
+
assert:
|
|
973
|
+
selectionCount:
|
|
974
|
+
min: 1
|
|
975
|
+
max: 1
|
|
976
|
+
```
|
|
977
|
+
|
|
978
|
+
V2 exact table-column profile:
|
|
979
|
+
|
|
980
|
+
```yaml
|
|
981
|
+
syntaxVersion: markdown-engine.validation@v2
|
|
982
|
+
rules:
|
|
983
|
+
- id: task-control.columns
|
|
984
|
+
select:
|
|
985
|
+
target: table
|
|
986
|
+
assert:
|
|
987
|
+
tableColumnsExact:
|
|
988
|
+
columns:
|
|
989
|
+
- Contract state
|
|
990
|
+
- Execution route
|
|
991
|
+
- State rationale
|
|
992
|
+
```
|
|
993
|
+
|
|
994
|
+
The assertion compares the complete normalized header sequence. It is stricter
|
|
995
|
+
than `tableColumnsRequired`, which continues to accept ordered-subsequence
|
|
996
|
+
matches with unrelated columns before, between, or after required names.
|
|
997
|
+
|
|
922
998
|
### OKF v0.1 Hard-Validation Profile Composition
|
|
923
999
|
|
|
924
1000
|
`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.
|
|
3
|
+
"version": "3.4.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-table-columns-exact.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.
|
|
4
|
+
VERSION="3.4.0"
|
|
5
5
|
PACKAGE="@jasonbelmonti/markdown-engine"
|
|
6
|
-
EXPECTED_SHA256="
|
|
6
|
+
EXPECTED_SHA256="41225925904c038c05392b19e7203bd723d1cbaaa47b48d96648fb0275d3d05b"
|
|
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}"
|