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,278 +0,0 @@
1
- #
2
- # Imandra Inc.
3
- #
4
- # speclogician/demos/cmd_demo.py
5
- #
6
-
7
- from __future__ import annotations
8
-
9
- from pathlib import Path
10
-
11
- import typer
12
- from rich.console import Console
13
- from rich.markdown import Markdown
14
- from rich.panel import Panel
15
- from rich.rule import Rule
16
- from rich.text import Text
17
-
18
- from speclogician.demos.loader import (
19
- discover_demos,
20
- load_demo,
21
- load_changes,
22
- )
23
- from speclogician.demos.runner import apply_demo_changes
24
- from speclogician.state.state import State
25
- from speclogician.state.change import StateChange
26
- from speclogician.utils import console
27
-
28
- app = typer.Typer(help="Browse and run SpecLogician demos (markdown + changes + launch).")
29
-
30
- DEFAULT_DEMOS_DIR = Path("demos").resolve()
31
- CACHE_FILENAME = "state.json"
32
-
33
-
34
- # -----------------------------------------------------------------------------
35
- # helpers
36
- # -----------------------------------------------------------------------------
37
-
38
- def _cache_path(demo_root: Path) -> Path:
39
- return demo_root / CACHE_FILENAME
40
-
41
- def _load_cached_state(cache_path: Path) -> State:
42
- data = cache_path.read_text(encoding="utf-8", errors="replace")
43
- # State is assumed to be a Pydantic model (v2): model_validate_json exists.
44
- return State.model_validate_json(data) # type: ignore[attr-defined]
45
-
46
-
47
- def _save_cached_state(state: State, cache_path: Path) -> None:
48
- cache_path.write_text(
49
- state.model_dump_json(indent=2), # type: ignore[attr-defined]
50
- encoding="utf-8",
51
- )
52
-
53
-
54
- def _build_state_from_changes(
55
- *,
56
- demo_root: Path,
57
- changes: list[StateChange],
58
- console: Console
59
- ) -> State:
60
- res = apply_demo_changes(
61
- changes=changes,
62
- console=console,
63
- initial_state=None,
64
- show_progress=True,
65
- )
66
- return res.state
67
-
68
-
69
- def _load_description(demo_root: Path) -> str:
70
- """
71
- """
72
- return (demo_root / "description.md").read_text()
73
-
74
- def _ensure_cache_exists(
75
- *,
76
- demo_root: Path,
77
- changes: list[StateChange],
78
- console: Console
79
- ) -> Path:
80
- """
81
- Cache policy:
82
- - demos run <name> : ALWAYS rebuild and overwrite cache
83
- - demos shell/tui : REQUIRE cache; if missing, we build it once (quietly) and save it
84
- """
85
- cache_path = _cache_path(demo_root)
86
- if cache_path.exists():
87
- return cache_path
88
-
89
- console.print(Text(f"Cache missing; building {cache_path.name}…", style="dim"))
90
- res = apply_demo_changes(
91
- changes=changes,
92
- console=console,
93
- initial_state=None,
94
- show_progress=False,
95
- )
96
- _save_cached_state(res.state, cache_path)
97
- return cache_path
98
-
99
- # -----------------------------------------------------------------------------
100
- # commands
101
- # -----------------------------------------------------------------------------
102
-
103
- @app.command("ls")
104
- def ls_cmd():
105
- demos = discover_demos(DEFAULT_DEMOS_DIR)
106
- if not demos:
107
- console.print(Text(f"No demos found in {DEFAULT_DEMOS_DIR}", style="yellow"))
108
- raise typer.Exit(0)
109
-
110
- console.print('[bold magenta italic]Available demos:')
111
- for d in demos:
112
- cache_path = _cache_path(d.root)
113
- description = _load_description(d.root).strip()
114
- cache_badge = "[green]cached[/green]" if cache_path.exists() else "[dim]no-cache[/dim]"
115
- console.print(f"• [bold]{d.name}[/bold] {cache_badge} [italic]{description}[/italic]")
116
-
117
-
118
- @app.command("artifacts")
119
- def artifacts_cmd(
120
- name: str = typer.Argument(..., help="Demo name (directory under demos/).")
121
- ):
122
-
123
- try:
124
- demo = load_demo(DEFAULT_DEMOS_DIR, name)
125
- except Exception as e:
126
- console.print(f'Failed to load in the demo: {str(e)}', style="bold red")
127
- raise typer.Exit(2)
128
-
129
- artifact_path = demo.artifacts_path
130
- if not artifact_path.exists():
131
- console.print(Text(f"No artifact.md at {artifact_path}", style="yellow"))
132
- raise typer.Exit(1)
133
-
134
- text = artifact_path.read_text(encoding="utf-8", errors="replace")
135
- console.print(Panel(Text(f"{demo.name}", style="bold"), title="Demo", border_style="magenta"))
136
- console.print(Markdown(text))
137
-
138
-
139
- @app.command("changes")
140
- def changes_cmd(
141
- name: str = typer.Argument(..., help="Demo name."),
142
- show_meta: bool = typer.Option(True, "--meta/--no-meta", help="Show per-change rationale Markdown."),
143
- ):
144
- try:
145
- demo = load_demo(DEFAULT_DEMOS_DIR, name)
146
- except Exception as e:
147
- console.print(f'Failed to load in the demo: {str(e)}', style="bold red")
148
- raise typer.Exit(2)
149
-
150
- changes: list[StateChange] = load_changes(demo)
151
-
152
- console.print(Panel(Text(demo.name, style="bold"), title="Demo changes", border_style="magenta"))
153
- console.print(Text(f"{len(changes)} changes", style="dim"))
154
- console.print()
155
-
156
- for i, ch in enumerate(changes, start=1):
157
- kind = getattr(ch, "kind", ch.__class__.__name__)
158
- console.print(Rule(f"[bold]{i}. {kind}[/bold]", style="magenta"))
159
-
160
- # Your StateChange implements __rich__ nicely.
161
- console.print(ch)
162
-
163
- if show_meta:
164
- meta = getattr(ch, "meta", None)
165
- if isinstance(meta, str) and meta.strip():
166
- console.print()
167
- console.print(Panel(Markdown(meta), title="rationale", border_style="cyan"))
168
-
169
- console.print()
170
-
171
-
172
- @app.command("run")
173
- def run_cmd(
174
- name: str = typer.Argument(..., help="Demo name."),
175
- ):
176
- """
177
- Run the demo from scratch (apply all changes) and overwrite demo/state.json.
178
- """
179
- try:
180
- demo = load_demo(DEFAULT_DEMOS_DIR, name)
181
- except Exception as e:
182
- console.print(f'Failed to load in the demo: {str(e)}', style="bold red")
183
- raise typer.Exit(2)
184
-
185
- changes: list[StateChange] = load_changes(demo)
186
-
187
- console.print(Panel(Text(demo.name, style="bold"), title="Running demo", border_style="magenta"))
188
- state = _build_state_from_changes(demo_root=demo.root, changes=changes, console=console)
189
-
190
- cache_path = _cache_path(demo.root)
191
- _save_cached_state(state, cache_path)
192
- console.print(Text(f"Saved cache: {cache_path}", style="dim"))
193
-
194
- console.print(Rule("[bold]Result[/bold]", style="magenta"))
195
-
196
- insts = getattr(state, "instances", None) or []
197
- if insts:
198
- latest = insts[0]
199
- console.print(Text("Latest instance:", style="bold"))
200
-
201
- # ---- Presentation layer (summary panel) ----
202
- try:
203
- from speclogician.presentation.ctx import RenderCtx
204
- from speclogician.presentation.builders.state_instance_summary import (
205
- build_state_instance_summary_pm,
206
- )
207
- from speclogician.presentation.renderers.state_instance_summary import (
208
- render_state_instance_summary,
209
- )
210
-
211
- ctx = RenderCtx(
212
- art_cont=getattr(latest, "art_container", None),
213
- art_map=getattr(latest, "art_map", None),
214
- )
215
- pm = build_state_instance_summary_pm(latest, ctx)
216
- console.print(render_state_instance_summary(pm, ctx=ctx))
217
- except Exception as e:
218
- # If presentation breaks, don’t break demos; fallback to raw rich/repr.
219
- console.print(Text(f"[dim]Summary renderer failed: {e}[/dim]"))
220
- console.print(latest.__rich__() if hasattr(latest, "__rich__") else repr(latest))
221
-
222
- return
223
-
224
- console.print(Text("State applied.", style="yellow"))
225
-
226
- @app.command('shell')
227
- def shell_cmd(
228
- name: str = typer.Argument(..., help='Demo name.'),
229
- ):
230
- """
231
- Start an interactive Python shell using the cached demo state (demo/state.json).
232
- If missing, it will be built once and saved.
233
- """
234
- try:
235
- demo = load_demo(DEFAULT_DEMOS_DIR, name)
236
- except Exception as e:
237
- console.print(f'Failed to load in the demo: {str(e)}', style="bold red")
238
- raise typer.Exit(2)
239
-
240
- changes: list[StateChange] = load_changes(demo)
241
-
242
- cache_path = _ensure_cache_exists(demo_root=demo.root, changes=changes, console=console)
243
- state = _load_cached_state(cache_path)
244
-
245
- import code
246
- banner = f"SpecLogician demo '{name}' loaded from cache. `state` is available."
247
- code.interact(banner=banner, local={"state": state})
248
-
249
-
250
- @app.command("tui")
251
- def tui_cmd(
252
- name: str = typer.Argument(..., help='Demo name.'),
253
- ):
254
- """
255
- Launch the Textual TUI using the cached demo state (demo/state.json).
256
- If missing, it will be built once and saved.
257
- """
258
- try:
259
- demo = load_demo(DEFAULT_DEMOS_DIR, name)
260
- except Exception as e:
261
- console.print(f'Failed to load in the demo: {str(e)}', style="bold red")
262
- raise typer.Exit(2)
263
-
264
- artifact_path = demo.artifacts_path
265
-
266
- if not artifact_path.exists():
267
- console.print(Text(f'No artifact.md at {artifact_path}', style="yellow"))
268
- raise typer.Exit(1)
269
-
270
- artifact_cmd = artifact_path.read_text(encoding='utf-8', errors='replace')
271
-
272
- changes: list[StateChange] = load_changes(demo)
273
-
274
- cache_path = _ensure_cache_exists(demo_root=demo.root, changes=changes, console=console)
275
- state = _load_cached_state(cache_path)
276
-
277
- from speclogician.tui.main_screen import SpecLogicianApp
278
- SpecLogicianApp(state=state, demo_md=artifact_cmd, demo_title=f'Demo: {name}').run()
@@ -1,135 +0,0 @@
1
- #
2
- # Imandra Inc.
3
- #
4
- # speclogician/demos/loader.py
5
- #
6
-
7
- from __future__ import annotations
8
-
9
- import importlib.util
10
- from pathlib import Path
11
- from typing import Any, Callable
12
-
13
- from speclogician.demos.model import DemoSpec
14
- from speclogician.state.state import State
15
- from speclogician.state.change import StateChange
16
-
17
-
18
- # -----------------------------------------------------------------------------
19
- # discovery / selection
20
- # -----------------------------------------------------------------------------
21
-
22
- def discover_demos(demos_dir: Path) -> list[DemoSpec]:
23
- demos: list[DemoSpec] = []
24
- if not demos_dir.exists():
25
- return demos
26
-
27
- for p in sorted(demos_dir.iterdir()):
28
- if not p.is_dir():
29
- continue
30
- if (p / "changes.py").exists():
31
- demos.append(DemoSpec(name=p.name, root=p))
32
- return demos
33
-
34
-
35
- def load_demo(demos_dir: Path, name: str) -> DemoSpec:
36
- root = demos_dir / name
37
- if not root.exists() or not root.is_dir():
38
- raise FileNotFoundError(f'demo not found: {name}')
39
- if not (root / "changes.py").exists():
40
- raise FileNotFoundError('demo missing changes.py')
41
- return DemoSpec(name=name, root=root)
42
-
43
-
44
- # -----------------------------------------------------------------------------
45
- # changes.py loader
46
- # -----------------------------------------------------------------------------
47
-
48
- def _load_module_from_path(py_path: Path, module_name: str) -> Any:
49
- spec = importlib.util.spec_from_file_location(module_name, str(py_path))
50
- if spec is None or spec.loader is None:
51
- raise RuntimeError(f"Could not import: {py_path}")
52
- mod = importlib.util.module_from_spec(spec)
53
- spec.loader.exec_module(mod) # type: ignore[attr-defined]
54
- return mod
55
-
56
-
57
- def load_changes(demo: DemoSpec) -> list[StateChange]:
58
- """
59
- Returns the list in `CHANGES` from the demo's changes.py.
60
- Kept as `Any` to avoid importing all StateChange subclasses here.
61
- """
62
- mod = _load_module_from_path(
63
- demo.changes_path,
64
- module_name=f"speclogician_demo_{demo.name}",
65
- )
66
- if not hasattr(mod, "CHANGES"):
67
- raise RuntimeError(f"{demo.changes_path} must define CHANGES = [...]")
68
- changes = getattr(mod, "CHANGES")
69
- if not isinstance(changes, list):
70
- raise RuntimeError(f"{demo.changes_path}: CHANGES must be a list")
71
- return changes
72
-
73
-
74
- def load_demo_name(demo: DemoSpec) -> str:
75
- mod = _load_module_from_path(
76
- demo.changes_path,
77
- module_name=f"speclogician_demo_name_{demo.name}",
78
- )
79
- return getattr(mod, "DEMO_NAME", demo.name)
80
-
81
-
82
- # -----------------------------------------------------------------------------
83
- # cache (state.json in demo folder)
84
- # -----------------------------------------------------------------------------
85
-
86
- def load_cached_state(demo: DemoSpec) -> State:
87
- """
88
- Used by `speclogician demos tui <name>` and `... shell <name>`.
89
-
90
- Strict: requires demo.state.json to exist.
91
- """
92
- p = demo.cache_path
93
- if not p.exists():
94
- raise FileNotFoundError(
95
- f"Demo cache missing: {p}\n"
96
- f"Expected a JSON-serialized State model at {p.name}."
97
- )
98
- return State.model_validate_json(p.read_text(encoding="utf-8"))
99
-
100
-
101
- def save_cached_state(demo: DemoSpec, state: State) -> None:
102
- """
103
- Writes demo.state.json (State model JSON) into the demo directory.
104
- """
105
- demo.root.mkdir(parents=True, exist_ok=True)
106
- demo.cache_path.write_text(
107
- state.model_dump_json(indent=2),
108
- encoding="utf-8",
109
- )
110
-
111
-
112
- # -----------------------------------------------------------------------------
113
- # execution (always run changes from empty state)
114
- # -----------------------------------------------------------------------------
115
-
116
- ApplyChangeFn = Callable[[State, Any], State]
117
-
118
-
119
- def run_changes_fresh(demo: DemoSpec, *, apply_change: ApplyChangeFn) -> State:
120
- """
121
- Used by `speclogician demos run <name>`.
122
-
123
- Always starts from an empty State and applies every change from changes.py.
124
-
125
- `apply_change` is injected to keep this module independent of the engine
126
- implementation. Typical usage:
127
-
128
- def apply_change(state: State, ch: StateChange) -> State:
129
- return state.process_change(ch)
130
-
131
- """
132
- state = State()
133
- for ch in load_changes(demo):
134
- state = apply_change(state, ch)
135
- return state
@@ -1,27 +0,0 @@
1
- #
2
- # Imandra Inc.
3
- #
4
- # speclogician/demos/model.py
5
- #
6
-
7
- from __future__ import annotations
8
-
9
- from dataclasses import dataclass
10
- from pathlib import Path
11
-
12
- @dataclass(frozen=True)
13
- class DemoSpec:
14
- name: str
15
- root: Path
16
-
17
- @property
18
- def artifacts_path(self) -> Path:
19
- return self.root / "artifacts.md"
20
-
21
- @property
22
- def description_path(self) -> Path:
23
- return self.root / "description.md"
24
-
25
- @property
26
- def changes_path(self) -> Path:
27
- return self.root / "changes.py"
@@ -1,51 +0,0 @@
1
- #
2
- # Imandra Inc.
3
- #
4
- # speclogician/demos/runner.py
5
- #
6
-
7
- from __future__ import annotations
8
-
9
- from dataclasses import dataclass
10
- from typing import Any, Optional
11
- from contextlib import nullcontext
12
-
13
- from rich.console import Console
14
- from rich.status import Status
15
-
16
- from speclogician.state.state import State
17
-
18
-
19
- @dataclass(frozen=True)
20
- class DemoRunResult:
21
- state: State
22
-
23
-
24
- def apply_demo_changes(
25
- *,
26
- changes: list[Any],
27
- console: Console,
28
- initial_state: Optional[State] = None,
29
- show_progress: bool = True,
30
- ) -> DemoRunResult:
31
- """
32
- Apply an ordered list of StateChange objects to a State.
33
- """
34
- state = initial_state or State()
35
-
36
- if show_progress:
37
- status_ctx = Status(
38
- "[bold cyan]Applying demo changes…[/bold cyan]",
39
- console=console,
40
- spinner="dots",
41
- )
42
- else:
43
- status_ctx = nullcontext() # type: ignore[name-defined]
44
-
45
- with status_ctx:
46
- for i, ch in enumerate(changes, start=1):
47
- if show_progress:
48
- status_ctx.update(f"[bold cyan]Applying change {i}/{len(changes)}:[/bold cyan] {ch.short_str()}")
49
- state.process_change(ch, json_only=False)
50
-
51
- return DemoRunResult(state=state)
@@ -1,11 +0,0 @@
1
- #
2
- # Imandra Inc.
3
- #
4
- # __init__.py
5
- #
6
-
7
- from .main import analyze_change
8
-
9
- __all__ = [
10
- "analyze_change"
11
- ]
@@ -1,29 +0,0 @@
1
- #
2
- # Imandra Inc.
3
- #
4
- # speclogician/logic/api/__init__.py
5
- #
6
-
7
- from .client import SpecLogicianImandraX
8
- from .decomp import (
9
- decomp_complement, decomp_intersection
10
- )
11
- from .scenario import (
12
- check_all_preds, check_action_preds, check_state_preds, check_intersection
13
- )
14
- from .traces import check_trace_iml_validity, check_trace_match
15
-
16
-
17
- __all__ = [
18
- "SpecLogicianImandraX",
19
- "decomp",
20
- "scenario",
21
- "check_trace_iml_validity",
22
- "check_trace_match",
23
- "check_all_preds",
24
- "check_action_preds",
25
- "check_state_preds",
26
- "check_intersection",
27
- "decomp_complement",
28
- "decomp_intersection"
29
- ]