@jasonbelmonti/markdown-engine 3.6.0 → 4.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (79) hide show
  1. package/CHANGELOG.md +27 -2
  2. package/README.md +52 -14
  3. package/SECURITY.md +6 -4
  4. package/dist/cli/declarative-validation.d.ts +3 -9
  5. package/dist/cli/declarative-validation.d.ts.map +1 -1
  6. package/dist/cli/declarative-validation.js +6 -16
  7. package/dist/cli/declarative-validation.js.map +1 -1
  8. package/dist/cli/run.d.ts.map +1 -1
  9. package/dist/cli/run.js +2 -0
  10. package/dist/cli/run.js.map +1 -1
  11. package/dist/cli/validate-args.d.ts +3 -1
  12. package/dist/cli/validate-args.d.ts.map +1 -1
  13. package/dist/cli/validate-args.js +46 -92
  14. package/dist/cli/validate-args.js.map +1 -1
  15. package/dist/cli/validation-output.d.ts +16 -0
  16. package/dist/cli/validation-output.d.ts.map +1 -0
  17. package/dist/cli/validation-output.js +27 -0
  18. package/dist/cli/validation-output.js.map +1 -0
  19. package/dist/cli/validation-report-cache.d.ts +3 -0
  20. package/dist/cli/validation-report-cache.d.ts.map +1 -0
  21. package/dist/cli/validation-report-cache.js +41 -0
  22. package/dist/cli/validation-report-cache.js.map +1 -0
  23. package/dist/cli/validation-report.d.ts +8 -0
  24. package/dist/cli/validation-report.d.ts.map +1 -0
  25. package/dist/cli/validation-report.js +24 -0
  26. package/dist/cli/validation-report.js.map +1 -0
  27. package/dist/cli/validation-summary.d.ts +47 -0
  28. package/dist/cli/validation-summary.d.ts.map +1 -0
  29. package/dist/cli/validation-summary.js +55 -0
  30. package/dist/cli/validation-summary.js.map +1 -0
  31. package/dist/declarative-validation/assertions/evaluator.d.ts.map +1 -1
  32. package/dist/declarative-validation/assertions/evaluator.js +3 -0
  33. package/dist/declarative-validation/assertions/evaluator.js.map +1 -1
  34. package/dist/declarative-validation/assertions/table-rows-complete.d.ts +4 -0
  35. package/dist/declarative-validation/assertions/table-rows-complete.d.ts.map +1 -0
  36. package/dist/declarative-validation/assertions/table-rows-complete.js +40 -0
  37. package/dist/declarative-validation/assertions/table-rows-complete.js.map +1 -0
  38. package/dist/declarative-validation/compiler/assertion-builders.d.ts.map +1 -1
  39. package/dist/declarative-validation/compiler/assertion-builders.js +2 -0
  40. package/dist/declarative-validation/compiler/assertion-builders.js.map +1 -1
  41. package/dist/declarative-validation/compiler/assertions.d.ts.map +1 -1
  42. package/dist/declarative-validation/compiler/assertions.js +1 -0
  43. package/dist/declarative-validation/compiler/assertions.js.map +1 -1
  44. package/dist/declarative-validation/compiler/compatibility.d.ts.map +1 -1
  45. package/dist/declarative-validation/compiler/compatibility.js +1 -0
  46. package/dist/declarative-validation/compiler/compatibility.js.map +1 -1
  47. package/dist/declarative-validation/compiler/plan.d.ts +2 -0
  48. package/dist/declarative-validation/compiler/plan.d.ts.map +1 -1
  49. package/dist/declarative-validation/compiler/table-rows-complete.d.ts +3 -0
  50. package/dist/declarative-validation/compiler/table-rows-complete.d.ts.map +1 -0
  51. package/dist/declarative-validation/compiler/table-rows-complete.js +17 -0
  52. package/dist/declarative-validation/compiler/table-rows-complete.js.map +1 -0
  53. package/dist/declarative-validation/profile/assertion-schema.d.ts.map +1 -1
  54. package/dist/declarative-validation/profile/assertion-schema.js +14 -0
  55. package/dist/declarative-validation/profile/assertion-schema.js.map +1 -1
  56. package/dist/declarative-validation/profile/index.d.ts +1 -0
  57. package/dist/declarative-validation/profile/index.d.ts.map +1 -1
  58. package/dist/internal/package-version.d.ts +1 -1
  59. package/dist/internal/package-version.js +1 -1
  60. package/dist-bundled/markdown-engine-cli.mjs +575 -422
  61. package/docs/contracts/declarative-validation.md +143 -9
  62. package/fixtures/declarative-validation/examples/table-rows-complete/README.md +65 -0
  63. package/fixtures/declarative-validation/examples/table-rows-complete/blockquote.md +3 -0
  64. package/fixtures/declarative-validation/examples/table-rows-complete/complete.md +3 -0
  65. package/fixtures/declarative-validation/examples/table-rows-complete/consumer-missing.md +50 -0
  66. package/fixtures/declarative-validation/examples/table-rows-complete/consumer-repaired.md +50 -0
  67. package/fixtures/declarative-validation/examples/table-rows-complete/excess.md +3 -0
  68. package/fixtures/declarative-validation/examples/table-rows-complete/explicit-empty.md +3 -0
  69. package/fixtures/declarative-validation/examples/table-rows-complete/header-only.md +2 -0
  70. package/fixtures/declarative-validation/examples/table-rows-complete/legacy.yaml +10 -0
  71. package/fixtures/declarative-validation/examples/table-rows-complete/missing.md +3 -0
  72. package/fixtures/declarative-validation/examples/table-rows-complete/multiple.md +5 -0
  73. package/fixtures/declarative-validation/examples/table-rows-complete/oracle.json +85 -0
  74. package/fixtures/declarative-validation/examples/table-rows-complete/profile.yaml +11 -0
  75. package/fixtures/declarative-validation/examples/table-rows-complete/shape.yaml +8 -0
  76. package/fixtures/declarative-validation/examples/table-rows-complete/syntax.md +3 -0
  77. package/package.json +2 -2
  78. package/scripts/install-markdown-engine-cli.sh +2 -2
  79. package/skills/profile-backed-markdown/SKILL.md +3 -1
