speclogician 0.0.0b1__py3-none-any.whl → 0.0.0.dev1__py3-none-any.whl

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 (153) hide show
  1. speclogician/agent/funcs.py +29 -0
  2. speclogician/cmd/agent_cmd.py +89 -0
  3. speclogician/cmd/data_cmd.py +24 -0
  4. speclogician/cmd/model_cmd.py +42 -0
  5. speclogician/cmd/overlay_cmd.py +30 -0
  6. speclogician/cmd/scenario_cmd.py +61 -0
  7. speclogician/cmd/state_cmd.py +52 -0
  8. speclogician/data/artifact.py +8 -50
  9. speclogician/data/container.py +18 -384
  10. speclogician/data/mapping.py +18 -17
  11. speclogician/data/refs.py +12 -11
  12. speclogician/data/reports.py +11 -0
  13. speclogician/data/traces.py +15 -6
  14. speclogician/llms/llmtools.py +102 -0
  15. speclogician/llms/overlay.py +264 -0
  16. speclogician/main.py +36 -102
  17. speclogician/modeling/__init__.py +0 -31
  18. speclogician/modeling/component.py +4 -60
  19. speclogician/modeling/conflict.py +5 -19
  20. speclogician/modeling/domain.py +93 -280
  21. speclogician/modeling/model.py +206 -0
  22. speclogician/modeling/predicates.py +20 -22
  23. speclogician/modeling/report.py +33 -0
  24. speclogician/modeling/scenario.py +119 -87
  25. speclogician/sl_cmd.py +76 -0
  26. speclogician/state/change.py +98 -378
  27. speclogician/state/state.py +183 -399
  28. speclogician/tui/box.tcss +10 -0
  29. speclogician/tui/tui.py +131 -0
  30. speclogician/utils/__init__.py +1 -70
  31. speclogician/utils/imx.py +195 -0
  32. speclogician/utils/load.py +25 -147
  33. speclogician/utils/prompt.md +1 -325
  34. speclogician-0.0.0.dev1.dist-info/METADATA +21 -0
  35. speclogician-0.0.0.dev1.dist-info/RECORD +43 -0
  36. speclogician/commands/__init__.py +0 -15
  37. speclogician/commands/cmd_ch.py +0 -616
  38. speclogician/commands/cmd_find.py +0 -256
  39. speclogician/commands/cmd_view.py +0 -202
  40. speclogician/commands/runner.py +0 -149
  41. speclogician/commands/utils.py +0 -101
  42. speclogician/demos/.DS_Store +0 -0
  43. speclogician/demos/cmd_demo.py +0 -278
  44. speclogician/demos/loader.py +0 -135
  45. speclogician/demos/model.py +0 -27
  46. speclogician/demos/runner.py +0 -51
  47. speclogician/logic/__init__.py +0 -11
  48. speclogician/logic/api/__init__.py +0 -29
  49. speclogician/logic/api/client.py +0 -606
  50. speclogician/logic/api/decomp.py +0 -67
  51. speclogician/logic/api/scenario.py +0 -102
  52. speclogician/logic/api/traces.py +0 -59
  53. speclogician/logic/lib/__init__.py +0 -19
  54. speclogician/logic/lib/complement.py +0 -107
  55. speclogician/logic/lib/domain_model.py +0 -59
  56. speclogician/logic/lib/predicates.py +0 -151
  57. speclogician/logic/lib/scenarios.py +0 -369
  58. speclogician/logic/lib/traces.py +0 -114
  59. speclogician/logic/lib/transitions.py +0 -104
  60. speclogician/logic/main.py +0 -246
  61. speclogician/logic/strings.py +0 -194
  62. speclogician/logic/utils.py +0 -135
  63. speclogician/modeling/complement.py +0 -104
  64. speclogician/modeling/spec.py +0 -306
  65. speclogician/modeling/spec_stats.py +0 -39
  66. speclogician/presentation/api.py +0 -244
  67. speclogician/presentation/builders/_links.py +0 -44
  68. speclogician/presentation/builders/container.py +0 -53
  69. speclogician/presentation/builders/data_artifact.py +0 -42
  70. speclogician/presentation/builders/domain.py +0 -54
  71. speclogician/presentation/builders/instances_list.py +0 -38
  72. speclogician/presentation/builders/predicate.py +0 -51
  73. speclogician/presentation/builders/recommendations.py +0 -41
  74. speclogician/presentation/builders/scenario.py +0 -41
  75. speclogician/presentation/builders/scenario_complement.py +0 -82
  76. speclogician/presentation/builders/smart_find.py +0 -39
  77. speclogician/presentation/builders/spec.py +0 -39
  78. speclogician/presentation/builders/state_diff.py +0 -150
  79. speclogician/presentation/builders/state_instance.py +0 -42
  80. speclogician/presentation/builders/state_instance_summary.py +0 -84
  81. speclogician/presentation/builders/trace.py +0 -58
  82. speclogician/presentation/ctx.py +0 -38
  83. speclogician/presentation/models/container.py +0 -44
  84. speclogician/presentation/models/data_artifact.py +0 -33
  85. speclogician/presentation/models/domain.py +0 -50
  86. speclogician/presentation/models/instances_list.py +0 -23
  87. speclogician/presentation/models/predicate.py +0 -60
  88. speclogician/presentation/models/recommendations.py +0 -34
  89. speclogician/presentation/models/scenario.py +0 -31
  90. speclogician/presentation/models/scenario_complement.py +0 -40
  91. speclogician/presentation/models/smart_find.py +0 -34
  92. speclogician/presentation/models/spec.py +0 -32
  93. speclogician/presentation/models/state_diff.py +0 -34
  94. speclogician/presentation/models/state_instance.py +0 -31
  95. speclogician/presentation/models/state_instance_summary.py +0 -102
  96. speclogician/presentation/models/trace.py +0 -42
  97. speclogician/presentation/preview/__init__.py +0 -13
  98. speclogician/presentation/preview/cli.py +0 -50
  99. speclogician/presentation/preview/fixtures/__init__.py +0 -205
  100. speclogician/presentation/preview/fixtures/artifact_container.py +0 -150
  101. speclogician/presentation/preview/fixtures/data_artifact.py +0 -144
  102. speclogician/presentation/preview/fixtures/domain_model.py +0 -162
  103. speclogician/presentation/preview/fixtures/instances_list.py +0 -162
  104. speclogician/presentation/preview/fixtures/predicate.py +0 -184
  105. speclogician/presentation/preview/fixtures/scenario.py +0 -84
  106. speclogician/presentation/preview/fixtures/scenario_complement.py +0 -81
  107. speclogician/presentation/preview/fixtures/smart_find.py +0 -140
  108. speclogician/presentation/preview/fixtures/spec.py +0 -95
  109. speclogician/presentation/preview/fixtures/state_diff.py +0 -158
  110. speclogician/presentation/preview/fixtures/state_instance.py +0 -128
  111. speclogician/presentation/preview/fixtures/state_instance_summary.py +0 -80
  112. speclogician/presentation/preview/fixtures/trace.py +0 -206
  113. speclogician/presentation/preview/registry.py +0 -42
  114. speclogician/presentation/renderers/__init__.py +0 -24
  115. speclogician/presentation/renderers/container.py +0 -136
  116. speclogician/presentation/renderers/data_artifact.py +0 -144
  117. speclogician/presentation/renderers/domain.py +0 -123
  118. speclogician/presentation/renderers/instances_list.py +0 -120
  119. speclogician/presentation/renderers/predicate.py +0 -180
  120. speclogician/presentation/renderers/recommendations.py +0 -90
  121. speclogician/presentation/renderers/scenario.py +0 -94
  122. speclogician/presentation/renderers/scenario_complement.py +0 -59
  123. speclogician/presentation/renderers/smart_find.py +0 -307
  124. speclogician/presentation/renderers/spec.py +0 -105
  125. speclogician/presentation/renderers/state_diff.py +0 -102
  126. speclogician/presentation/renderers/state_instance.py +0 -82
  127. speclogician/presentation/renderers/state_instance_summary.py +0 -143
  128. speclogician/presentation/renderers/trace.py +0 -122
  129. speclogician/shell/app.py +0 -170
  130. speclogician/shell/shell_ch.py +0 -263
  131. speclogician/shell/shell_view.py +0 -153
  132. speclogician/state/change_result.py +0 -32
  133. speclogician/state/diff.py +0 -191
  134. speclogician/state/inst.py +0 -574
  135. speclogician/state/recommendation.py +0 -13
  136. speclogician/state/recommender.py +0 -577
  137. speclogician/state/state_stats.py +0 -133
  138. speclogician/tui/__init__.py +0 -0
  139. speclogician/tui/app.py +0 -257
  140. speclogician/tui/app.tcss +0 -160
  141. speclogician/tui/demo.py +0 -45
  142. speclogician/tui/images/speclogician-full.png +0 -0
  143. speclogician/tui/images/speclogician-minimal.png +0 -0
  144. speclogician/tui/main_screen.py +0 -454
  145. speclogician/tui/splash_screen.py +0 -51
  146. speclogician/tui/stats_screen.py +0 -125
  147. speclogician/utils/testing.py +0 -151
  148. speclogician-0.0.0b1.dist-info/METADATA +0 -116
  149. speclogician-0.0.0b1.dist-info/RECORD +0 -139
  150. /speclogician/{presentation → agent}/__init__.py +0 -0
  151. /speclogician/{presentation/builders → cmd}/__init__.py +0 -0
  152. /speclogician/{presentation/models → llms}/__init__.py +0 -0
  153. {speclogician-0.0.0b1.dist-info → speclogician-0.0.0.dev1.dist-info}/WHEEL +0 -0
