domainforge 0.13.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 (481) hide show
  1. package/.cargo/config.toml +6 -0
  2. package/.claude/settings.local.json +18 -0
  3. package/.coderabbit.yml +43 -0
  4. package/.codex/skills/release-management/SKILL.md +151 -0
  5. package/.codex/skills/release-management/agents/openai.yaml +4 -0
  6. package/.github/actions/decrypt-secrets/action.yml +121 -0
  7. package/.github/agents/Coder.agent.md +97 -0
  8. package/.github/agents/DeepResearch.agent.md +61 -0
  9. package/.github/chatmodes/tdd.vibepro.chatmode.md +1183 -0
  10. package/.github/copilot-instructions.md +13 -0
  11. package/.github/dependabot.yml +68 -0
  12. package/.github/workflows/README.md +165 -0
  13. package/.github/workflows/ci.yml +335 -0
  14. package/.github/workflows/dependabot-automerge.yml +114 -0
  15. package/.github/workflows/dependency-review.yml +27 -0
  16. package/.github/workflows/deploy.yml +87 -0
  17. package/.github/workflows/prepare-release.yml +168 -0
  18. package/.github/workflows/release-crates.yml +42 -0
  19. package/.github/workflows/release-npm.yml +137 -0
  20. package/.github/workflows/release-please.yml +29 -0
  21. package/.github/workflows/release-pypi.yml +96 -0
  22. package/.gitkeep +1 -0
  23. package/.release-please-manifest.json +5 -0
  24. package/.sea-registry.toml +10 -0
  25. package/.serena/project.yml +133 -0
  26. package/.sops.yaml +10 -0
  27. package/AGENTS.md +216 -0
  28. package/CHANGELOG.md +400 -0
  29. package/CLAUDE.md +62 -0
  30. package/CONTRIBUTING.md +323 -0
  31. package/Cargo.lock +3612 -0
  32. package/Cargo.toml +12 -0
  33. package/LICENSE +201 -0
  34. package/README.md +660 -0
  35. package/README_PYTHON.md +256 -0
  36. package/README_TYPESCRIPT.md +305 -0
  37. package/README_WASM.md +329 -0
  38. package/RELEASE_NOTES.md +41 -0
  39. package/bun.lock +378 -0
  40. package/bunfig.toml +11 -0
  41. package/check_output.txt +83 -0
  42. package/clippy_output.txt +80 -0
  43. package/commitlint.config.cjs +8 -0
  44. package/deny.toml +42 -0
  45. package/devbox.json +14 -0
  46. package/devbox.lock +76 -0
  47. package/docs/RELEASE_PROCESS.md +360 -0
  48. package/docs/diagnostics.md +161 -0
  49. package/docs/doc_guidelines.md +53 -0
  50. package/docs/explanations/README.md +21 -0
  51. package/docs/explanations/architecture-overview.md +109 -0
  52. package/docs/explanations/cross-language-binding-strategy.md +68 -0
  53. package/docs/explanations/graph-store-design.md +47 -0
  54. package/docs/explanations/performance-benchmarks.md +63 -0
  55. package/docs/explanations/policy-evaluation-logic.md +106 -0
  56. package/docs/explanations/semantic-modeling-concepts.md +109 -0
  57. package/docs/explanations/three-valued-logic.md +66 -0
  58. package/docs/explanations/versioning-strategy.md +45 -0
  59. package/docs/governance.md +168 -0
  60. package/docs/how-tos/README.md +46 -0
  61. package/docs/how-tos/ci-cd-validation.md +93 -0
  62. package/docs/how-tos/create-custom-units.md +125 -0
  63. package/docs/how-tos/define-policies.md +119 -0
  64. package/docs/how-tos/export-to-calm.md +110 -0
  65. package/docs/how-tos/export-to-protobuf.md +312 -0
  66. package/docs/how-tos/extend-grammar.md +133 -0
  67. package/docs/how-tos/generate-rdf-turtle.md +106 -0
  68. package/docs/how-tos/import-from-calm.md +114 -0
  69. package/docs/how-tos/import-from-sbvr.md +249 -0
  70. package/docs/how-tos/install-cli.md +126 -0
  71. package/docs/how-tos/parse-sea-files.md +132 -0
  72. package/docs/how-tos/policy-evaluation-modes.md +30 -0
  73. package/docs/how-tos/run-cross-language-tests.md +115 -0
  74. package/docs/how-tos/troubleshoot-napi-builds.md +55 -0
  75. package/docs/how-tos/use-modules-imports.md +285 -0
  76. package/docs/index.md +13 -0
  77. package/docs/plans/canonical-normalizer.md +121 -0
  78. package/docs/plans/cd_improvement.md +112 -0
  79. package/docs/plans/cli-ast.md +29 -0
  80. package/docs/plans/expression-bindings-and-normalizer-integration.md +174 -0
  81. package/docs/plans/protobuf_advanced_features_plan.md +597 -0
  82. package/docs/plans/protobuf_plan.yml +525 -0
  83. package/docs/plans/refactor_dsl_architecture.md +131 -0
  84. package/docs/plans/release-plan.md +163 -0
  85. package/docs/plans/sea_fmt_implementation_plan.md +516 -0
  86. package/docs/playbooks/README.md +18 -0
  87. package/docs/playbooks/adding-new-primitive.md +68 -0
  88. package/docs/playbooks/debugging-parser-failures.md +42 -0
  89. package/docs/playbooks/local-release-preparation.md +139 -0
  90. package/docs/playbooks/migrating-schema-versions.md +43 -0
  91. package/docs/playbooks/onboarding-contributors.md +64 -0
  92. package/docs/playbooks/releasing-beta.md +86 -0
  93. package/docs/playbooks/secret-management.md +64 -0
  94. package/docs/reference/README.md +199 -0
  95. package/docs/reference/ast-json-api.md +427 -0
  96. package/docs/reference/calm-mapping.md +519 -0
  97. package/docs/reference/cli-commands.md +588 -0
  98. package/docs/reference/configuration.md +202 -0
  99. package/docs/reference/error-codes.md +664 -0
  100. package/docs/reference/generated-artifacts-policy.md +53 -0
  101. package/docs/reference/grammar-spec.md +255 -0
  102. package/docs/reference/primitives-api.md +317 -0
  103. package/docs/reference/protobuf-api.md +426 -0
  104. package/docs/reference/python-api.md +485 -0
  105. package/docs/reference/registry.md +50 -0
  106. package/docs/reference/sea-dsl-ai-cheatsheet.yaml +913 -0
  107. package/docs/reference/security-model.md +74 -0
  108. package/docs/reference/typescript-api.md +508 -0
  109. package/docs/reference/wasm-api.md +420 -0
  110. package/docs/semantic-pack-review.md +144 -0
  111. package/docs/semantic-pack-signing.md +234 -0
  112. package/docs/semantic-packs.md +284 -0
  113. package/docs/specs/ADR-001-sea-dsl-semantic-source-of-truth.md +33 -0
  114. package/docs/specs/ADR-002-projection-first-class-construct.md +50 -0
  115. package/docs/specs/ADR-003-protobuf-projection-target.md +51 -0
  116. package/docs/specs/ADR-004-projection-compatibility-semantics.md +57 -0
  117. package/docs/specs/ADR-005-multi-language-support-strategy.md +112 -0
  118. package/docs/specs/ADR-006-error-handling-strategy.md +115 -0
  119. package/docs/specs/ADR-007-policy-evaluation-engine.md +95 -0
  120. package/docs/specs/ADR-008-knowledge-graph-integration.md +90 -0
  121. package/docs/specs/ADR-009-module-resolution-strategy.md +115 -0
  122. package/docs/specs/ADR-010-unit-system.md +106 -0
  123. package/docs/specs/PRD-001-sea-projection-framework.md +155 -0
  124. package/docs/specs/PRD-002-sea-cli-tooling.md +169 -0
  125. package/docs/specs/PRD-003-dsl-core-capabilities.md +275 -0
  126. package/docs/specs/README.md +62 -0
  127. package/docs/specs/SDS-001-protobuf-projection-engine.md +451 -0
  128. package/docs/specs/SDS-002-sea-core-architecture.md +268 -0
  129. package/docs/specs/SDS-003-parser-semantic-graph.md +377 -0
  130. package/docs/specs/SDS-004-policy-engine-design.md +362 -0
  131. package/docs/specs/SDS-005-knowledge-graph-module.md +364 -0
  132. package/docs/specs/SDS-006-calm-integration.md +367 -0
  133. package/docs/specs/SDS-007-sbvr-import.md +347 -0
  134. package/docs/templates/template_explanation.md +14 -0
  135. package/docs/templates/template_howto.md +21 -0
  136. package/docs/templates/template_playbook.md +21 -0
  137. package/docs/templates/template_reference.md +17 -0
  138. package/docs/templates/template_tutorial.md +24 -0
  139. package/docs/tutorials/README.md +12 -0
  140. package/docs/tutorials/first-sea-model.md +85 -0
  141. package/docs/tutorials/getting-started.md +98 -0
  142. package/docs/tutorials/python-binding-quickstart.md +107 -0
  143. package/docs/tutorials/typescript-binding-quickstart.md +91 -0
  144. package/docs/tutorials/wasm-in-browser.md +75 -0
  145. package/domainforge-core/CHANGELOG.md +138 -0
  146. package/domainforge-core/Cargo.toml +101 -0
  147. package/domainforge-core/MIGRATING.md +32 -0
  148. package/domainforge-core/README.md +197 -0
  149. package/domainforge-core/benchmark_results.txt +51 -0
  150. package/domainforge-core/build.rs +6 -0
  151. package/domainforge-core/deny.toml +31 -0
  152. package/domainforge-core/docs/specs/projections/sbvr_kg_mapping.md +43 -0
  153. package/domainforge-core/examples/basic.sea +7 -0
  154. package/domainforge-core/examples/cli/import_export_workflow.sh +38 -0
  155. package/domainforge-core/examples/cli/validate_example.sh +30 -0
  156. package/domainforge-core/examples/evolution_semantics.sea +31 -0
  157. package/domainforge-core/examples/parser_demo.rs +203 -0
  158. package/domainforge-core/grammar/sea.pest +408 -0
  159. package/domainforge-core/schemas/calm-v1.schema.json +170 -0
  160. package/domainforge-core/schemas/shacl/sea_shapes.ttl +19 -0
  161. package/domainforge-core/src/authority/compiler.rs +309 -0
  162. package/domainforge-core/src/authority/environment.rs +203 -0
  163. package/domainforge-core/src/authority/error.rs +164 -0
  164. package/domainforge-core/src/authority/fact_resolver.rs +224 -0
  165. package/domainforge-core/src/authority/mod.rs +25 -0
  166. package/domainforge-core/src/authority/pack.rs +133 -0
  167. package/domainforge-core/src/authority/policy.rs +224 -0
  168. package/domainforge-core/src/authority/resolver.rs +446 -0
  169. package/domainforge-core/src/authority/trace.rs +217 -0
  170. package/domainforge-core/src/authority/transform.rs +168 -0
  171. package/domainforge-core/src/authority/types.rs +617 -0
  172. package/domainforge-core/src/bin/domainforge.rs +25 -0
  173. package/domainforge-core/src/calm/export.rs +538 -0
  174. package/domainforge-core/src/calm/import.rs +1220 -0
  175. package/domainforge-core/src/calm/mod.rs +9 -0
  176. package/domainforge-core/src/calm/models.rs +108 -0
  177. package/domainforge-core/src/calm/sbvr_import.rs +9 -0
  178. package/domainforge-core/src/cli/authority.rs +149 -0
  179. package/domainforge-core/src/cli/format.rs +85 -0
  180. package/domainforge-core/src/cli/import.rs +133 -0
  181. package/domainforge-core/src/cli/mod.rs +64 -0
  182. package/domainforge-core/src/cli/normalize.rs +180 -0
  183. package/domainforge-core/src/cli/pack.rs +904 -0
  184. package/domainforge-core/src/cli/parse.rs +112 -0
  185. package/domainforge-core/src/cli/project.rs +294 -0
  186. package/domainforge-core/src/cli/registry.rs +41 -0
  187. package/domainforge-core/src/cli/test.rs +12 -0
  188. package/domainforge-core/src/cli/validate.rs +195 -0
  189. package/domainforge-core/src/cli/validate_kg.rs +80 -0
  190. package/domainforge-core/src/concept_id.rs +89 -0
  191. package/domainforge-core/src/error/diagnostics.rs +426 -0
  192. package/domainforge-core/src/error/fuzzy.rs +253 -0
  193. package/domainforge-core/src/error/mod.rs +13 -0
  194. package/domainforge-core/src/formatter/comments.rs +223 -0
  195. package/domainforge-core/src/formatter/config.rs +114 -0
  196. package/domainforge-core/src/formatter/mod.rs +22 -0
  197. package/domainforge-core/src/formatter/printer.rs +906 -0
  198. package/domainforge-core/src/graph/mod.rs +858 -0
  199. package/domainforge-core/src/graph/to_ast.rs +66 -0
  200. package/domainforge-core/src/kg.rs +1476 -0
  201. package/domainforge-core/src/kg_import.rs +251 -0
  202. package/domainforge-core/src/lib.rs +203 -0
  203. package/domainforge-core/src/module/mod.rs +1 -0
  204. package/domainforge-core/src/module/resolver.rs +260 -0
  205. package/domainforge-core/src/parser/ast.rs +2919 -0
  206. package/domainforge-core/src/parser/ast_convert.rs +494 -0
  207. package/domainforge-core/src/parser/ast_schema.rs +491 -0
  208. package/domainforge-core/src/parser/error.rs +291 -0
  209. package/domainforge-core/src/parser/lint.rs +39 -0
  210. package/domainforge-core/src/parser/mod.rs +193 -0
  211. package/domainforge-core/src/parser/printer.rs +702 -0
  212. package/domainforge-core/src/parser/profiles.rs +71 -0
  213. package/domainforge-core/src/parser/string_utils.rs +138 -0
  214. package/domainforge-core/src/patterns.rs +68 -0
  215. package/domainforge-core/src/policy/core.rs +1148 -0
  216. package/domainforge-core/src/policy/expression.rs +399 -0
  217. package/domainforge-core/src/policy/mod.rs +18 -0
  218. package/domainforge-core/src/policy/normalize.rs +1028 -0
  219. package/domainforge-core/src/policy/quantifier.rs +940 -0
  220. package/domainforge-core/src/policy/three_valued.rs +140 -0
  221. package/domainforge-core/src/policy/three_valued_microbench.rs +104 -0
  222. package/domainforge-core/src/policy/type_inference.rs +67 -0
  223. package/domainforge-core/src/policy/violation.rs +36 -0
  224. package/domainforge-core/src/primitives/concept_change.rs +61 -0
  225. package/domainforge-core/src/primitives/entity.rs +224 -0
  226. package/domainforge-core/src/primitives/flow.rs +111 -0
  227. package/domainforge-core/src/primitives/instance.rs +93 -0
  228. package/domainforge-core/src/primitives/mapping_contract.rs +50 -0
  229. package/domainforge-core/src/primitives/metric.rs +79 -0
  230. package/domainforge-core/src/primitives/mod.rs +25 -0
  231. package/domainforge-core/src/primitives/projection_contract.rs +50 -0
  232. package/domainforge-core/src/primitives/quantity.rs +56 -0
  233. package/domainforge-core/src/primitives/relation.rs +68 -0
  234. package/domainforge-core/src/primitives/resource.rs +237 -0
  235. package/domainforge-core/src/primitives/resource_instance.rs +88 -0
  236. package/domainforge-core/src/primitives/role.rs +49 -0
  237. package/domainforge-core/src/projection/buf.rs +404 -0
  238. package/domainforge-core/src/projection/contracts.rs +22 -0
  239. package/domainforge-core/src/projection/engine.rs +19 -0
  240. package/domainforge-core/src/projection/mod.rs +16 -0
  241. package/domainforge-core/src/projection/protobuf.rs +3331 -0
  242. package/domainforge-core/src/projection/registry.rs +43 -0
  243. package/domainforge-core/src/python/authority.rs +253 -0
  244. package/domainforge-core/src/python/error.rs +227 -0
  245. package/domainforge-core/src/python/formatter.rs +86 -0
  246. package/domainforge-core/src/python/graph.rs +366 -0
  247. package/domainforge-core/src/python/mod.rs +9 -0
  248. package/domainforge-core/src/python/policy.rs +651 -0
  249. package/domainforge-core/src/python/primitives.rs +796 -0
  250. package/domainforge-core/src/python/registry.rs +98 -0
  251. package/domainforge-core/src/python/semantic_pack.rs +619 -0
  252. package/domainforge-core/src/python/units.rs +96 -0
  253. package/domainforge-core/src/registry/mod.rs +432 -0
  254. package/domainforge-core/src/registry/tests.rs +210 -0
  255. package/domainforge-core/src/sbvr.rs +744 -0
  256. package/domainforge-core/src/semantic_pack/builder.rs +470 -0
  257. package/domainforge-core/src/semantic_pack/canonical_json.rs +184 -0
  258. package/domainforge-core/src/semantic_pack/diagnostics.rs +214 -0
  259. package/domainforge-core/src/semantic_pack/diff.rs +216 -0
  260. package/domainforge-core/src/semantic_pack/mod.rs +31 -0
  261. package/domainforge-core/src/semantic_pack/pack_set.rs +240 -0
  262. package/domainforge-core/src/semantic_pack/resolver.rs +437 -0
  263. package/domainforge-core/src/semantic_pack/review.rs +125 -0
  264. package/domainforge-core/src/semantic_pack/schema.rs +342 -0
  265. package/domainforge-core/src/semantic_pack/signing.rs +105 -0
  266. package/domainforge-core/src/semantic_pack/validator.rs +368 -0
  267. package/domainforge-core/src/semantic_version.rs +140 -0
  268. package/domainforge-core/src/test_utils.rs +12 -0
  269. package/domainforge-core/src/typescript/authority.rs +184 -0
  270. package/domainforge-core/src/typescript/error.rs +146 -0
  271. package/domainforge-core/src/typescript/formatter.rs +76 -0
  272. package/domainforge-core/src/typescript/graph.rs +391 -0
  273. package/domainforge-core/src/typescript/mod.rs +9 -0
  274. package/domainforge-core/src/typescript/policy.rs +564 -0
  275. package/domainforge-core/src/typescript/primitives.rs +784 -0
  276. package/domainforge-core/src/typescript/registry.rs +88 -0
  277. package/domainforge-core/src/typescript/semantic_pack.rs +470 -0
  278. package/domainforge-core/src/typescript/units.rs +76 -0
  279. package/domainforge-core/src/units/mod.rs +462 -0
  280. package/domainforge-core/src/uuid_module.rs +42 -0
  281. package/domainforge-core/src/validation_error.rs +818 -0
  282. package/domainforge-core/src/validation_result.rs +30 -0
  283. package/domainforge-core/src/wasm/authority.rs +192 -0
  284. package/domainforge-core/src/wasm/error.rs +145 -0
  285. package/domainforge-core/src/wasm/formatter.rs +69 -0
  286. package/domainforge-core/src/wasm/graph.rs +471 -0
  287. package/domainforge-core/src/wasm/mod.rs +16 -0
  288. package/domainforge-core/src/wasm/policy.rs +607 -0
  289. package/domainforge-core/src/wasm/primitives.rs +295 -0
  290. package/domainforge-core/src/wasm/semantic_pack.rs +471 -0
  291. package/domainforge-core/src/wasm/units.rs +62 -0
  292. package/domainforge-core/std/aws.sea +6 -0
  293. package/domainforge-core/std/core.sea +6 -0
  294. package/domainforge-core/std/http.sea +27 -0
  295. package/domainforge-core/tests/aggregation_enhanced_tests.rs +162 -0
  296. package/domainforge-core/tests/aggregation_eval_tests.rs +248 -0
  297. package/domainforge-core/tests/aggregation_integration_tests.rs +379 -0
  298. package/domainforge-core/tests/aggregation_parser_tests.rs +92 -0
  299. package/domainforge-core/tests/aggregation_tests.rs +102 -0
  300. package/domainforge-core/tests/authority_conformance_tests.rs +1173 -0
  301. package/domainforge-core/tests/calm_round_trip_tests.rs +283 -0
  302. package/domainforge-core/tests/calm_schema_validation_tests.rs +137 -0
  303. package/domainforge-core/tests/cast_operator_tests.rs +85 -0
  304. package/domainforge-core/tests/cli_binary_check.rs +37 -0
  305. package/domainforge-core/tests/cli_import_tests.rs +291 -0
  306. package/domainforge-core/tests/cli_path_traversal_tests.rs +124 -0
  307. package/domainforge-core/tests/cli_tests.rs +63 -0
  308. package/domainforge-core/tests/diagnostics_tests.rs +203 -0
  309. package/domainforge-core/tests/dimension_unit_tests.rs +80 -0
  310. package/domainforge-core/tests/entity_tests.rs +69 -0
  311. package/domainforge-core/tests/evolution_semantics_tests.rs +157 -0
  312. package/domainforge-core/tests/flow_tests.rs +78 -0
  313. package/domainforge-core/tests/flow_unit_validation_tests.rs +31 -0
  314. package/domainforge-core/tests/graph_integration_tests.rs +218 -0
  315. package/domainforge-core/tests/graph_tests.rs +626 -0
  316. package/domainforge-core/tests/import_parsing_tests.rs +23 -0
  317. package/domainforge-core/tests/instance_integration_tests.rs +98 -0
  318. package/domainforge-core/tests/instance_parsing_tests.rs +58 -0
  319. package/domainforge-core/tests/instance_tests.rs +61 -0
  320. package/domainforge-core/tests/kg_uri_encoding_tests.rs +53 -0
  321. package/domainforge-core/tests/lint_tests.rs +19 -0
  322. package/domainforge-core/tests/metric_tests.rs +143 -0
  323. package/domainforge-core/tests/module_resolution_tests.rs +100 -0
  324. package/domainforge-core/tests/namespace_registry_tests.rs +247 -0
  325. package/domainforge-core/tests/null_handling_tests.rs +26 -0
  326. package/domainforge-core/tests/parser_ast_v3.rs +53 -0
  327. package/domainforge-core/tests/parser_dimension_registry_tests.rs +20 -0
  328. package/domainforge-core/tests/parser_integration_tests.rs +294 -0
  329. package/domainforge-core/tests/parser_metadata_tests.rs +97 -0
  330. package/domainforge-core/tests/parser_resource_domain_only_graph_test.rs +21 -0
  331. package/domainforge-core/tests/parser_resource_limits_tests.rs +122 -0
  332. package/domainforge-core/tests/parser_tests.rs +512 -0
  333. package/domainforge-core/tests/pattern_semantics_tests.rs +87 -0
  334. package/domainforge-core/tests/phase_14_determinism_tests.rs +166 -0
  335. package/domainforge-core/tests/phase_15_validation_error_tests.rs +136 -0
  336. package/domainforge-core/tests/phase_16_unicode_tests.rs +248 -0
  337. package/domainforge-core/tests/phase_17_export_tests.rs +285 -0
  338. package/domainforge-core/tests/phase_17_round_trip_tests.rs +264 -0
  339. package/domainforge-core/tests/policy_tests.rs +635 -0
  340. package/domainforge-core/tests/primitives_integration_tests.rs +151 -0
  341. package/domainforge-core/tests/print_rdf_xml.rs +14 -0
  342. package/domainforge-core/tests/printer_tests.rs +204 -0
  343. package/domainforge-core/tests/profile_tests.rs +35 -0
  344. package/domainforge-core/tests/projection_contracts_tests.rs +154 -0
  345. package/domainforge-core/tests/protobuf_projection_tests.rs +199 -0
  346. package/domainforge-core/tests/quantity_tests.rs +41 -0
  347. package/domainforge-core/tests/rdf_xml_typed_literal_tests.rs +105 -0
  348. package/domainforge-core/tests/registry_schema_tests.rs +33 -0
  349. package/domainforge-core/tests/resource_tests.rs +50 -0
  350. package/domainforge-core/tests/resource_unit_tests.rs +24 -0
  351. package/domainforge-core/tests/roles_relations_tests.rs +61 -0
  352. package/domainforge-core/tests/round_trip_tests.rs +34 -0
  353. package/domainforge-core/tests/runtime_toggle_tests.rs +70 -0
  354. package/domainforge-core/tests/sbvr_fact_schema_tests.rs +60 -0
  355. package/domainforge-core/tests/sbvr_flow_facts_tests.rs +55 -0
  356. package/domainforge-core/tests/sbvr_parsing_tests.rs +53 -0
  357. package/domainforge-core/tests/semantic_pack_alias_resolution.rs +197 -0
  358. package/domainforge-core/tests/semantic_pack_build.rs +302 -0
  359. package/domainforge-core/tests/semantic_pack_consumer_smoke.rs +150 -0
  360. package/domainforge-core/tests/semantic_pack_pack_set.rs +160 -0
  361. package/domainforge-core/tests/semantic_pack_signing.rs +157 -0
  362. package/domainforge-core/tests/semantic_pack_three_valued.rs +250 -0
  363. package/domainforge-core/tests/semantic_pack_validate.rs +196 -0
  364. package/domainforge-core/tests/std_lib_tests.rs +37 -0
  365. package/domainforge-core/tests/temporal_evaluation_tests.rs +159 -0
  366. package/domainforge-core/tests/temporal_semantics_tests.rs +214 -0
  367. package/domainforge-core/tests/three_valued_quantifiers_tests.rs +164 -0
  368. package/domainforge-core/tests/turtle_entity_export_tests.rs +38 -0
  369. package/domainforge-core/tests/turtle_escaping_tests.rs +53 -0
  370. package/domainforge-core/tests/turtle_resource_export_tests.rs +34 -0
  371. package/domainforge-core/tests/type_inference_tests.rs +40 -0
  372. package/domainforge-core/tests/unicode_validation_tests.rs +169 -0
  373. package/domainforge-core/tests/unit_tests.rs +81 -0
  374. package/domainforge-core/tests/validate_tests.rs +38 -0
  375. package/domainforge-core/tests/validation_unit_mismatch_tests.rs +83 -0
  376. package/domainforge-core/tests/wasm_tests.rs +229 -0
  377. package/domainforge-python/CHANGELOG-python.md +12 -0
  378. package/domainforge-python/MIGRATING.md +24 -0
  379. package/domainforge-python/README.md +256 -0
  380. package/domainforge-python/domainforge/__init__.py +95 -0
  381. package/domainforge-python/domainforge/domainforge.pyi +519 -0
  382. package/domainforge-python/pyproject.toml +36 -0
  383. package/domainforge-typescript/CHANGELOG-typescript.md +12 -0
  384. package/domainforge-typescript/LICENSE +201 -0
  385. package/domainforge-typescript/MIGRATING.md +24 -0
  386. package/domainforge-typescript/README.md +305 -0
  387. package/domainforge-typescript/index.d.ts +452 -0
  388. package/domainforge-typescript/index.js +361 -0
  389. package/domainforge-typescript/package.json +60 -0
  390. package/example.js +61 -0
  391. package/examples/browser.html +366 -0
  392. package/examples/namespaces/finance/cashflow.sea +5 -0
  393. package/examples/namespaces/logistics/core.sea +7 -0
  394. package/examples/observability_metrics.sea +38 -0
  395. package/fixtures/semantic_packs/acme_procurement/domain/entities.sea +39 -0
  396. package/fixtures/semantic_packs/acme_procurement/domain/metrics.sea +11 -0
  397. package/fixtures/semantic_packs/acme_procurement/domain/relations.sea +7 -0
  398. package/fixtures/semantic_packs/acme_procurement/domain/resources.sea +9 -0
  399. package/fixtures/semantic_packs/acme_procurement/review/acme.procurement.semantic-review.jsonl +7 -0
  400. package/fixtures/semantic_packs/acme_procurement/tests/ambiguous_vendor_alias.sea +8 -0
  401. package/fixtures/semantic_packs/acme_procurement/tests/deprecated_vendor_alias.sea +8 -0
  402. package/fixtures/semantic_packs/acme_procurement/tests/invalid_relation.sea +3 -0
  403. package/fixtures/semantic_packs/acme_procurement/tests/proposed_concept.sea +8 -0
  404. package/fixtures/semantic_packs/acme_procurement/tests/rejected_concept.sea +8 -0
  405. package/fixtures/semantic_packs/acme_procurement/tests/unit_mismatch.sea +7 -0
  406. package/fixtures/semantic_packs/acme_procurement/tests/unknown_vendor_policy.sea +8 -0
  407. package/fixtures/semantic_packs/acme_procurement/tests/valid_purchase_policy.sea +8 -0
  408. package/index.d.ts +2 -0
  409. package/index.js +8 -0
  410. package/justfile +200 -0
  411. package/lefthook.yml +13 -0
  412. package/lib/validate_native_exports.d.ts +4 -0
  413. package/lib/validate_native_exports.js +12 -0
  414. package/package.json +22 -0
  415. package/pytest.ini +5 -0
  416. package/python/tests/test_registry.py +75 -0
  417. package/python/tests/test_units.py +18 -0
  418. package/release-please-config.json +49 -0
  419. package/requirements-dev.txt +3 -0
  420. package/requirements.txt +3 -0
  421. package/rust-toolchain.toml +3 -0
  422. package/schemas/ast-v1.schema.json +72 -0
  423. package/schemas/ast-v2.schema.json +1200 -0
  424. package/schemas/ast-v3.schema.json +1200 -0
  425. package/schemas/sea-registry.schema.json +45 -0
  426. package/scripts/build-python.sh +37 -0
  427. package/scripts/build-release.sh +279 -0
  428. package/scripts/build-typescript.sh +13 -0
  429. package/scripts/build-wasm.sh +113 -0
  430. package/scripts/bump-version.sh +245 -0
  431. package/scripts/check_unused_test_imports.py +85 -0
  432. package/scripts/ci_tasks.py +379 -0
  433. package/scripts/clear_debug_test.sh +10 -0
  434. package/scripts/create-github-release.sh +262 -0
  435. package/scripts/create-tag.sh +203 -0
  436. package/scripts/find_and_link_test_binary.sh +70 -0
  437. package/scripts/generate-changelog.sh +271 -0
  438. package/scripts/generate-release-notes.sh +205 -0
  439. package/scripts/lint_release_security.py +96 -0
  440. package/scripts/lint_release_workflows.py +82 -0
  441. package/scripts/lint_workflow_gates.py +113 -0
  442. package/scripts/optimized-wasm-build.sh +61 -0
  443. package/scripts/patch_napi_types.py +62 -0
  444. package/scripts/pre-release-check.sh +289 -0
  445. package/scripts/prepare_rust_debug.sh +52 -0
  446. package/scripts/release.sh +373 -0
  447. package/scripts/resolve_rust_binary.py +230 -0
  448. package/scripts/run_commitlint.sh +29 -0
  449. package/scripts/test-all.sh +77 -0
  450. package/scripts/update_launch_program.py +93 -0
  451. package/secrets/README.md +27 -0
  452. package/secrets/secrets.yaml +21 -0
  453. package/test_integration.py +67 -0
  454. package/tests/test_authority.py +328 -0
  455. package/tests/test_ci_tasks.py +143 -0
  456. package/tests/test_expression.py +256 -0
  457. package/tests/test_golden_payment_flow.py +42 -0
  458. package/tests/test_graph.py +127 -0
  459. package/tests/test_instance.py +136 -0
  460. package/tests/test_parser.py +82 -0
  461. package/tests/test_primitives.py +68 -0
  462. package/tests/test_role_relation_parity.py +56 -0
  463. package/tests/test_runtime_toggle.py +156 -0
  464. package/tests/test_semantic_pack.py +639 -0
  465. package/tests/test_three_valued_eval.py +159 -0
  466. package/tsconfig.json +30 -0
  467. package/typescript-tests/advanced.test.ts +165 -0
  468. package/typescript-tests/authority.test.ts +216 -0
  469. package/typescript-tests/expression.test.ts +228 -0
  470. package/typescript-tests/golden-payment-flow.test.ts +51 -0
  471. package/typescript-tests/graph.test.ts +142 -0
  472. package/typescript-tests/native-binding.test.ts +20 -0
  473. package/typescript-tests/primitives.test.ts +88 -0
  474. package/typescript-tests/registry.test.ts +122 -0
  475. package/typescript-tests/role_relation.test.ts +63 -0
  476. package/typescript-tests/runtime_toggle.test.ts +141 -0
  477. package/typescript-tests/semantic-pack.test.ts +556 -0
  478. package/typescript-tests/three_valued_eval.test.ts +135 -0
  479. package/typescript-tests/units.test.ts +36 -0
  480. package/vitest.config.ts +13 -0
  481. package/wasm_demo.html +225 -0
