dsh-logicprobe 0.9.0 → 1.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 (63) hide show
  1. package/README.en-US.md +79 -14
  2. package/README.md +79 -14
  3. package/lib/baseline.js +142 -0
  4. package/lib/client.js +56 -1
  5. package/lib/compose-tool.js +1 -1
  6. package/lib/concurrency.js +14 -0
  7. package/lib/data-engine.js +42 -8
  8. package/lib/engine.js +379 -79
  9. package/lib/export-tool.js +27 -2
  10. package/lib/granularity.js +237 -0
  11. package/lib/index.js +63 -41
  12. package/lib/report-diff-tool.js +39 -0
  13. package/lib/structure-tool.js +64 -0
  14. package/lib/structure.js +648 -0
  15. package/lib/tool.js +3 -3
  16. package/lib/types/baseline.d.ts +69 -0
  17. package/lib/types/concurrency.d.ts +10 -0
  18. package/lib/types/data-engine.d.ts +13 -1
  19. package/lib/types/engine.d.ts +138 -1
  20. package/lib/types/granularity.d.ts +106 -0
  21. package/lib/types/index.d.ts +9 -8
  22. package/lib/types/report-diff-tool.d.ts +8 -0
  23. package/lib/types/structure-tool.d.ts +10 -0
  24. package/lib/types/structure.d.ts +156 -0
  25. package/lib/types/tool.d.ts +2 -2
  26. package/lib/types/uml.d.ts +89 -0
  27. package/lib/uml-tool.js +36 -7
  28. package/lib/uml.js +217 -23
  29. package/locale/en.json +6 -0
  30. package/locale/zh.json +6 -0
  31. package/package.json +16 -14
  32. package/skills/logicprobe/SKILL.md +84 -58
  33. package/skills/logicprobe/references/dsh-model-schema.md +81 -10
  34. package/skills/logicprobe/references/gap-routing-guide.md +37 -36
  35. package/skills/logicprobe/references/hash-spec.md +128 -0
  36. package/skills/logicprobe/references/logic-verification-guide.md +27 -250
  37. package/skills/logicprobe-concurrency/SKILL.md +43 -0
  38. package/skills/{logicprobe → logicprobe-concurrency}/references/concurrency-risk-guide.md +1 -1
  39. package/skills/logicprobe-datamodel/SKILL.md +5 -4
  40. package/skills/logicprobe-datamodel/references/data-model-guide.md +1 -1
  41. package/skills/logicprobe-datamodel/references/data-model-schema.md +1 -1
  42. package/skills/logicprobe-structure/SKILL.md +95 -0
  43. package/skills/logicprobe-structure/references/structure-review-guide.md +177 -0
  44. package/skills/logicprobe-uml/SKILL.md +55 -0
  45. package/skills/{logicprobe → logicprobe-uml}/references/uml-modeling-guide.md +120 -8
  46. package/src/baseline.ts +180 -0
  47. package/src/client.js +56 -1
  48. package/src/compose-tool.ts +47 -47
  49. package/src/concurrency.ts +23 -0
  50. package/src/data-engine.ts +51 -9
  51. package/src/engine.ts +441 -67
  52. package/src/export-tool.ts +73 -48
  53. package/src/granularity.ts +312 -0
  54. package/src/index.ts +63 -41
  55. package/src/report-diff-tool.ts +43 -0
  56. package/src/structure-tool.ts +68 -0
  57. package/src/structure.ts +724 -0
  58. package/src/tool.ts +3 -3
  59. package/src/uml-tool.ts +38 -8
  60. package/src/uml.ts +275 -24
  61. package/skills/logicprobe/references/logicprobe-engine.py +0 -4943
  62. package/skills/logicprobe/references/verification-harness.py +0 -959
  63. package/skills/logicprobe-datamodel/references/data-model-harness.py +0 -528
@@ -1,4 +1,5 @@
1
1
  import { createHash } from 'node:crypto';
2
+ import { REPORT_SCHEMAS, verdictOfFindings } from './engine.js';
2
3
  export const DATA_ENGINE_SCHEMA_VERSION = 1;