@@ -1,37 +1,34 @@
1
1
  #
2
2
  # Imandra Inc.
3
3
  #
4
- # speclogician/modeling/predicates.py
4
+ # predicates.py
5
5
  #
6
6
 
7
- from typing import Literal
8
- from enum import StrEnum
9
7
 
10
- from .component import SrcComponent
8
+ from .component import ModelComponent
11
9
 
12
- class PredicateType(StrEnum):
13
- STATE = "state"
14
- ACTION = "action"
15
-
16
- class StatePredicate(SrcComponent):
10
+ class StatePredicate(ModelComponent):
17
11
  """
18
- Predicate on the state only
19
12
  """
20
- kind: Literal["state_predicate"] = "state_predicate"
13
+ name : str # name of the predicate
14
+ body : str # actual implementation
21
15
 
22
16
  def __str__ (self):
23
- """ """
17
+ """
18
+ """
24
19
  return f"{self.name} s"
25
20
 
26
21
  def to_iml (self):
27
- """ Return the IML representation of the StatePredicate """
28
- return f"let {self.name} (s : state) : bool = \n {self.src_code}\n"
22
+ """
23
+ """
24
+ return f"let {self.name} (s : state) : bool = \n {self.body}\n"
29
25
 
30
- class ActionPredicate(SrcComponent):
26
+ class ActionPredicate(ModelComponent):
31
27
  """
32
28
  Predicate involving a state and an action
33
29
  """
