speclogician 0.0.0b1__tar.gz → 0.0.0.dev1__tar.gz

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 (172) hide show
  1. speclogician-0.0.0.dev1/PKG-INFO +21 -0
  2. speclogician-0.0.0.dev1/README.md +5 -0
  3. {speclogician-0.0.0b1 → speclogician-0.0.0.dev1}/pyproject.toml +1 -8
  4. speclogician-0.0.0.dev1/src/speclogician/agent/funcs.py +29 -0
  5. speclogician-0.0.0.dev1/src/speclogician/cmd/agent_cmd.py +89 -0
  6. speclogician-0.0.0.dev1/src/speclogician/cmd/data_cmd.py +24 -0
  7. speclogician-0.0.0.dev1/src/speclogician/cmd/model_cmd.py +42 -0
  8. speclogician-0.0.0.dev1/src/speclogician/cmd/overlay_cmd.py +30 -0
  9. speclogician-0.0.0.dev1/src/speclogician/cmd/scenario_cmd.py +61 -0
  10. speclogician-0.0.0.dev1/src/speclogician/cmd/state_cmd.py +52 -0
  11. speclogician-0.0.0.dev1/src/speclogician/data/artifact.py +21 -0
  12. speclogician-0.0.0.dev1/src/speclogician/data/container.py +36 -0
  13. {speclogician-0.0.0b1 → speclogician-0.0.0.dev1}/src/speclogician/data/mapping.py +18 -17
  14. speclogician-0.0.0.dev1/src/speclogician/data/refs.py +25 -0
  15. speclogician-0.0.0.dev1/src/speclogician/data/reports.py +11 -0
  16. speclogician-0.0.0.dev1/src/speclogician/data/traces.py +35 -0
  17. speclogician-0.0.0.dev1/src/speclogician/llms/llmtools.py +102 -0
  18. speclogician-0.0.0.dev1/src/speclogician/llms/overlay.py +264 -0
  19. speclogician-0.0.0.dev1/src/speclogician/main.py +73 -0
  20. speclogician-0.0.0.dev1/src/speclogician/modeling/component.py +15 -0
  21. speclogician-0.0.0.dev1/src/speclogician/modeling/conflict.py +12 -0
  22. speclogician-0.0.0.dev1/src/speclogician/modeling/domain.py +162 -0
  23. speclogician-0.0.0.dev1/src/speclogician/modeling/model.py +206 -0
  24. speclogician-0.0.0.dev1/src/speclogician/modeling/predicates.py +57 -0
  25. speclogician-0.0.0.dev1/src/speclogician/modeling/report.py +33 -0
  26. speclogician-0.0.0.dev1/src/speclogician/modeling/scenario.py +194 -0
  27. speclogician-0.0.0.dev1/src/speclogician/sl_cmd.py +76 -0
  28. speclogician-0.0.0.dev1/src/speclogician/state/change.py +148 -0
  29. speclogician-0.0.0.dev1/src/speclogician/state/state.py +249 -0
  30. speclogician-0.0.0.dev1/src/speclogician/tui/box.tcss +10 -0
  31. speclogician-0.0.0.dev1/src/speclogician/tui/tui.py +131 -0
  32. speclogician-0.0.0.dev1/src/speclogician/utils/__init__.py +9 -0
  33. speclogician-0.0.0.dev1/src/speclogician/utils/imx.py +195 -0
  34. speclogician-0.0.0.dev1/src/speclogician/utils/load.py +44 -0
  35. speclogician-0.0.0.dev1/src/speclogician/utils/prompt.md +1 -0
  36. speclogician-0.0.0b1/PKG-INFO +0 -116
  37. speclogician-0.0.0b1/README.md +0 -100
  38. speclogician-0.0.0b1/src/speclogician/commands/__init__.py +0 -15
  39. speclogician-0.0.0b1/src/speclogician/commands/cmd_ch.py +0 -616
  40. speclogician-0.0.0b1/src/speclogician/commands/cmd_find.py +0 -256
  41. speclogician-0.0.0b1/src/speclogician/commands/cmd_view.py +0 -202
  42. speclogician-0.0.0b1/src/speclogician/commands/runner.py +0 -149
  43. speclogician-0.0.0b1/src/speclogician/commands/utils.py +0 -101
  44. speclogician-0.0.0b1/src/speclogician/data/artifact.py +0 -63
  45. speclogician-0.0.0b1/src/speclogician/data/container.py +0 -402
  46. speclogician-0.0.0b1/src/speclogician/data/refs.py +0 -24
  47. speclogician-0.0.0b1/src/speclogician/data/traces.py +0 -26
  48. speclogician-0.0.0b1/src/speclogician/demos/.DS_Store +0 -0
  49. speclogician-0.0.0b1/src/speclogician/demos/cmd_demo.py +0 -278
  50. speclogician-0.0.0b1/src/speclogician/demos/loader.py +0 -135
  51. speclogician-0.0.0b1/src/speclogician/demos/model.py +0 -27
  52. speclogician-0.0.0b1/src/speclogician/demos/runner.py +0 -51
  53. speclogician-0.0.0b1/src/speclogician/logic/__init__.py +0 -11
  54. speclogician-0.0.0b1/src/speclogician/logic/api/__init__.py +0 -29
  55. speclogician-0.0.0b1/src/speclogician/logic/api/client.py +0 -606
  56. speclogician-0.0.0b1/src/speclogician/logic/api/decomp.py +0 -67
  57. speclogician-0.0.0b1/src/speclogician/logic/api/scenario.py +0 -102
  58. speclogician-0.0.0b1/src/speclogician/logic/api/traces.py +0 -59
  59. speclogician-0.0.0b1/src/speclogician/logic/lib/__init__.py +0 -19
  60. speclogician-0.0.0b1/src/speclogician/logic/lib/complement.py +0 -107
  61. speclogician-0.0.0b1/src/speclogician/logic/lib/domain_model.py +0 -59
  62. speclogician-0.0.0b1/src/speclogician/logic/lib/predicates.py +0 -151
  63. speclogician-0.0.0b1/src/speclogician/logic/lib/scenarios.py +0 -369
  64. speclogician-0.0.0b1/src/speclogician/logic/lib/traces.py +0 -114
  65. speclogician-0.0.0b1/src/speclogician/logic/lib/transitions.py +0 -104
  66. speclogician-0.0.0b1/src/speclogician/logic/main.py +0 -246
  67. speclogician-0.0.0b1/src/speclogician/logic/strings.py +0 -194
  68. speclogician-0.0.0b1/src/speclogician/logic/utils.py +0 -135
  69. speclogician-0.0.0b1/src/speclogician/main.py +0 -139
  70. speclogician-0.0.0b1/src/speclogician/modeling/__init__.py +0 -31
  71. speclogician-0.0.0b1/src/speclogician/modeling/complement.py +0 -104
  72. speclogician-0.0.0b1/src/speclogician/modeling/component.py +0 -71
  73. speclogician-0.0.0b1/src/speclogician/modeling/conflict.py +0 -26
  74. speclogician-0.0.0b1/src/speclogician/modeling/domain.py +0 -349
  75. speclogician-0.0.0b1/src/speclogician/modeling/predicates.py +0 -59
  76. speclogician-0.0.0b1/src/speclogician/modeling/scenario.py +0 -162
  77. speclogician-0.0.0b1/src/speclogician/modeling/spec.py +0 -306
  78. speclogician-0.0.0b1/src/speclogician/modeling/spec_stats.py +0 -39
  79. speclogician-0.0.0b1/src/speclogician/presentation/api.py +0 -244
  80. speclogician-0.0.0b1/src/speclogician/presentation/builders/_links.py +0 -44
  81. speclogician-0.0.0b1/src/speclogician/presentation/builders/container.py +0 -53
  82. speclogician-0.0.0b1/src/speclogician/presentation/builders/data_artifact.py +0 -42
  83. speclogician-0.0.0b1/src/speclogician/presentation/builders/domain.py +0 -54
  84. speclogician-0.0.0b1/src/speclogician/presentation/builders/instances_list.py +0 -38
  85. speclogician-0.0.0b1/src/speclogician/presentation/builders/predicate.py +0 -51
  86. speclogician-0.0.0b1/src/speclogician/presentation/builders/recommendations.py +0 -41
  87. speclogician-0.0.0b1/src/speclogician/presentation/builders/scenario.py +0 -41
  88. speclogician-0.0.0b1/src/speclogician/presentation/builders/scenario_complement.py +0 -82
  89. speclogician-0.0.0b1/src/speclogician/presentation/builders/smart_find.py +0 -39
  90. speclogician-0.0.0b1/src/speclogician/presentation/builders/spec.py +0 -39
  91. speclogician-0.0.0b1/src/speclogician/presentation/builders/state_diff.py +0 -150
  92. speclogician-0.0.0b1/src/speclogician/presentation/builders/state_instance.py +0 -42
  93. speclogician-0.0.0b1/src/speclogician/presentation/builders/state_instance_summary.py +0 -84
  94. speclogician-0.0.0b1/src/speclogician/presentation/builders/trace.py +0 -58
  95. speclogician-0.0.0b1/src/speclogician/presentation/ctx.py +0 -38
  96. speclogician-0.0.0b1/src/speclogician/presentation/models/container.py +0 -44
  97. speclogician-0.0.0b1/src/speclogician/presentation/models/data_artifact.py +0 -33
  98. speclogician-0.0.0b1/src/speclogician/presentation/models/domain.py +0 -50
  99. speclogician-0.0.0b1/src/speclogician/presentation/models/instances_list.py +0 -23
  100. speclogician-0.0.0b1/src/speclogician/presentation/models/predicate.py +0 -60
  101. speclogician-0.0.0b1/src/speclogician/presentation/models/recommendations.py +0 -34
  102. speclogician-0.0.0b1/src/speclogician/presentation/models/scenario.py +0 -31
  103. speclogician-0.0.0b1/src/speclogician/presentation/models/scenario_complement.py +0 -40
  104. speclogician-0.0.0b1/src/speclogician/presentation/models/smart_find.py +0 -34
  105. speclogician-0.0.0b1/src/speclogician/presentation/models/spec.py +0 -32
  106. speclogician-0.0.0b1/src/speclogician/presentation/models/state_diff.py +0 -34
  107. speclogician-0.0.0b1/src/speclogician/presentation/models/state_instance.py +0 -31
  108. speclogician-0.0.0b1/src/speclogician/presentation/models/state_instance_summary.py +0 -102
  109. speclogician-0.0.0b1/src/speclogician/presentation/models/trace.py +0 -42
  110. speclogician-0.0.0b1/src/speclogician/presentation/preview/__init__.py +0 -13
  111. speclogician-0.0.0b1/src/speclogician/presentation/preview/cli.py +0 -50
  112. speclogician-0.0.0b1/src/speclogician/presentation/preview/fixtures/__init__.py +0 -205
  113. speclogician-0.0.0b1/src/speclogician/presentation/preview/fixtures/artifact_container.py +0 -150
  114. speclogician-0.0.0b1/src/speclogician/presentation/preview/fixtures/data_artifact.py +0 -144
  115. speclogician-0.0.0b1/src/speclogician/presentation/preview/fixtures/domain_model.py +0 -162
  116. speclogician-0.0.0b1/src/speclogician/presentation/preview/fixtures/instances_list.py +0 -162
  117. speclogician-0.0.0b1/src/speclogician/presentation/preview/fixtures/predicate.py +0 -184
  118. speclogician-0.0.0b1/src/speclogician/presentation/preview/fixtures/scenario.py +0 -84
  119. speclogician-0.0.0b1/src/speclogician/presentation/preview/fixtures/scenario_complement.py +0 -81
  120. speclogician-0.0.0b1/src/speclogician/presentation/preview/fixtures/smart_find.py +0 -140
  121. speclogician-0.0.0b1/src/speclogician/presentation/preview/fixtures/spec.py +0 -95
  122. speclogician-0.0.0b1/src/speclogician/presentation/preview/fixtures/state_diff.py +0 -158
  123. speclogician-0.0.0b1/src/speclogician/presentation/preview/fixtures/state_instance.py +0 -128
  124. speclogician-0.0.0b1/src/speclogician/presentation/preview/fixtures/state_instance_summary.py +0 -80
  125. speclogician-0.0.0b1/src/speclogician/presentation/preview/fixtures/trace.py +0 -206
  126. speclogician-0.0.0b1/src/speclogician/presentation/preview/registry.py +0 -42
  127. speclogician-0.0.0b1/src/speclogician/presentation/renderers/__init__.py +0 -24
  128. speclogician-0.0.0b1/src/speclogician/presentation/renderers/container.py +0 -136
  129. speclogician-0.0.0b1/src/speclogician/presentation/renderers/data_artifact.py +0 -144
  130. speclogician-0.0.0b1/src/speclogician/presentation/renderers/domain.py +0 -123
  131. speclogician-0.0.0b1/src/speclogician/presentation/renderers/instances_list.py +0 -120
  132. speclogician-0.0.0b1/src/speclogician/presentation/renderers/predicate.py +0 -180
  133. speclogician-0.0.0b1/src/speclogician/presentation/renderers/recommendations.py +0 -90
  134. speclogician-0.0.0b1/src/speclogician/presentation/renderers/scenario.py +0 -94
  135. speclogician-0.0.0b1/src/speclogician/presentation/renderers/scenario_complement.py +0 -59
  136. speclogician-0.0.0b1/src/speclogician/presentation/renderers/smart_find.py +0 -307
  137. speclogician-0.0.0b1/src/speclogician/presentation/renderers/spec.py +0 -105
  138. speclogician-0.0.0b1/src/speclogician/presentation/renderers/state_diff.py +0 -102
  139. speclogician-0.0.0b1/src/speclogician/presentation/renderers/state_instance.py +0 -82
  140. speclogician-0.0.0b1/src/speclogician/presentation/renderers/state_instance_summary.py +0 -143
  141. speclogician-0.0.0b1/src/speclogician/presentation/renderers/trace.py +0 -122
  142. speclogician-0.0.0b1/src/speclogician/shell/app.py +0 -170
  143. speclogician-0.0.0b1/src/speclogician/shell/shell_ch.py +0 -263
  144. speclogician-0.0.0b1/src/speclogician/shell/shell_view.py +0 -153
  145. speclogician-0.0.0b1/src/speclogician/state/change.py +0 -428
  146. speclogician-0.0.0b1/src/speclogician/state/change_result.py +0 -32
  147. speclogician-0.0.0b1/src/speclogician/state/diff.py +0 -191
  148. speclogician-0.0.0b1/src/speclogician/state/inst.py +0 -574
  149. speclogician-0.0.0b1/src/speclogician/state/recommendation.py +0 -13
  150. speclogician-0.0.0b1/src/speclogician/state/recommender.py +0 -577
  151. speclogician-0.0.0b1/src/speclogician/state/state.py +0 -465
  152. speclogician-0.0.0b1/src/speclogician/state/state_stats.py +0 -133
  153. speclogician-0.0.0b1/src/speclogician/tui/app.py +0 -257
  154. speclogician-0.0.0b1/src/speclogician/tui/app.tcss +0 -160
  155. speclogician-0.0.0b1/src/speclogician/tui/demo.py +0 -45
  156. speclogician-0.0.0b1/src/speclogician/tui/images/speclogician-full.png +0 -0
  157. speclogician-0.0.0b1/src/speclogician/tui/images/speclogician-minimal.png +0 -0
  158. speclogician-0.0.0b1/src/speclogician/tui/main_screen.py +0 -454
  159. speclogician-0.0.0b1/src/speclogician/tui/splash_screen.py +0 -51
  160. speclogician-0.0.0b1/src/speclogician/tui/stats_screen.py +0 -125
  161. speclogician-0.0.0b1/src/speclogician/utils/__init__.py +0 -78
  162. speclogician-0.0.0b1/src/speclogician/utils/load.py +0 -166
  163. speclogician-0.0.0b1/src/speclogician/utils/prompt.md +0 -325
  164. speclogician-0.0.0b1/src/speclogician/utils/testing.py +0 -151
  165. {speclogician-0.0.0b1 → speclogician-0.0.0.dev1}/src/speclogician/__init__.py +0 -0
  166. {speclogician-0.0.0b1/src/speclogician/data → speclogician-0.0.0.dev1/src/speclogician/agent}/__init__.py +0 -0
  167. {speclogician-0.0.0b1/src/speclogician/presentation → speclogician-0.0.0.dev1/src/speclogician/cmd}/__init__.py +0 -0
  168. {speclogician-0.0.0b1/src/speclogician/presentation/builders → speclogician-0.0.0.dev1/src/speclogician/data}/__init__.py +0 -0
  169. {speclogician-0.0.0b1/src/speclogician/presentation/models → speclogician-0.0.0.dev1/src/speclogician/llms}/__init__.py +0 -0
  170. {speclogician-0.0.0b1/src/speclogician/state → speclogician-0.0.0.dev1/src/speclogician/modeling}/__init__.py +0 -0
  171. {speclogician-0.0.0b1 → speclogician-0.0.0.dev1}/src/speclogician/py.typed +0 -0
  172. {speclogician-0.0.0b1/src/speclogician/tui → speclogician-0.0.0.dev1/src/speclogician/state}/__init__.py +0 -0
