speclogician 0.0.0b1__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.
- speclogician/__init__.py +0 -0
- speclogician/commands/__init__.py +15 -0
- speclogician/commands/cmd_ch.py +616 -0
- speclogician/commands/cmd_find.py +256 -0
- speclogician/commands/cmd_view.py +202 -0
- speclogician/commands/runner.py +149 -0
- speclogician/commands/utils.py +101 -0
- speclogician/data/__init__.py +0 -0
- speclogician/data/artifact.py +63 -0
- speclogician/data/container.py +402 -0
- speclogician/data/mapping.py +88 -0
- speclogician/data/refs.py +24 -0
- speclogician/data/traces.py +26 -0
- speclogician/demos/.DS_Store +0 -0
- speclogician/demos/cmd_demo.py +278 -0
- speclogician/demos/loader.py +135 -0
- speclogician/demos/model.py +27 -0
- speclogician/demos/runner.py +51 -0
- speclogician/logic/__init__.py +11 -0
- speclogician/logic/api/__init__.py +29 -0
- speclogician/logic/api/client.py +606 -0
- speclogician/logic/api/decomp.py +67 -0
- speclogician/logic/api/scenario.py +102 -0
- speclogician/logic/api/traces.py +59 -0
- speclogician/logic/lib/__init__.py +19 -0
- speclogician/logic/lib/complement.py +107 -0
- speclogician/logic/lib/domain_model.py +59 -0
- speclogician/logic/lib/predicates.py +151 -0
- speclogician/logic/lib/scenarios.py +369 -0
- speclogician/logic/lib/traces.py +114 -0
- speclogician/logic/lib/transitions.py +104 -0
- speclogician/logic/main.py +246 -0
- speclogician/logic/strings.py +194 -0
- speclogician/logic/utils.py +135 -0
- speclogician/main.py +139 -0
- speclogician/modeling/__init__.py +31 -0
- speclogician/modeling/complement.py +104 -0
- speclogician/modeling/component.py +71 -0
- speclogician/modeling/conflict.py +26 -0
- speclogician/modeling/domain.py +349 -0
- speclogician/modeling/predicates.py +59 -0
- speclogician/modeling/scenario.py +162 -0
- speclogician/modeling/spec.py +306 -0
- speclogician/modeling/spec_stats.py +39 -0
- speclogician/presentation/__init__.py +0 -0
- speclogician/presentation/api.py +244 -0
- speclogician/presentation/builders/__init__.py +0 -0
- speclogician/presentation/builders/_links.py +44 -0
- speclogician/presentation/builders/container.py +53 -0
- speclogician/presentation/builders/data_artifact.py +42 -0
- speclogician/presentation/builders/domain.py +54 -0
- speclogician/presentation/builders/instances_list.py +38 -0
- speclogician/presentation/builders/predicate.py +51 -0
- speclogician/presentation/builders/recommendations.py +41 -0
- speclogician/presentation/builders/scenario.py +41 -0
- speclogician/presentation/builders/scenario_complement.py +82 -0
- speclogician/presentation/builders/smart_find.py +39 -0
- speclogician/presentation/builders/spec.py +39 -0
- speclogician/presentation/builders/state_diff.py +150 -0
- speclogician/presentation/builders/state_instance.py +42 -0
- speclogician/presentation/builders/state_instance_summary.py +84 -0
- speclogician/presentation/builders/trace.py +58 -0
- speclogician/presentation/ctx.py +38 -0
- speclogician/presentation/models/__init__.py +0 -0
- speclogician/presentation/models/container.py +44 -0
- speclogician/presentation/models/data_artifact.py +33 -0
- speclogician/presentation/models/domain.py +50 -0
- speclogician/presentation/models/instances_list.py +23 -0
- speclogician/presentation/models/predicate.py +60 -0
- speclogician/presentation/models/recommendations.py +34 -0
- speclogician/presentation/models/scenario.py +31 -0
- speclogician/presentation/models/scenario_complement.py +40 -0
- speclogician/presentation/models/smart_find.py +34 -0
- speclogician/presentation/models/spec.py +32 -0
- speclogician/presentation/models/state_diff.py +34 -0
- speclogician/presentation/models/state_instance.py +31 -0
- speclogician/presentation/models/state_instance_summary.py +102 -0
- speclogician/presentation/models/trace.py +42 -0
- speclogician/presentation/preview/__init__.py +13 -0
- speclogician/presentation/preview/cli.py +50 -0
- speclogician/presentation/preview/fixtures/__init__.py +205 -0
- speclogician/presentation/preview/fixtures/artifact_container.py +150 -0
- speclogician/presentation/preview/fixtures/data_artifact.py +144 -0
- speclogician/presentation/preview/fixtures/domain_model.py +162 -0
- speclogician/presentation/preview/fixtures/instances_list.py +162 -0
- speclogician/presentation/preview/fixtures/predicate.py +184 -0
- speclogician/presentation/preview/fixtures/scenario.py +84 -0
- speclogician/presentation/preview/fixtures/scenario_complement.py +81 -0
- speclogician/presentation/preview/fixtures/smart_find.py +140 -0
- speclogician/presentation/preview/fixtures/spec.py +95 -0
- speclogician/presentation/preview/fixtures/state_diff.py +158 -0
- speclogician/presentation/preview/fixtures/state_instance.py +128 -0
- speclogician/presentation/preview/fixtures/state_instance_summary.py +80 -0
- speclogician/presentation/preview/fixtures/trace.py +206 -0
- speclogician/presentation/preview/registry.py +42 -0
- speclogician/presentation/renderers/__init__.py +24 -0
- speclogician/presentation/renderers/container.py +136 -0
- speclogician/presentation/renderers/data_artifact.py +144 -0
- speclogician/presentation/renderers/domain.py +123 -0
- speclogician/presentation/renderers/instances_list.py +120 -0
- speclogician/presentation/renderers/predicate.py +180 -0
- speclogician/presentation/renderers/recommendations.py +90 -0
- speclogician/presentation/renderers/scenario.py +94 -0
- speclogician/presentation/renderers/scenario_complement.py +59 -0
- speclogician/presentation/renderers/smart_find.py +307 -0
- speclogician/presentation/renderers/spec.py +105 -0
- speclogician/presentation/renderers/state_diff.py +102 -0
- speclogician/presentation/renderers/state_instance.py +82 -0
- speclogician/presentation/renderers/state_instance_summary.py +143 -0
- speclogician/presentation/renderers/trace.py +122 -0
- speclogician/py.typed +0 -0
- speclogician/shell/app.py +170 -0
- speclogician/shell/shell_ch.py +263 -0
- speclogician/shell/shell_view.py +153 -0
- speclogician/state/__init__.py +0 -0
- speclogician/state/change.py +428 -0
- speclogician/state/change_result.py +32 -0
- speclogician/state/diff.py +191 -0
- speclogician/state/inst.py +574 -0
- speclogician/state/recommendation.py +13 -0
- speclogician/state/recommender.py +577 -0
- speclogician/state/state.py +465 -0
- speclogician/state/state_stats.py +133 -0
- speclogician/tui/__init__.py +0 -0
- speclogician/tui/app.py +257 -0
- speclogician/tui/app.tcss +160 -0
- speclogician/tui/demo.py +45 -0
- speclogician/tui/images/speclogician-full.png +0 -0
- speclogician/tui/images/speclogician-minimal.png +0 -0
- speclogician/tui/main_screen.py +454 -0
- speclogician/tui/splash_screen.py +51 -0
- speclogician/tui/stats_screen.py +125 -0
- speclogician/utils/__init__.py +78 -0
- speclogician/utils/load.py +166 -0
- speclogician/utils/prompt.md +325 -0
- speclogician/utils/testing.py +151 -0
- speclogician-0.0.0b1.dist-info/METADATA +116 -0
- speclogician-0.0.0b1.dist-info/RECORD +139 -0
- speclogician-0.0.0b1.dist-info/WHEEL +4 -0
|
@@ -0,0 +1,191 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Imandra Inc.
|
|
3
|
+
#
|
|
4
|
+
# speclogician/state/diff.py
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
from enum import StrEnum
|
|
8
|
+
from typing import TypeAlias, Callable, TypeVar, Generic
|
|
9
|
+
from pydantic import BaseModel, Field
|
|
10
|
+
|
|
11
|
+
from ..modeling.domain import BaseStatus
|
|
12
|
+
from speclogician.modeling.complement import ScenarioComplementDiff
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
class ComparisonOutcome(StrEnum):
|
|
16
|
+
""" When we compare the before/after values, we'll use this as the comparison outcome """
|
|
17
|
+
UNKNOWN = "unknown"
|
|
18
|
+
NO_CHANGE = "no_change"
|
|
19
|
+
NO_CHANGE_GOOD = "no_change_good"
|
|
20
|
+
NO_CHANGE_BAD = "no_change_bad"
|
|
21
|
+
IMPROVED = "improved"
|
|
22
|
+
DECLINED = "declined"
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
T = TypeVar("T")
|
|
26
|
+
|
|
27
|
+
ComparisonFn: TypeAlias = Callable[[T, T], ComparisonOutcome]
|
|
28
|
+
|
|
29
|
+
class ValueDiff(BaseModel, Generic[T]):
|
|
30
|
+
""" Represents a change (before → after) with an explanatory label
|
|
31
|
+
and an interpretation of whether increases/decreases are “good”. """
|
|
32
|
+
|
|
33
|
+
label : str
|
|
34
|
+
before: T
|
|
35
|
+
after: T
|
|
36
|
+
comp_func : ComparisonFn[T] | None = Field(default=None, exclude=True)
|
|
37
|
+
hint : None | dict[ComparisonOutcome, str] = None
|
|
38
|
+
|
|
39
|
+
def is_different(self) -> bool:
|
|
40
|
+
if self.comp_func:
|
|
41
|
+
return self.comp_func(self.before, self.after) in (ComparisonOutcome.IMPROVED, ComparisonOutcome.DECLINED)
|
|
42
|
+
return self.before != self.after
|
|
43
|
+
|
|
44
|
+
|
|
45
|
+
# comparison functions
|
|
46
|
+
|
|
47
|
+
def base_status_comp (before : BaseStatus, after : BaseStatus) -> ComparisonOutcome:
|
|
48
|
+
""" """
|
|
49
|
+
# TODO there's prob a nice way to do this without explicit write out...
|
|
50
|
+
match (before, after):
|
|
51
|
+
case (BaseStatus.UNKNOWN, BaseStatus.UNKNOWN):
|
|
52
|
+
return ComparisonOutcome.NO_CHANGE_BAD
|
|
53
|
+
case (BaseStatus.UNKNOWN, _):
|
|
54
|
+
return ComparisonOutcome.IMPROVED
|
|
55
|
+
case (BaseStatus.INVALID_IML, BaseStatus.VALID):
|
|
56
|
+
return ComparisonOutcome.IMPROVED
|
|
57
|
+
case (BaseStatus.INVALID_IML, BaseStatus.INVALID_IML):
|
|
58
|
+
return ComparisonOutcome.NO_CHANGE_BAD
|
|
59
|
+
case (BaseStatus.VALID, BaseStatus.VALID):
|
|
60
|
+
return ComparisonOutcome.NO_CHANGE_GOOD
|
|
61
|
+
case (BaseStatus.VALID, _):
|
|
62
|
+
return ComparisonOutcome.DECLINED
|
|
63
|
+
case (_, _):
|
|
64
|
+
return ComparisonOutcome.UNKNOWN
|
|
65
|
+
|
|
66
|
+
def bool_true_is_good (before : bool, after : bool) -> ComparisonOutcome:
|
|
67
|
+
""" Compare two boolean values where `true` is good """
|
|
68
|
+
match (before, after):
|
|
69
|
+
case (False, False):
|
|
70
|
+
return ComparisonOutcome.NO_CHANGE_BAD
|
|
71
|
+
case (False, True):
|
|
72
|
+
return ComparisonOutcome.IMPROVED
|
|
73
|
+
case (True, False):
|
|
74
|
+
return ComparisonOutcome.DECLINED
|
|
75
|
+
case (True, True):
|
|
76
|
+
return ComparisonOutcome.NO_CHANGE_GOOD
|
|
77
|
+
|
|
78
|
+
def bool_true_is_bad(before: bool, after: bool) -> ComparisonOutcome:
|
|
79
|
+
match (before, after):
|
|
80
|
+
case (False, False):
|
|
81
|
+
return ComparisonOutcome.NO_CHANGE_GOOD
|
|
82
|
+
case (False, True):
|
|
83
|
+
return ComparisonOutcome.DECLINED
|
|
84
|
+
case (True, False):
|
|
85
|
+
return ComparisonOutcome.IMPROVED
|
|
86
|
+
case (True, True):
|
|
87
|
+
return ComparisonOutcome.NO_CHANGE_BAD
|
|
88
|
+
|
|
89
|
+
def numeric_increase_good(before: int | float, after: int | float) -> ComparisonOutcome:
|
|
90
|
+
"""
|
|
91
|
+
Increase is good (e.g. matched counts).
|
|
92
|
+
"""
|
|
93
|
+
if before == after:
|
|
94
|
+
return ComparisonOutcome.NO_CHANGE_GOOD if before > 0 else ComparisonOutcome.NO_CHANGE
|
|
95
|
+
elif before < after:
|
|
96
|
+
return ComparisonOutcome.IMPROVED
|
|
97
|
+
else:
|
|
98
|
+
return ComparisonOutcome.DECLINED
|
|
99
|
+
|
|
100
|
+
|
|
101
|
+
def numeric_increase_bad(before: int | float, after: int | float) -> ComparisonOutcome:
|
|
102
|
+
"""
|
|
103
|
+
Increase is bad (e.g. errors, inconsistencies).
|
|
104
|
+
"""
|
|
105
|
+
if before == after:
|
|
106
|
+
return ComparisonOutcome.NO_CHANGE_BAD if before > 0 else ComparisonOutcome.NO_CHANGE_GOOD
|
|
107
|
+
elif before < after:
|
|
108
|
+
return ComparisonOutcome.DECLINED
|
|
109
|
+
else:
|
|
110
|
+
return ComparisonOutcome.IMPROVED
|
|
111
|
+
|
|
112
|
+
def complement_regions_decrease_good(before: int | None, after: int | None) -> ComparisonOutcome:
|
|
113
|
+
"""
|
|
114
|
+
Complement represents uncovered space.
|
|
115
|
+
Smaller complement => improved coverage.
|
|
116
|
+
"""
|
|
117
|
+
if before is None or after is None:
|
|
118
|
+
return ComparisonOutcome.UNKNOWN
|
|
119
|
+
if after < before:
|
|
120
|
+
return ComparisonOutcome.IMPROVED
|
|
121
|
+
if after > before:
|
|
122
|
+
return ComparisonOutcome.DECLINED
|
|
123
|
+
return ComparisonOutcome.NO_CHANGE
|
|
124
|
+
|
|
125
|
+
|
|
126
|
+
def complement_present_comp(before: bool, after: bool) -> ComparisonOutcome:
|
|
127
|
+
"""
|
|
128
|
+
Presence itself isn't strictly good/bad; treat as UNKNOWN unless equal.
|
|
129
|
+
(We separately judge region count where smaller is better.)
|
|
130
|
+
"""
|
|
131
|
+
if before == after:
|
|
132
|
+
return ComparisonOutcome.NO_CHANGE
|
|
133
|
+
return ComparisonOutcome.UNKNOWN
|
|
134
|
+
|
|
135
|
+
|
|
136
|
+
class StateDiff(BaseModel):
|
|
137
|
+
""" Statistical summary of changes between two states """
|
|
138
|
+
|
|
139
|
+
# Domain model-related value diffs
|
|
140
|
+
base_status : ValueDiff[BaseStatus] # Base status
|
|
141
|
+
base_has_state : ValueDiff[bool] # Does the base have state defined?
|
|
142
|
+
base_has_action : ValueDiff[bool] # Does the base have action defined?
|
|
143
|
+
|
|
144
|
+
# State predicates
|
|
145
|
+
num_state_preds_total : ValueDiff[int] #
|
|
146
|
+
num_state_preds_matched : ValueDiff[int] #
|
|
147
|
+
num_state_preds_valid_logic : ValueDiff[int] #
|
|
148
|
+
num_state_preds_errored : ValueDiff[int] #
|
|
149
|
+
|
|
150
|
+
# state x action predicates
|
|
151
|
+
num_action_preds_total : ValueDiff[int] #
|
|
152
|
+
num_action_preds_matched : ValueDiff[int] #
|
|
153
|
+
num_action_preds_valid_logic : ValueDiff[int] #
|
|
154
|
+
num_action_preds_errored : ValueDiff[int] #
|
|
155
|
+
|
|
156
|
+
# Predicates
|
|
157
|
+
num_preds_total : ValueDiff[int] # Total number of predicates
|
|
158
|
+
num_preds_matched : ValueDiff[int] # Predicates matched
|
|
159
|
+
num_preds_valid_logic : ValueDiff[int] # Number of predicates with valid logic
|
|
160
|
+
num_preds_errored : ValueDiff[int] # Number of predicates with errors
|
|
161
|
+
|
|
162
|
+
# Transitions
|
|
163
|
+
num_trans_total : ValueDiff[int] # Total number
|
|
164
|
+
num_trans_matched : ValueDiff[int] # Number matched
|
|
165
|
+
num_trans_valid_logic : ValueDiff[int] # Number with valid logic
|
|
166
|
+
num_trans_errored : ValueDiff[int] # Number of transitions with errors
|
|
167
|
+
|
|
168
|
+
# Scenarios
|
|
169
|
+
num_sc_total : ValueDiff[int] # Total number of scenarios
|
|
170
|
+
num_sc_missing : ValueDiff[int] # Missing predicates/transitions
|
|
171
|
+
num_sc_matched : ValueDiff[int] # Scenarios matched vs artifacts
|
|
172
|
+
num_sc_inconsistent : ValueDiff[int] # Scenarios inconsistent
|
|
173
|
+
|
|
174
|
+
# Conflicts (spec-level)
|
|
175
|
+
num_sc_conflicted : ValueDiff[int] # Total conflicts (all kinds)
|
|
176
|
+
num_sc_overlap : ValueDiff[int] # Overlap conflicts
|
|
177
|
+
num_sc_consumed : ValueDiff[int] # Consumed conflicts
|
|
178
|
+
|
|
179
|
+
# Test traces
|
|
180
|
+
num_test_traces_total : ValueDiff[int] # Total number of test traces
|
|
181
|
+
num_test_traces_logic_good : ValueDiff[int] # Valid logic
|
|
182
|
+
num_test_traces_matched : ValueDiff[int] # Matched traces
|
|
183
|
+
|
|
184
|
+
# Log traces
|
|
185
|
+
num_log_traces_total : ValueDiff[int] # Total number of log traces
|
|
186
|
+
num_log_traces_logic_good : ValueDiff[int] # Number of log traces with valid logic
|
|
187
|
+
num_log_traces_matched : ValueDiff[int] # Number of matched traces
|
|
188
|
+
|
|
189
|
+
scenario_comp_present: ValueDiff[bool]
|
|
190
|
+
num_comp_regions_total: ValueDiff[int | None]
|
|
191
|
+
scenario_comp_diff: ScenarioComplementDiff | None = None
|