34
- kind: Literal["action_predicate"] = "action_predicate"
30
+ name : str # name of the predicate
31
+ body : str # body
35
32
 
36
33
  def __str__(self):
37
34
  """
@@ -40,20 +37,21 @@ class ActionPredicate(SrcComponent):
40
37
 
41
38
  def to_iml(self):
42
39
  """
43
- Return the IML representation of the ActionPredicate
40
+ Convert to IML here
44
41
  """
45
- return f"let {self.name} (s : state) (a : action) : bool = \n {self.src_code}\n"
42
+ return f"let {self.name} (s : state) (a : action) : bool = \n {self.body}\n"
46
43
 
47
- class Transition(SrcComponent):
44
+ class Transition(ModelComponent):
48
45
  """
49
46
  Transition functions are used to update the state
50
47
  """
51
- kind: Literal["transition"] = "transition"
48
+ name : str # Name of the transition function
49
+ body : str # Name of the
50
+
52
51
  def __str__ (self):
53
52
  return f"{self.name} s a"
54
53
 
55
54
  def to_iml (self):
56
55
  """
57
- Return the IML representation of the transition
58
56
  """
59
- return f"let {self.name} (s : state) (a : action) : state = \n {self.src_code}"
57
+ return f"let {self.name} (s : state) (a : action) : state = \n {self.body}"
@@ -0,0 +1,33 @@
1
+ #
2
+ # Imandra Inc.
3
+ #
4
+ # report.py
5
+ #
6
+
7
+ from pydantic import BaseModel
8
+
9
+ class DomainModelReport(BaseModel):
10
+ """
11
+ Domain model report
12
+ """
13
+ pass
14
+
15
+ class ScenarioReport(BaseModel):
16
+ """
17
+ Scenario report
18
+ """
19
+
20
+ num_scenarios : int
21
+ num_failed : int
22
+ num_conflicted : int
23
+
24
+ class ModelReport(BaseModel):
25
+ """
26
+ """
27
+ dmodel_report : DomainModelReport
28
+ scenario_report : ScenarioReport
29
+
30
+ class ArtifactReport(BaseModel):
31
+ """
32
+ """
33
+ pass
@@ -1,93 +1,40 @@
1
1
  #
2
2
  # Imandra Inc.
3
3
  #
4
- # speclogician/modeling/scenario.py
4
+ # scenario.py
5
5
  #
6
6
 
7
- from __future__ import annotations
8
-
9
- from typing import TypeAlias, Sequence
10
- from pydantic import BaseModel, Field, field_validator, model_validator
11
-
12
- from .component import ModelComponent, validate_iml_identifier
13
-
14
-
15
- class ScenarioDelta(BaseModel):
16
- """We'll use this to edit Scenarios."""
17
- add: list[str] = Field(default_factory=list)
18
- remove: list[str] = Field(default_factory=list)
19
-
20
- @field_validator("add", "remove")
21
- @classmethod
22
- def _dedup_and_strip(cls, xs: list[str]) -> list[str]:
23
- # normalize, drop empties, dedup preserving order
24
- out: list[str] = []
25
- seen: set[str] = set()
26
- for x in xs:
27
- x = x.strip()
28
- if not x or x in seen:
29
- continue
30
- out.append(x)
31
- seen.add(x)
32
- return out
33
-
34
- @field_validator("add", "remove")
35
- @classmethod
36
- def _validate_identifiers(cls, xs: list[str]) -> list[str]:
37
- # Reuse the canonical IML identifier validation
38
- for x in xs:
39
- validate_iml_identifier(x)
40
- return xs
41
-
42
- @model_validator(mode="after")
43
- def _no_overlap(self) -> "ScenarioDelta":
44
- overlap = set(self.add) & set(self.remove)
45
- if overlap:
46
- raise ValueError(f"Names cannot be both added and removed: {sorted(overlap)}")
47
- return self
48
-
49
- def is_empty(self) -> bool:
50
- return not self.add and not self.remove
51
-
52
- def is_add_only(self) -> bool:
53
- return not self.remove
54
-
55
- class Valid(BaseModel):
56
- """ The scenario's valid """
57
- pass
58
-
59
- class Inconsistent(BaseModel):
60
- """ Scenario is inconsistent - the combination of predicates is unsatisfiable """
61
- pass
62
-
63
- class Missing(BaseModel):
64
- """ Referenced model components are missing """
65
- missing_preds : list[str] = Field(default_factory=list)
66
- missing_trans : list[str] = Field(default_factory=list)
67
-
68
- ComponentStatus : TypeAlias = Valid | Inconsistent | Missing
7
+ from rich.table import Table
8
+ from rich.syntax import Syntax
9
+
10
+ from pydantic import BaseModel
11
+ from .component import ModelComponent
12
+ from .predicates import (
13
+ StatePredicate,
14
+ ActionPredicate,
15
+ Transition
16
+ )
17
+ from .domain import DomainModel
18
+ from ..utils.imx import check_instance
19
+
69
20
 