@@ -0,0 +1,21 @@
1
+ Metadata-Version: 2.3
2
+ Name: speclogician
3
+ Version: 0.0.0.dev1
4
+ Summary: SpecLogicain AI framework for data-driven formal program specification synthesis, verification and analysis
5
+ Author: denis, hongyu
6
+ Author-email: denis <denis@imandra.ai>, hongyu <hongyu@imandra.ai>
7
+ Requires-Dist: imandrax-api-models>=18.0.0
8
+ Requires-Dist: iml-query>=0.5.1
9
+ Requires-Dist: pydantic>=2.12.5
10
+ Requires-Dist: rich>=14.2.0
11
+ Requires-Dist: textual>=6.11.0
12
+ Requires-Dist: typer>=0.20.0
13
+ Requires-Python: >=3.12
14
+ Project-URL: Homepage, https://speclogician.dev/
15
+ Description-Content-Type: text/markdown
16
+
17
+ # SpecLogician
18
+ SpecLogicain AI framework for data-driven formal program specification synthesis, verification and analysis
19
+
20
+
21
+ www.speclogician.dev
@@ -0,0 +1,5 @@
1
+ # SpecLogician
2
+ SpecLogicain AI framework for data-driven formal program specification synthesis, verification and analysis
3
+
4
+
5
+ www.speclogician.dev
@@ -1,6 +1,6 @@
1
1
  [project]