@@ -1,10 +1,11 @@
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-08-15
4
+ Last updated: 2026-09-25
5
5
  Current v2 surface: flat-rule result/evidence shell, generic selector
6
6
  `selectionCount` bounds, document `sourceLength` schema and runtime
7
- measurement, exact normalized table-header `tableColumnsExact` assertions, ID count-bound schema and
7
+ measurement, opt-in body-row `tableRowsComplete` assertions, exact normalized
8
+ table-header `tableColumnsExact` assertions, ID count-bound schema and
8
9
  runtime evaluator contract, plus `tableColumnCoverage` schema, compiled-plan,
9
10
  and runtime evaluator contract, `frontmatterShape` schema, compiled-plan, and
10
11
  runtime evaluator contract, `textFormat` schema, compiled-plan, and runtime
@@ -237,7 +238,7 @@ emit `profile.config.invalidShape`.
237
238
  Rule-level `when` is allowed only on v2 rules. Branch-level `when` remains
238
239
  unsupported. V1 profiles preserve the original flat rule authoring contract;
239
240
  grouped `anyOf` / `allOf`, ID count bounds, `tableColumnCoverage`,
240
- `tableColumnsExact`, `frontmatterShape`, `textFormat`, and rule-level `when` are v2 additions.
241
+ `tableColumnsExact`, `tableRowsComplete`, `frontmatterShape`, `textFormat`, and rule-level `when` are v2 additions.
241
242
 
242
243
  Profile values must be JSON-safe data properties after YAML materialization.
243
244
  Functions, accessors, proxies, cyclic structures, sparse arrays, `undefined`