70
21
  class Scenario(ModelComponent):
71
22
  """
72
- Scenario contains
23
+ Concrete clauses are direct translations of the test cases
73
24
  """
74
-
75
25
  name : str
76
26
 
77
- # Predicates and transition functions are components
78
- component_status : ComponentStatus = Valid()
79
-
80
- given: Sequence[str] = Field(default_factory=list)
81
- when: Sequence[str] = Field(default_factory=list)
82
- then: Sequence[str] = Field(default_factory=list)
83
-
27
+ given : list[str]
28
+ when : list[str]
29
+ then : list[str]
84
30
 
85
31
  # When we check the DomainModel and this is missing,
86
32
  # we'll then set these fields
87
- preds_missing : list[str] = Field(default_factory=list)
88
- trans_missing : list[str] = Field(default_factory=list)
33
+ preds_missing : list[str] = []
34
+ trans_missing : list[str] = []
89
35
 
90
36
  # These contain consistency checks
37
+ # TODO we'll expand these later with details on
91
38
  # why precisely they're inconsistent
92
39
  given_preds_consistent : bool = True
93
40
  when_preds_consistent : bool = True
@@ -102,22 +49,90 @@ class Scenario(ModelComponent):
102
49
  when_str = "\n&& ".join(map(lambda x: f"{x} s a", self.when))