2
2
  name = "speclogician"
3
- version = "0.0.0b1"
3
+ version = "0.0.0.dev1"
4
4
  description = "SpecLogicain AI framework for data-driven formal program specification synthesis, verification and analysis"
5
5
  readme = "README.md"
6
6
  authors = [
@@ -21,12 +21,5 @@ dependencies = [
21
21
  requires = ["uv_build>=0.8.22,<0.9.0"]
22
22
  build-backend = "uv_build"
23
23
 
24
- [dependency-groups]
25
- dev = [
26
- "dotenv>=0.9.9",
27
- "pytest>=9.0.2",
28
- "pytest-asyncio>=1.3.0",
29
- ]
30
-
31
24
  [project.urls]
32
25
  Homepage = "https://speclogician.dev/"
@@ -0,0 +1,29 @@
1
+ #
2
+ # Imandra Inc.
3
+ #
4
+ # agent.py
5
+ #
6
+
7
+
8
+ import sys
9
+ from pathlib import Path
10
+
11
+ from ..state.state import State
12
+ from ..llms.llmtools import test_formalizer
13
+ from ..llms.overlay import Overlay
14
+
15
+ def process_test_file (
16
+ path : Path,
17
+ state : State,
18
+ overlay : Overlay
19
+ ) -> State:
20
+ """
21
+ Process a file state to the state
22
+ """
23
+
24
+ try:
25
+ tf = test_formalizer (str(path), overlay, state)
26
+ except Exception as e:
27
+ raise Exception (f"Failed to process test file: []")
28
+
29
+ return state.add_test_formalization(tf)
@@ -0,0 +1,89 @@
1
+ #
2
+ # Imandra Inc.
3
+ #
4
+ # agent_cmd.py
5
+ #
6
+
7
+ import typer
8
+ import os
9
+ from pathlib import Path
10
+ from typing import Annotated
11
+
12
+ from rich.progress import track
13
+
14
+ from ..llms.overlay import Overlays
15
+ from ..agent.funcs import process_test_file
16
+ from ..state.state import State
17
+ from ..utils import console
18
+ from ..utils.load import load_overlays, load_state
19
+
20
+ app = typer.Typer()
21
+
22
+
23
+ @app.command(help="Add a single file to the formalization state")
24
+ def proc_test_file (
25
+ filepath : Annotated[str, typer.Argument()],
26
+ overlay_name : Annotated[str, typer.Argument(help="Overlay to use. It should also contain the file extension we'll use")]
27
+ ):
28
+
29
+ overlays = load_overlays()
30
+ state = load_state()
31
+
32
+ tgt_path = Path(filepath).parent / filepath
33
+
34
+ overlay = overlays.get(overlay_name)
35
+ if overlay is None:
36
+ console.print(f":warning: Could not find an overlay named {overlay_name}!")
37
+ return
38
+
39
+ try:
40
+ process_test_file(tgt_path, state, overlay)
41
+ except Exception as e:
42
+ console.print(f"🛑 Caught an error when adding file: {e}")
43
+ return
44
+
45
+ # Add the state definition here
46
+
47
+ typer.secho(f"✅ Successfully added {filepath} to the formalization state!")
48
+
49
+ @app.command(help="Run full cycle formalization for a specified directory")
50
+ def proc_test_dir (
51
+ dirpath : Annotated[str, typer.Argument(help="Target directory with tests that should be formalized")],
52
+ overlay_name : Annotated[str, typer.Argument(help="Overlay to use. It should also contain the file extension we'll use")],
53
+ clean : Annotated[bool, typer.Option(help="Should we override any tests from these files already present in the state?")] = False
54
+ ):
55
+
56
+ state = load_state()
57
+
58
+ overlays = load_overlays()
59
+ overlay = overlays.get(overlay_name)
60
+
61
+ if overlay is None:
62
+ typer.secho(f"🛑 Could not find an overlay named {overlay_name}!", err=True)
63
+ return
64
+
65
+ filepaths = os.listdir(dirpath)
66
+ filepaths = list(filter(lambda x: x.endswith(overlay.ext.strip()), filepaths))
67
+
68
+ console.print(f"Identified {len(filepaths)} to process")
69
+
70
+ count = 0
71
+
72
+ for i in track(range(len(filepaths)), description=f"Processing {dirpath}..."):
73
+
74
+ try:
75
+ process_test_file(Path(filepaths[i]), state, overlay)
76
+ except Exception as e:
77
+ console.print(f"Failed on {filepaths[i]}: {e}")
78
+
79
+ count += 1
80
+
81
+ console.print(f":robot:Processed {count} files!")
82
+
83
+ try:
84
+ state.save(dirpath)
85
+ except Exception as e:
86
+ typer.echo(f"🛑 Caught error when saving the formalization state: {e}")
87
+ return
88
+
89
+ typer.secho(f"✅ Successfully saved the formalization state to {dirpath}")
@@ -0,0 +1,24 @@
1
+ #
2
+ # Imandra Inc.
3
+ #
4
+ # data_cmd.py
5
+ #
6
+
7
+ import typer
8
+ from typing import Annotated
9
+
10
+ app = typer.Typer()
11
+
12
+ @app.command(name="list")
13
+ def data_list():
14
+ """
15
+ List the available data sources
16
+ """
17
+ pass
18
+
19
+ tests_app = typer.Typer()
20
+ @tests_app.command(name="tests")
21
+ def list (
22
+ max_num_tests : Annotated[int, typer.Argument(help="Maximum number of tests to displayed")]
23
+ ):
24
+ pass
@@ -0,0 +1,42 @@
1
+ #
2
+ # Imandra Inc.
3
+ #
4
+ # model_cmd.py
5
+ #
6
+
7
+ import typer
8
+ from typing import Annotated
9
+ from rich.syntax import Syntax
10
+
11
+ from ..utils import console
12
+ from ..utils.load import load_state
13
+
14
+ app = typer.Typer()
15
+
16
+ @app.command(name="summary", help="")
17
+ def summary():
18
+ """
19
+ """
20
+
21
+ state = load_state()
22
+
23
+ console.print(state.curr_state().model.report())
24
+
25
+ @app.command(name="code", help="Generate the IML code for the Domain Model")
26
+ def get_code(
27
+ filepath : Annotated[str|None, typer.Option(help="Output filepath")] = None
28
+ ):
29
+
30
+ state = load_state()
31
+
32
+ console.print(Syntax(state.curr_state().model.domain_model.to_iml(), "OCaml"))
33
+
34
+ if filepath is not None:
35
+ try:
36
+ with open(filepath, 'w') as outfile:
37
+ print(state.curr_state().model.domain_model.to_iml(), file=outfile)
38
+ except Exception as e:
39
+ console.print(f"🛑 Failed to write domain model to disk: {e}",)
40
+ return
41
+
42
+ console.print(f"✅ Successfully wrote domain model to disk: {filepath}")
@@ -0,0 +1,30 @@
1
+ #
2
+ # Imandra Inc.
3
+ #
4
+ # overlay_cmd.py
5
+ #
6
+
7
+ from typing import Annotated
8
+ from rich import print as printr
9
+ import typer
10
+
11
+ from ..utils.load import load_overlays
12
+
13
+ app = typer.Typer()
14
+
15
+ @app.command(name="list", help="list the available overlays")
16
+ def list_():
17
+ overlays = load_overlays()
18
+ overlays.list_overlays()
19
+
20
+ @app.command(name="view", help="View individual template")
21
+ def view(
22
+ name : Annotated[str, typer.Argument(help="Name of the template to view")]
23
+ ):
24
+
25
+ overlays = load_overlays()
26
+ if name not in overlays.names():
27
+ typer.secho(f"🛑 No template with name {name} found!", err=True)
28
+ return
29
+
30
+ printr(overlays.get(name))
@@ -0,0 +1,61 @@
1
+ #
2
+ # Imandra Inc.
3
+ #
4
+ # scenario_cmd.py
5
+ #
6
+
7
+ import typer
8
+
9
+ from ..state.state import State
10
+ from ..utils.load import load_state
11
+
12
+ from typing import Annotated
13
+
14
+
15
+ app = typer.Typer()
16
+
17
+ @app.command(name="summary", help="Summary of the available scenarios")
18
+ def summary():
19
+ """
20
+ """
21
+
22
+ state = load_state()
23
+
24
+ @app.command(name="view", help="View a specific scenario")
25
+ def view(
26
+ sc_id : int,
27
+ scenario_name : str
28
+ ):
29
+ """
30
+ """
31
+
32
+ state = load_state()
33
+
34
+ @app.command(name="rm", help="Remove a scenario")
35
+ def rm_scenario():
36
+ """
37
+ """
38
+
39
+ state = load_state()
40
+
41
+ @app.command(name="add", help="Add a scenario")
42
+ def add_scenario(
43
+ name : Annotated[str, typer.Argument(help="Name to be given to the scenario, must be unique")]
44
+ ):
45
+ """
46
+ """
47
+ state = load_state()
48
+
49
+ @app.command(name="edit", help="Edit a scenario")
50
+ def edit_scenario():
51
+ """
52
+ """
53
+
54
+ state = load_state()
55
+
56
+ @app.command(name="search", help="Search for a particular scenario by predicate/transition functions")
57
+ def search(q : str):
58
+ """
59
+ """
60
+
61
+ state = load_state()
@@ -0,0 +1,52 @@
1
+ #
2
+ # Imandra Inc.
3
+ #
4
+ # state_cmd.py
5
+ #
6
+
7
+ import typer
8
+ import sys
9
+ from typing import Annotated
10
+
11
+ from ..state.state import State
12
+ from ..utils import console
13
+ from ..utils.load import load_state
14
+
15
+ global state
16
+ state : State
17
+
18
+ app = typer.Typer()
19
+
20
+ @app.command(name="list", help="List all state instances")
21
+ def list_states (
22
+ max_num_states : Annotated[int, typer.Argument(help="Maximum number of states")]=10
23
+ ):
24
+ """
25
+ List the state instances
26
+ """
27
+ state = load_state()
28
+ console.print(state.inst_list())
29
+
30
+ @app.command(name="set", help="Set current state to a specific idx in the list")
31
+ def set (
32
+ state_idx : Annotated[int, typer.Argument(help="")]
33
+ ):
34
+
35
+ state = load_state()
36
+
37
+ try:
38
+ state.set_curr_state_idx (state_idx)
39
+ except Exception as e:
40
+ console.print(f"Caught error: {e}")
41
+ sys.exit(0)
42
+
43
+ console.print("Update current state idx to {state_idx}")
44
+
45
+ @app.command(name="summary", help="Provide summary of the current state instance")
46
+ def summary():
47
+ """
48
+ Provide a summary of the current state
49
+ """
50
+
51
+ state : State = load_state()
52
+ console.print(state.curr_state().report())
@@ -0,0 +1,21 @@
1
+ #
2
+ # Imandra Inc.
3
+ #
4
+ # artifact.py
5
+ #
6
+
7
+ import uuid
8
+ from pydantic import BaseModel, Field
9
+
10
+ class Artifact(BaseModel):
11
+ """
12
+ """
13
+ art_id : str = Field(default_factory=lambda: str(uuid.uuid4())) # assigned task ID, new one created if not provided
14
+
15
+ class TraceArtifact(Artifact):
16
+
17
+ given : str
18
+ when : str
19
+ then : str
20
+
21
+ valid_iml : bool = False
@@ -0,0 +1,36 @@
1
+ #
2
+ # Imandra Inc.
3
+ #
4
+ # container.py
5
+ #
6
+
7
+ from pydantic import BaseModel
8
+
9
+ from .traces import TestTrace, LogTrace
10
+ from .refs import DocRef, SrcCodeRef
11
+
12
+ class ArtifactSummaryInfo(BaseModel):
13
+ """ """
14
+ pass
15
+
16
+ class ArtifactContainer(BaseModel):
17
+ """
18
+ Artifact container
19
+ """
20
+
21
+ test_traces : list[TestTrace] = []
22
+ log_traces : list[LogTrace] = []
23
+ doc_ref : list[DocRef] = []
24
+ src_code : list[SrcCodeRef] = []
25
+
26
+
27
+ def info(self):
28
+ """
29
+ """
30
+
31
+ return {'hello': 123}
32
+
33
+ def add(self):
34
+ """ """
35
+ pass
36
+
@@ -1,10 +1,11 @@
1
1
  #
2
2
  # Imandra Inc.
3
3
  #
4
- # speclogician/data/mapping.py
4
+ # mapping.py
5
5
  #
6
6
 
7
- from pydantic import BaseModel, Field
7
+ from pydantic import BaseModel
8
+ from typing import Dict
8
9
 
9
10
  from enum import StrEnum
10
11
 
@@ -18,39 +19,39 @@ class ArtifactMap(BaseModel):
18
19
  handle potentially large datasets (e.g. massive logs)
19
20
  """
20
21
 
21
- art_to_comp_map: dict[str, list[str]] = Field(default_factory=dict)
22
- comp_to_art_map: dict[str, list[str]] = Field(default_factory=dict)
22
+ art_to_comp_map : Dict[str, list[str]] = {}
23
+ comp_to_art_map : Dict[str, list[str]] = {}
23
24
 
24
- def add_connection (self, art_id : str, comp_name : str):
25
+ def add_connection (self, art_id : str, comp_id : str):
25
26
  """
26
27
  Add a link between artifact and model component
27
28
  """
28
29
  if art_id not in self.art_to_comp_map:
29
30
  self.art_to_comp_map[art_id] = []
30
31
 
31
- if comp_name not in self.art_to_comp_map[art_id]:
32
- self.art_to_comp_map[art_id].append(comp_name)
32
+ if comp_id not in self.art_to_comp_map[art_id]:
33
+ self.art_to_comp_map[art_id].append(comp_id)
33
34
 
34
- if comp_name not in self.comp_to_art_map:
35
- self.comp_to_art_map[comp_name] = []
35
+ if comp_id not in self.comp_to_art_map:
36
+ self.comp_to_art_map[comp_id] = []
36
37
 
37
- if art_id not in self.comp_to_art_map[comp_name]:
38
- self.comp_to_art_map[comp_name].append(art_id)
38
+ if art_id not in self.comp_to_art_map[comp_id]:
39
+ self.comp_to_art_map[comp_id].append(art_id)
39
40
 
40
- def rem_connection (self, artifact_id : str, comp_name : str):
41
+ def rem_connection (self, artifact_id : str, comp_id : str):
41
42
  """
42
43
  Remove a connection
43
44
  """
44
45
 
45
46
  if artifact_id in self.art_to_comp_map:
46
- if comp_name in self.art_to_comp_map[artifact_id]:
47
- self.art_to_comp_map[artifact_id].remove(comp_name)
47
+ if comp_id in self.art_to_comp_map[artifact_id]:
48
+ self.art_to_comp_map[artifact_id].remove(comp_id)
48
49
  else:
49
50
  return False
50
51
 
51
- if comp_name in self.comp_to_art_map:
52
- if artifact_id in self.comp_to_art_map[comp_name]:
53
- self.comp_to_art_map[comp_name].remove(artifact_id)
52
+ if comp_id in self.comp_to_art_map:
53
+ if artifact_id in self.comp_to_art_map[comp_id]:
54
+ self.comp_to_art_map[comp_id].remove(artifact_id)
54
55
 
55
56
  def rem_element (self, elem_type : ElementType, str_id : str):
56
57
  """
@@ -0,0 +1,25 @@
1
+ #
2
+ # Imandra Inc.
3
+ #
4
+ # refs.py
5
+ #
6
+
7
+ from .artifact import Artifact
8
+
9
+ class DocRef(Artifact):
10
+ """
11
+ Documentation reference
12
+ """
13
+ meta : str
14
+ text : str
15
+
16
+ class SrcCodeRef(Artifact):
17
+ """
18
+ Source code reference
19
+ """
20
+
21
+ meta : str #
22
+ language : str #
23
+ file_path : str #
24
+ src_code : str #
25
+ iml_code : str #
@@ -0,0 +1,11 @@
1
+ #
2
+ # Imandra Inc.
3
+ #
4
+ # reports.py
5
+ #
6
+
7
+ from pydantic import BaseModel
8
+
9
+
10
+ class TestFormalization(BaseModel):
11
+ pass
@@ -0,0 +1,35 @@
1
+ #
2
+ # Imandra Inc.
3
+ #
4
+ # trace.py
5
+ #
6
+
7
+ from .artifact import TraceArtifact
8
+
9
+ class TestTrace (TraceArtifact):
10
+ """
11
+ Test trace formalization
12
+ """
13
+
14
+ name : str # Test case name
15
+ filepath : str # Original test filepath
16
+ language : str # Language of the original source code
17
+ contents : str # Original test contents
18
+ time : str # Time when this done
19
+
20
+ # Contain
21
+
22
+ class LogTrace(TraceArtifact):
23
+ """
24
+ Log tace formalization
25
+ """
26
+
27
+ filename : str #
28
+ contents : str # Contents of the log entry
29
+
30
+ # Formalized entry
31
+ given : str
32
+ when : str
33
+ then : str
34
+
35
+
@@ -0,0 +1,102 @@
1
+ #
2
+ # Imandra Inc.
3
+ #
4
+ # llmtools.py
5
+ #
6
+
7
+ import datetime, os, dotenv, sys, yaml, typer
8
+ from typing import Optional
9
+ from pathlib import Path
10
+ from ..data.reports import TestFormalization
11
+ from llms.overlay import Overlay
12
+
13
+ #from langchain_anthropic import ChatAnthropic
14
+ dotenv.load_dotenv("../.env")
15
+
16
+ llm = None
17
+
18
+ #ChatAnthropic (
19
+ # model_name="claude-sonnet-4-20250514",
20
+ # api_key=os.environ["ANTHROPIC_API_KEY"],
21
+ #)
22
+
23
+
24
+ def test_formalizer (
25
+ filepath : str,
26
+ overlay : Overlay,
27
+ domain_model : Optional[str] = "N/A",
28
+ ) -> TestFormalization:
29
+ """
30
+ Returns a tuple of the logic and the type model
31
+ """
32
+
33
+ test_case = Path(filepath).read_text()
34
+ try:
35
+ generic_prompt = Path("../prompts/generic.md").read_text()
36
+ except Exception as e:
37
+ print(f"Failed to load in the generic prompt: {e}")
38
+ sys.exit(0)
39
+
40
+ prompt = f"""
41
+ {generic_prompt}
42
+
43
+ {overlay}
44
+
45
+ Domain model:
46
+ ----
47
+ {domain_model}
48
+ ----
49
+
50
+ Test case:
51
+ ----
52
+ {test_case}
53
+ ----
54
+ """
55
+
56
+ structured_model = llm.with_structured_output(FormalizationResponse)
57
+
58
+ # Let's call the LLM
59
+ try:
60
+ response : FormalizationResponse = structured_model.invoke(prompt)
61
+ except Exception as e:
62
+ typer.secho(f"Failed to make the LLM call: {e}", err=True)
63
+ sys.exit(0)
64
+
65
+ tf = TestFormalization(
66
+ name = response.test_name_str,
67
+ language = overlay.language,
68
+ filepath = filepath,
69
+ contents = test_case,
70
+ time = str(datetime.datetime.now()),
71
+ scenarios = response.scenarios,
72
+ domain_model = response.domain_model,
73
+ )
74
+
75
+ return tf
76
+
77
+ def retry_test_formalization (
78
+ tf : TestFormalization,
79
+ model_response : str,
80
+ ) -> TestFormalization:
81
+ """
82
+ Make the call again to
83
+ """
84
+
85
+ return tf
86
+
87
+ if __name__ == "__main__":
88
+
89
+ base_dir = "../data/gherkin"
90
+ paths = os.listdir(base_dir)
91
+ overlay = Overlay.from_file("../overlays/gherkin.yaml")
92
+ domain_model : str = "N/A"
93
+
94
+ responses : list[LLMResponse] = []
95
+
96
+ for path in paths:
97
+ r = test_formalizer(os.path.join(base_dir, paths[0]), overlay, domain_model)
98
+ responses.append(r)
99
+ domain_model = r.domain_model
100
+
101
+ for r in responses:
102
+ print (yaml.dump(r, default_flow_style=False))