3
4
  const KNOWN_TYPES = new Set([
4
5
  'string', 'integer', 'number', 'boolean', 'uuid', 'date', 'datetime', 'timestamp',
@@ -847,18 +848,25 @@ function buildDataComparisonSummary(before, after, options) {
847
848
  export function runDataVerification(input, options = {}) {
848
849
  const validation = validateDataModel(input);
849
850
  if (!validation.ok) {
851
+ const findings = validation.errors.map((message) => ({ code: 'DATA_MODEL_INVALID', severity: 'error', message }));
852
+ const modelCheck = {
853
+ id: 'DATA_MODEL',
854
+ name: 'Data Model Validation',
855
+ status: 'fail',
856
+ detail: 'Data model schema validation failed: ' + validation.errors.length + ' errors',
857
+ findings,
858
+ };
850
859
  return {
851
860
  ok: false,
861
+ ran: true,
862
+ ...verdictOfFindings(findings),
863
+ schema: REPORT_SCHEMAS.datamodel,
852
864
  schemaVersion: 1,
853
865
  modelHash: '',
866
+ hashes: { modelHash: '' },
854
867
  summary: { entities: 0, fields: 0, errors: validation.errors.length, warnings: 0, checksRun: 0 },
855
- checks: [{
856
- id: 'DATA_MODEL',
857
- name: 'Data Model Validation',
858
- status: 'fail',
859
- detail: 'Data model schema validation failed: ' + validation.errors.length + ' errors',
860
- findings: validation.errors.map((message) => ({ code: 'DATA_MODEL_INVALID', severity: 'error', message })),
861
- }],
868
+ checks: [modelCheck],
869
+ nextSteps: dataNextSteps([modelCheck]),
862
870
  };
863
871
  }
864
872
  const model = validation.model;
@@ -884,10 +892,15 @@ export function runDataVerification(input, options = {}) {
884
892
  if (options.beforeModel !== undefined) {
885
893
  const beforeValidation = validateDataModel(options.beforeModel);
886
894
  if (!beforeValidation.ok) {
895
+ const beforeFindings = beforeValidation.errors.map((message) => ({ code: 'BEFORE_DATA_MODEL_INVALID', severity: 'error', message }));
887
896
  return {
888
897
  ok: false,
898
+ ran: true,
899
+ ...verdictOfFindings([...checks.flatMap((check) => check.findings), ...beforeFindings]),
900
+ schema: REPORT_SCHEMAS.datamodel,
889
901
  schemaVersion: 1,
890
902
  modelHash: dataModelHash(model),
903
+ hashes: { modelHash: dataModelHash(model) },
891
904
  summary: {
892
905
  entities: model.entities.length,
893
906
  fields: allFieldPaths(model).length,
@@ -902,9 +915,10 @@ export function runDataVerification(input, options = {}) {
902
915
  name: 'Before Data Model Validation',
903
916
  status: 'fail',
904
917
  detail: 'Before data model schema validation failed: ' + beforeValidation.errors.length + ' errors',
905
- findings: beforeValidation.errors.map((message) => ({ code: 'BEFORE_DATA_MODEL_INVALID', severity: 'error', message })),
918
+ findings: beforeFindings,
906
919
  },
907
920
  ],
921
+ nextSteps: dataNextSteps(checks),
908
922
  };
909
923
  }
910
924
  const before = beforeValidation.model;
@@ -915,8 +929,12 @@ export function runDataVerification(input, options = {}) {
915
929
  const warnings = checks.reduce((sum, check) => sum + check.findings.filter((finding) => finding.severity === 'warning').length, 0);
916
930
  return {
917
931
  ok: true,
932
+ ran: true,
933
+ ...verdictOfFindings(checks.flatMap((check) => check.findings)),
934
+ schema: REPORT_SCHEMAS.datamodel,
918
935
  schemaVersion: 1,
919
936
  modelHash: dataModelHash(model),
937
+ hashes: { modelHash: dataModelHash(model) },
920
938
  summary: {
921
939
  entities: model.entities.length,
922
940
  fields: allFieldPaths(model).length,
@@ -925,6 +943,22 @@ export function runDataVerification(input, options = {}) {
925
943
  checksRun: checks.length,
926
944
  },
927
945
  checks,
946
+ nextSteps: dataNextSteps(checks),
928
947
  ...(comparison === undefined ? {} : { comparison }),
929
948
  };
930
949
  }
950
+ /**
951
+ * The next-steps list every data report carries, derived only from the checks so two
952
+ * runs over the same model produce the same list.
953
+ */
954
+ function dataNextSteps(checks) {
955
+ const steps = [];
956
+ const failed = checks.filter((check) => check.status === 'fail').map((check) => check.id + ' ' + check.name);
957
+ const warningCodes = [...new Set(checks.flatMap((check) => check.findings).filter((finding) => finding.severity === 'warning').map((finding) => finding.code))].sort();
958
+ if (failed.length > 0)
959
+ steps.push('Resolve the failing checks first: ' + failed.join(', ') + '.');
960
+ if (warningCodes.length > 0)
961
+ steps.push('Review the warning findings (' + warningCodes.join(', ') + '): a nullable field or a missing index is a decision, not silence.');
962
+ steps.push('Re-run with beforeModel plus the mapping/copy/migration options after the change to prove the data behaviour did not regress (DD1-DD4).');
963
+ return steps;
964
+ }