103
50
 
104
51
  match (len(self.given), len(self.when)):
105
- case (0, 0):
106
- return ""
107
- case (_, 0):
108
- return given_str
109
- case (0, _):
110
- return when_str
111
- case (_, _):
112
- return f"{given_str} \n&& {when_str}"
52
+ case (0, 0): return ""
53
+ case (_, 0): return given_str
54
+ case (0, _): return when_str
55
+ case (_, _): return f"{given_str} \n&& {when_str}"
56
+
57
+ def check_state_preds (self, model:DomainModel) -> bool:
58
+ """
59
+ Check that the state predicates are consistent (i.e. there's an instance)
60
+ """
61
+
62
+ state_preds_str = "\n&& ".join(map(lambda x: f"{x} s", self.given))
63
+
64
+ instance_query = f"""
65
+ let pred_check (s : state) =
66
+ {state_preds_str}
67
+
68
+ instance(pred_check)
69
+ """
70
+ print (instance_query)
71
+
72
+ return check_instance(model.to_iml(), instance_query)
73
+
74
+ def check_action_preds (self, model:DomainModel) -> bool:
75
+ """
76
+ Check that the action predicates are consistent (i.e. there's an instance that satisfies them)
77
+ """
78
+
79
+ if len(self.when) == 0: return True
80
+
81
+ action_preds_str = "\n&& ".join(map(lambda x: f"{x} s a", self.when))
82
+
83
+ instance_query = f"""
84
+ let pred_check (s : state) (a : action) =
85
+ {action_preds_str}
86
+
87
+ instance(pred_check)
88
+ """
89
+ print (instance_query)
90
+
91
+ return check_instance(model.to_iml(), instance_query)
92
+
93
+ def check_all_preds(self, model:DomainModel) -> bool:
94
+ """
95
+ Will return True if there's an instance for all the
96
+ """
97
+
98
+ if len(self.when) == 0 and len(self.given) == 0:
99
+ return True
100
+
101
+ instance_query = f"""
102
+
103
+ let pred_check (s : state) (a : action) =
104
+ {self.pred_calls_to_iml()}
105
+
106
+ instance(pred_check)
107
+ """
108
+
109
+ return check_instance(model.to_iml(), instance_query)
110
+
111
+ def check_preds (self, model:DomainModel):
112
+ """
113
+ Check the predicates and update their status
114
+ """
115
+
116
+ self.preds_missing = []
117
+ for p in self.given + self.when:
118
+ if not model.pred_exists(p):
119
+ self.preds_missing.append(p)
120
+
121
+ self.trans_missing = []
122
+ for t in self.then:
123
+ if not model.trans_exists(t):
124
+ self.trans_missing.append(t)
125
+
126
+ self.given_preds_consistent = self.check_state_preds(model)
127
+ self.when_preds_consistent = self.check_action_preds(model)
128
+ self.all_preds_consistent = self.check_all_preds(model)
113
129
 