@@ -308,6 +309,7 @@ interface DeclarativeAssertion {
308
309
  tableColumnsRequired?: {
309
310
  columns: readonly string[];
310
311
  };
312
+ tableRowsComplete?: true; // v2 only
311
313
  tableColumnsExact?: {
312
314
  columns: readonly string[];
313
315
  };
@@ -392,6 +394,7 @@ Selector/assertion compatibility is part of the public contract:
392
394
  | `sectionsRequired` | `document` |
393
395
  | `tableColumnsRequired` | `table` |
394
396
  | `tableColumnsExact` | `table` |
397
+ | `tableRowsComplete` | `table` |
395
398
  | `ids` | all supported selector targets |
396
399
  | `references` | `document` |
397
400
  | `tableColumnCoverage` | `document` |
@@ -433,6 +436,32 @@ the normal selected-table source evidence is retained. This assertion does not
433
436
  change the ordered-subsequence behavior of `tableColumnsRequired` or table
434
437
  selector `header` / `tableHeader` matching.
435
438
 
439
+ For v2 profiles, `tableRowsComplete: true` requires every body row of each
440
+ selected table to have exactly that table's normalized header column positions.
441
+ Only `true` is admitted; `false`, objects, strings and other payloads emit
442
+ `profile.config.invalidShape`. Only `table` selectors are compatible. V1 rejects
443
+ the assertion through the existing unsupported-assertion/key behavior.
444
+
445
+ The assertion compares normalized cell coordinates, not text or Markdown pipe
446
+ characters. Missing and excess cells both fail. An explicitly present empty cell
447
+ passes shape; compose `text.nonBlank` on required `tableCell` columns to reject
448
+ blank content. A header-only table passes shape; compose a `tableRow`
449
+ `selectionCount` minimum to require body rows. No matched tables fails with
450
+ `profile.validation.emptySelection`. Existing table section/header selectors
451
+ scope the check, including tables in descendant sections; unselected malformed
452
+ tables do not fail it. Header matching and normalization are unchanged.
453
+
454
+ Each malformed row emits one `profile.validation.assertionFailed` at the rule's
455
+ severity. Its deterministic message names the table target ID, body row index
456
+ (header is row 0; first body row is 1), and expected/actual zero-based column
457
+ positions. For example: `Selected table "node:0:table" body row 1 must have column
458
+ positions [0,1]; found [0].` Source evidence is the first available body-cell
459
+ range in column order, not a fabricated missing-cell or full-row range. When no
460
+ body-cell range is available, the diagnostic omits `sourceRange`, even if a table
461
+ range is known. Normal diagnostic ordering applies; without ranges, selected-table
462
+ order and numeric row order are retained. This check needs no original source
463
+ text and does not alter GFM parsing or strengthen existing profiles.
464
+
436
465
  `sectionsRequired.order` defaults to `none`. `strict` checks that configured
437
466
  headings appear as an ordered subsequence in the normalized section tree
438
467
  flattened in source order.
@@ -568,7 +597,7 @@ parsing, or implement date ordering.
568
597
 
569
598
  Empty selector results produce `profile.validation.emptySelection` for exists,
570
599
  table, ID, reference, text, occurrence, text-length, text-format, and
571
- tableColumnsExact assertions.
600
+ tableColumnsExact and tableRowsComplete assertions.
572
601
  `selectionCount` instead evaluates the empty selection as zero. Document-scoped
573
602
  required-section, required-frontmatter, and frontmatter-shape assertions
574
603
  evaluate against the document.
@@ -769,7 +798,7 @@ that use `sourceLength`.
769
798
  The declarative validation CLI command is:
770
799
 
771
800
  ```sh
772
- markdown-engine validate --file <markdown-file> --profile <profile-file> [--format json]
801
+ markdown-engine validate --file <markdown-file> --profile <profile-file> [--format json] [--output full|summary] [--report-file <new-file>]
773
802
  ```
774
803
 
775
804
  `--format json` is the default and only supported validation output format.
@@ -780,7 +809,7 @@ The CLI reads and checks the profile before reading the Markdown file. Profile
780
809
  parse, config, and compile failures emit profile-stage JSON and do not parse or
781
810
  validate the Markdown file.
782
811
 
783
- After profile compilation succeeds, the CLI emits a validation-result JSON
812
+ With `--output full`, after profile compilation succeeds the CLI emits a validation-result JSON
784
813
  shape whether the document passes or fails. Validation CLI results include
785
814
  evidence. V2 CLI results use the same validation-result arm of the CLI JSON
786
815
  union; there is no extra CLI discriminator beyond
@@ -788,7 +817,7 @@ union; there is no extra CLI discriminator beyond
788
817
 
789
818
  ## CLI JSON Union
790
819
 
791
- The CLI JSON output is:
820
+ The explicit `--output full` CLI JSON output is:
792
821
 
793
822
  ```ts
794
823
  type DeclarativeValidationCliJsonResult =
@@ -816,13 +845,87 @@ profiles, that same validation-result JSON can include `evaluatedRuleCount`,
816
845
  `skippedRuleCount`, `status: "skipped"`, nested `when` diagnostics, and
817
846
  `evaluation.kind: "skipped"`.
818
847
 
848
+ ## Compact Validation Output
849
+
850
+ The default `--output summary` emits the CLI-only
851
+ `schemaVersion: "markdown-engine.validation-summary.v1"` representation and saves
852
+ a complete report automatically. `--output full` preserves the earlier full JSON
853
+ contract and serialization without creating an automatic report.
854
+ Both modes still use `--format json`. Each new selector accepts spaced or
855
+ assignment syntax and may occur only once. Missing/blank paths, unsupported
856
+ output modes are usage errors (exit 2). Summary mode does not require a report path.
857
+ These options do not apply to the normalization command.
858
+
859
+ Summary fields:
860
+
861
+ | Field | Meaning |
862
+ | --- | --- |
863
+ | `schemaVersion` | Exact `markdown-engine.validation-summary.v1` discriminator. |
864
+ | `valid`, `exitCode` | Original validation verdict and its 0/1 CLI status. |
865
+ | `stage` | `profile` for rejected profiles; otherwise `validation`, including normalization failures. |
866
+ | `engineVersion`, `runtimeVersion` | Producing package and Node versions, including profile-stage failures. |
867
+ | `profile` | Existing admitted-profile metadata, when available, including V2 evaluated/skipped counts. |
868
+ | `evidence` | Existing input/profile hashes, engine/runtime versions and optional sourceLength; no duplicated rule results or diagnostics. Omitted when full-result evidence is absent. |
869
+ | `diagnosticCounts` | Total and error/warning/info counts over all top-level diagnostics. |
870
+ | `diagnostics` | Up to ten top-level diagnostics, ordered error, warning, info; existing order is preserved within a severity. |
871
+ | `diagnosticsOmitted` | Number of top-level diagnostics not shown. |
872
+ | `diagnosticsTruncated` | Number of shown diagnostics with at least one shortened field. |
873
+ | `report` | Absolute `path`, UTF-8 `bytes`, and raw-file `sha256` of the complete retained result, including its final newline. |
874
+
875
+ Shown diagnostics preserve severity and available sourceRange. Messages are
876
+ limited to 512 UTF-16 code units; code and ruleId to 128 each, including a final
877
+ ellipsis when shortened. Each diagnostic has `truncatedFields`, naming exactly
878
+ which fields were shortened (empty when none). Full unmodified fields remain
879
+ in the report. Counts exclude nested skipped-applicability and branch details,
880
+ which remain in the complete result. A passing verdict can contain warnings;
881
+ summary presentation neither discards those warnings nor changes the exit code.
882
+
883
+ The full report is byte-identical to `--output full` stdout for the same invocation's
884
+ validation result: stable pretty JSON followed by one newline. Its raw-file
885
+ SHA-256 is distinct from normalized `evidence.inputHash` and `profileHash`.
886
+ Summary stdout has stable JSON key ordering and one final newline, with no rule
887
+ result arrays. Automatic report paths are unique, so summary bytes vary between
888
+ invocations; full results and evidence remain deterministic. These presentation fields are not additions to the engine's
889
+ public API result types or evidence hashes.
890
+
891
+ Automatic reports use unique `report-<UUID>.json` filenames under
892
+ `$XDG_CACHE_HOME/markdown-engine/validation-reports` when that environment value
893
+ is absolute, otherwise `~/.cache/markdown-engine/validation-reports`. Missing
894
+ cache directories are created with mode 0700, and report files with mode 0600
895
+ (subject to platform support and the process umask). Automatic writes best-effort
896
+ prune regular generated-name reports whose modification time is older than seven
897
+ days; recent files, unrelated names, directories and symlinks are left alone.
898
+ Pruning errors do not change the verdict after successful report publication.
899
+ Cleanup runs only on automatic writes and is not a disk quota or retention
900
+ guarantee; external cache cleanup may remove files sooner. Reserve this cache for
901
+ disposable reports and use an explicit path outside it for durable evidence.
902
+
903
+ `--report-file` overrides automatic storage and is also permitted with full output.
904
+ Explicit writes do not run cache cleanup. Relative destinations resolve
905
+ against the invocation's current working directory. The parent directory must
906
+ exist; the destination must not exist. Report publication stages a complete file
907
+ in that directory, then publishes it with an exclusive hard link and removes
908
+ the temporary file. Existing files, directories, symlinks and hard links are
909
+ never replaced. Filesystems that do not support this operation report an I/O
910
+ error. Report bytes are written before any validation JSON is emitted to stdout.
911
+ `--output full` without `--report-file` performs no report/cache filesystem work.
912
+
913
+ A report-publication failure overrides a 0/1 validation status with exit 2,
914
+ emits a stderr error, and emits no validation JSON to stdout. Usage or input-read
915
+ failures continue to use the existing stderr contract and do not create a report.
916
+ Profile-stage validation failures create an automatic report in summary mode or
917
+ an explicit report when requested, retain
918
+ exit 1, and omit unavailable evidence identities from the summary. The report
919
+ writer and automatic cache are narrow CLI filesystem-output boundaries; the validator/API do not gain
920
+ persistence or filesystem-write behavior.
921
+
819
922
  ## Exit Codes
820
923
 
821
924
  | Exit code | Meaning |
822
925
  | --- | --- |
823
926
  | `0` | Validation completed with no top-level error-severity diagnostics. |
824
927
  | `1` | Profile/config/compile, Markdown normalization, document-version mismatch, or top-level validation diagnostics include at least one error. |
825
- | `2` | CLI usage, unsupported format, unknown argument, missing argument value, repeated singleton flag, unsupported `--document-version`, or local file read error. |
928
+ | `2` | CLI usage, unsupported format, unknown argument, missing argument value, repeated singleton flag, unsupported `--document-version`, or local file read/report-publication error. |
826
929
 
827
930
  ## Compatibility And Migration
828
931
 
@@ -927,6 +1030,36 @@ Migration notes:
927
1030
 
928
1031
  ## Examples
929
1032
 
1033
+ ### Opt-in table body completeness
1034
+
1035
+ ```yaml
1036
+ syntaxVersion: markdown-engine.validation@v2
1037
+ documentVersion: 1.0.0
1038
+ rules:
1039
+ - id: sources.rows.complete
1040
+ select:
1041
+ target: table
1042
+ section: Sources and baseline
1043
+ assert:
1044
+ tableRowsComplete: true
1045
+ - id: sources.identity.nonblank
1046
+ select:
1047
+ target: tableCell
1048
+ section: Sources and baseline
1049
+ column: SHA-256 / immutable identity
1050
+ assert:
1051
+ text:
1052
+ nonBlank: true
1053
+ ```
1054
+
1055
+ The [runnable table-row example](../../fixtures/declarative-validation/examples/table-rows-complete/README.md)
1056
+ adapts delegation-planner's missing-dynamic-row-cell reproducer. It demonstrates
1057
+ legacy header-only validation passing the truncated row, opt-in shape validation
1058
+ failing at that row, and a repaired document passing directly through Engine.
1059
+ Consumer-owned section selection remains profile policy; no supplemental shape
1060
+ parser is needed. Older installed runtimes do not admit this new assertion;
1061
+ adoption requires a separately released compatible runtime.
1062
+
930
1063
  Minimal profile:
931
1064
 
932
1065
  ```yaml
@@ -1145,7 +1278,8 @@ recursive grouped rules, branch-level `when`, profile-defined predicates,
1145
1278
  assertion-specific evidence payloads, a separate skipped-rule evidence channel,
1146
1279
  and a new CLI JSON discriminator.
1147
1280
 
1148
- The CLI reads only the caller-specified local Markdown and profile files. The
1281
+ The CLI reads caller-specified local Markdown and profile files and manages its
1282
+ documented automatic-report cache. The
1149
1283
  API owns no file traversal, daemon, database, browser runtime, network service,
1150
1284
  agent adapter, MCP transport, runtime lens, or persistent cache.
1151
1285
 
@@ -0,0 +1,65 @@
1
+ # Table body completeness
2
+
3
+ `tableRowsComplete: true` is an opt-in v2 assertion for `table` selectors. It
4
+ compares each body row's normalized column positions with its table's header.
5
+ Missing and excess cells fail. Header validation remains independent.
6
+
7
+ From the repository root, build and run the example:
8
+
9
+ ```sh
10
+ npm run build
11
+ node dist/cli/index.js validate --file fixtures/declarative-validation/examples/table-rows-complete/consumer-missing.md --profile fixtures/declarative-validation/examples/table-rows-complete/legacy.yaml --format json
12
+ node dist/cli/index.js validate --file fixtures/declarative-validation/examples/table-rows-complete/consumer-missing.md --profile fixtures/declarative-validation/examples/table-rows-complete/profile.yaml --format json
13
+ node dist/cli/index.js validate --file fixtures/declarative-validation/examples/table-rows-complete/consumer-repaired.md --profile fixtures/declarative-validation/examples/table-rows-complete/profile.yaml --format json
14
+ ```
15
+
16
+ Expected exits are **0, 1, 0**. The second command reports rule `sources.columns`,
17
+ body row 2 at source line 20, expected `[0,1,2,3]`, actual `[0,1,2]`. Its range
18
+ locates the first available cell of the failing row. Table and row identities
19
+ remain in the message when cell ranges are unavailable; no location is invented.
20
+
21
+ `consumer-missing.md` is adapted from delegation-planner commit
22
+ `bc11ace3e50315313d428f3b681424fee910aef3`,
23
+ `skills/delegation-planner/validation/fixtures/missing-dynamic-row-cell.md`,
24
+ with an unrelated metadata row omitted.
25
+ `consumer-repaired.md` adds the missing execution-plan identity cell.
26
+ `legacy.yaml` checks the exact source-table header; `profile.yaml` adds only the
27
+ row-completeness assertion. This focused adaptation proves Engine's shape decision
28
+ without invoking or migrating the consumer helper. It does not claim to validate
29
+ all delegation policy, source integrity, reserved markers or semantic readiness.
30
+
31
+ `oracle.json` records independently authored valid/invalid decisions, row indexes,
32
+ source lines and actual column positions for the small Markdown fixtures. API and
33
+ real CLI tests use these expectations. Fixtures include escaped pipes, inline code,
34
+ Unicode, a blockquote table, excess and truncated rows, and explicit empty cells.
35
+
36
+ An explicit empty cell (`| x | |`) passes shape. Require nonblank values separately:
37
+
38
+ ```yaml
39
+ - id: values.required
40
+ select:
41
+ target: tableCell
42
+ column: B
43
+ assert:
44
+ text:
45
+ nonBlank: true
46
+ ```
47
+
48
+ A header-only table also passes shape. To require body rows, compose:
49
+
50
+ ```yaml
51
+ - id: rows.required
52
+ select:
53
+ target: tableRow
54
+ assert:
55
+ selectionCount:
56
+ min: 1
57
+ ```
58
+
59
+ Apply the same section/header scope to composed rules when appropriate. Unmatched
60
+ table selection fails with `profile.validation.emptySelection`; unselected
61
+ malformed tables do not affect the rule. Section selection includes descendant
62
+ sections. The Engine parser and normalized document remain unchanged.
63
+
64
+ Older runtimes reject this assertion. These commands use the local build;
65
+ release, installed-runtime adoption and consumer-helper removal are separate work.
@@ -0,0 +1,3 @@
1
+ > | A | B |
2
+ > | --- | --- |
3
+ > | x |
@@ -0,0 +1,3 @@
1
+ | A | B |
2
+ | --- | --- |
3
+ | x | y |
@@ -0,0 +1,50 @@
1
+ ---
2
+ type: DelegationPlan
3
+ artifact_version: "2.0"
4
+ revision: "1"
5
+ delegation_id: fixture
6
+ ---
7
+ # Structural fixture only
8
+
9
+ ## Control
10
+
11
+ | State | Granularity | Selected pilot extent | Max attempts per packet | Scheduling |
12
+ | --- | --- | --- | --- | --- |
13
+ | READY | action | DP-WP-1 | 2 | Serial |
14
+
15
+ ## Sources and baseline
16
+
17
+ | Role | Full read path / reference | Revision | SHA-256 / immutable identity |
18
+ | --- | --- | --- | --- |
19
+ | Source contract | /fixture/task.md | 1 | synthetic-source-identity |
20
+ | Execution plan | /fixture/plan.md | 1 |
21
+ | Repository baseline and instructions | /fixture/repository | initial | synthetic-code-identity |
22
+ | Upstream validation | /fixture/validation.json | 1 | synthetic-validation-identity |
23
+
24
+ ## Model roster
25
+
26
+ | Order | Model | Reasoning effort | Harness | Availability evidence |
27
+ | --- | --- | --- | --- | --- |
28
+ | 1 | gpt-6-luna | medium | manual | Unverified; check before dispatch |
29
+
30
+ ## Ordered assignments
31
+
32
+ | Packet / coordinator | Ordered source steps | Source outcomes | Worker packet | Model / effort | Selection basis | Escalation / stop |
33
+ | --- | --- | --- | --- | --- | --- | --- |
34
+ | DP-WP-1 | EP-ACT-1, EP-GATE-1 | TD-SC-1 | /fixture/DP-WP-1.md | gpt-6-luna / medium | experimental; bounded fixture | Stop after two total attempts |
35
+
36
+ ## Readiness
37
+
38
+ | Field | Value |
39
+ | --- | --- |
40
+ | Audit decision | PASS |
41
+ | Audit evidence | Synthetic mapping only; not dispatchable real work |
42
+ | Dispatch prerequisites | Obtain real sources, authorization and model availability |
43
+ | Blockers | None |
44
+ | Resume condition | Not applicable |
45
+
46
+ ## Revision note
47
+
48
+ | Field | Value |
49
+ | --- | --- |
50
+ | Change and authority | Initial independent structural fixture; no implementation authority |
@@ -0,0 +1,50 @@
1
+ ---
2
+ type: DelegationPlan
3
+ artifact_version: "2.0"
4
+ revision: "1"
5
+ delegation_id: fixture
6
+ ---
7
+ # Structural fixture only
8
+
9
+ ## Control
10
+
11
+ | State | Granularity | Selected pilot extent | Max attempts per packet | Scheduling |
12
+ | --- | --- | --- | --- | --- |
13
+ | READY | action | DP-WP-1 | 2 | Serial |
14
+
15
+ ## Sources and baseline
16
+
17
+ | Role | Full read path / reference | Revision | SHA-256 / immutable identity |
18
+ | --- | --- | --- | --- |
19
+ | Source contract | /fixture/task.md | 1 | synthetic-source-identity |
20
+ | Execution plan | /fixture/plan.md | 1 | synthetic-plan-identity |
21
+ | Repository baseline and instructions | /fixture/repository | initial | synthetic-code-identity |
22
+ | Upstream validation | /fixture/validation.json | 1 | synthetic-validation-identity |
23
+
24
+ ## Model roster
25
+
26
+ | Order | Model | Reasoning effort | Harness | Availability evidence |
27
+ | --- | --- | --- | --- | --- |
28
+ | 1 | gpt-6-luna | medium | manual | Unverified; check before dispatch |
29
+
30
+ ## Ordered assignments
31
+
32
+ | Packet / coordinator | Ordered source steps | Source outcomes | Worker packet | Model / effort | Selection basis | Escalation / stop |
33
+ | --- | --- | --- | --- | --- | --- | --- |
34
+ | DP-WP-1 | EP-ACT-1, EP-GATE-1 | TD-SC-1 | /fixture/DP-WP-1.md | gpt-6-luna / medium | experimental; bounded fixture | Stop after two total attempts |
35
+
36
+ ## Readiness
37
+
38
+ | Field | Value |
39
+ | --- | --- |
40
+ | Audit decision | PASS |
41
+ | Audit evidence | Synthetic mapping only; not dispatchable real work |
42
+ | Dispatch prerequisites | Obtain real sources, authorization and model availability |
43
+ | Blockers | None |
44
+ | Resume condition | Not applicable |
45
+
46
+ ## Revision note
47
+
48
+ | Field | Value |
49
+ | --- | --- |
50
+ | Change and authority | Initial independent structural fixture; no implementation authority |
@@ -0,0 +1,3 @@
1
+ | A | B |
2
+ | --- | --- |
3
+ | x | y | z |
@@ -0,0 +1,3 @@
1
+ | A | B |
2
+ | --- | --- |
3
+ | x | |
@@ -0,0 +1,10 @@
1
+ syntaxVersion: markdown-engine.validation@v2
2
+ documentVersion: 1.0.0
3
+ rules:
4
+ - id: sources.columns
5
+ select:
6
+ target: table
7
+ section: Sources and baseline
8
+ assert:
9
+ tableColumnsExact:
10
+ columns: [Role, Full read path / reference, Revision, SHA-256 / immutable identity]
@@ -0,0 +1,3 @@
1
+ | A | B |
2
+ | --- | --- |
3
+ | x |
@@ -0,0 +1,5 @@
1
+ | A | B |
2
+ | --- | --- |
3
+ | x |
4
+ | x | y | z |
5
+ | z | q |
@@ -0,0 +1,85 @@
1
+ [
2
+ {
3
+ "name": "complete",
4
+ "valid": true,
5
+ "failures": []
6
+ },
7
+ {
8
+ "name": "missing",
9
+ "valid": false,
10
+ "failures": [
11
+ {
12
+ "row": 1,
13
+ "line": 3,
14
+ "actual": [
15
+ 0
16
+ ]
17
+ }
18
+ ]
19
+ },
20
+ {
21
+ "name": "excess",
22
+ "valid": false,
23
+ "failures": [
24
+ {
25
+ "row": 1,
26
+ "line": 3,
27
+ "actual": [
28
+ 0,
29
+ 1,
30
+ 2
31
+ ]
32
+ }
33
+ ]
34
+ },
35
+ {
36
+ "name": "explicit-empty",
37
+ "valid": true,
38
+ "failures": []
39
+ },
40
+ {
41
+ "name": "header-only",
42
+ "valid": true,
43
+ "failures": []
44
+ },
45
+ {
46
+ "name": "syntax",
47
+ "valid": true,
48
+ "failures": []
49
+ },
50
+ {
51
+ "name": "multiple",
52
+ "valid": false,
53
+ "failures": [
54
+ {
55
+ "row": 1,
56
+ "line": 3,
57
+ "actual": [
58
+ 0
59
+ ]
60
+ },
61
+ {
62
+ "row": 2,
63
+ "line": 4,
64
+ "actual": [
65
+ 0,
66
+ 1,
67
+ 2
68
+ ]
69
+ }
70
+ ]
71
+ },
72
+ {
73
+ "name": "blockquote",
74
+ "valid": false,
75
+ "failures": [
76
+ {
77
+ "row": 1,
78
+ "line": 3,
79
+ "actual": [
80
+ 0
81
+ ]
82
+ }
83
+ ]
84
+ }
85
+ ]
@@ -0,0 +1,11 @@
1
+ syntaxVersion: markdown-engine.validation@v2
2
+ documentVersion: 1.0.0
3
+ rules:
4
+ - id: sources.columns
5
+ select:
6
+ target: table
7
+ section: Sources and baseline
8
+ assert:
9
+ tableColumnsExact:
10
+ columns: [Role, Full read path / reference, Revision, SHA-256 / immutable identity]
11
+ tableRowsComplete: true
@@ -0,0 +1,8 @@
1
+ syntaxVersion: markdown-engine.validation@v2
2
+ documentVersion: 1.0.0
3
+ rules:
4
+ - id: rows.complete
5
+ select:
6
+ target: table
7
+ assert:
8
+ tableRowsComplete: true
@@ -0,0 +1,3 @@
1
+ | A | B |
2
+ | --- | --- |
3
+ | 雪 \| 🌲 | `a \| b` |
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@jasonbelmonti/markdown-engine",
3
- "version": "3.6.0",
3
+ "version": "4.0.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-filtered-coverage.test.ts tests/declarative-validation-visible-text.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/**\"",
74
+ "test:validation:assertions": "npm run build && vitest run tests/declarative-validation-assertions.test.ts tests/declarative-validation-filtered-coverage.test.ts tests/declarative-validation-visible-text.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-table-rows-complete.test.ts tests/declarative-validation-table-rows-complete-config.test.ts tests/declarative-validation-table-rows-complete-cli.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.6.0"
4
+ VERSION="4.0.0"
5
5
  PACKAGE="@jasonbelmonti/markdown-engine"
6
- EXPECTED_SHA256="69b855d4d3623d7cdb91a3ed09631715dde8b96fc57f49864ae2c7c7c071ad83"
6
+ EXPECTED_SHA256="afc4dfe3846f30f1e8ad70d77e818bd3bcfc9d62ef844a857c523ebaf758c97f"
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}"
@@ -18,7 +18,9 @@ node scripts/validate-profile-backed-markdown.mjs --file /path/to/file.md
18
18
  ```
19
19
 
20
20
  2. Treat stdout as the validator JSON source of truth. Do not infer pass/fail
21
- from prose or repair notes.
21
+ from prose or repair notes. Compact output includes total diagnostic counts
22
+ and a full-report path; inspect that report only when omitted details matter.
23
+ Automatic reports are cached for seven days and may be removed by later runs.
22
24
  3. If validation fails, rerun with `--repair-brief` to emit compact repair
23
25
  guidance on stderr while preserving validator JSON on stdout.
24
26
  4. Edit the Markdown file only when the user asked for repair. Do not edit