@primmel/primmel 1.3.2 → 1.4.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/dist/index.d.ts +40 -4
- package/dist/index.d.ts.map +1 -1
- package/dist/index.js +112 -1
- package/dist/index.js.map +1 -1
- package/dist/src/check-allowlist.d.ts +56 -0
- package/dist/src/check-allowlist.d.ts.map +1 -0
- package/dist/src/check-allowlist.js +307 -0
- package/dist/src/check-allowlist.js.map +1 -0
- package/dist/src/check-rules.d.ts +17 -0
- package/dist/src/check-rules.d.ts.map +1 -0
- package/dist/src/check-rules.js +351 -0
- package/dist/src/check-rules.js.map +1 -0
- package/dist/src/check.d.ts +115 -0
- package/dist/src/check.d.ts.map +1 -0
- package/dist/src/check.js +4164 -0
- package/dist/src/check.js.map +1 -0
- package/dist/src/export/rdf-competency-questions.d.ts +11 -0
- package/dist/src/export/rdf-competency-questions.d.ts.map +1 -0
- package/dist/src/export/rdf-competency-questions.js +99 -0
- package/dist/src/export/rdf-competency-questions.js.map +1 -0
- package/dist/src/export/rdf-shapes.d.ts +3 -0
- package/dist/src/export/rdf-shapes.d.ts.map +1 -0
- package/dist/src/export/rdf-shapes.js +225 -0
- package/dist/src/export/rdf-shapes.js.map +1 -0
- package/dist/src/export/rdf-vocabulary.d.ts +125 -0
- package/dist/src/export/rdf-vocabulary.d.ts.map +1 -0
- package/dist/src/export/rdf-vocabulary.js +230 -0
- package/dist/src/export/rdf-vocabulary.js.map +1 -0
- package/dist/src/export/rdf.d.ts +92 -0
- package/dist/src/export/rdf.d.ts.map +1 -0
- package/dist/src/export/rdf.js +707 -0
- package/dist/src/export/rdf.js.map +1 -0
- package/dist/src/export/reqif.d.ts +81 -0
- package/dist/src/export/reqif.d.ts.map +1 -0
- package/dist/src/export/reqif.js +703 -0
- package/dist/src/export/reqif.js.map +1 -0
- package/dist/src/instance-resolution.d.ts +68 -0
- package/dist/src/instance-resolution.d.ts.map +1 -0
- package/dist/src/instance-resolution.js +239 -0
- package/dist/src/instance-resolution.js.map +1 -0
- package/dist/src/mapping-coverage.d.ts +220 -0
- package/dist/src/mapping-coverage.d.ts.map +1 -0
- package/dist/src/mapping-coverage.js +528 -0
- package/dist/src/mapping-coverage.js.map +1 -0
- package/dist/src/model-diff.d.ts +198 -0
- package/dist/src/model-diff.d.ts.map +1 -0
- package/dist/src/model-diff.js +914 -0
- package/dist/src/model-diff.js.map +1 -0
- package/dist/src/operational-state.d.ts +112 -0
- package/dist/src/operational-state.d.ts.map +1 -0
- package/dist/src/operational-state.js +162 -0
- package/dist/src/operational-state.js.map +1 -0
- package/dist/src/package-diff.d.ts +36 -0
- package/dist/src/package-diff.d.ts.map +1 -0
- package/dist/src/package-diff.js +104 -0
- package/dist/src/package-diff.js.map +1 -0
- package/dist/src/ser-des/config/acceptance.d.ts +10 -0
- package/dist/src/ser-des/config/acceptance.d.ts.map +1 -0
- package/dist/src/ser-des/config/acceptance.js +163 -0
- package/dist/src/ser-des/config/acceptance.js.map +1 -0
- package/dist/src/ser-des/config/activityArchetype.d.ts +5 -0
- package/dist/src/ser-des/config/activityArchetype.d.ts.map +1 -0
- package/dist/src/ser-des/config/activityArchetype.js +78 -0
- package/dist/src/ser-des/config/activityArchetype.js.map +1 -0
- package/dist/src/ser-des/config/artifact.d.ts +16 -0
- package/dist/src/ser-des/config/artifact.d.ts.map +1 -0
- package/dist/src/ser-des/config/artifact.js +392 -0
- package/dist/src/ser-des/config/artifact.js.map +1 -0
- package/dist/src/ser-des/config/calculation.d.ts.map +1 -1
- package/dist/src/ser-des/config/calculation.js +214 -12
- package/dist/src/ser-des/config/calculation.js.map +1 -1
- package/dist/src/ser-des/config/comment.d.ts +34 -0
- package/dist/src/ser-des/config/comment.d.ts.map +1 -0
- package/dist/src/ser-des/config/comment.js +121 -0
- package/dist/src/ser-des/config/comment.js.map +1 -0
- package/dist/src/ser-des/config/competenceKind.d.ts +8 -0
- package/dist/src/ser-des/config/competenceKind.d.ts.map +1 -0
- package/dist/src/ser-des/config/competenceKind.js +266 -0
- package/dist/src/ser-des/config/competenceKind.js.map +1 -0
- package/dist/src/ser-des/config/composition.d.ts +6 -0
- package/dist/src/ser-des/config/composition.d.ts.map +1 -0
- package/dist/src/ser-des/config/composition.js +165 -0
- package/dist/src/ser-des/config/composition.js.map +1 -0
- package/dist/src/ser-des/config/conformanceClass.d.ts +9 -0
- package/dist/src/ser-des/config/conformanceClass.d.ts.map +1 -0
- package/dist/src/ser-des/config/conformanceClass.js +128 -0
- package/dist/src/ser-des/config/conformanceClass.js.map +1 -0
- package/dist/src/ser-des/config/conformanceTest.d.ts +6 -0
- package/dist/src/ser-des/config/conformanceTest.d.ts.map +1 -0
- package/dist/src/ser-des/config/conformanceTest.js +929 -0
- package/dist/src/ser-des/config/conformanceTest.js.map +1 -0
- package/dist/src/ser-des/config/constraint.d.ts +5 -0
- package/dist/src/ser-des/config/constraint.d.ts.map +1 -0
- package/dist/src/ser-des/config/constraint.js +108 -0
- package/dist/src/ser-des/config/constraint.js.map +1 -0
- package/dist/src/ser-des/config/data.d.ts.map +1 -1
- package/dist/src/ser-des/config/data.js +105 -12
- package/dist/src/ser-des/config/data.js.map +1 -1
- package/dist/src/ser-des/config/design.d.ts +9 -0
- package/dist/src/ser-des/config/design.d.ts.map +1 -0
- package/dist/src/ser-des/config/design.js +847 -0
- package/dist/src/ser-des/config/design.js.map +1 -0
- package/dist/src/ser-des/config/discrepancyRecord.d.ts +5 -0
- package/dist/src/ser-des/config/discrepancyRecord.d.ts.map +1 -0
- package/dist/src/ser-des/config/discrepancyRecord.js +109 -0
- package/dist/src/ser-des/config/discrepancyRecord.js.map +1 -0
- package/dist/src/ser-des/config/dual.d.ts +9 -0
- package/dist/src/ser-des/config/dual.d.ts.map +1 -0
- package/dist/src/ser-des/config/dual.js +84 -0
- package/dist/src/ser-des/config/dual.js.map +1 -0
- package/dist/src/ser-des/config/field-parser.d.ts +92 -7
- package/dist/src/ser-des/config/field-parser.d.ts.map +1 -1
- package/dist/src/ser-des/config/field-parser.js +844 -29
- package/dist/src/ser-des/config/field-parser.js.map +1 -1
- package/dist/src/ser-des/config/form.d.ts.map +1 -1
- package/dist/src/ser-des/config/form.js +356 -134
- package/dist/src/ser-des/config/form.js.map +1 -1
- package/dist/src/ser-des/config/formulasUsed.d.ts +9 -0
- package/dist/src/ser-des/config/formulasUsed.d.ts.map +1 -0
- package/dist/src/ser-des/config/formulasUsed.js +126 -0
- package/dist/src/ser-des/config/formulasUsed.js.map +1 -0
- package/dist/src/ser-des/config/index.d.ts.map +1 -1
- package/dist/src/ser-des/config/index.js +180 -1
- package/dist/src/ser-des/config/index.js.map +1 -1
- package/dist/src/ser-des/config/instance.d.ts +22 -0
- package/dist/src/ser-des/config/instance.d.ts.map +1 -0
- package/dist/src/ser-des/config/instance.js +266 -0
- package/dist/src/ser-des/config/instance.js.map +1 -0
- package/dist/src/ser-des/config/invariant.d.ts +9 -0
- package/dist/src/ser-des/config/invariant.d.ts.map +1 -0
- package/dist/src/ser-des/config/invariant.js +143 -0
- package/dist/src/ser-des/config/invariant.js.map +1 -0
- package/dist/src/ser-des/config/mapProfile.d.ts.map +1 -1
- package/dist/src/ser-des/config/mapProfile.js +199 -14
- package/dist/src/ser-des/config/mapProfile.js.map +1 -1
- package/dist/src/ser-des/config/metadata.js +6 -6
- package/dist/src/ser-des/config/metadata.js.map +1 -1
- package/dist/src/ser-des/config/monitor.d.ts +9 -0
- package/dist/src/ser-des/config/monitor.d.ts.map +1 -0
- package/dist/src/ser-des/config/monitor.js +322 -0
- package/dist/src/ser-des/config/monitor.js.map +1 -0
- package/dist/src/ser-des/config/note.d.ts.map +1 -1
- package/dist/src/ser-des/config/note.js +16 -1
- package/dist/src/ser-des/config/note.js.map +1 -1
- package/dist/src/ser-des/config/packageManifest.d.ts +5 -0
- package/dist/src/ser-des/config/packageManifest.d.ts.map +1 -0
- package/dist/src/ser-des/config/packageManifest.js +349 -0
- package/dist/src/ser-des/config/packageManifest.js.map +1 -0
- package/dist/src/ser-des/config/passport.d.ts +9 -0
- package/dist/src/ser-des/config/passport.d.ts.map +1 -0
- package/dist/src/ser-des/config/passport.js +191 -0
- package/dist/src/ser-des/config/passport.js.map +1 -0
- package/dist/src/ser-des/config/process.d.ts +5 -3
- package/dist/src/ser-des/config/process.d.ts.map +1 -1
- package/dist/src/ser-des/config/process.js +915 -8
- package/dist/src/ser-des/config/process.js.map +1 -1
- package/dist/src/ser-des/config/quantity.d.ts +21 -0
- package/dist/src/ser-des/config/quantity.d.ts.map +1 -0
- package/dist/src/ser-des/config/quantity.js +114 -0
- package/dist/src/ser-des/config/quantity.js.map +1 -0
- package/dist/src/ser-des/config/quantityRegister.d.ts +9 -0
- package/dist/src/ser-des/config/quantityRegister.d.ts.map +1 -0
- package/dist/src/ser-des/config/quantityRegister.js +202 -0
- package/dist/src/ser-des/config/quantityRegister.js.map +1 -0
- package/dist/src/ser-des/config/reference.d.ts.map +1 -1
- package/dist/src/ser-des/config/reference.js +6 -0
- package/dist/src/ser-des/config/reference.js.map +1 -1
- package/dist/src/ser-des/config/referenceMaterial.d.ts +5 -0
- package/dist/src/ser-des/config/referenceMaterial.d.ts.map +1 -0
- package/dist/src/ser-des/config/referenceMaterial.js +296 -0
- package/dist/src/ser-des/config/referenceMaterial.js.map +1 -0
- package/dist/src/ser-des/config/requirement.d.ts +16 -0
- package/dist/src/ser-des/config/requirement.d.ts.map +1 -0
- package/dist/src/ser-des/config/requirement.js +579 -0
- package/dist/src/ser-des/config/requirement.js.map +1 -0
- package/dist/src/ser-des/config/role.d.ts.map +1 -1
- package/dist/src/ser-des/config/role.js +12 -0
- package/dist/src/ser-des/config/role.js.map +1 -1
- package/dist/src/ser-des/config/series.d.ts +9 -0
- package/dist/src/ser-des/config/series.d.ts.map +1 -0
- package/dist/src/ser-des/config/series.js +121 -0
- package/dist/src/ser-des/config/series.js.map +1 -0
- package/dist/src/ser-des/config/sourceDiscrepancy.d.ts +11 -0
- package/dist/src/ser-des/config/sourceDiscrepancy.d.ts.map +1 -0
- package/dist/src/ser-des/config/sourceDiscrepancy.js +83 -0
- package/dist/src/ser-des/config/sourceDiscrepancy.js.map +1 -0
- package/dist/src/ser-des/config/stateMachine.d.ts.map +1 -1
- package/dist/src/ser-des/config/stateMachine.js +189 -38
- package/dist/src/ser-des/config/stateMachine.js.map +1 -1
- package/dist/src/ser-des/config/subform.d.ts.map +1 -1
- package/dist/src/ser-des/config/subform.js +25 -33
- package/dist/src/ser-des/config/subform.js.map +1 -1
- package/dist/src/ser-des/config/subject.d.ts +58 -0
- package/dist/src/ser-des/config/subject.d.ts.map +1 -0
- package/dist/src/ser-des/config/subject.js +2093 -0
- package/dist/src/ser-des/config/subject.js.map +1 -0
- package/dist/src/ser-des/config/symbol.d.ts.map +1 -1
- package/dist/src/ser-des/config/symbol.js +130 -6
- package/dist/src/ser-des/config/symbol.js.map +1 -1
- package/dist/src/ser-des/config/table.d.ts.map +1 -1
- package/dist/src/ser-des/config/table.js +373 -7
- package/dist/src/ser-des/config/table.js.map +1 -1
- package/dist/src/ser-des/config/term.d.ts.map +1 -1
- package/dist/src/ser-des/config/term.js +107 -0
- package/dist/src/ser-des/config/term.js.map +1 -1
- package/dist/src/ser-des/config/testPointSet.d.ts +5 -0
- package/dist/src/ser-des/config/testPointSet.d.ts.map +1 -0
- package/dist/src/ser-des/config/testPointSet.js +199 -0
- package/dist/src/ser-des/config/testPointSet.js.map +1 -0
- package/dist/src/ser-des/config/testSequence.d.ts +9 -0
- package/dist/src/ser-des/config/testSequence.d.ts.map +1 -0
- package/dist/src/ser-des/config/testSequence.js +206 -0
- package/dist/src/ser-des/config/testSequence.js.map +1 -0
- package/dist/src/ser-des/config/text.d.ts +5 -0
- package/dist/src/ser-des/config/text.d.ts.map +1 -0
- package/dist/src/ser-des/config/text.js +106 -0
- package/dist/src/ser-des/config/text.js.map +1 -0
- package/dist/src/ser-des/config/twin.d.ts +31 -0
- package/dist/src/ser-des/config/twin.d.ts.map +1 -0
- package/dist/src/ser-des/config/twin.js +362 -0
- package/dist/src/ser-des/config/twin.js.map +1 -0
- package/dist/src/ser-des/config/verdict.d.ts +5 -0
- package/dist/src/ser-des/config/verdict.d.ts.map +1 -0
- package/dist/src/ser-des/config/verdict.js +159 -0
- package/dist/src/ser-des/config/verdict.js.map +1 -0
- package/dist/src/ser-des/config/viewProfile.d.ts.map +1 -1
- package/dist/src/ser-des/config/viewProfile.js +7 -0
- package/dist/src/ser-des/config/viewProfile.js.map +1 -1
- package/dist/src/ser-des/includes.d.ts.map +1 -1
- package/dist/src/ser-des/includes.js +5 -2
- package/dist/src/ser-des/includes.js.map +1 -1
- package/dist/src/ser-des/index.d.ts +12 -0
- package/dist/src/ser-des/index.d.ts.map +1 -1
- package/dist/src/ser-des/index.js +42 -0
- package/dist/src/ser-des/index.js.map +1 -1
- package/dist/src/ser-des/package.d.ts +53 -0
- package/dist/src/ser-des/package.d.ts.map +1 -0
- package/dist/src/ser-des/package.js +404 -0
- package/dist/src/ser-des/package.js.map +1 -0
- package/dist/src/ser-des/parse-block.d.ts.map +1 -1
- package/dist/src/ser-des/parse-block.js +7 -1
- package/dist/src/ser-des/parse-block.js.map +1 -1
- package/dist/src/ser-des/parse.d.ts.map +1 -1
- package/dist/src/ser-des/parse.js +45 -0
- package/dist/src/ser-des/parse.js.map +1 -1
- package/dist/src/ser-des/prm.d.ts +53 -0
- package/dist/src/ser-des/prm.d.ts.map +1 -0
- package/dist/src/ser-des/prm.js +257 -0
- package/dist/src/ser-des/prm.js.map +1 -0
- package/dist/src/ser-des/resolve.d.ts.map +1 -1
- package/dist/src/ser-des/resolve.js +1 -0
- package/dist/src/ser-des/resolve.js.map +1 -1
- package/dist/src/ser-des/tokenize.d.ts +11 -0
- package/dist/src/ser-des/tokenize.d.ts.map +1 -1
- package/dist/src/ser-des/tokenize.js +28 -1
- package/dist/src/ser-des/tokenize.js.map +1 -1
- package/dist/src/ser-des/types.d.ts +56 -1
- package/dist/src/ser-des/types.d.ts.map +1 -1
- package/dist/src/spelling.d.ts +35 -0
- package/dist/src/spelling.d.ts.map +1 -0
- package/dist/src/spelling.js +140 -0
- package/dist/src/spelling.js.map +1 -0
- package/dist/src/text-coverage.d.ts +164 -0
- package/dist/src/text-coverage.d.ts.map +1 -0
- package/dist/src/text-coverage.js +679 -0
- package/dist/src/text-coverage.js.map +1 -0
- package/dist/src/time.d.ts +55 -0
- package/dist/src/time.d.ts.map +1 -0
- package/dist/src/time.js +223 -0
- package/dist/src/time.js.map +1 -0
- package/dist/src/type-expr.d.ts +31 -0
- package/dist/src/type-expr.d.ts.map +1 -0
- package/dist/src/type-expr.js +110 -0
- package/dist/src/type-expr.js.map +1 -0
- package/dist/src/types/Acceptance.d.ts +31 -0
- package/dist/src/types/Acceptance.d.ts.map +1 -0
- package/dist/src/types/Acceptance.js +12 -0
- package/dist/src/types/Acceptance.js.map +1 -0
- package/dist/src/types/ActivityArchetype.d.ts +14 -0
- package/dist/src/types/ActivityArchetype.d.ts.map +1 -0
- package/dist/src/types/ActivityArchetype.js +17 -0
- package/dist/src/types/ActivityArchetype.js.map +1 -0
- package/dist/src/types/Artifact.d.ts +117 -0
- package/dist/src/types/Artifact.d.ts.map +1 -0
- package/dist/src/types/Artifact.js +35 -0
- package/dist/src/types/Artifact.js.map +1 -0
- package/dist/src/types/Calculation.d.ts +49 -0
- package/dist/src/types/Calculation.d.ts.map +1 -1
- package/dist/src/types/Comment.d.ts +23 -0
- package/dist/src/types/Comment.d.ts.map +1 -0
- package/dist/src/types/Comment.js +3 -0
- package/dist/src/types/Comment.js.map +1 -0
- package/dist/src/types/CompetenceKind.d.ts +70 -0
- package/dist/src/types/CompetenceKind.d.ts.map +1 -0
- package/dist/src/types/CompetenceKind.js +3 -0
- package/dist/src/types/CompetenceKind.js.map +1 -0
- package/dist/src/types/Composition.d.ts +80 -0
- package/dist/src/types/Composition.d.ts.map +1 -0
- package/dist/src/types/Composition.js +44 -0
- package/dist/src/types/Composition.js.map +1 -0
- package/dist/src/types/ConformanceClass.d.ts +22 -0
- package/dist/src/types/ConformanceClass.d.ts.map +1 -0
- package/dist/src/types/ConformanceClass.js +7 -0
- package/dist/src/types/ConformanceClass.js.map +1 -0
- package/dist/src/types/ConformanceTest.d.ts +206 -0
- package/dist/src/types/ConformanceTest.d.ts.map +1 -0
- package/dist/src/types/ConformanceTest.js +3 -0
- package/dist/src/types/ConformanceTest.js.map +1 -0
- package/dist/src/types/Constraint.d.ts +34 -0
- package/dist/src/types/Constraint.d.ts.map +1 -0
- package/dist/src/types/Constraint.js +3 -0
- package/dist/src/types/Constraint.js.map +1 -0
- package/dist/src/types/Design.d.ts +147 -0
- package/dist/src/types/Design.d.ts.map +1 -0
- package/dist/src/types/Design.js +10 -0
- package/dist/src/types/Design.js.map +1 -0
- package/dist/src/types/DiscrepancyRecord.d.ts +42 -0
- package/dist/src/types/DiscrepancyRecord.d.ts.map +1 -0
- package/dist/src/types/DiscrepancyRecord.js +3 -0
- package/dist/src/types/DiscrepancyRecord.js.map +1 -0
- package/dist/src/types/Form.d.ts +132 -1
- package/dist/src/types/Form.d.ts.map +1 -1
- package/dist/src/types/FormulasUsed.d.ts +95 -0
- package/dist/src/types/FormulasUsed.d.ts.map +1 -0
- package/dist/src/types/FormulasUsed.js +64 -0
- package/dist/src/types/FormulasUsed.js.map +1 -0
- package/dist/src/types/Instance.d.ts +105 -0
- package/dist/src/types/Instance.d.ts.map +1 -0
- package/dist/src/types/Instance.js +40 -0
- package/dist/src/types/Instance.js.map +1 -0
- package/dist/src/types/Invariant.d.ts +82 -0
- package/dist/src/types/Invariant.d.ts.map +1 -0
- package/dist/src/types/Invariant.js +50 -0
- package/dist/src/types/Invariant.js.map +1 -0
- package/dist/src/types/MapProfile.d.ts +36 -1
- package/dist/src/types/MapProfile.d.ts.map +1 -1
- package/dist/src/types/Monitor.d.ts +144 -0
- package/dist/src/types/Monitor.d.ts.map +1 -0
- package/dist/src/types/Monitor.js +74 -0
- package/dist/src/types/Monitor.js.map +1 -0
- package/dist/src/types/Note.d.ts +4 -1
- package/dist/src/types/Note.d.ts.map +1 -1
- package/dist/src/types/Package.d.ts +161 -0
- package/dist/src/types/Package.d.ts.map +1 -0
- package/dist/src/types/Package.js +3 -0
- package/dist/src/types/Package.js.map +1 -0
- package/dist/src/types/Passport.d.ts +125 -0
- package/dist/src/types/Passport.d.ts.map +1 -0
- package/dist/src/types/Passport.js +84 -0
- package/dist/src/types/Passport.js.map +1 -0
- package/dist/src/types/Quantity.d.ts +99 -0
- package/dist/src/types/Quantity.d.ts.map +1 -0
- package/dist/src/types/Quantity.js +24 -0
- package/dist/src/types/Quantity.js.map +1 -0
- package/dist/src/types/Reference.d.ts +2 -0
- package/dist/src/types/Reference.d.ts.map +1 -1
- package/dist/src/types/ReferenceMaterial.d.ts +53 -0
- package/dist/src/types/ReferenceMaterial.d.ts.map +1 -0
- package/dist/src/types/ReferenceMaterial.js +14 -0
- package/dist/src/types/ReferenceMaterial.js.map +1 -0
- package/dist/src/types/Requirement.d.ts +111 -0
- package/dist/src/types/Requirement.d.ts.map +1 -0
- package/dist/src/types/Requirement.js +10 -0
- package/dist/src/types/Requirement.js.map +1 -0
- package/dist/src/types/Role.d.ts +4 -0
- package/dist/src/types/Role.d.ts.map +1 -1
- package/dist/src/types/Series.d.ts +31 -0
- package/dist/src/types/Series.d.ts.map +1 -0
- package/dist/src/types/Series.js +14 -0
- package/dist/src/types/Series.js.map +1 -0
- package/dist/src/types/SourceDiscrepancy.d.ts +21 -0
- package/dist/src/types/SourceDiscrepancy.d.ts.map +1 -0
- package/dist/src/types/SourceDiscrepancy.js +13 -0
- package/dist/src/types/SourceDiscrepancy.js.map +1 -0
- package/dist/src/types/Standard.d.ts +68 -0
- package/dist/src/types/Standard.d.ts.map +1 -1
- package/dist/src/types/StateMachine.d.ts +43 -0
- package/dist/src/types/StateMachine.d.ts.map +1 -1
- package/dist/src/types/StateMachine.js +7 -0
- package/dist/src/types/StateMachine.js.map +1 -1
- package/dist/src/types/Subject.d.ts +432 -0
- package/dist/src/types/Subject.d.ts.map +1 -0
- package/dist/src/types/Subject.js +13 -0
- package/dist/src/types/Subject.js.map +1 -0
- package/dist/src/types/Symbol.d.ts +31 -1
- package/dist/src/types/Symbol.d.ts.map +1 -1
- package/dist/src/types/Table.d.ts +43 -0
- package/dist/src/types/Table.d.ts.map +1 -1
- package/dist/src/types/Term.d.ts +29 -0
- package/dist/src/types/Term.d.ts.map +1 -1
- package/dist/src/types/TestPointSet.d.ts +33 -0
- package/dist/src/types/TestPointSet.d.ts.map +1 -0
- package/dist/src/types/TestPointSet.js +11 -0
- package/dist/src/types/TestPointSet.js.map +1 -0
- package/dist/src/types/TestSequence.d.ts +105 -0
- package/dist/src/types/TestSequence.d.ts.map +1 -0
- package/dist/src/types/TestSequence.js +65 -0
- package/dist/src/types/TestSequence.js.map +1 -0
- package/dist/src/types/Text.d.ts +21 -0
- package/dist/src/types/Text.d.ts.map +1 -0
- package/dist/src/types/Text.js +38 -0
- package/dist/src/types/Text.js.map +1 -0
- package/dist/src/types/Time.d.ts +43 -0
- package/dist/src/types/Time.d.ts.map +1 -0
- package/dist/src/types/Time.js +14 -0
- package/dist/src/types/Time.js.map +1 -0
- package/dist/src/types/Twin.d.ts +155 -0
- package/dist/src/types/Twin.d.ts.map +1 -0
- package/dist/src/types/Twin.js +102 -0
- package/dist/src/types/Twin.js.map +1 -0
- package/dist/src/types/Verdict.d.ts +40 -0
- package/dist/src/types/Verdict.d.ts.map +1 -0
- package/dist/src/types/Verdict.js +14 -0
- package/dist/src/types/Verdict.js.map +1 -0
- package/dist/src/types/ViewProfile.d.ts +6 -0
- package/dist/src/types/ViewProfile.d.ts.map +1 -1
- package/dist/src/types/data.d.ts +27 -0
- package/dist/src/types/data.d.ts.map +1 -1
- package/dist/src/types/process.d.ts +231 -0
- package/dist/src/types/process.d.ts.map +1 -1
- package/dist-browser/index.mjs +6699 -661
- package/dist-cli/primmel.mjs +21462 -0
- package/package.json +61 -5
|
@@ -0,0 +1,914 @@
|
|
|
1
|
+
"use strict";
|
|
2
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
3
|
+
// Model diff (TODO.roadmap/28; doctrine ch. 13 §13.2–§13.3): the ONE
|
|
4
|
+
// structural diff the core owes lifecycle management. Not a text diff of
|
|
5
|
+
// PRL files — a diff of MODEL ELEMENTS, keyed by stable id (never file
|
|
6
|
+
// position), classified by tier, powering three consumers:
|
|
7
|
+
//
|
|
8
|
+
// 1. edition comparison — "what changed between R 60:2017 and
|
|
9
|
+
// R 60:2021?" answered in model terms (formatDiffReport);
|
|
10
|
+
// 2. change audit — the diff between any two states of one
|
|
11
|
+
// package is the audit trail (working tree vs baseline, baseline vs
|
|
12
|
+
// baseline — the CLI takes two directories);
|
|
13
|
+
// 3. clause-drift detection — the provenance edges of shared elements
|
|
14
|
+
// whose source clause moved between editions light up as a table
|
|
15
|
+
// (the R 60:2017→2021 renumbering made machine-visible).
|
|
16
|
+
//
|
|
17
|
+
// Two properties make the diff trustworthy (§13.2):
|
|
18
|
+
// - id-keyed, not position-keyed: renaming a file or reordering the
|
|
19
|
+
// declaration list is not a model change;
|
|
20
|
+
// - tier-annotated: every change reports its tier (chapter 1), so an
|
|
21
|
+
// edition review reads "secondary: 3 requirements changed limits"
|
|
22
|
+
// instead of "47 files touched".
|
|
23
|
+
//
|
|
24
|
+
// The change kinds (§13.2): added / removed / changed (classified by
|
|
25
|
+
// WHAT changed: anchor / statement / binding / limit / applicability /
|
|
26
|
+
// structure / provenance) / moved (same id, ONLY the anchor changed — a
|
|
27
|
+
// re-anchored binds_to, e.g. model.parameters → model.software). The
|
|
28
|
+
// anchor aspect holds ONLY location fields (bindsTo / parent / targets);
|
|
29
|
+
// binding-surface CONTENT (a calculation's input/output signature, a
|
|
30
|
+
// requirement's subjects/channel) classifies as `changed — binding`,
|
|
31
|
+
// never moved — §13.2's moved is "same id, different anchor or
|
|
32
|
+
// location", and a signature is neither. The four sets partition the
|
|
33
|
+
// element space (§13.7): an id is added, removed, or shared; a shared id
|
|
34
|
+
// is unchanged, moved, or changed.
|
|
35
|
+
//
|
|
36
|
+
// Provenance is edition-normalized: a source ref
|
|
37
|
+
// `urn:oiml:pub:r:60-2:2021 # clause-2.10.4` compares on its doc BASIS
|
|
38
|
+
// (the URN with the edition segment stripped) + clause, so the expected
|
|
39
|
+
// edition re-citation (2017 → 2021 at an unchanged clause) is NOT a
|
|
40
|
+
// model change, while a clause move IS — and feeds the clause-drift
|
|
41
|
+
// table.
|
|
42
|
+
//
|
|
43
|
+
// The mapping diff is first-class (mappings are first-class, ch. 5):
|
|
44
|
+
// pairs added/removed, description/justification changes, and the
|
|
45
|
+
// coverage delta — a reference component dropping from full to partial
|
|
46
|
+
// cover is a COMPUTED finding (the coverage calculus), never an authored
|
|
47
|
+
// one (§13.7).
|
|
48
|
+
//
|
|
49
|
+
// Pure module: no fs. Loading package directories (plus their .prm files
|
|
50
|
+
// and sources-prd payloads) lives in package-diff.ts; the CLI in
|
|
51
|
+
// scripts/check.mts (`primmel diff`) wires both.
|
|
52
|
+
// ─────────────────────────────────────────────────────────────────────
|
|
53
|
+
Object.defineProperty(exports, "__esModule", { value: true });
|
|
54
|
+
exports.TIER_BY_FIELD = exports.TIER_ORDER = void 0;
|
|
55
|
+
exports.canonical = canonical;
|
|
56
|
+
exports.normalizeSourceRef = normalizeSourceRef;
|
|
57
|
+
exports.elementIndex = elementIndex;
|
|
58
|
+
exports.clauseTextKey = clauseTextKey;
|
|
59
|
+
exports.diffStandards = diffStandards;
|
|
60
|
+
exports.formatDiffReport = formatDiffReport;
|
|
61
|
+
const mapping_coverage_1 = require("./mapping-coverage");
|
|
62
|
+
exports.TIER_ORDER = [
|
|
63
|
+
'foundations',
|
|
64
|
+
'primary',
|
|
65
|
+
'secondary',
|
|
66
|
+
'tertiary',
|
|
67
|
+
'cross-cutting',
|
|
68
|
+
];
|
|
69
|
+
/**
|
|
70
|
+
* The tier of every diffable Standard collection (chapter 1's table):
|
|
71
|
+
* foundations = what everything references (vocabulary, parties, units,
|
|
72
|
+
* registers); primary = the subject and its aspects (the instrument
|
|
73
|
+
* chain, attributes, behaviors, conditions, instances, duals, artifacts);
|
|
74
|
+
* secondary = models ANCHORED to primary aspect paths (requirements,
|
|
75
|
+
* tests, forms, verdict quantities, tables of limits); tertiary =
|
|
76
|
+
* execution and judgment (processes, entities, registries, state
|
|
77
|
+
* machines, approvals, monitors, passports); cross-cutting = annotation
|
|
78
|
+
* and traceability furniture (notes, invariants, test sequences,
|
|
79
|
+
* formulas-used traces, links).
|
|
80
|
+
*
|
|
81
|
+
* mapProfiles are deliberately ABSENT: mappings are not tiered elements
|
|
82
|
+
* — the mapping diff owns them (pairs + coverage delta).
|
|
83
|
+
*/
|
|
84
|
+
exports.TIER_BY_FIELD = {
|
|
85
|
+
terms: 'foundations',
|
|
86
|
+
references: 'foundations',
|
|
87
|
+
roles: 'foundations',
|
|
88
|
+
quantityRegisters: 'foundations',
|
|
89
|
+
enums: 'foundations',
|
|
90
|
+
variables: 'foundations',
|
|
91
|
+
figures: 'foundations',
|
|
92
|
+
activityArchetypes: 'foundations',
|
|
93
|
+
connectorProfiles: 'foundations',
|
|
94
|
+
subjects: 'primary',
|
|
95
|
+
instruments: 'primary',
|
|
96
|
+
attributeDefinitions: 'primary',
|
|
97
|
+
capabilities: 'primary',
|
|
98
|
+
behaviors: 'primary',
|
|
99
|
+
conditionSets: 'primary',
|
|
100
|
+
instances: 'primary',
|
|
101
|
+
duals: 'primary',
|
|
102
|
+
artifactDefinitions: 'primary',
|
|
103
|
+
artifactInstances: 'primary',
|
|
104
|
+
requirements: 'secondary',
|
|
105
|
+
requirementClasses: 'secondary',
|
|
106
|
+
conformanceTests: 'secondary',
|
|
107
|
+
conformanceClasses: 'secondary',
|
|
108
|
+
forms: 'secondary',
|
|
109
|
+
subforms: 'secondary',
|
|
110
|
+
symbols: 'secondary',
|
|
111
|
+
calculations: 'secondary',
|
|
112
|
+
verdicts: 'secondary',
|
|
113
|
+
tables: 'secondary',
|
|
114
|
+
testPointSets: 'secondary',
|
|
115
|
+
referenceMaterials: 'secondary',
|
|
116
|
+
processes: 'tertiary',
|
|
117
|
+
pages: 'tertiary',
|
|
118
|
+
dataclasses: 'tertiary',
|
|
119
|
+
regs: 'tertiary',
|
|
120
|
+
gateways: 'tertiary',
|
|
121
|
+
events: 'tertiary',
|
|
122
|
+
approvals: 'tertiary',
|
|
123
|
+
stateMachines: 'tertiary',
|
|
124
|
+
monitors: 'tertiary',
|
|
125
|
+
// Passports (TODO.roadmap/35) are tertiary beside monitors: the
|
|
126
|
+
// twin-wave serving machinery — a monitor is continuous judgment, a
|
|
127
|
+
// passport is continuous serving (§14.6: "served by the endpoint,
|
|
128
|
+
// verified through the engine").
|
|
129
|
+
passports: 'tertiary',
|
|
130
|
+
viewProfiles: 'tertiary',
|
|
131
|
+
provisions: 'tertiary',
|
|
132
|
+
notes: 'cross-cutting',
|
|
133
|
+
// Invariants (smart gap-close E9) are cross-cutting beside notes: the
|
|
134
|
+
// typed replacement for the note-family encoding — doctrine about the
|
|
135
|
+
// model, not machinery inside it (the enforcement claims point at the
|
|
136
|
+
// gates/linker rules that execute; the invariant itself declares).
|
|
137
|
+
invariants: 'cross-cutting',
|
|
138
|
+
// Test sequences (smart gap-close E10) are cross-cutting beside
|
|
139
|
+
// invariants: a required ordering is doctrine about how the
|
|
140
|
+
// conformance tests must run on a sample, not a test itself — the
|
|
141
|
+
// steps reference the tests; the sequence itself declares.
|
|
142
|
+
testSequences: 'cross-cutting',
|
|
143
|
+
// Formulas-used traces (smart gap-close E11) are cross-cutting beside
|
|
144
|
+
// test sequences: a trace is doctrine about which registry formulas a
|
|
145
|
+
// conformance test's evaluation invokes, not a test itself — the
|
|
146
|
+
// entry references the test and the formulas; the trace itself
|
|
147
|
+
// declares.
|
|
148
|
+
formulasUsed: 'cross-cutting',
|
|
149
|
+
links: 'cross-cutting',
|
|
150
|
+
// Text content sets (TODO.roadmap/25 + smart gap-close E13; TODO.v2/12)
|
|
151
|
+
// are cross-cutting beside notes: an alternate spelling is annotation
|
|
152
|
+
// — a translation never changes what the model demands. The id is the
|
|
153
|
+
// full nested address (<element-id>.<path…>.<field>); the diff matches
|
|
154
|
+
// on it whole.
|
|
155
|
+
texts: 'cross-cutting',
|
|
156
|
+
};
|
|
157
|
+
// ── canonical content ────────────────────────────────────────────────
|
|
158
|
+
/**
|
|
159
|
+
* Deterministic serialization: sorted object keys, arrays in declared
|
|
160
|
+
* order (within-element order is significant — procedure steps and
|
|
161
|
+
* applicability entries are meaningful sequences), `_`-prefixed keys
|
|
162
|
+
* (resolver internals) dropped, shared resolved references guarded
|
|
163
|
+
* against cycles.
|
|
164
|
+
*/
|
|
165
|
+
function canonical(value) {
|
|
166
|
+
const stack = [];
|
|
167
|
+
const ser = (v) => {
|
|
168
|
+
if (v === undefined) {
|
|
169
|
+
return 'null';
|
|
170
|
+
}
|
|
171
|
+
if (v === null || typeof v !== 'object') {
|
|
172
|
+
return JSON.stringify(v) ?? 'null';
|
|
173
|
+
}
|
|
174
|
+
if (Array.isArray(v)) {
|
|
175
|
+
return '[' + v.map(ser).join(',') + ']';
|
|
176
|
+
}
|
|
177
|
+
if (stack.includes(v)) {
|
|
178
|
+
return '"[Circular]"';
|
|
179
|
+
}
|
|
180
|
+
stack.push(v);
|
|
181
|
+
const keys = Object.keys(v)
|
|
182
|
+
.filter(k => !k.startsWith('_'))
|
|
183
|
+
.sort();
|
|
184
|
+
const out = '{' +
|
|
185
|
+
keys
|
|
186
|
+
.map(k => JSON.stringify(k) + ':' + ser(v[k]))
|
|
187
|
+
.join(',') +
|
|
188
|
+
'}';
|
|
189
|
+
stack.pop();
|
|
190
|
+
return out;
|
|
191
|
+
};
|
|
192
|
+
return ser(value);
|
|
193
|
+
}
|
|
194
|
+
const DOC_FRAGMENT = /#([^#]*)$/;
|
|
195
|
+
/**
|
|
196
|
+
* Normalize a source ref onto its doc basis: `urn:oiml:pub:r:60-2:2021`
|
|
197
|
+
* → basis `urn:oiml:pub:r:60-2`, edition `2021`. A `#fragment` suffix on
|
|
198
|
+
* the doc moves into the fragment slot. The trailing segment counts as an
|
|
199
|
+
* edition when it is all digits (the OIML URN convention
|
|
200
|
+
* `urn:oiml:pub:<doc>:<year>`); other URNs compare whole.
|
|
201
|
+
*/
|
|
202
|
+
function normalizeSourceRef(doc, clause, fragment = '') {
|
|
203
|
+
let rest = doc ?? '';
|
|
204
|
+
let frag = fragment ?? '';
|
|
205
|
+
const hash = DOC_FRAGMENT.exec(rest);
|
|
206
|
+
if (hash) {
|
|
207
|
+
rest = rest.slice(0, hash.index);
|
|
208
|
+
if (!frag) {
|
|
209
|
+
frag = hash[1];
|
|
210
|
+
}
|
|
211
|
+
}
|
|
212
|
+
const colon = rest.lastIndexOf(':');
|
|
213
|
+
let basis = rest;
|
|
214
|
+
let edition = '';
|
|
215
|
+
if (colon >= 0) {
|
|
216
|
+
const tail = rest.slice(colon + 1);
|
|
217
|
+
if (/^\d+$/.test(tail)) {
|
|
218
|
+
basis = rest.slice(0, colon);
|
|
219
|
+
edition = tail;
|
|
220
|
+
}
|
|
221
|
+
}
|
|
222
|
+
return { basis, edition, clause: clause ?? '', fragment: frag };
|
|
223
|
+
}
|
|
224
|
+
const PROVENANCE_FIELDS = ['source', 'sourceRef', 'sourceRefs'];
|
|
225
|
+
/**
|
|
226
|
+
* Aspect classification per kind: which fields answer "WHAT changed".
|
|
227
|
+
* The ANCHOR aspect holds only location fields — a change to nothing
|
|
228
|
+
* but these is a MOVE (§13.2: "same id, different anchor or location").
|
|
229
|
+
* The BINDING aspect holds binding-surface CONTENT (a calculation's
|
|
230
|
+
* input/output signature, a requirement's subject slots and channel) —
|
|
231
|
+
* a change there is `changed — binding`, never moved. Kinds without a
|
|
232
|
+
* spec use the generic scheme — statement (the narrative fields
|
|
233
|
+
* present), anchor (the anchor fields present), provenance, structure
|
|
234
|
+
* (everything else). Text content sets are the one per-ENTRY scheme
|
|
235
|
+
* (TODO.v2/12): one aspect per spelling code (`spelling:<code>`), so a
|
|
236
|
+
* spelling added/removed or a value changed names its entry, never the
|
|
237
|
+
* whole set.
|
|
238
|
+
*/
|
|
239
|
+
const ASPECT_SPECS = {
|
|
240
|
+
requirements: {
|
|
241
|
+
statement: ['name', 'statement', 'guidance'],
|
|
242
|
+
anchor: ['bindsTo'],
|
|
243
|
+
binding: ['subjects', 'channel'],
|
|
244
|
+
limit: ['limit', 'acceptanceCriteria'],
|
|
245
|
+
applicability: ['applicability'],
|
|
246
|
+
},
|
|
247
|
+
conformanceTests: {
|
|
248
|
+
statement: ['name', 'purpose', 'method', 'guidance'],
|
|
249
|
+
anchor: ['targets', 'bindsTo'],
|
|
250
|
+
binding: ['testSubject', 'conditionsToEnforce'],
|
|
251
|
+
limit: [
|
|
252
|
+
'acceptanceCriteria',
|
|
253
|
+
'acceptanceCriteriaType',
|
|
254
|
+
'acceptanceCriteriaDescription',
|
|
255
|
+
'acceptancePassIf',
|
|
256
|
+
'acceptance',
|
|
257
|
+
'preconditions',
|
|
258
|
+
],
|
|
259
|
+
applicability: ['applicability'],
|
|
260
|
+
},
|
|
261
|
+
calculations: {
|
|
262
|
+
statement: ['name', 'label', 'description'],
|
|
263
|
+
// inputs/output/params are the SIGNATURE (§13.2 `changed` territory)
|
|
264
|
+
// — a calculation has no anchor, so it can never report moved.
|
|
265
|
+
binding: ['inputs', 'output', 'params'],
|
|
266
|
+
limit: ['expression', 'ruleType', 'lookup', 'profile'],
|
|
267
|
+
},
|
|
268
|
+
};
|
|
269
|
+
/** Generic statement fields (first present wins the aspect). */
|
|
270
|
+
const GENERIC_STATEMENT = [
|
|
271
|
+
'name',
|
|
272
|
+
'label',
|
|
273
|
+
'title',
|
|
274
|
+
'description',
|
|
275
|
+
'definition',
|
|
276
|
+
'statement',
|
|
277
|
+
'purpose',
|
|
278
|
+
'text',
|
|
279
|
+
];
|
|
280
|
+
/**
|
|
281
|
+
* Generic anchor fields — a change to one of these, and ONLY these,
|
|
282
|
+
* classifies the element as MOVED (re-anchored / relocated), not changed.
|
|
283
|
+
*/
|
|
284
|
+
const GENERIC_ANCHOR = [
|
|
285
|
+
'parent',
|
|
286
|
+
'bindsTo',
|
|
287
|
+
'targets',
|
|
288
|
+
'conformanceProcessId',
|
|
289
|
+
'conformanceProcessIds',
|
|
290
|
+
];
|
|
291
|
+
function provenanceOf(el) {
|
|
292
|
+
const out = [];
|
|
293
|
+
const push = (r) => {
|
|
294
|
+
if (r && typeof r === 'object' && (r.doc || r.clause)) {
|
|
295
|
+
out.push(normalizeSourceRef(r.doc ?? '', r.clause ?? '', r.fragment));
|
|
296
|
+
}
|
|
297
|
+
};
|
|
298
|
+
push(el.source);
|
|
299
|
+
push(el.sourceRef);
|
|
300
|
+
for (const r of el.sourceRefs ?? []) {
|
|
301
|
+
push(r);
|
|
302
|
+
}
|
|
303
|
+
// A conformance test's `reference` field holds the raw doc URN of its
|
|
304
|
+
// structured reference block (v2) — edition and all. It duplicates the
|
|
305
|
+
// structured edge; treat it as provenance so the expected edition
|
|
306
|
+
// re-citation stays invisible (the legacy free-string form — not
|
|
307
|
+
// urn-shaped — stays in structure, where it diffs as content).
|
|
308
|
+
const refString = el.reference;
|
|
309
|
+
if (typeof refString === 'string' && refString.startsWith('urn:')) {
|
|
310
|
+
push({ doc: refString, clause: '' });
|
|
311
|
+
}
|
|
312
|
+
// De-duplicate identical edges ON THE COMPARABLE FORM (edition-stripped
|
|
313
|
+
// — the YAML→PRL emission repeats the headline `reference:` as a source
|
|
314
|
+
// entry; one edge, not two).
|
|
315
|
+
const seen = new Set();
|
|
316
|
+
return out.filter(r => {
|
|
317
|
+
const k = provenanceEdgeKey(r);
|
|
318
|
+
if (seen.has(k)) {
|
|
319
|
+
return false;
|
|
320
|
+
}
|
|
321
|
+
seen.add(k);
|
|
322
|
+
return true;
|
|
323
|
+
});
|
|
324
|
+
}
|
|
325
|
+
/**
|
|
326
|
+
* The comparable form of a provenance edge: basis + clause + fragment,
|
|
327
|
+
* EDITION-STRIPPED. The expected edition re-citation (2017 → 2021 at an
|
|
328
|
+
* unchanged clause) is not a model change; a clause move is.
|
|
329
|
+
*/
|
|
330
|
+
function provenanceEdgeKey(r) {
|
|
331
|
+
return canonical({ basis: r.basis, clause: r.clause, fragment: r.fragment });
|
|
332
|
+
}
|
|
333
|
+
function elementOf(field, el) {
|
|
334
|
+
// `id` everywhere except the state machines, which key by the bound
|
|
335
|
+
// entity's name (the construct declares entityName, no id).
|
|
336
|
+
const id = String(el.id ?? el.entityName ?? '');
|
|
337
|
+
const tier = exports.TIER_BY_FIELD[field] ?? 'cross-cutting';
|
|
338
|
+
const provenance = provenanceOf(el);
|
|
339
|
+
const consumed = new Set(PROVENANCE_FIELDS);
|
|
340
|
+
// The urn-shaped `reference` string was lifted into provenance — do not
|
|
341
|
+
// diff its raw (edition-carrying) form again in structure.
|
|
342
|
+
if (typeof el.reference === 'string' && el.reference.startsWith('urn:')) {
|
|
343
|
+
consumed.add('reference');
|
|
344
|
+
}
|
|
345
|
+
const aspects = {};
|
|
346
|
+
const spec = ASPECT_SPECS[field];
|
|
347
|
+
const pick = (fields) => {
|
|
348
|
+
const out = {};
|
|
349
|
+
for (const f of fields) {
|
|
350
|
+
if (el[f] !== undefined) {
|
|
351
|
+
out[f] = el[f];
|
|
352
|
+
consumed.add(f);
|
|
353
|
+
}
|
|
354
|
+
}
|
|
355
|
+
return out;
|
|
356
|
+
};
|
|
357
|
+
if (spec) {
|
|
358
|
+
for (const [aspect, fields] of Object.entries(spec)) {
|
|
359
|
+
const picked = pick(fields ?? []);
|
|
360
|
+
if (Object.keys(picked).length > 0) {
|
|
361
|
+
aspects[aspect] = canonical(picked);
|
|
362
|
+
}
|
|
363
|
+
}
|
|
364
|
+
}
|
|
365
|
+
else if (field === 'texts') {
|
|
366
|
+
// Content sets diff PER SPELLING ENTRY (TODO.v2/12): one aspect per
|
|
367
|
+
// spelling code — a spelling added/removed or a value changed names
|
|
368
|
+
// its entry (`spelling:<code>`), never the whole set. The value AND
|
|
369
|
+
// the conversion provenance (`via`) are the entry's content. A
|
|
370
|
+
// duplicate code within one set is a data error (C89 owns it): the
|
|
371
|
+
// last entry wins the aspect, like a duplicate element id wins its
|
|
372
|
+
// slot.
|
|
373
|
+
consumed.add('entries');
|
|
374
|
+
const entries = el.entries ??
|
|
375
|
+
[];
|
|
376
|
+
for (const e of entries) {
|
|
377
|
+
if (e && typeof e.spelling === 'string') {
|
|
378
|
+
aspects[`spelling:${e.spelling}`] = canonical({
|
|
379
|
+
value: e.value,
|
|
380
|
+
via: e.via,
|
|
381
|
+
});
|
|
382
|
+
}
|
|
383
|
+
}
|
|
384
|
+
}
|
|
385
|
+
else {
|
|
386
|
+
const statement = pick(GENERIC_STATEMENT);
|
|
387
|
+
if (Object.keys(statement).length > 0) {
|
|
388
|
+
aspects.statement = canonical(statement);
|
|
389
|
+
}
|
|
390
|
+
const anchor = pick(GENERIC_ANCHOR);
|
|
391
|
+
if (Object.keys(anchor).length > 0) {
|
|
392
|
+
aspects.anchor = canonical(anchor);
|
|
393
|
+
}
|
|
394
|
+
}
|
|
395
|
+
if (provenance.length > 0) {
|
|
396
|
+
// The provenance ASPECT compares edges edition-stripped (the expected
|
|
397
|
+
// edition re-citation is invisible to the structural diff); clause
|
|
398
|
+
// moves show up here AND feed the clause-drift table.
|
|
399
|
+
aspects.provenance = canonical(provenance.map(r => ({
|
|
400
|
+
basis: r.basis,
|
|
401
|
+
clause: r.clause,
|
|
402
|
+
fragment: r.fragment,
|
|
403
|
+
})));
|
|
404
|
+
}
|
|
405
|
+
const rest = {};
|
|
406
|
+
for (const [k, v] of Object.entries(el)) {
|
|
407
|
+
if (!consumed.has(k) && k !== 'id') {
|
|
408
|
+
rest[k] = v;
|
|
409
|
+
}
|
|
410
|
+
}
|
|
411
|
+
aspects.structure = canonical(rest);
|
|
412
|
+
return { key: `${field}:${id}`, id, kind: field, tier, aspects, provenance };
|
|
413
|
+
}
|
|
414
|
+
/**
|
|
415
|
+
* The id-keyed element index of a Standard — the diff's normalized input.
|
|
416
|
+
* Renaming a file or reordering declarations leaves the index untouched.
|
|
417
|
+
* A duplicate `kind:id` key is a DATA ERROR (the duplicate-id linter owns
|
|
418
|
+
* it): the last declaration wins the slot, so a diff over an unlinted
|
|
419
|
+
* package with duplicates under-reports. Keys of overwritten duplicates
|
|
420
|
+
* are collected into `duplicates` when given — the caller surfaces them
|
|
421
|
+
* as warnings (diffStandards does).
|
|
422
|
+
*/
|
|
423
|
+
function elementIndex(standard, duplicates) {
|
|
424
|
+
const out = new Map();
|
|
425
|
+
for (const field of Object.keys(exports.TIER_BY_FIELD)) {
|
|
426
|
+
const items = standard[field];
|
|
427
|
+
if (!Array.isArray(items)) {
|
|
428
|
+
continue;
|
|
429
|
+
}
|
|
430
|
+
for (const el of items) {
|
|
431
|
+
// The element id is `id` for every diffable collection except the
|
|
432
|
+
// state machines, whose key is the bound entity's name
|
|
433
|
+
// (`entityName` — the state_machine construct declares no `id`;
|
|
434
|
+
// without this the machines were silently invisible to the diff,
|
|
435
|
+
// cascades and all — smart gap-close E12).
|
|
436
|
+
if (el && typeof el === 'object' && ('id' in el || 'entityName' in el)) {
|
|
437
|
+
const d = elementOf(field, el);
|
|
438
|
+
if (out.has(d.key)) {
|
|
439
|
+
duplicates?.push(d.key);
|
|
440
|
+
}
|
|
441
|
+
out.set(d.key, d);
|
|
442
|
+
}
|
|
443
|
+
}
|
|
444
|
+
}
|
|
445
|
+
return out;
|
|
446
|
+
}
|
|
447
|
+
function clauseTextKey(basis, clause) {
|
|
448
|
+
return `${basis}#${clause}`;
|
|
449
|
+
}
|
|
450
|
+
function packageVersion(m) {
|
|
451
|
+
return m?.version ?? '';
|
|
452
|
+
}
|
|
453
|
+
/** Fold dot-descendants: drop clause c when the set also holds a parent. */
|
|
454
|
+
function foldClauses(clauses) {
|
|
455
|
+
const sorted = [...new Set(clauses)].sort();
|
|
456
|
+
return sorted.filter(c => !sorted.some(p => p !== c && c.startsWith(p + '.')));
|
|
457
|
+
}
|
|
458
|
+
function diffMappings(a, b, options) {
|
|
459
|
+
const recordsA = options.mappingsA ?? (0, mapping_coverage_1.collectMappings)(a);
|
|
460
|
+
const recordsB = options.mappingsB ?? (0, mapping_coverage_1.collectMappings)(b);
|
|
461
|
+
const keyOf = (m) => `${m.sourceModel}#${m.source}⇒${m.target}`;
|
|
462
|
+
const mapA = new Map(recordsA.map(m => [keyOf(m), m]));
|
|
463
|
+
const mapB = new Map(recordsB.map(m => [keyOf(m), m]));
|
|
464
|
+
const added = [];
|
|
465
|
+
const removed = [];
|
|
466
|
+
const changed = [];
|
|
467
|
+
for (const [k, m] of mapB) {
|
|
468
|
+
if (!mapA.has(k)) {
|
|
469
|
+
added.push(m);
|
|
470
|
+
}
|
|
471
|
+
}
|
|
472
|
+
for (const [k, m] of mapA) {
|
|
473
|
+
const other = mapB.get(k);
|
|
474
|
+
if (!other) {
|
|
475
|
+
removed.push(m);
|
|
476
|
+
continue;
|
|
477
|
+
}
|
|
478
|
+
const aspects = [];
|
|
479
|
+
if (m.description !== other.description) {
|
|
480
|
+
aspects.push('description');
|
|
481
|
+
}
|
|
482
|
+
if (m.justification !== other.justification) {
|
|
483
|
+
aspects.push('justification');
|
|
484
|
+
}
|
|
485
|
+
if (aspects.length > 0) {
|
|
486
|
+
changed.push({
|
|
487
|
+
source: m.source,
|
|
488
|
+
sourceModel: m.sourceModel,
|
|
489
|
+
target: m.target,
|
|
490
|
+
aspects,
|
|
491
|
+
});
|
|
492
|
+
}
|
|
493
|
+
}
|
|
494
|
+
// Coverage delta — COMPUTED per target namespace on both sides, never
|
|
495
|
+
// authored (§13.7). The tree is the caller's reference, else the side's
|
|
496
|
+
// own alias forest; a namespace with no tree either side is silent.
|
|
497
|
+
const namespaces = new Set([
|
|
498
|
+
...recordsA.map(m => m.targetModel),
|
|
499
|
+
...recordsB.map(m => m.targetModel),
|
|
500
|
+
]);
|
|
501
|
+
const coverageDelta = [];
|
|
502
|
+
const namespacesSkipped = [];
|
|
503
|
+
for (const ns of [...namespaces].sort()) {
|
|
504
|
+
const forestOf = (std) => {
|
|
505
|
+
const ref = options.references?.[ns];
|
|
506
|
+
if (ref) {
|
|
507
|
+
return ref;
|
|
508
|
+
}
|
|
509
|
+
const forest = (0, mapping_coverage_1.buildProcessTree)(std, { idPrefix: `${ns}#` });
|
|
510
|
+
return forest.length > 0 ? forest : null;
|
|
511
|
+
};
|
|
512
|
+
const treeA = forestOf(a);
|
|
513
|
+
const treeB = forestOf(b);
|
|
514
|
+
if (!treeA && !treeB) {
|
|
515
|
+
namespacesSkipped.push(ns);
|
|
516
|
+
continue;
|
|
517
|
+
}
|
|
518
|
+
const levels = new Map();
|
|
519
|
+
if (treeA) {
|
|
520
|
+
const report = (0, mapping_coverage_1.computeCoverage)(a, treeA, recordsA, ns);
|
|
521
|
+
for (const c of report.components) {
|
|
522
|
+
levels.set(c.id, { from: c.coverage });
|
|
523
|
+
}
|
|
524
|
+
}
|
|
525
|
+
if (treeB) {
|
|
526
|
+
const report = (0, mapping_coverage_1.computeCoverage)(b, treeB, recordsB, ns);
|
|
527
|
+
for (const c of report.components) {
|
|
528
|
+
const row = levels.get(c.id) ?? {};
|
|
529
|
+
row.to = c.coverage;
|
|
530
|
+
levels.set(c.id, row);
|
|
531
|
+
}
|
|
532
|
+
}
|
|
533
|
+
for (const [component, row] of [...levels.entries()].sort()) {
|
|
534
|
+
const from = row.from ?? 'absent';
|
|
535
|
+
const to = row.to ?? 'absent';
|
|
536
|
+
if (from !== to) {
|
|
537
|
+
coverageDelta.push({ namespace: ns, component, from, to });
|
|
538
|
+
}
|
|
539
|
+
}
|
|
540
|
+
}
|
|
541
|
+
return { added, removed, changed, coverageDelta, namespacesSkipped };
|
|
542
|
+
}
|
|
543
|
+
function diffClauseDrift(shared, options) {
|
|
544
|
+
const raw = [];
|
|
545
|
+
for (const [elA, elB] of shared) {
|
|
546
|
+
const bases = new Set([
|
|
547
|
+
...elA.provenance.map(r => r.basis),
|
|
548
|
+
...elB.provenance.map(r => r.basis),
|
|
549
|
+
]);
|
|
550
|
+
for (const basis of [...bases].sort()) {
|
|
551
|
+
const clausesOf = (el) => foldClauses(el.provenance.filter(r => r.basis === basis).map(r => r.clause)).filter(c => c.length > 0);
|
|
552
|
+
const oldC = clausesOf(elA);
|
|
553
|
+
const newC = clausesOf(elB);
|
|
554
|
+
const removedC = oldC.filter(c => !newC.includes(c));
|
|
555
|
+
const addedC = newC.filter(c => !oldC.includes(c));
|
|
556
|
+
if (removedC.length === 0 && addedC.length === 0) {
|
|
557
|
+
continue;
|
|
558
|
+
}
|
|
559
|
+
const entry = {
|
|
560
|
+
key: elA.key,
|
|
561
|
+
id: elA.id,
|
|
562
|
+
kind: elA.kind,
|
|
563
|
+
tier: elA.tier,
|
|
564
|
+
};
|
|
565
|
+
// Deterministic pairing. A clause SPLIT (1:N — the old clause's
|
|
566
|
+
// content landed in several new clauses, the R 60 humidity case)
|
|
567
|
+
// pairs the one old clause with each new one; a MERGE (N:1) pairs
|
|
568
|
+
// each old clause with the one new one; equal counts zip in sorted
|
|
569
|
+
// order; leftovers are de-cited / re-cited rows. The N:N zip is
|
|
570
|
+
// POSITIONAL: crossed multi-renumberings inside one element
|
|
571
|
+
// (2.1 → 3.2 AND 2.2 → 3.1) would mis-pair — no recorded case;
|
|
572
|
+
// the pairing is deterministic and documented.
|
|
573
|
+
if (removedC.length === 1 && addedC.length > 1) {
|
|
574
|
+
for (const c of addedC) {
|
|
575
|
+
raw.push({
|
|
576
|
+
doc: basis,
|
|
577
|
+
from: removedC[0],
|
|
578
|
+
to: c,
|
|
579
|
+
kind: 'renumbered',
|
|
580
|
+
citedBy: entry,
|
|
581
|
+
});
|
|
582
|
+
}
|
|
583
|
+
}
|
|
584
|
+
else if (addedC.length === 1 && removedC.length > 1) {
|
|
585
|
+
for (const c of removedC) {
|
|
586
|
+
raw.push({
|
|
587
|
+
doc: basis,
|
|
588
|
+
from: c,
|
|
589
|
+
to: addedC[0],
|
|
590
|
+
kind: 'renumbered',
|
|
591
|
+
citedBy: entry,
|
|
592
|
+
});
|
|
593
|
+
}
|
|
594
|
+
}
|
|
595
|
+
else {
|
|
596
|
+
const pairs = Math.min(removedC.length, addedC.length);
|
|
597
|
+
for (let i = 0; i < pairs; i++) {
|
|
598
|
+
raw.push({
|
|
599
|
+
doc: basis,
|
|
600
|
+
from: removedC[i],
|
|
601
|
+
to: addedC[i],
|
|
602
|
+
kind: 'renumbered',
|
|
603
|
+
citedBy: entry,
|
|
604
|
+
});
|
|
605
|
+
}
|
|
606
|
+
for (const c of removedC.slice(pairs)) {
|
|
607
|
+
raw.push({
|
|
608
|
+
doc: basis,
|
|
609
|
+
from: c,
|
|
610
|
+
to: '',
|
|
611
|
+
kind: 'decited',
|
|
612
|
+
citedBy: entry,
|
|
613
|
+
});
|
|
614
|
+
}
|
|
615
|
+
for (const c of addedC.slice(pairs)) {
|
|
616
|
+
raw.push({
|
|
617
|
+
doc: basis,
|
|
618
|
+
from: '',
|
|
619
|
+
to: c,
|
|
620
|
+
kind: 'recited',
|
|
621
|
+
citedBy: entry,
|
|
622
|
+
});
|
|
623
|
+
}
|
|
624
|
+
}
|
|
625
|
+
}
|
|
626
|
+
}
|
|
627
|
+
// Aggregate per (doc, from, to): the drift TABLE rows with their
|
|
628
|
+
// citing elements — "2.10.3 → 2.10.4, cited by 2 elements".
|
|
629
|
+
const textOf = (row) => {
|
|
630
|
+
if (row.kind !== 'renumbered' ||
|
|
631
|
+
!options.sentencesA ||
|
|
632
|
+
!options.sentencesB) {
|
|
633
|
+
return 'unavailable';
|
|
634
|
+
}
|
|
635
|
+
const tA = options.sentencesA.get(clauseTextKey(row.doc, row.from));
|
|
636
|
+
const tB = options.sentencesB.get(clauseTextKey(row.doc, row.to));
|
|
637
|
+
if (tA === undefined || tB === undefined) {
|
|
638
|
+
return 'unavailable';
|
|
639
|
+
}
|
|
640
|
+
return tA.replace(/\s+/g, ' ').trim() === tB.replace(/\s+/g, ' ').trim()
|
|
641
|
+
? 'same'
|
|
642
|
+
: 'differed';
|
|
643
|
+
};
|
|
644
|
+
const rows = new Map();
|
|
645
|
+
for (const r of raw) {
|
|
646
|
+
const text = textOf(r);
|
|
647
|
+
const key = `${r.doc}|${r.from}|${r.to}|${r.kind}|${text}`;
|
|
648
|
+
let row = rows.get(key);
|
|
649
|
+
if (!row) {
|
|
650
|
+
row = {
|
|
651
|
+
doc: r.doc,
|
|
652
|
+
from: r.from,
|
|
653
|
+
to: r.to,
|
|
654
|
+
kind: r.kind,
|
|
655
|
+
text,
|
|
656
|
+
citedBy: [],
|
|
657
|
+
};
|
|
658
|
+
rows.set(key, row);
|
|
659
|
+
}
|
|
660
|
+
if (!row.citedBy.some(e => e.key === r.citedBy.key)) {
|
|
661
|
+
row.citedBy.push(r.citedBy);
|
|
662
|
+
}
|
|
663
|
+
}
|
|
664
|
+
return [...rows.values()].sort((x, y) => `${x.doc} ${x.from} ${x.to}`.localeCompare(`${y.doc} ${y.from} ${y.to}`));
|
|
665
|
+
}
|
|
666
|
+
/**
|
|
667
|
+
* The change-report label for one differing aspect. Text content sets
|
|
668
|
+
* carry the per-entry scheme (TODO.v2/12 — `spelling:<code>` aspects):
|
|
669
|
+
* the label names the entry-level change — a spelling added, a spelling
|
|
670
|
+
* removed, a value (or its `via` provenance) changed. Every other kind
|
|
671
|
+
* reports the bare aspect name.
|
|
672
|
+
*/
|
|
673
|
+
function labelAspect(elA, elB, name) {
|
|
674
|
+
if (elA.kind !== 'texts' || !name.startsWith('spelling:')) {
|
|
675
|
+
return name;
|
|
676
|
+
}
|
|
677
|
+
if (!(name in elA.aspects)) {
|
|
678
|
+
return `${name} (added)`;
|
|
679
|
+
}
|
|
680
|
+
if (!(name in elB.aspects)) {
|
|
681
|
+
return `${name} (removed)`;
|
|
682
|
+
}
|
|
683
|
+
return `${name} (changed)`;
|
|
684
|
+
}
|
|
685
|
+
/**
|
|
686
|
+
* The structural model diff between two loaded Standards (§13.2). `a` is
|
|
687
|
+
* the OLD state, `b` the NEW one (edition comparison reads 2017 → 2021).
|
|
688
|
+
*/
|
|
689
|
+
function diffStandards(a, b, options = {}) {
|
|
690
|
+
const duplicatesA = [];
|
|
691
|
+
const duplicatesB = [];
|
|
692
|
+
const indexA = elementIndex(a, duplicatesA);
|
|
693
|
+
const indexB = elementIndex(b, duplicatesB);
|
|
694
|
+
const added = [];
|
|
695
|
+
const removed = [];
|
|
696
|
+
const changed = [];
|
|
697
|
+
const moved = [];
|
|
698
|
+
const shared = [];
|
|
699
|
+
let unchanged = 0;
|
|
700
|
+
const tally = Object.fromEntries(exports.TIER_ORDER.map(t => [
|
|
701
|
+
t,
|
|
702
|
+
{ added: 0, removed: 0, changed: 0, moved: 0, unchanged: 0 },
|
|
703
|
+
]));
|
|
704
|
+
for (const [key, elB] of indexB) {
|
|
705
|
+
if (!indexA.has(key)) {
|
|
706
|
+
added.push({ key, id: elB.id, kind: elB.kind, tier: elB.tier });
|
|
707
|
+
tally[elB.tier].added++;
|
|
708
|
+
}
|
|
709
|
+
}
|
|
710
|
+
for (const [key, elA] of indexA) {
|
|
711
|
+
const elB = indexB.get(key);
|
|
712
|
+
if (!elB) {
|
|
713
|
+
removed.push({ key, id: elA.id, kind: elA.kind, tier: elA.tier });
|
|
714
|
+
tally[elA.tier].removed++;
|
|
715
|
+
continue;
|
|
716
|
+
}
|
|
717
|
+
shared.push([elA, elB]);
|
|
718
|
+
const aspects = new Set([
|
|
719
|
+
...Object.keys(elA.aspects),
|
|
720
|
+
...Object.keys(elB.aspects),
|
|
721
|
+
]);
|
|
722
|
+
const differing = [...aspects].filter(name => (elA.aspects[name] ?? '<absent>') !== (elB.aspects[name] ?? '<absent>'));
|
|
723
|
+
if (differing.length === 0) {
|
|
724
|
+
unchanged++;
|
|
725
|
+
tally[elA.tier].unchanged++;
|
|
726
|
+
}
|
|
727
|
+
else if (differing.every(name => name === 'anchor')) {
|
|
728
|
+
// MOVED — same id, only the anchor changed (§13.2): a requirement
|
|
729
|
+
// re-anchored to a corrected aspect path, a process re-parented.
|
|
730
|
+
// Binding-surface CONTENT (a signature, subject slots, a channel)
|
|
731
|
+
// is `changed — binding`, never a move.
|
|
732
|
+
moved.push({
|
|
733
|
+
key,
|
|
734
|
+
id: elA.id,
|
|
735
|
+
kind: elA.kind,
|
|
736
|
+
tier: elA.tier,
|
|
737
|
+
from: elA.aspects.anchor ?? '',
|
|
738
|
+
to: elB.aspects.anchor ?? '',
|
|
739
|
+
});
|
|
740
|
+
tally[elA.tier].moved++;
|
|
741
|
+
}
|
|
742
|
+
else {
|
|
743
|
+
changed.push({
|
|
744
|
+
key,
|
|
745
|
+
id: elA.id,
|
|
746
|
+
kind: elA.kind,
|
|
747
|
+
tier: elA.tier,
|
|
748
|
+
aspects: differing.map(name => labelAspect(elA, elB, name)).sort(),
|
|
749
|
+
});
|
|
750
|
+
tally[elA.tier].changed++;
|
|
751
|
+
}
|
|
752
|
+
}
|
|
753
|
+
const mappings = diffMappings(a, b, options);
|
|
754
|
+
const clauseDrift = diffClauseDrift(shared, options);
|
|
755
|
+
const empty = added.length === 0 &&
|
|
756
|
+
removed.length === 0 &&
|
|
757
|
+
changed.length === 0 &&
|
|
758
|
+
moved.length === 0 &&
|
|
759
|
+
mappings.added.length === 0 &&
|
|
760
|
+
mappings.removed.length === 0 &&
|
|
761
|
+
mappings.changed.length === 0 &&
|
|
762
|
+
mappings.coverageDelta.length === 0 &&
|
|
763
|
+
clauseDrift.length === 0;
|
|
764
|
+
const mA = a.packageManifest;
|
|
765
|
+
const mB = b.packageManifest;
|
|
766
|
+
const aLabel = options.aLabel ?? (mA?.id ? `${mA.id}@${packageVersion(mA) || '?'}` : 'a');
|
|
767
|
+
const bLabel = options.bLabel ?? (mB?.id ? `${mB.id}@${packageVersion(mB) || '?'}` : 'b');
|
|
768
|
+
const editionComparison = !!mA?.id && mA.id === mB?.id && packageVersion(mA) !== packageVersion(mB);
|
|
769
|
+
// Duplicate kind:id keys are a data error (the duplicate-id linter owns
|
|
770
|
+
// them) — but a diff over an UNLINTED package must not stay silent: the
|
|
771
|
+
// last declaration won the slot, so the diff under-reports that side.
|
|
772
|
+
const dupWarning = (label, key) => `${label}: duplicate element ${key} — the last declaration wins (a data error the duplicate-id linter owns); this side under-reports`;
|
|
773
|
+
const warnings = [
|
|
774
|
+
...duplicatesA.map(k => dupWarning(aLabel, k)),
|
|
775
|
+
...duplicatesB.map(k => dupWarning(bLabel, k)),
|
|
776
|
+
];
|
|
777
|
+
return {
|
|
778
|
+
aLabel,
|
|
779
|
+
bLabel,
|
|
780
|
+
editionComparison,
|
|
781
|
+
aVersion: packageVersion(mA),
|
|
782
|
+
bVersion: packageVersion(mB),
|
|
783
|
+
added: added.sort((x, y) => x.key.localeCompare(y.key)),
|
|
784
|
+
removed: removed.sort((x, y) => x.key.localeCompare(y.key)),
|
|
785
|
+
changed: changed.sort((x, y) => x.key.localeCompare(y.key)),
|
|
786
|
+
moved: moved.sort((x, y) => x.key.localeCompare(y.key)),
|
|
787
|
+
unchanged,
|
|
788
|
+
byTier: tally,
|
|
789
|
+
mappings,
|
|
790
|
+
clauseDrift,
|
|
791
|
+
warnings,
|
|
792
|
+
empty,
|
|
793
|
+
};
|
|
794
|
+
}
|
|
795
|
+
// ── the edition-comparison report ────────────────────────────────────
|
|
796
|
+
function fmtEntry(e) {
|
|
797
|
+
return `[${e.tier}/${e.kind}] ${e.id}`;
|
|
798
|
+
}
|
|
799
|
+
/**
|
|
800
|
+
* Compact rendering of a moved element's anchor change: one line per
|
|
801
|
+
* DIFFERING anchor field (`bindsTo: ["a"] → ["b"]`), never the
|
|
802
|
+
* whole-aspect JSON dump. Falls back to the raw from/to pair when the
|
|
803
|
+
* aspect is not the field-object form the engine emits.
|
|
804
|
+
*/
|
|
805
|
+
function formatAnchorChange(from, to) {
|
|
806
|
+
try {
|
|
807
|
+
const a = (from ? JSON.parse(from) : {});
|
|
808
|
+
const b = (to ? JSON.parse(to) : {});
|
|
809
|
+
const fields = [...new Set([...Object.keys(a), ...Object.keys(b)])].sort();
|
|
810
|
+
const lines = fields
|
|
811
|
+
.filter(f => canonical(a[f]) !== canonical(b[f]))
|
|
812
|
+
.map(f => `${f}: ${canonical(a[f])} → ${canonical(b[f])}`);
|
|
813
|
+
if (lines.length > 0) {
|
|
814
|
+
return lines;
|
|
815
|
+
}
|
|
816
|
+
}
|
|
817
|
+
catch {
|
|
818
|
+
// Not the field-object form — fall through to the raw rendering.
|
|
819
|
+
}
|
|
820
|
+
return [`from ${from}`, `to ${to}`];
|
|
821
|
+
}
|
|
822
|
+
/**
|
|
823
|
+
* The human-readable change summary between two package states — the
|
|
824
|
+
* edition-comparison report (§13.3.1): tier-annotated tallies, the
|
|
825
|
+
* added/removed/changed/moved lists with classified aspects, the mapping
|
|
826
|
+
* diff with its computed coverage delta, and the clause-drift table
|
|
827
|
+
* (renumbered clauses, re-cited provisions) — the R 60:2017→2021
|
|
828
|
+
* renumbering made machine-visible.
|
|
829
|
+
*/
|
|
830
|
+
function formatDiffReport(diff) {
|
|
831
|
+
const lines = [];
|
|
832
|
+
const heading = diff.editionComparison
|
|
833
|
+
? `edition comparison — ${diff.aLabel} → ${diff.bLabel}`
|
|
834
|
+
: `model diff — ${diff.aLabel} → ${diff.bLabel}`;
|
|
835
|
+
lines.push(`primmel diff: ${heading}`);
|
|
836
|
+
lines.push('');
|
|
837
|
+
lines.push(`elements: +${diff.added.length} -${diff.removed.length} ` +
|
|
838
|
+
`~${diff.changed.length} >${diff.moved.length} ` +
|
|
839
|
+
`(${diff.unchanged} unchanged)`);
|
|
840
|
+
lines.push('');
|
|
841
|
+
lines.push('by tier: added removed changed moved unchanged');
|
|
842
|
+
for (const tier of exports.TIER_ORDER) {
|
|
843
|
+
const t = diff.byTier[tier];
|
|
844
|
+
lines.push(` ${tier.padEnd(13)} ${String(t.added).padStart(5)} ${String(t.removed).padStart(8)} ${String(t.changed).padStart(8)} ${String(t.moved).padStart(6)} ${String(t.unchanged).padStart(9)}`);
|
|
845
|
+
}
|
|
846
|
+
if (diff.added.length > 0) {
|
|
847
|
+
lines.push('', 'added:');
|
|
848
|
+
for (const e of diff.added) {
|
|
849
|
+
lines.push(` + ${fmtEntry(e)}`);
|
|
850
|
+
}
|
|
851
|
+
}
|
|
852
|
+
if (diff.removed.length > 0) {
|
|
853
|
+
lines.push('', 'removed:');
|
|
854
|
+
for (const e of diff.removed) {
|
|
855
|
+
lines.push(` - ${fmtEntry(e)}`);
|
|
856
|
+
}
|
|
857
|
+
}
|
|
858
|
+
if (diff.changed.length > 0) {
|
|
859
|
+
lines.push('', 'changed:');
|
|
860
|
+
for (const e of diff.changed) {
|
|
861
|
+
lines.push(` ~ ${fmtEntry(e)} — ${e.aspects.join(', ')}`);
|
|
862
|
+
}
|
|
863
|
+
}
|
|
864
|
+
if (diff.moved.length > 0) {
|
|
865
|
+
lines.push('', 'moved (re-anchored):');
|
|
866
|
+
for (const e of diff.moved) {
|
|
867
|
+
lines.push(` > ${fmtEntry(e)}`);
|
|
868
|
+
for (const l of formatAnchorChange(e.from, e.to)) {
|
|
869
|
+
lines.push(` ${l}`);
|
|
870
|
+
}
|
|
871
|
+
}
|
|
872
|
+
}
|
|
873
|
+
if (diff.warnings.length > 0) {
|
|
874
|
+
lines.push('', 'warnings:');
|
|
875
|
+
for (const w of diff.warnings) {
|
|
876
|
+
lines.push(` ${w}`);
|
|
877
|
+
}
|
|
878
|
+
}
|
|
879
|
+
const m = diff.mappings;
|
|
880
|
+
lines.push('');
|
|
881
|
+
lines.push(`mappings: +${m.added.length} -${m.removed.length} ~${m.changed.length} pairs` +
|
|
882
|
+
(m.coverageDelta.length > 0
|
|
883
|
+
? `, ${m.coverageDelta.length} coverage deltas`
|
|
884
|
+
: '') +
|
|
885
|
+
(m.namespacesSkipped.length > 0
|
|
886
|
+
? ` (coverage silent for ${m.namespacesSkipped.join(', ')} — no reference tree)`
|
|
887
|
+
: ''));
|
|
888
|
+
for (const r of m.added) {
|
|
889
|
+
lines.push(` + ${r.sourceModel}#${r.source} ⇒ ${r.target}`);
|
|
890
|
+
}
|
|
891
|
+
for (const r of m.removed) {
|
|
892
|
+
lines.push(` - ${r.sourceModel}#${r.source} ⇒ ${r.target}`);
|
|
893
|
+
}
|
|
894
|
+
for (const c of m.changed) {
|
|
895
|
+
lines.push(` ~ ${c.sourceModel}#${c.source} ⇒ ${c.target} — ${c.aspects.join(', ')}`);
|
|
896
|
+
}
|
|
897
|
+
for (const d of m.coverageDelta) {
|
|
898
|
+
lines.push(` coverage ${d.namespace}#${d.component}: ${d.from} → ${d.to}`);
|
|
899
|
+
}
|
|
900
|
+
lines.push('');
|
|
901
|
+
if (diff.clauseDrift.length === 0) {
|
|
902
|
+
lines.push('clause drift: none');
|
|
903
|
+
}
|
|
904
|
+
else {
|
|
905
|
+
lines.push('clause drift:');
|
|
906
|
+
lines.push(` ${'doc'.padEnd(26)} ${'clause (old)'.padEnd(13)} ${'clause (new)'.padEnd(13)} ${'kind'.padEnd(10)} ${'text'.padEnd(11)} cited by`);
|
|
907
|
+
for (const r of diff.clauseDrift) {
|
|
908
|
+
const cited = r.citedBy.map(e => e.id).join(', ');
|
|
909
|
+
lines.push(` ${r.doc.padEnd(26)} ${(r.from || '—').padEnd(13)} ${(r.to || '—').padEnd(13)} ${r.kind.padEnd(10)} ${r.text.padEnd(11)} ${cited}`);
|
|
910
|
+
}
|
|
911
|
+
}
|
|
912
|
+
return lines.join('\n');
|
|
913
|
+
}
|
|
914
|
+
//# sourceMappingURL=model-diff.js.map
|