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,256 @@
1
+ """Tests for Expression and NormalizedExpression bindings."""
2
+
3
+ from domainforge import (
4
+ Expression,
5
+ NormalizedExpression,
6
+ BinaryOp,
7
+ UnaryOp,
8
+ Quantifier,
9
+ AggregateFunction,
10
+ WindowSpec,
11
+ )
12
+
13
+
14
+ class TestExpressionFactoryMethods:
15
+ """Tests for Expression factory methods."""
16
+
17
+ def test_literal_bool(self):
18
+ """Test creating boolean literal expressions."""
19
+ expr = Expression.literal(True)
20
+ assert str(expr) == "true"
21
+
22
+ expr_false = Expression.literal(False)
23
+ assert str(expr_false) == "false"
24
+
25
+ def test_literal_number(self):
26
+ """Test creating number literal expressions."""
27
+ expr = Expression.literal(42)
28
+ assert str(expr) == "42"
29
+
30
+ expr_float = Expression.literal(3.14)
31
+ assert "3.14" in str(expr_float)
32
+
33
+ def test_literal_string(self):
34
+ """Test creating string literal expressions."""
35
+ expr = Expression.literal("hello")
36
+ assert "hello" in str(expr)
37
+
38
+ def test_variable(self):
39
+ """Test creating variable expressions."""
40
+ expr = Expression.variable("x")
41
+ assert str(expr) == "x"
42
+
43
+ def test_quantity(self):
44
+ """Test creating quantity literal expressions."""
45
+ expr = Expression.quantity("100", "USD")
46
+ assert "100" in str(expr)
47
+ assert "USD" in str(expr)
48
+
49
+ def test_time(self):
50
+ """Test creating time literal expressions."""
51
+ expr = Expression.time("2025-01-01T00:00:00Z")
52
+ assert "2025-01-01" in str(expr)
53
+
54
+ def test_interval(self):
55
+ """Test creating interval literal expressions."""
56
+ expr = Expression.interval("2025-01-01T09:00:00Z", "2025-01-01T17:00:00Z")
57
+ assert "09:00:00" in str(expr)
58
+ assert "17:00:00" in str(expr)
59
+
60
+ def test_binary(self):
61
+ """Test creating binary expressions."""
62
+ left = Expression.variable("a")
63
+ right = Expression.variable("b")
64
+ expr = Expression.binary(BinaryOp.And, left, right)
65
+ result = str(expr)
66
+ assert "AND" in result
67
+ assert "a" in result
68
+ assert "b" in result
69
+
70
+ def test_unary_not(self):
71
+ """Test creating unary NOT expressions."""
72
+ operand = Expression.variable("x")
73
+ expr = Expression.unary(UnaryOp.Not, operand)
74
+ result = str(expr)
75
+ assert "NOT" in result
76
+ assert "x" in result
77
+
78
+ def test_unary_negate(self):
79
+ """Test creating unary negation expressions."""
80
+ operand = Expression.variable("x")
81
+ expr = Expression.unary(UnaryOp.Negate, operand)
82
+ assert "x" in str(expr)
83
+
84
+ def test_member_access(self):
85
+ """Test creating member access expressions."""
86
+ expr = Expression.member_access("user", "name")
87
+ result = str(expr)
88
+ assert "user" in result
89
+ assert "name" in result
90
+
91
+ def test_cast(self):
92
+ """Test creating cast expressions."""
93
+ operand = Expression.variable("x")
94
+ expr = Expression.cast(operand, "Money")
95
+ result = str(expr)
96
+ assert "x" in result
97
+ assert "Money" in result
98
+
99
+ def test_quantifier_forall(self):
100
+ """Test creating ForAll quantifier expressions."""
101
+ collection = Expression.variable("items")
102
+ condition = Expression.variable("valid")
103
+ expr = Expression.quantifier(Quantifier.ForAll, "x", collection, condition)
104
+ result = str(expr)
105
+ assert "ForAll" in result or "forall" in result.lower()
106
+
107
+ def test_aggregation(self):
108
+ """Test creating aggregation expressions."""
109
+ collection = Expression.variable("items")
110
+ expr = Expression.aggregation(AggregateFunction.Count, collection)
111
+ result = str(expr)
112
+ assert "COUNT" in result or "count" in result.lower()
113
+
114
+
115
+ class TestNormalization:
116
+ """Tests for expression normalization."""
117
+
118
+ def test_normalize_returns_normalized_expression(self):
119
+ """Test that normalize() returns a NormalizedExpression."""
120
+ expr = Expression.variable("x")
121
+ normalized = expr.normalize()
122
+ assert isinstance(normalized, NormalizedExpression)
123
+
124
+ def test_identity_elimination_and_true(self):
125
+ """Test that `true AND x` normalizes to `x`."""
126
+ true_expr = Expression.literal(True)
127
+ x_expr = Expression.variable("x")
128
+ expr = Expression.binary(BinaryOp.And, true_expr, x_expr)
129
+ normalized = expr.normalize()
130
+ assert str(normalized) == "x"
131
+
132
+ def test_identity_elimination_or_false(self):
133
+ """Test that `false OR x` normalizes to `x`."""
134
+ false_expr = Expression.literal(False)
135
+ x_expr = Expression.variable("x")
136
+ expr = Expression.binary(BinaryOp.Or, false_expr, x_expr)
137
+ normalized = expr.normalize()
138
+ assert str(normalized) == "x"
139
+
140
+ def test_commutative_sorting(self):
141
+ """Test that commutative operators sort operands."""
142
+ b = Expression.variable("b")
143
+ a = Expression.variable("a")
144
+ expr = Expression.binary(BinaryOp.And, b, a)
145
+ normalized = expr.normalize()
146
+ # After normalization, should be (a AND b)
147
+ result = str(normalized)
148
+ assert result == "(a AND b)"
149
+
150
+ def test_idempotence(self):
151
+ """Test that `a AND a` normalizes to `a`."""
152
+ a = Expression.variable("a")
153
+ expr = Expression.binary(BinaryOp.And, a, a)
154
+ normalized = expr.normalize()
155
+ assert str(normalized) == "a"
156
+
157
+ def test_double_negation_elimination(self):
158
+ """Test that `NOT NOT x` normalizes to `x`."""
159
+ x = Expression.variable("x")
160
+ not_x = Expression.unary(UnaryOp.Not, x)
161
+ not_not_x = Expression.unary(UnaryOp.Not, not_x)
162
+ normalized = not_not_x.normalize()
163
+ assert str(normalized) == "x"
164
+
165
+
166
+ class TestEquivalence:
167
+ """Tests for expression equivalence checking."""
168
+
169
+ def test_equivalent_expressions(self):
170
+ """Test that equivalent expressions are recognized as equivalent."""
171
+ a1 = Expression.variable("a")
172
+ b1 = Expression.variable("b")
173
+ expr1 = Expression.binary(BinaryOp.And, a1, b1)
174
+
175
+ a2 = Expression.variable("a")
176
+ b2 = Expression.variable("b")
177
+ expr2 = Expression.binary(BinaryOp.And, b2, a2)
178
+
179
+ assert expr1.is_equivalent(expr2)
180
+
181
+ def test_non_equivalent_expressions(self):
182
+ """Test that non-equivalent expressions are recognized as non-equivalent."""
183
+ a = Expression.variable("a")
184
+ b = Expression.variable("b")
185
+ c = Expression.variable("c")
186
+
187
+ expr1 = Expression.binary(BinaryOp.And, a, b)
188
+ expr2 = Expression.binary(BinaryOp.And, a, c)
189
+
190
+ assert not expr1.is_equivalent(expr2)
191
+
192
+
193
+ class TestStableHash:
194
+ """Tests for stable hash functionality."""
195
+
196
+ def test_stable_hash_is_deterministic(self):
197
+ """Test that stable hash is deterministic."""
198
+ expr = Expression.variable("x")
199
+ hash1 = expr.normalize().stable_hash()
200
+ hash2 = expr.normalize().stable_hash()
201
+ assert hash1 == hash2
202
+
203
+ def test_equivalent_expressions_have_same_hash(self):
204
+ """Test that equivalent expressions have the same hash."""
205
+ a1 = Expression.variable("a")
206
+ b1 = Expression.variable("b")
207
+ expr1 = Expression.binary(BinaryOp.And, a1, b1)
208
+
209
+ a2 = Expression.variable("a")
210
+ b2 = Expression.variable("b")
211
+ expr2 = Expression.binary(BinaryOp.And, b2, a2)
212
+
213
+ assert expr1.normalize().stable_hash() == expr2.normalize().stable_hash()
214
+
215
+
216
+ class TestNormalizedExpressionMethods:
217
+ """Tests for NormalizedExpression methods."""
218
+
219
+ def test_inner_expression(self):
220
+ """Test that inner_expression returns an Expression."""
221
+ expr = Expression.variable("x")
222
+ normalized = expr.normalize()
223
+ inner = normalized.inner_expression()
224
+ assert isinstance(inner, Expression)
225
+ assert str(inner) == "x"
226
+
227
+ def test_str_representation(self):
228
+ """Test string representation of NormalizedExpression."""
229
+ expr = Expression.variable("x")
230
+ normalized = expr.normalize()
231
+ assert str(normalized) == "x"
232
+
233
+ def test_repr_includes_hash(self):
234
+ """Test that repr includes hash information."""
235
+ expr = Expression.variable("x")
236
+ normalized = expr.normalize()
237
+ repr_str = repr(normalized)
238
+ assert "NormalizedExpression" in repr_str
239
+ assert "hash" in repr_str.lower()
240
+
241
+
242
+ class TestWindowSpec:
243
+ """Tests for WindowSpec."""
244
+
245
+ def test_window_spec_creation(self):
246
+ """Test WindowSpec creation."""
247
+ ws = WindowSpec(30, "days")
248
+ assert ws.duration == 30
249
+ assert ws.unit == "days"
250
+
251
+ def test_window_spec_repr(self):
252
+ """Test WindowSpec repr."""
253
+ ws = WindowSpec(24, "hours")
254
+ repr_str = repr(ws)
255
+ assert "24" in repr_str
256
+ assert "hours" in repr_str
@@ -0,0 +1,42 @@
1
+ from domainforge import Graph
2
+
3
+ PAYMENT_DSL = """
4
+ Role "Payer"
5
+ Role "Payee"
6
+
7
+ Resource "Money" units
8
+
9
+ Entity "Alice"
10
+ Entity "Bob"
11
+
12
+ Flow "Money" from "Alice" to "Bob" quantity 10
13
+
14
+ Relation "Payment"
15
+ subject: "Payer"
16
+ predicate: "pays"
17
+ object: "Payee"
18
+ via: flow "Money"
19
+ """
20
+
21
+
22
+ def test_payment_flow_parity_from_dsl():
23
+ graph = Graph.parse(PAYMENT_DSL)
24
+
25
+ assert graph.entity_count() == 2
26
+ assert graph.resource_count() == 1
27
+ assert graph.flow_count() == 1
28
+
29
+ flows = graph.all_flows()
30
+ assert len(flows) == 1
31
+ flow = flows[0]
32
+ # Validate flow quantity and resource name (resource API supported by Python binding)
33
+ assert flow.quantity == 10
34
+ alice_id = graph.find_entity_by_name("Alice")
35
+ bob_id = graph.find_entity_by_name("Bob")
36
+ assert alice_id is not None
37
+ assert bob_id is not None
38
+ assert flow.from_id == alice_id
39
+ assert flow.to_id == bob_id
40
+ res = graph.get_resource(flow.resource_id)
41
+ assert res is not None
42
+ assert res.name == "Money"
@@ -0,0 +1,127 @@
1
+ import pytest
2
+ import domainforge
3
+
4
+
5
+ def test_graph_creation():
6
+ graph = domainforge.Graph()
7
+ assert graph.entity_count() == 0
8
+ assert graph.resource_count() == 0
9
+ assert graph.flow_count() == 0
10
+
11
+
12
+ def test_graph_add_entity():
13
+ graph = domainforge.Graph()
14
+ entity = domainforge.Entity("Warehouse")
15
+
16
+ graph.add_entity(entity)
17
+ assert graph.entity_count() == 1
18
+ assert graph.has_entity(entity.id)
19
+
20
+
21
+ def test_graph_add_resource():
22
+ graph = domainforge.Graph()
23
+ resource = domainforge.Resource("Cameras", "units")
24
+
25
+ graph.add_resource(resource)
26
+ assert graph.resource_count() == 1
27
+ assert graph.has_resource(resource.id)
28
+
29
+
30
+ def test_graph_add_flow():
31
+ graph = domainforge.Graph()
32
+ warehouse = domainforge.Entity("Warehouse")
33
+ factory = domainforge.Entity("Factory")
34
+ cameras = domainforge.Resource("Cameras", "units")
35
+
36
+ graph.add_entity(warehouse)
37
+ graph.add_entity(factory)
38
+ graph.add_resource(cameras)
39
+
40
+ flow = domainforge.Flow(cameras.id, warehouse.id, factory.id, 100.0)
41
+ graph.add_flow(flow)
42
+
43
+ assert graph.flow_count() == 1
44
+ assert graph.has_flow(flow.id)
45
+
46
+
47
+ def test_graph_flow_validation():
48
+ graph = domainforge.Graph()
49
+ warehouse = domainforge.Entity("Warehouse")
50
+ factory = domainforge.Entity("Factory")
51
+ cameras = domainforge.Resource("Cameras", "units")
52
+
53
+ graph.add_entity(warehouse)
54
+ graph.add_resource(cameras)
55
+
56
+ flow = domainforge.Flow(cameras.id, warehouse.id, factory.id, 100.0)
57
+
58
+ with pytest.raises(ValueError, match="Target entity not found"):
59
+ graph.add_flow(flow)
60
+
61
+
62
+ def test_graph_get_entity():
63
+ graph = domainforge.Graph()
64
+ entity = domainforge.Entity("Warehouse")
65
+ graph.add_entity(entity)
66
+
67
+ retrieved = graph.get_entity(entity.id)
68
+ assert retrieved is not None
69
+ assert retrieved.id == entity.id
70
+ assert retrieved.name == entity.name
71
+
72
+
73
+ def test_graph_find_entity_by_name():
74
+ graph = domainforge.Graph()
75
+ entity = domainforge.Entity("Warehouse")
76
+ graph.add_entity(entity)
77
+
78
+ found_id = graph.find_entity_by_name("Warehouse")
79
+ assert found_id == entity.id
80
+
81
+ not_found = graph.find_entity_by_name("Nonexistent")
82
+ assert not_found is None
83
+
84
+
85
+ def test_graph_flows_from():
86
+ graph = domainforge.Graph()
87
+ warehouse = domainforge.Entity("Warehouse")
88
+ factory1 = domainforge.Entity("Factory1")
89
+ factory2 = domainforge.Entity("Factory2")
90
+ cameras = domainforge.Resource("Cameras", "units")
91
+
92
+ graph.add_entity(warehouse)
93
+ graph.add_entity(factory1)
94
+ graph.add_entity(factory2)
95
+ graph.add_resource(cameras)
96
+
97
+ flow1 = domainforge.Flow(cameras.id, warehouse.id, factory1.id, 100.0)
98
+ flow2 = domainforge.Flow(cameras.id, warehouse.id, factory2.id, 50.0)
99
+
100
+ graph.add_flow(flow1)
101
+ graph.add_flow(flow2)
102
+
103
+ flows = graph.flows_from(warehouse.id)
104
+ assert len(flows) == 2
105
+
106
+
107
+ def test_graph_all_methods():
108
+ graph = domainforge.Graph()
109
+ e1 = domainforge.Entity("E1")
110
+ e2 = domainforge.Entity("E2")
111
+ r1 = domainforge.Resource("R1", "units")
112
+
113
+ graph.add_entity(e1)
114
+ graph.add_entity(e2)
115
+ graph.add_resource(r1)
116
+
117
+ flow = domainforge.Flow(r1.id, e1.id, e2.id, 10.0)
118
+ graph.add_flow(flow)
119
+
120
+ all_entities = graph.all_entities()
121
+ assert len(all_entities) == 2
122
+
123
+ all_resources = graph.all_resources()
124
+ assert len(all_resources) == 1
125
+
126
+ all_flows = graph.all_flows()
127
+ assert len(all_flows) == 1
@@ -0,0 +1,136 @@
1
+ """
2
+ Additional Python tests for SEA DSL bindings - ResourceInstance support
3
+ """
4
+
5
+ import pytest
6
+ import domainforge
7
+
8
+
9
+ def test_instance_creation():
10
+ """Test creating a ResourceInstance"""
11
+ entity = domainforge.Entity("Warehouse")
12
+ resource = domainforge.Resource("Camera", "units")
13
+
14
+ instance = domainforge.ResourceInstance(resource.id, entity.id)
15
+ assert instance.resource_id == resource.id
16
+ assert instance.entity_id == entity.id
17
+ assert len(instance.id) == 36
18
+
19
+
20
+ def test_instance_with_namespace():
21
+ """Test creating a ResourceInstance with namespace"""
22
+ entity = domainforge.Entity("Warehouse", "logistics")
23
+ resource = domainforge.Resource("Camera", "units", "inventory")
24
+
25
+ instance = domainforge.ResourceInstance(resource.id, entity.id, "inventory")
26
+ assert instance.namespace == "inventory"
27
+
28
+
29
+ def test_instance_attributes():
30
+ """Test ResourceInstance attributes"""
31
+ entity = domainforge.Entity("Warehouse")
32
+ resource = domainforge.Resource("Camera", "units")
33
+
34
+ instance = domainforge.ResourceInstance(resource.id, entity.id)
35
+ instance.set_attribute("serial_number", "CAM-12345")
36
+ assert instance.get_attribute("serial_number") == "CAM-12345"
37
+
38
+
39
+ def test_graph_add_instance():
40
+ """Test adding a ResourceInstance to a Graph"""
41
+ graph = domainforge.Graph()
42
+ entity = domainforge.Entity("Warehouse")
43
+ resource = domainforge.Resource("Camera", "units")
44
+
45
+ graph.add_entity(entity)
46
+ graph.add_resource(resource)
47
+
48
+ instance = domainforge.ResourceInstance(resource.id, entity.id)
49
+ graph.add_instance(instance)
50
+
51
+ assert graph.instance_count() == 1
52
+
53
+
54
+ def test_graph_instance_validation():
55
+ """Test Graph validates ResourceInstance references"""
56
+ graph = domainforge.Graph()
57
+ entity = domainforge.Entity("Warehouse")
58
+ resource = domainforge.Resource("Camera", "units")
59
+
60
+ graph.add_entity(entity)
61
+ # Not adding resource
62
+
63
+ instance = domainforge.ResourceInstance(resource.id, entity.id)
64
+
65
+ with pytest.raises(ValueError, match="Resource not found"):
66
+ graph.add_instance(instance)
67
+
68
+
69
+ def test_round_trip_serialization():
70
+ """Test that primitives can be serialized and remain valid"""
71
+ graph = domainforge.Graph()
72
+
73
+ # Create a complete model
74
+ warehouse = domainforge.Entity("Warehouse", "logistics")
75
+ warehouse.set_attribute("location", "NYC")
76
+
77
+ factory = domainforge.Entity("Factory", "manufacturing")
78
+ factory.set_attribute("capacity", 10000)
79
+
80
+ cameras = domainforge.Resource("Camera", "units", "inventory")
81
+ cameras.set_attribute("model", "X100")
82
+
83
+ graph.add_entity(warehouse)
84
+ graph.add_entity(factory)
85
+ graph.add_resource(cameras)
86
+
87
+ flow = domainforge.Flow(cameras.id, warehouse.id, factory.id, 500.0)
88
+ flow.set_attribute("priority", "high")
89
+ graph.add_flow(flow)
90
+
91
+ instance = domainforge.ResourceInstance(cameras.id, warehouse.id, "inventory")
92
+ instance.set_attribute("serial", "SN-001")
93
+ graph.add_instance(instance)
94
+
95
+ # Verify the graph state
96
+ assert graph.entity_count() == 2
97
+ assert graph.resource_count() == 1
98
+ assert graph.flow_count() == 1
99
+ assert graph.instance_count() == 1
100
+
101
+ # Verify we can retrieve and check attributes
102
+ retrieved_entity = graph.get_entity(warehouse.id)
103
+ assert retrieved_entity.get_attribute("location") == "NYC"
104
+
105
+
106
+ def test_error_handling_invalid_references():
107
+ """Test that proper errors are raised for invalid references"""
108
+ graph = domainforge.Graph()
109
+ warehouse = domainforge.Entity("Warehouse")
110
+ graph.add_entity(warehouse)
111
+
112
+ # Try to create flow with non-existent IDs
113
+ fake_resource_id = "00000000-0000-0000-0000-000000000000"
114
+ fake_entity_id = "11111111-1111-1111-1111-111111111111"
115
+
116
+ flow = domainforge.Flow(fake_resource_id, warehouse.id, fake_entity_id, 100.0)
117
+
118
+ with pytest.raises(ValueError):
119
+ graph.add_flow(flow)
120
+
121
+
122
+ def test_namespace_isolation():
123
+ """Test that namespaces properly isolate entities"""
124
+ graph = domainforge.Graph()
125
+
126
+ warehouse_logistics = domainforge.Entity("Warehouse", "logistics")
127
+ warehouse_storage = domainforge.Entity("Warehouse", "storage")
128
+
129
+ graph.add_entity(warehouse_logistics)
130
+ graph.add_entity(warehouse_storage)
131
+
132
+ assert graph.entity_count() == 2
133
+
134
+ # Both should exist independently
135
+ assert graph.has_entity(warehouse_logistics.id)
136
+ assert graph.has_entity(warehouse_storage.id)
@@ -0,0 +1,82 @@
1
+ import pytest
2
+ import domainforge
3
+
4
+
5
+ def test_parse_basic():
6
+ source = '''
7
+ Entity "Warehouse" in logistics
8
+ Entity "Factory" in logistics
9
+ Resource "Cameras" units
10
+ '''
11
+
12
+ graph = domainforge.Graph.parse(source)
13
+ assert graph.entity_count() == 2
14
+ assert graph.resource_count() == 1
15
+
16
+
17
+ def test_parse_with_flow():
18
+ source = '''
19
+ Entity "Warehouse"
20
+ Entity "Factory"
21
+ Resource "Cameras" units
22
+ Flow "Cameras" from "Warehouse" to "Factory" quantity 100
23
+ '''
24
+
25
+ graph = domainforge.Graph.parse(source)
26
+ assert graph.entity_count() == 2
27
+ assert graph.resource_count() == 1
28
+ assert graph.flow_count() == 1
29
+
30
+
31
+ def test_parse_complex():
32
+ source = '''
33
+ Entity "Supplier" in supply_chain
34
+ Entity "Warehouse" in supply_chain
35
+ Entity "Store" in retail
36
+
37
+ Resource "Widgets" units
38
+ Resource "Gadgets" units
39
+
40
+ Flow "Widgets" from "Supplier" to "Warehouse" quantity 500
41
+ Flow "Widgets" from "Warehouse" to "Store" quantity 300
42
+ Flow "Gadgets" from "Supplier" to "Warehouse" quantity 200
43
+ '''
44
+
45
+ graph = domainforge.Graph.parse(source)
46
+ assert graph.entity_count() == 3
47
+ assert graph.resource_count() == 2
48
+ assert graph.flow_count() == 3
49
+
50
+
51
+ def test_parse_invalid_syntax():
52
+ source = '''
53
+ Entity "Warehouse"
54
+ Invalid syntax here
55
+ '''
56
+
57
+ with pytest.raises(ValueError, match="Parse error"):
58
+ domainforge.Graph.parse(source)
59
+
60
+
61
+ def test_parse_empty():
62
+ source = ""
63
+ graph = domainforge.Graph.parse(source)
64
+ assert graph.entity_count() == 0
65
+
66
+
67
+ def test_parsed_graph_query():
68
+ source = '''
69
+ Entity "Warehouse"
70
+ Entity "Factory"
71
+ Resource "Steel" tons
72
+ Flow "Steel" from "Warehouse" to "Factory" quantity 50
73
+ '''
74
+
75
+ graph = domainforge.Graph.parse(source)
76
+
77
+ warehouse_id = graph.find_entity_by_name("Warehouse")
78
+ assert warehouse_id is not None
79
+
80
+ flows = graph.flows_from(warehouse_id)
81
+ assert len(flows) == 1
82
+ assert flows[0].quantity == 50.0