114
130
  def eval_transition (self, state_val:str, act_val:str) -> str:
115
131
  """
116
132
  Given concrete state and action values, evaluate the set of transitions
117
133
  """
118
134
 
119
- if len(self.then) == 0:
120
- return state_val
135
+ if len(self.then) == 0: return state_val
121
136
 
122
137
  trans_iml = ""
123
138
  for t in self.then:
@@ -139,12 +154,12 @@ class Scenario(ModelComponent):
139
154
 
140
155
  {when_str}
141
156
  """
157
+
142
158
  return s
143
159
 
144
160
  def full_model_to_iml(self):
145
161
  """
146
- Create the full model (we omit the 'else' at the end because this is intended to be used with
147
- other scenarios
162
+ Create the full model
148
163
  """
149
164
  given_str = "&& \n".join(map(str, self.given))
150
165
  when_str = "&& \n".join(map(str, self.when))
@@ -159,4 +174,21 @@ in let when_true =
159
174
  in if given_true && when_true then
160
175
  ({then_str})
161
176
  """
162
- return s
177
+ return s
178
+
179
+ def __rich__ (self):
180
+ table = Table("Attribute", "Value", show_lines=True)
181
+
182
+ table.add_row("Name", self.name)
183
+
184
+ table.add_row("Given predicates", Syntax("\n".join(self.given), 'OCaml'))
185
+ table.add_row("When predicates", Syntax("\n".join(self.when), 'OCaml'))
186
+ table.add_row("Then transitions", Syntax("\n".join(self.then), 'OCaml'))
187
+
188
+ return table
189
+
190
+ class FormalizationReponse(BaseModel):
191
+ """ """
192
+ test_name_str : str
193
+ scenarios : list[Scenario]
194
+ domain_model : str
speclogician/sl_cmd.py ADDED
@@ -0,0 +1,76 @@
1
+ #
2
+ # Imandra Inc.
3
+ #
4
+ # sl_cmd.py
5
+ #
6
+
7
+ from cmd2 import Cmd
8
+
9
+ class SpecLogicianCmdApp(Cmd):
10
+ """
11
+ """
12
+
13
+ def __init__ (self):
14
+ """
15
+ """
16
+ Cmd.__init__(self, include_py=True)
17
+
18
+ pass
19
+
20
+ def do_data_view(self):
21
+ """
22
+ """
23
+ pass
24
+
25
+ def do_data_tests(self):
26
+ """ """
27
+ pass
28
+
29
+ def do_data_tests_view(self):
30
+ """
31
+ """
32
+ pass
33
+
34
+ def do_scenario_view(self):
35
+ """
36
+ """
37
+ pass
38
+
39
+ def do_scenario_list (self):
40
+ """
41
+ """
42
+ pass
43
+
44
+ def do_scenario_update(self):
45
+ """
46
+ """
47
+ pass
48
+
49
+ def do_scenario_rm(self):
50
+ """
51
+ """
52
+ pass
53
+
54
+ def do_dmodel_view(self, _):
55
+ """
56
+ Print out the whole domain model
57
+ """
58
+ pass
59
+
60
+ def do_dmodel_predicates_state(self, _):
61
+ """ Print just the state predicates """
62
+ pass
63
+
64
+ def do_dmodel_predicates_action(self, _):
65
+ """ """
66
+ pass
67
+
68
+ def do_dmodel_transitions(self, _):
69
+ """ """
70
+ pass
71
+
72
+ if __name__ == "__main__":
73
+ import sys
74
+
75
+ c = SpecLogicianCmdApp()
76
+ sys.exit(c.cmdloop())