@@ -0,0 +1,818 @@
1
+ use crate::units::Dimension;
2
+ #[cfg(feature = "python")]
3
+ use pyo3::{IntoPyObject, PyAny, Python};
4
+ use std::fmt;
5
+
6
+ /// Threshold for fuzzy matching suggestions (Levenshtein distance)
7
+ pub const FUZZY_MATCH_THRESHOLD: usize = 2;
8
+
9
+ /// Position in source code (line and column, 1-indexed)
10
+ #[derive(Debug, Clone, Copy, PartialEq, Eq)]
11
+ pub struct Position {
12
+ pub line: usize,
13
+ pub column: usize,
14
+ }
15
+
16
+ impl Position {
17
+ pub fn new(line: usize, column: usize) -> Result<Self, String> {
18
+ if line == 0 || column == 0 {
19
+ Err(format!(
20
+ "Position line and column must be >= 1. Got line={}, column={}",
21
+ line, column
22
+ ))
23
+ } else {
24
+ Ok(Self { line, column })
25
+ }
26
+ }
27
+ }
28
+
29
+ impl fmt::Display for Position {
30
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
31
+ write!(f, "{}:{}", self.line, self.column)
32
+ }
33
+ }
34
+
35
+ /// Source range with start and end positions
36
+ #[derive(Debug, Clone, Copy, PartialEq, Eq)]
37
+ pub struct SourceRange {
38
+ pub start: Position,
39
+ pub end: Position,
40
+ }
41
+
42
+ impl SourceRange {
43
+ pub fn new(start: Position, end: Position) -> Self {
44
+ Self { start, end }
45
+ }
46
+
47
+ pub fn from_line_col(
48
+ start_line: usize,
49
+ start_col: usize,
50
+ end_line: usize,
51
+ end_col: usize,
52
+ ) -> Result<Self, String> {
53
+ Ok(Self {
54
+ start: Position::new(start_line, start_col)?,
55
+ end: Position::new(end_line, end_col)?,
56
+ })
57
+ }
58
+
59
+ pub fn single_position(line: usize, column: usize) -> Result<Self, String> {
60
+ let pos = Position::new(line, column)?;
61
+ Ok(Self {
62
+ start: pos,
63
+ end: pos,
64
+ })
65
+ }
66
+ }
67
+
68
+ impl fmt::Display for SourceRange {
69
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
70
+ if self.start == self.end {
71
+ write!(f, "{}", self.start)
72
+ } else if self.start.line == self.end.line {
73
+ write!(
74
+ f,
75
+ "{}:{}-{}",
76
+ self.start.line, self.start.column, self.end.column
77
+ )
78
+ } else {
79
+ write!(f, "{} to {}", self.start, self.end)
80
+ }
81
+ }
82
+ }
83
+
84
+ /// Error codes for all validation errors
85
+ #[derive(Debug, Clone, Copy, PartialEq, Eq)]
86
+ #[allow(non_camel_case_types)]
87
+ pub enum ErrorCode {
88
+ // E001-E099: Syntax and parsing errors
89
+ E001_UndefinedEntity,
90
+ E002_UndefinedResource,
91
+ E003_UnitMismatch,
92
+ E004_TypeMismatch,
93
+ E005_SyntaxError,
94
+ E006_InvalidExpression,
95
+ E007_DuplicateDeclaration,
96
+ E008_UndefinedVariable,
97
+ E009_InvalidQuantity,
98
+ E010_InvalidIdentifier,
99
+
100
+ // E100-E199: Type system errors
101
+ E100_IncompatibleTypes,
102
+ E101_InvalidTypeConversion,
103
+ E102_TypeInferenceFailed,
104
+ E103_InvalidOperandType,
105
+ E104_InvalidComparisonType,
106
+
107
+ // E200-E299: Unit and dimension errors
108
+ E200_DimensionMismatch,
109
+ E201_InvalidUnit,
110
+ E202_UnitConversionFailed,
111
+ E203_IncompatibleDimensions,
112
+
113
+ // E300-E399: Scope and reference errors
114
+ E300_VariableNotInScope,
115
+ E301_UndefinedReference,
116
+ E302_CircularReference,
117
+ E303_InvalidReference,
118
+
119
+ // E400-E499: Policy validation errors
120
+ E400_PolicyEvaluationFailed,
121
+ E401_InvalidPolicyExpression,
122
+ E402_DeterminismViolation,
123
+ E403_InvalidModality,
124
+
125
+ // E500-E599: Namespace and module errors
126
+ E500_NamespaceNotFound,
127
+ E501_AmbiguousNamespace,
128
+ E502_InvalidNamespace,
129
+ E503_ModuleNotFound,
130
+ E504_SymbolNotExported,
131
+ E505_CircularDependency,
132
+ E506_AmbiguousImport,
133
+ E507_InvalidExport,
134
+ }
135
+
136
+ impl ErrorCode {
137
+ pub fn as_str(&self) -> &'static str {
138
+ match self {
139
+ // Syntax and parsing
140
+ ErrorCode::E001_UndefinedEntity => "E001",
141
+ ErrorCode::E002_UndefinedResource => "E002",
142
+ ErrorCode::E003_UnitMismatch => "E003",
143
+ ErrorCode::E004_TypeMismatch => "E004",
144
+ ErrorCode::E005_SyntaxError => "E005",
145
+ ErrorCode::E006_InvalidExpression => "E006",
146
+ ErrorCode::E007_DuplicateDeclaration => "E007",
147
+ ErrorCode::E008_UndefinedVariable => "E008",
148
+ ErrorCode::E009_InvalidQuantity => "E009",
149
+ ErrorCode::E010_InvalidIdentifier => "E010",
150
+
151
+ // Type system
152
+ ErrorCode::E100_IncompatibleTypes => "E100",
153
+ ErrorCode::E101_InvalidTypeConversion => "E101",
154
+ ErrorCode::E102_TypeInferenceFailed => "E102",
155
+ ErrorCode::E103_InvalidOperandType => "E103",
156
+ ErrorCode::E104_InvalidComparisonType => "E104",
157
+
158
+ // Units and dimensions
159
+ ErrorCode::E200_DimensionMismatch => "E200",
160
+ ErrorCode::E201_InvalidUnit => "E201",
161
+ ErrorCode::E202_UnitConversionFailed => "E202",
162
+ ErrorCode::E203_IncompatibleDimensions => "E203",
163
+
164
+ // Scope and references
165
+ ErrorCode::E300_VariableNotInScope => "E300",
166
+ ErrorCode::E301_UndefinedReference => "E301",
167
+ ErrorCode::E302_CircularReference => "E302",
168
+ ErrorCode::E303_InvalidReference => "E303",
169
+
170
+ // Policy validation
171
+ ErrorCode::E400_PolicyEvaluationFailed => "E400",
172
+ ErrorCode::E401_InvalidPolicyExpression => "E401",
173
+ ErrorCode::E402_DeterminismViolation => "E402",
174
+ ErrorCode::E403_InvalidModality => "E403",
175
+
176
+ // Namespace and modules
177
+ ErrorCode::E500_NamespaceNotFound => "E500",
178
+ ErrorCode::E501_AmbiguousNamespace => "E501",
179
+ ErrorCode::E502_InvalidNamespace => "E502",
180
+ ErrorCode::E503_ModuleNotFound => "E503",
181
+ ErrorCode::E504_SymbolNotExported => "E504",
182
+ ErrorCode::E505_CircularDependency => "E505",
183
+ ErrorCode::E506_AmbiguousImport => "E506",
184
+ ErrorCode::E507_InvalidExport => "E507",
185
+ }
186
+ }
187
+
188
+ pub fn description(&self) -> &'static str {
189
+ match self {
190
+ ErrorCode::E001_UndefinedEntity => "Undefined entity",
191
+ ErrorCode::E002_UndefinedResource => "Undefined resource",
192
+ ErrorCode::E003_UnitMismatch => "Unit mismatch",
193
+ ErrorCode::E004_TypeMismatch => "Type mismatch",
194
+ ErrorCode::E005_SyntaxError => "Syntax error",
195
+ ErrorCode::E006_InvalidExpression => "Invalid expression",
196
+ ErrorCode::E007_DuplicateDeclaration => "Duplicate declaration",
197
+ ErrorCode::E008_UndefinedVariable => "Undefined variable",
198
+ ErrorCode::E009_InvalidQuantity => "Invalid quantity",
199
+ ErrorCode::E010_InvalidIdentifier => "Invalid identifier",
200
+ ErrorCode::E100_IncompatibleTypes => "Incompatible types",
201
+ ErrorCode::E101_InvalidTypeConversion => "Invalid type conversion",
202
+ ErrorCode::E102_TypeInferenceFailed => "Type inference failed",
203
+ ErrorCode::E103_InvalidOperandType => "Invalid operand type",
204
+ ErrorCode::E104_InvalidComparisonType => "Invalid comparison type",
205
+ ErrorCode::E200_DimensionMismatch => "Dimension mismatch",
206
+ ErrorCode::E201_InvalidUnit => "Invalid unit",
207
+ ErrorCode::E202_UnitConversionFailed => "Unit conversion failed",
208
+ ErrorCode::E203_IncompatibleDimensions => "Incompatible dimensions",
209
+ ErrorCode::E300_VariableNotInScope => "Variable not in scope",
210
+ ErrorCode::E301_UndefinedReference => "Undefined reference",
211
+ ErrorCode::E302_CircularReference => "Circular reference",
212
+ ErrorCode::E303_InvalidReference => "Invalid reference",
213
+ ErrorCode::E400_PolicyEvaluationFailed => "Policy evaluation failed",
214
+ ErrorCode::E401_InvalidPolicyExpression => "Invalid policy expression",
215
+ ErrorCode::E402_DeterminismViolation => "Determinism violation",
216
+ ErrorCode::E403_InvalidModality => "Invalid modality",
217
+ ErrorCode::E500_NamespaceNotFound => "Namespace not found",
218
+ ErrorCode::E501_AmbiguousNamespace => "Ambiguous namespace",
219
+ ErrorCode::E502_InvalidNamespace => "Invalid namespace",
220
+ ErrorCode::E503_ModuleNotFound => "Module not found",
221
+ ErrorCode::E504_SymbolNotExported => "Imported symbol is not exported",
222
+ ErrorCode::E505_CircularDependency => "Circular dependency detected",
223
+ ErrorCode::E506_AmbiguousImport => "Ambiguous import",
224
+ ErrorCode::E507_InvalidExport => "Invalid export",
225
+ }
226
+ }
227
+ }
228
+
229
+ impl fmt::Display for ErrorCode {
230
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
231
+ write!(f, "{}", self.as_str())
232
+ }
233
+ }
234
+
235
+ #[derive(Debug, Clone, PartialEq, Eq, serde::Serialize)]
236
+ pub enum ReferenceType {
237
+ Entity,
238
+ Resource,
239
+ Variable,
240
+ Flow,
241
+ Other(String),
242
+ }
243
+
244
+ impl fmt::Display for ReferenceType {
245
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
246
+ match self {
247
+ ReferenceType::Entity => write!(f, "Entity"),
248
+ ReferenceType::Resource => write!(f, "Resource"),
249
+ ReferenceType::Variable => write!(f, "Variable"),
250
+ ReferenceType::Flow => write!(f, "Flow"),
251
+ ReferenceType::Other(s) => write!(f, "{}", s),
252
+ }
253
+ }
254
+ }
255
+
256
+ #[cfg(feature = "python")]
257
+ impl<'py> IntoPyObject<'py> for ReferenceType {
258
+ type Target = PyAny;
259
+ type Output = pyo3::Bound<'py, PyAny>;
260
+ type Error = pyo3::PyErr;
261
+
262
+ fn into_pyobject(self, py: Python<'py>) -> pyo3::PyResult<Self::Output> {
263
+ Ok(pyo3::types::PyString::new(py, &self.to_string()).into_any())
264
+ }
265
+ }
266
+
267
+ #[derive(Debug, Clone)]
268
+ pub enum ValidationError {
269
+ SyntaxError {
270
+ message: String,
271
+ line: usize,
272
+ column: usize,
273
+ end_line: Option<usize>,
274
+ end_column: Option<usize>,
275
+ },
276
+ TypeError {
277
+ message: String,
278
+ location: String,
279
+ expected_type: Option<String>,
280
+ found_type: Option<String>,
281
+ suggestion: Option<String>,
282
+ },
283
+ UnitError {
284
+ expected: Dimension,
285
+ found: Dimension,
286
+ location: String,
287
+ suggestion: Option<String>,
288
+ },
289
+ ScopeError {
290
+ variable: String,
291
+ available_in: Vec<String>,
292
+ location: String,
293
+ suggestion: Option<String>,
294
+ },
295
+ DeterminismError {
296
+ message: String,
297
+ hint: String,
298
+ },
299
+ UndefinedReference {
300
+ reference_type: ReferenceType,
301
+ name: String,
302
+ location: String,
303
+ suggestion: Option<String>,
304
+ },
305
+ DuplicateDeclaration {
306
+ name: String,
307
+ first_location: String,
308
+ second_location: String,
309
+ },
310
+ InvalidExpression {
311
+ message: String,
312
+ location: String,
313
+ suggestion: Option<String>,
314
+ },
315
+ }
316
+
317
+ impl ValidationError {
318
+ /// Get the error code for this validation error
319
+ pub fn error_code(&self) -> ErrorCode {
320
+ match self {
321
+ ValidationError::SyntaxError { .. } => ErrorCode::E005_SyntaxError,
322
+ ValidationError::TypeError { .. } => ErrorCode::E004_TypeMismatch,
323
+ ValidationError::UnitError { .. } => ErrorCode::E003_UnitMismatch,
324
+ ValidationError::ScopeError { .. } => ErrorCode::E300_VariableNotInScope,
325
+ ValidationError::DeterminismError { .. } => ErrorCode::E402_DeterminismViolation,
326
+ ValidationError::UndefinedReference { reference_type, .. } => match reference_type {
327
+ ReferenceType::Entity => ErrorCode::E001_UndefinedEntity,
328
+ ReferenceType::Resource => ErrorCode::E002_UndefinedResource,
329
+ ReferenceType::Variable => ErrorCode::E008_UndefinedVariable,
330
+ _ => ErrorCode::E301_UndefinedReference,
331
+ },
332
+ ValidationError::DuplicateDeclaration { .. } => ErrorCode::E007_DuplicateDeclaration,
333
+ ValidationError::InvalidExpression { .. } => ErrorCode::E006_InvalidExpression,
334
+ }
335
+ }
336
+
337
+ /// Get the source range for this error (if available)
338
+ pub fn range(&self) -> Option<SourceRange> {
339
+ match self {
340
+ ValidationError::SyntaxError {
341
+ line,
342
+ column,
343
+ end_line,
344
+ end_column,
345
+ ..
346
+ } => {
347
+ // We ignore errors here as this is just for reporting
348
+ let start =
349
+ Position::new(*line, *column).unwrap_or_else(|_| Position::new(1, 1).unwrap());
350
+ let end = match (end_line, end_column) {
351
+ (Some(el), Some(ec)) => Position::new(*el, *ec).unwrap_or(start),
352
+ _ => start,
353
+ };
354
+ Some(SourceRange::new(start, end))
355
+ }
356
+ _ => None, // Other variants use string locations for now
357
+ }
358
+ }
359
+
360
+ /// Get a user-friendly location string
361
+ pub fn location_string(&self) -> Option<String> {
362
+ match self {
363
+ ValidationError::SyntaxError { line, column, .. } => {
364
+ Some(format!("{}:{}", line, column))
365
+ }
366
+ ValidationError::TypeError { location, .. }
367
+ | ValidationError::UnitError { location, .. }
368
+ | ValidationError::ScopeError { location, .. }
369
+ | ValidationError::UndefinedReference { location, .. }
370
+ | ValidationError::InvalidExpression { location, .. } => Some(location.clone()),
371
+ ValidationError::DuplicateDeclaration {
372
+ second_location, ..
373
+ } => Some(second_location.clone()),
374
+ ValidationError::DeterminismError { .. } => None,
375
+ }
376
+ }
377
+
378
+ pub fn syntax_error(message: impl Into<String>, line: usize, column: usize) -> Self {
379
+ Self::SyntaxError {
380
+ message: message.into(),
381
+ line,
382
+ column,
383
+ end_line: None,
384
+ end_column: None,
385
+ }
386
+ }
387
+
388
+ pub fn syntax_error_with_range(
389
+ message: impl Into<String>,
390
+ line: usize,
391
+ column: usize,
392
+ end_line: usize,
393
+ end_column: usize,
394
+ ) -> Self {
395
+ Self::SyntaxError {
396
+ message: message.into(),
397
+ line,
398
+ column,
399
+ end_line: Some(end_line),
400
+ end_column: Some(end_column),
401
+ }
402
+ }
403
+
404
+ pub fn type_error(message: impl Into<String>, location: impl Into<String>) -> Self {
405
+ Self::TypeError {
406
+ message: message.into(),
407
+ location: location.into(),
408
+ expected_type: None,
409
+ found_type: None,
410
+ suggestion: None,
411
+ }
412
+ }
413
+
414
+ pub fn unit_error(expected: Dimension, found: Dimension, location: impl Into<String>) -> Self {
415
+ Self::UnitError {
416
+ expected,
417
+ found,
418
+ location: location.into(),
419
+ suggestion: None,
420
+ }
421
+ }
422
+
423
+ pub fn scope_error(
424
+ variable: impl Into<String>,
425
+ available_in: Vec<String>,
426
+ location: impl Into<String>,
427
+ ) -> Self {
428
+ Self::ScopeError {
429
+ variable: variable.into(),
430
+ available_in,
431
+ location: location.into(),
432
+ suggestion: None,
433
+ }
434
+ }
435
+
436
+ pub fn determinism_error(message: impl Into<String>, hint: impl Into<String>) -> Self {
437
+ Self::DeterminismError {
438
+ message: message.into(),
439
+ hint: hint.into(),
440
+ }
441
+ }
442
+
443
+ pub fn undefined_reference(
444
+ reference_type: impl Into<String>,
445
+ name: impl Into<String>,
446
+ location: impl Into<String>,
447
+ ) -> Self {
448
+ Self::UndefinedReference {
449
+ reference_type: ReferenceType::Other(reference_type.into()),
450
+ name: name.into(),
451
+ location: location.into(),
452
+ suggestion: None,
453
+ }
454
+ }
455
+
456
+ pub fn duplicate_declaration(
457
+ name: impl Into<String>,
458
+ first_location: impl Into<String>,
459
+ second_location: impl Into<String>,
460
+ ) -> Self {
461
+ Self::DuplicateDeclaration {
462
+ name: name.into(),
463
+ first_location: first_location.into(),
464
+ second_location: second_location.into(),
465
+ }
466
+ }
467
+
468
+ pub fn invalid_expression(message: impl Into<String>, location: impl Into<String>) -> Self {
469
+ Self::InvalidExpression {
470
+ message: message.into(),
471
+ location: location.into(),
472
+ suggestion: None,
473
+ }
474
+ }
475
+
476
+ pub fn with_suggestion(mut self, suggestion: impl Into<String>) -> Self {
477
+ match &mut self {
478
+ ValidationError::UnitError { suggestion: s, .. } => {
479
+ *s = Some(suggestion.into());
480
+ }
481
+ ValidationError::TypeError { suggestion: s, .. } => {
482
+ *s = Some(suggestion.into());
483
+ }
484
+ ValidationError::ScopeError { suggestion: s, .. } => {
485
+ *s = Some(suggestion.into());
486
+ }
487
+ ValidationError::UndefinedReference { suggestion: s, .. } => {
488
+ *s = Some(suggestion.into());
489
+ }
490
+ ValidationError::InvalidExpression { suggestion: s, .. } => {
491
+ *s = Some(suggestion.into());
492
+ }
493
+ _ => {}
494
+ }
495
+ self
496
+ }
497
+
498
+ pub fn with_types(
499
+ mut self,
500
+ expected_type: impl Into<String>,
501
+ found_type: impl Into<String>,
502
+ ) -> Self {
503
+ if let ValidationError::TypeError {
504
+ expected_type: e,
505
+ found_type: f,
506
+ ..
507
+ } = &mut self
508
+ {
509
+ *e = Some(expected_type.into());
510
+ *f = Some(found_type.into());
511
+ }
512
+ self
513
+ }
514
+
515
+ // Additional convenience constructors for common error patterns
516
+
517
+ /// Create an error for an undefined Entity with a helpful suggestion
518
+ pub fn undefined_entity(name: impl Into<String>, location: impl Into<String>) -> Self {
519
+ let name = name.into();
520
+ Self::UndefinedReference {
521
+ reference_type: ReferenceType::Entity,
522
+ name: name.clone(),
523
+ location: location.into(),
524
+ suggestion: Some(format!("Did you mean to define 'Entity \"{}\"'?", name)),
525
+ }
526
+ }
527
+
528
+ /// Create an error for an undefined Resource with a helpful suggestion
529
+ pub fn undefined_resource(name: impl Into<String>, location: impl Into<String>) -> Self {
530
+ let name = name.into();
531
+ Self::UndefinedReference {
532
+ reference_type: ReferenceType::Resource,
533
+ name: name.clone(),
534
+ location: location.into(),
535
+ suggestion: Some(format!("Did you mean to define 'Resource \"{}\"'?", name)),
536
+ }
537
+ }
538
+
539
+ /// Create an error for an undefined Flow with a helpful suggestion
540
+ pub fn undefined_flow(name: impl Into<String>, location: impl Into<String>) -> Self {
541
+ let name = name.into();
542
+ Self::UndefinedReference {
543
+ reference_type: ReferenceType::Flow,
544
+ name: name.clone(),
545
+ location: location.into(),
546
+ suggestion: Some(format!(
547
+ "Did you mean to define a Flow involving '{}'?",
548
+ name
549
+ )),
550
+ }
551
+ }
552
+
553
+ /// Create a unit mismatch error with automatic suggestion
554
+ pub fn unit_mismatch(
555
+ expected: Dimension,
556
+ found: Dimension,
557
+ location: impl Into<String>,
558
+ ) -> Self {
559
+ let suggestion = Some(format!(
560
+ "Expected dimension {:?} but found {:?}. Consider using unit conversion or checking your unit definitions.",
561
+ expected, found
562
+ ));
563
+ Self::UnitError {
564
+ expected,
565
+ found,
566
+ location: location.into(),
567
+ suggestion,
568
+ }
569
+ }
570
+
571
+ /// Create a type mismatch error with types and suggestion
572
+ pub fn type_mismatch(
573
+ expected: impl Into<String>,
574
+ found: impl Into<String>,
575
+ location: impl Into<String>,
576
+ ) -> Self {
577
+ let expected = expected.into();
578
+ let found = found.into();
579
+ Self::TypeError {
580
+ message: format!("Type mismatch: expected {}, found {}", expected, found),
581
+ location: location.into(),
582
+ expected_type: Some(expected.clone()),
583
+ found_type: Some(found.clone()),
584
+ suggestion: Some(format!(
585
+ "Convert {} to {} or adjust the expression",
586
+ found, expected
587
+ )),
588
+ }
589
+ }
590
+
591
+ /// Create a scope error with available variables listed
592
+ pub fn variable_not_in_scope(
593
+ variable: impl Into<String>,
594
+ available: Vec<String>,
595
+ location: impl Into<String>,
596
+ ) -> Self {
597
+ let variable = variable.into();
598
+ let suggestion = if !available.is_empty() {
599
+ Some(format!(
600
+ "Available variables: {}. Did you mean one of these?",
601
+ available.join(", ")
602
+ ))
603
+ } else {
604
+ Some("No variables are currently in scope.".to_string())
605
+ };
606
+
607
+ Self::ScopeError {
608
+ variable,
609
+ available_in: available,
610
+ location: location.into(),
611
+ suggestion,
612
+ }
613
+ }
614
+
615
+ /// Create an undefined entity error with fuzzy matching suggestions
616
+ ///
617
+ /// # Arguments
618
+ /// * `name` - The undefined entity name
619
+ /// * `location` - Source location of the error
620
+ /// * `candidates` - Available entity names to suggest
621
+ fn undefined_reference_with_candidates(
622
+ reference_type: ReferenceType,
623
+ name: String,
624
+ location: String,
625
+ candidates: &[String],
626
+ ) -> Self {
627
+ use crate::error::fuzzy::find_best_match;
628
+
629
+ let suggestion = find_best_match(&name, candidates, FUZZY_MATCH_THRESHOLD)
630
+ .map(|match_name| format!("Did you mean '{}'?", match_name))
631
+ .or_else(|| {
632
+ Some(format!(
633
+ "Did you mean to define '{} \"{}\"'?",
634
+ reference_type, name
635
+ ))
636
+ });
637
+
638
+ Self::UndefinedReference {
639
+ reference_type,
640
+ name,
641
+ location,
642
+ suggestion,
643
+ }
644
+ }
645
+
646
+ /// Create an undefined entity error with fuzzy matching suggestions
647
+ ///
648
+ /// # Arguments
649
+ /// * `name` - The undefined entity name
650
+ /// * `location` - Source location of the error
651
+ /// * `candidates` - Available entity names to suggest
652
+ pub fn undefined_entity_with_candidates(
653
+ name: impl Into<String>,
654
+ location: impl Into<String>,
655
+ candidates: &[String],
656
+ ) -> Self {
657
+ Self::undefined_reference_with_candidates(
658
+ ReferenceType::Entity,
659
+ name.into(),
660
+ location.into(),
661
+ candidates,
662
+ )
663
+ }
664
+
665
+ /// Create an undefined resource error with fuzzy matching suggestions
666
+ pub fn undefined_resource_with_candidates(
667
+ name: impl Into<String>,
668
+ location: impl Into<String>,
669
+ candidates: &[String],
670
+ ) -> Self {
671
+ Self::undefined_reference_with_candidates(
672
+ ReferenceType::Resource,
673
+ name.into(),
674
+ location.into(),
675
+ candidates,
676
+ )
677
+ }
678
+
679
+ /// Create an undefined variable error with fuzzy matching suggestions
680
+ pub fn undefined_variable_with_candidates(
681
+ name: impl Into<String>,
682
+ location: impl Into<String>,
683
+ candidates: &[String],
684
+ ) -> Self {
685
+ use crate::error::fuzzy::suggest_similar;
686
+
687
+ let name = name.into();
688
+ let matches = suggest_similar(&name, candidates, FUZZY_MATCH_THRESHOLD);
689
+ let suggestion = if !matches.is_empty() {
690
+ let quoted: Vec<String> = matches.iter().map(|m| format!("'{}'", m)).collect();
691
+ Some(format!("Did you mean {}?", quoted.join(", ")))
692
+ } else {
693
+ Some("No similar variables found in scope.".to_string())
694
+ };
695
+
696
+ Self::UndefinedReference {
697
+ reference_type: ReferenceType::Variable,
698
+ name,
699
+ location: location.into(),
700
+ suggestion,
701
+ }
702
+ }
703
+ }
704
+
705
+ impl fmt::Display for ValidationError {
706
+ fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
707
+ match self {
708
+ ValidationError::SyntaxError {
709
+ message,
710
+ line,
711
+ column,
712
+ end_line,
713
+ end_column,
714
+ } => {
715
+ if let (Some(el), Some(ec)) = (end_line, end_column) {
716
+ write!(
717
+ f,
718
+ "Syntax error at {}:{} to {}:{}: {}",
719
+ line, column, el, ec, message
720
+ )
721
+ } else {
722
+ write!(f, "Syntax error at {}:{}: {}", line, column, message)
723
+ }
724
+ }
725
+ ValidationError::TypeError {
726
+ message,
727
+ location,
728
+ expected_type,
729
+ found_type,
730
+ suggestion,
731
+ } => {
732
+ write!(f, "Type error at {}: {}", location, message)?;
733
+ if let (Some(exp), Some(fnd)) = (expected_type, found_type) {
734
+ write!(f, " (expected {}, found {})", exp, fnd)?;
735
+ }
736
+ if let Some(sug) = suggestion {
737
+ write!(f, "\n Suggestion: {}", sug)?;
738
+ }
739
+ Ok(())
740
+ }
741
+ ValidationError::UnitError {
742
+ expected,
743
+ found,
744
+ location,
745
+ suggestion,
746
+ } => {
747
+ write!(
748
+ f,
749
+ "Unit error at {}: incompatible dimensions (expected {:?}, found {:?})",
750
+ location, expected, found
751
+ )?;
752
+ if let Some(sug) = suggestion {
753
+ write!(f, "\n Suggestion: {}", sug)?;
754
+ }
755
+ Ok(())
756
+ }
757
+ ValidationError::ScopeError {
758
+ variable,
759
+ available_in,
760
+ location,
761
+ suggestion,
762
+ } => {
763
+ write!(
764
+ f,
765
+ "Scope error at {}: variable '{}' not in scope",
766
+ location, variable
767
+ )?;
768
+ if !available_in.is_empty() {
769
+ write!(f, "\n Available in: {}", available_in.join(", "))?;
770
+ }
771
+ if let Some(sug) = suggestion {
772
+ write!(f, "\n Suggestion: {}", sug)?;
773
+ }
774
+ Ok(())
775
+ }
776
+ ValidationError::DeterminismError { message, hint } => {
777
+ write!(f, "Determinism error: {}", message)?;
778
+ write!(f, "\n Hint: {}", hint)
779
+ }
780
+ ValidationError::UndefinedReference {
781
+ reference_type,
782
+ name,
783
+ location,
784
+ suggestion,
785
+ } => {
786
+ write!(f, "Undefined {} '{}' at {}", reference_type, name, location)?;
787
+ if let Some(sug) = suggestion {
788
+ write!(f, "\n Suggestion: {}", sug)?;
789
+ }
790
+ Ok(())
791
+ }
792
+ ValidationError::DuplicateDeclaration {
793
+ name,
794
+ first_location,
795
+ second_location,
796
+ } => {
797
+ write!(
798
+ f,
799
+ "Duplicate declaration of '{}': first at {}, duplicate at {}",
800
+ name, first_location, second_location
801
+ )
802
+ }
803
+ ValidationError::InvalidExpression {
804
+ message,
805
+ location,
806
+ suggestion,
807
+ } => {
808
+ write!(f, "Invalid expression at {}: {}", location, message)?;
809
+ if let Some(sug) = suggestion {
810
+ write!(f, "\n Suggestion: {}", sug)?;
811
+ }
812
+ Ok(())
813
+ }
814
+ }
815
+ }
816
+ }
817
+
818
+ impl std::error::Error for ValidationError {}