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.
- speclogician/agent/funcs.py +29 -0
- speclogician/cmd/agent_cmd.py +89 -0
- speclogician/cmd/data_cmd.py +24 -0
- speclogician/cmd/model_cmd.py +42 -0
- speclogician/cmd/overlay_cmd.py +30 -0
- speclogician/cmd/scenario_cmd.py +61 -0
- speclogician/cmd/state_cmd.py +52 -0
- speclogician/data/artifact.py +8 -50
- speclogician/data/container.py +18 -384
- speclogician/data/mapping.py +18 -17
- speclogician/data/refs.py +12 -11
- speclogician/data/reports.py +11 -0
- speclogician/data/traces.py +15 -6
- speclogician/llms/llmtools.py +102 -0
- speclogician/llms/overlay.py +264 -0
- speclogician/main.py +36 -102
- speclogician/modeling/__init__.py +0 -31
- speclogician/modeling/component.py +4 -60
- speclogician/modeling/conflict.py +5 -19
- speclogician/modeling/domain.py +93 -280
- speclogician/modeling/model.py +206 -0
- speclogician/modeling/predicates.py +20 -22
- speclogician/modeling/report.py +33 -0
- speclogician/modeling/scenario.py +119 -87
- speclogician/sl_cmd.py +76 -0
- speclogician/state/change.py +98 -378
- speclogician/state/state.py +183 -399
- speclogician/tui/box.tcss +10 -0
- speclogician/tui/tui.py +131 -0
- speclogician/utils/__init__.py +1 -70
- speclogician/utils/imx.py +195 -0
- speclogician/utils/load.py +25 -147
- speclogician/utils/prompt.md +1 -325
- speclogician-0.0.0.dev1.dist-info/METADATA +21 -0
- speclogician-0.0.0.dev1.dist-info/RECORD +43 -0
- speclogician/commands/__init__.py +0 -15
- speclogician/commands/cmd_ch.py +0 -616
- speclogician/commands/cmd_find.py +0 -256
- speclogician/commands/cmd_view.py +0 -202
- speclogician/commands/runner.py +0 -149
- speclogician/commands/utils.py +0 -101
- speclogician/demos/.DS_Store +0 -0
- speclogician/demos/cmd_demo.py +0 -278
- speclogician/demos/loader.py +0 -135
- speclogician/demos/model.py +0 -27
- speclogician/demos/runner.py +0 -51
- speclogician/logic/__init__.py +0 -11
- speclogician/logic/api/__init__.py +0 -29
- speclogician/logic/api/client.py +0 -606
- speclogician/logic/api/decomp.py +0 -67
- speclogician/logic/api/scenario.py +0 -102
- speclogician/logic/api/traces.py +0 -59
- speclogician/logic/lib/__init__.py +0 -19
- speclogician/logic/lib/complement.py +0 -107
- speclogician/logic/lib/domain_model.py +0 -59
- speclogician/logic/lib/predicates.py +0 -151
- speclogician/logic/lib/scenarios.py +0 -369
- speclogician/logic/lib/traces.py +0 -114
- speclogician/logic/lib/transitions.py +0 -104
- speclogician/logic/main.py +0 -246
- speclogician/logic/strings.py +0 -194
- speclogician/logic/utils.py +0 -135
- speclogician/modeling/complement.py +0 -104
- speclogician/modeling/spec.py +0 -306
- speclogician/modeling/spec_stats.py +0 -39
- speclogician/presentation/api.py +0 -244
- speclogician/presentation/builders/_links.py +0 -44
- speclogician/presentation/builders/container.py +0 -53
- speclogician/presentation/builders/data_artifact.py +0 -42
- speclogician/presentation/builders/domain.py +0 -54
- speclogician/presentation/builders/instances_list.py +0 -38
- speclogician/presentation/builders/predicate.py +0 -51
- speclogician/presentation/builders/recommendations.py +0 -41
- speclogician/presentation/builders/scenario.py +0 -41
- speclogician/presentation/builders/scenario_complement.py +0 -82
- speclogician/presentation/builders/smart_find.py +0 -39
- speclogician/presentation/builders/spec.py +0 -39
- speclogician/presentation/builders/state_diff.py +0 -150
- speclogician/presentation/builders/state_instance.py +0 -42
- speclogician/presentation/builders/state_instance_summary.py +0 -84
- speclogician/presentation/builders/trace.py +0 -58
- speclogician/presentation/ctx.py +0 -38
- speclogician/presentation/models/container.py +0 -44
- speclogician/presentation/models/data_artifact.py +0 -33
- speclogician/presentation/models/domain.py +0 -50
- speclogician/presentation/models/instances_list.py +0 -23
- speclogician/presentation/models/predicate.py +0 -60
- speclogician/presentation/models/recommendations.py +0 -34
- speclogician/presentation/models/scenario.py +0 -31
- speclogician/presentation/models/scenario_complement.py +0 -40
- speclogician/presentation/models/smart_find.py +0 -34
- speclogician/presentation/models/spec.py +0 -32
- speclogician/presentation/models/state_diff.py +0 -34
- speclogician/presentation/models/state_instance.py +0 -31
- speclogician/presentation/models/state_instance_summary.py +0 -102
- speclogician/presentation/models/trace.py +0 -42
- speclogician/presentation/preview/__init__.py +0 -13
- speclogician/presentation/preview/cli.py +0 -50
- speclogician/presentation/preview/fixtures/__init__.py +0 -205
- speclogician/presentation/preview/fixtures/artifact_container.py +0 -150
- speclogician/presentation/preview/fixtures/data_artifact.py +0 -144
- speclogician/presentation/preview/fixtures/domain_model.py +0 -162
- speclogician/presentation/preview/fixtures/instances_list.py +0 -162
- speclogician/presentation/preview/fixtures/predicate.py +0 -184
- speclogician/presentation/preview/fixtures/scenario.py +0 -84
- speclogician/presentation/preview/fixtures/scenario_complement.py +0 -81
- speclogician/presentation/preview/fixtures/smart_find.py +0 -140
- speclogician/presentation/preview/fixtures/spec.py +0 -95
- speclogician/presentation/preview/fixtures/state_diff.py +0 -158
- speclogician/presentation/preview/fixtures/state_instance.py +0 -128
- speclogician/presentation/preview/fixtures/state_instance_summary.py +0 -80
- speclogician/presentation/preview/fixtures/trace.py +0 -206
- speclogician/presentation/preview/registry.py +0 -42
- speclogician/presentation/renderers/__init__.py +0 -24
- speclogician/presentation/renderers/container.py +0 -136
- speclogician/presentation/renderers/data_artifact.py +0 -144
- speclogician/presentation/renderers/domain.py +0 -123
- speclogician/presentation/renderers/instances_list.py +0 -120
- speclogician/presentation/renderers/predicate.py +0 -180
- speclogician/presentation/renderers/recommendations.py +0 -90
- speclogician/presentation/renderers/scenario.py +0 -94
- speclogician/presentation/renderers/scenario_complement.py +0 -59
- speclogician/presentation/renderers/smart_find.py +0 -307
- speclogician/presentation/renderers/spec.py +0 -105
- speclogician/presentation/renderers/state_diff.py +0 -102
- speclogician/presentation/renderers/state_instance.py +0 -82
- speclogician/presentation/renderers/state_instance_summary.py +0 -143
- speclogician/presentation/renderers/trace.py +0 -122
- speclogician/shell/app.py +0 -170
- speclogician/shell/shell_ch.py +0 -263
- speclogician/shell/shell_view.py +0 -153
- speclogician/state/change_result.py +0 -32
- speclogician/state/diff.py +0 -191
- speclogician/state/inst.py +0 -574
- speclogician/state/recommendation.py +0 -13
- speclogician/state/recommender.py +0 -577
- speclogician/state/state_stats.py +0 -133
- speclogician/tui/__init__.py +0 -0
- speclogician/tui/app.py +0 -257
- speclogician/tui/app.tcss +0 -160
- speclogician/tui/demo.py +0 -45
- speclogician/tui/images/speclogician-full.png +0 -0
- speclogician/tui/images/speclogician-minimal.png +0 -0
- speclogician/tui/main_screen.py +0 -454
- speclogician/tui/splash_screen.py +0 -51
- speclogician/tui/stats_screen.py +0 -125
- speclogician/utils/testing.py +0 -151
- speclogician-0.0.0b1.dist-info/METADATA +0 -116
- speclogician-0.0.0b1.dist-info/RECORD +0 -139
- /speclogician/{presentation → agent}/__init__.py +0 -0
- /speclogician/{presentation/builders → cmd}/__init__.py +0 -0
- /speclogician/{presentation/models → llms}/__init__.py +0 -0
- {speclogician-0.0.0b1.dist-info → speclogician-0.0.0.dev1.dist-info}/WHEEL +0 -0
|
@@ -1,120 +0,0 @@
|
|
|
1
|
-
#
|
|
2
|
-
# Imandra Inc.
|
|
3
|
-
#
|
|
4
|
-
# speclogician/presentation/renderers/instances_list.py
|
|
5
|
-
#
|
|
6
|
-
|
|
7
|
-
from __future__ import annotations
|
|
8
|
-
|
|
9
|
-
from rich import box
|
|
10
|
-
from rich.panel import Panel
|
|
11
|
-
from rich.table import Table, Column
|
|
12
|
-
from rich.text import Text
|
|
13
|
-
|
|
14
|
-
from speclogician.presentation.ctx import RenderCtx
|
|
15
|
-
from speclogician.presentation.models.instances_list import InstancesListPM
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def _bullet_list(changes: str) -> Text:
|
|
19
|
-
"""
|
|
20
|
-
Render a comma-separated change list as a left-aligned bullet list.
|
|
21
|
-
"""
|
|
22
|
-
if not changes:
|
|
23
|
-
return Text("–", style="dim")
|
|
24
|
-
|
|
25
|
-
items = [c.strip() for c in changes.split(",") if c.strip()]
|
|
26
|
-
if not items:
|
|
27
|
-
return Text("–", style="dim")
|
|
28
|
-
|
|
29
|
-
txt = Text()
|
|
30
|
-
for i, item in enumerate(items):
|
|
31
|
-
if i > 0:
|
|
32
|
-
txt.append("\n")
|
|
33
|
-
txt.append("• ", style="dim")
|
|
34
|
-
txt.append(item)
|
|
35
|
-
return txt
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def render_instances_list(pm: InstancesListPM, *, ctx: RenderCtx):
|
|
39
|
-
b = box.MINIMAL if ctx.compact else box.SIMPLE
|
|
40
|
-
|
|
41
|
-
columns = [
|
|
42
|
-
Column(header="State ID", justify="center"),
|
|
43
|
-
Column(header="Changes", justify="left"),
|
|
44
|
-
Column(header="Domain model", justify="center"),
|
|
45
|
-
Column(header="Preds\n# (Errors, Used)", justify="center"),
|
|
46
|
-
Column(header="Scenarios\n# (Errors, Used)", justify="center"),
|
|
47
|
-
Column(header="Test traces\n# (Formalized, Matched)", justify="center"),
|
|
48
|
-
Column(header="Log traces\n# (Formalized, Matched)", justify="center"),
|
|
49
|
-
Column(header="Src code arts\n# (Matched)", justify="center"),
|
|
50
|
-
Column(header="Doc arts\n# (Matched)", justify="center"),
|
|
51
|
-
]
|
|
52
|
-
|
|
53
|
-
t = Table(
|
|
54
|
-
*columns,
|
|
55
|
-
title="SpecLogician State List",
|
|
56
|
-
expand=True,
|
|
57
|
-
highlight=True,
|
|
58
|
-
show_edge=False,
|
|
59
|
-
box=b,
|
|
60
|
-
)
|
|
61
|
-
|
|
62
|
-
for idx, row in enumerate(pm.rows):
|
|
63
|
-
if idx > 0:
|
|
64
|
-
t.add_section() # thin separator between instances
|
|
65
|
-
|
|
66
|
-
s = row.summary
|
|
67
|
-
|
|
68
|
-
# ---- Domain model ----
|
|
69
|
-
domain_str = str(getattr(s, "base_status", "unknown"))
|
|
70
|
-
|
|
71
|
-
# ---- Predicates (totals) ----
|
|
72
|
-
preds_total = int(getattr(s, "num_preds_total", 0) or 0)
|
|
73
|
-
preds_err = int(getattr(s, "num_preds_errored", 0) or 0)
|
|
74
|
-
preds_used = int(getattr(s, "num_preds_matched", 0) or 0)
|
|
75
|
-
preds_str = f"{preds_total} ({preds_err}, {preds_used})"
|
|
76
|
-
|
|
77
|
-
# These are also available:
|
|
78
|
-
# num_state_preds_total / matched / errored
|
|
79
|
-
# num_action_preds_total / matched / errored
|
|
80
|
-
|
|
81
|
-
# ---- Scenarios ----
|
|
82
|
-
sc_total = int(getattr(s, "num_sc_total", 0) or 0)
|
|
83
|
-
sc_missing = int(getattr(s, "num_sc_missing", 0) or 0)
|
|
84
|
-
sc_inconsistent = int(getattr(s, "num_sc_inconsistent", 0) or 0)
|
|
85
|
-
sc_conflicted = int(getattr(s, "num_sc_conflicted", 0) or 0)
|
|
86
|
-
|
|
87
|
-
# "Errors" bucket includes: missing + inconsistent + conflicted
|
|
88
|
-
sc_err = sc_missing + sc_inconsistent + sc_conflicted
|
|
89
|
-
sc_used = int(getattr(s, "num_sc_matched", 0) or 0)
|
|
90
|
-
sc_str = f"{sc_total} ({sc_err}, {sc_used})"
|
|
91
|
-
|
|
92
|
-
# ---- Test traces ----
|
|
93
|
-
tt_total = int(getattr(s, "num_test_traces_total", 0) or 0)
|
|
94
|
-
tt_formal = int(getattr(s, "num_test_traces_logic_good", 0) or 0)
|
|
95
|
-
tt_matched = int(getattr(s, "num_test_traces_matched", 0) or 0)
|
|
96
|
-
test_str = f"{tt_total} ({tt_formal}, {tt_matched})"
|
|
97
|
-
|
|
98
|
-
# ---- Log traces ----
|
|
99
|
-
lt_total = int(getattr(s, "num_log_traces_total", 0) or 0)
|
|
100
|
-
lt_formal = int(getattr(s, "num_log_traces_logic_good", 0) or 0)
|
|
101
|
-
lt_matched = int(getattr(s, "num_log_traces_matched", 0) or 0)
|
|
102
|
-
log_str = f"{lt_total} ({lt_formal}, {lt_matched})"
|
|
103
|
-
|
|
104
|
-
# ---- Data artifacts ----
|
|
105
|
-
src_matched = int(getattr(s, "num_src_code_arts_matched", 0) or 0)
|
|
106
|
-
doc_matched = int(getattr(s, "num_doc_arts_matched", 0) or 0)
|
|
107
|
-
|
|
108
|
-
t.add_row(
|
|
109
|
-
Text(row.state_label, style="bold green" if idx == 0 else ""),
|
|
110
|
-
_bullet_list(row.changes),
|
|
111
|
-
Text(domain_str),
|
|
112
|
-
Text(preds_str),
|
|
113
|
-
Text(sc_str),
|
|
114
|
-
Text(test_str),
|
|
115
|
-
Text(log_str),
|
|
116
|
-
Text(str(src_matched)),
|
|
117
|
-
Text(str(doc_matched)),
|
|
118
|
-
)
|
|
119
|
-
|
|
120
|
-
return Panel(t, title="[bold]Instances[/bold]", border_style="magenta")
|
|
@@ -1,180 +0,0 @@
|
|
|
1
|
-
#
|
|
2
|
-
# Imandra Inc.
|
|
3
|
-
#
|
|
4
|
-
# speclogician/presentation/renderers/predicate.py
|
|
5
|
-
#
|
|
6
|
-
|
|
7
|
-
from __future__ import annotations
|
|
8
|
-
|
|
9
|
-
from rich import box
|
|
10
|
-
from rich.console import Group, RenderableType
|
|
11
|
-
from rich.panel import Panel
|
|
12
|
-
from rich.syntax import Syntax
|
|
13
|
-
from rich.table import Table
|
|
14
|
-
from rich.text import Text
|
|
15
|
-
|
|
16
|
-
from speclogician.presentation.ctx import RenderCtx
|
|
17
|
-
from speclogician.presentation.models.predicate import PredicatePM, TransitionPM
|
|
18
|
-
from speclogician.utils import IMLValidity
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
# -----------------------------------------------------------------------------
|
|
22
|
-
# small helpers
|
|
23
|
-
# -----------------------------------------------------------------------------
|
|
24
|
-
|
|
25
|
-
def _meta_table(*, ctx: RenderCtx) -> Table:
|
|
26
|
-
b = box.MINIMAL if getattr(ctx, "compact", False) else box.SIMPLE
|
|
27
|
-
t = Table(
|
|
28
|
-
show_header=False,
|
|
29
|
-
box=b,
|
|
30
|
-
show_edge=False,
|
|
31
|
-
pad_edge=False,
|
|
32
|
-
expand=False,
|
|
33
|
-
)
|
|
34
|
-
# Make keys a bit more prominent than before (consistent with your newer style)
|
|
35
|
-
t.add_column(style="bold", no_wrap=True)
|
|
36
|
-
t.add_column(justify="left")
|
|
37
|
-
return t
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
def _badge(v: IMLValidity) -> Text:
|
|
41
|
-
# Normalize: v may be enum; keep it robust
|
|
42
|
-
s = (getattr(v, "value", str(v)) or "").lower()
|
|
43
|
-
|
|
44
|
-
if s == "valid":
|
|
45
|
-
return Text("✓ valid", style="bold green")
|
|
46
|
-
if s == "invalid":
|
|
47
|
-
return Text("✗ invalid", style="bold red")
|
|
48
|
-
if s == "unknown":
|
|
49
|
-
return Text("? unknown", style="bold yellow")
|
|
50
|
-
return Text(str(getattr(v, "value", v)), style="bold yellow")
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
def _empty(text: str = "∅ empty") -> Text:
|
|
54
|
-
return Text(text, style="dim")
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
def _code_block(*, title: str, code: str, lang: str) -> RenderableType:
|
|
58
|
-
# word_wrap=True tends to look better in narrow terminals
|
|
59
|
-
return Panel(
|
|
60
|
-
Syntax(code, lang, line_numbers=False, word_wrap=True),
|
|
61
|
-
title=title,
|
|
62
|
-
border_style="cyan",
|
|
63
|
-
)
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
def _snippet(s: str, *, limit: int = 200) -> str:
|
|
67
|
-
s2 = (s or "").strip()
|
|
68
|
-
if not s2:
|
|
69
|
-
return ""
|
|
70
|
-
if len(s2) <= limit:
|
|
71
|
-
return s2
|
|
72
|
-
return s2[:limit] + "…"
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
def section(t: Table, label: str) -> None:
|
|
76
|
-
t.add_row(Text(label, style="italic dim"), Text(""))
|
|
77
|
-
|
|
78
|
-
def field(t: Table, name: str, value: Text | str) -> None:
|
|
79
|
-
t.add_row(
|
|
80
|
-
Text(f" {name}", style="bold"), # ⬅️ indent
|
|
81
|
-
value if isinstance(value, Text) else Text(str(value)),
|
|
82
|
-
)
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
# -----------------------------------------------------------------------------
|
|
86
|
-
# main renderers
|
|
87
|
-
# -----------------------------------------------------------------------------
|
|
88
|
-
|
|
89
|
-
def render_predicate(pm: PredicatePM, *, ctx: RenderCtx) -> RenderableType:
|
|
90
|
-
t = _meta_table(ctx=ctx)
|
|
91
|
-
|
|
92
|
-
# ── Identity ─────────────────────────────
|
|
93
|
-
section(t, "Identity")
|
|
94
|
-
field(t, "name", Text(pm.name or "-", style="bold"))
|
|
95
|
-
field(t, "signature", Text(pm.signature or "", style="dim"))
|
|
96
|
-
field(t, "type", Text(str(pm.pred_type), style="cyan"))
|
|
97
|
-
if ctx.show_ids:
|
|
98
|
-
field(t, "comp_id", Text(pm.comp_id or "", style="dim"))
|
|
99
|
-
field(t, "updated", Text(pm.last_updated.isoformat(), style="dim"))
|
|
100
|
-
|
|
101
|
-
# ── Logic ────────────────────────────────
|
|
102
|
-
section(t, "Logic")
|
|
103
|
-
field(t, "iml_valid", _badge(pm.is_iml_valid))
|
|
104
|
-
if pm.iml_error:
|
|
105
|
-
field(t, "iml_error", Text(pm.iml_error, style="red"))
|
|
106
|
-
|
|
107
|
-
# ── Connections ──────────────────────────
|
|
108
|
-
section(t, "Connections")
|
|
109
|
-
field(t, "linked artifacts", pm.links.total)
|
|
110
|
-
field(t, "test / log traces", f"{pm.links.test_traces}/{pm.links.log_traces}")
|
|
111
|
-
field(t, "doc / src refs", f"{pm.links.doc_refs}/{pm.links.src_code_refs}")
|
|
112
|
-
if pm.links.unresolved_ids:
|
|
113
|
-
field(t, "unresolved", Text(str(pm.links.unresolved_ids), style="yellow"))
|
|
114
|
-
|
|
115
|
-
blocks: list[RenderableType] = [t]
|
|
116
|
-
|
|
117
|
-
if ctx.show_code:
|
|
118
|
-
blocks.append(Text(""))
|
|
119
|
-
blocks.append(
|
|
120
|
-
Panel(
|
|
121
|
-
Syntax(pm.iml or "(* empty *)", "ocaml", word_wrap=True),
|
|
122
|
-
title="iml",
|
|
123
|
-
border_style="cyan",
|
|
124
|
-
)
|
|
125
|
-
)
|
|
126
|
-
|
|
127
|
-
border = "blue" if pm.kind == "state_predicate" else "magenta"
|
|
128
|
-
return Panel(
|
|
129
|
-
Group(*blocks),
|
|
130
|
-
title=f"[bold]Predicate[/bold]: {pm.name or '-'}",
|
|
131
|
-
border_style=border,
|
|
132
|
-
)
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
def render_transition(pm: TransitionPM, *, ctx: RenderCtx) -> RenderableType:
|
|
136
|
-
t = _meta_table(ctx=ctx)
|
|
137
|
-
|
|
138
|
-
# Section: identity
|
|
139
|
-
t.add_row(Text("Identity", style="italic dim"), Text(""))
|
|
140
|
-
t.add_row(Text("name"), Text(pm.name or "-", style="bold"))
|
|
141
|
-
t.add_row(Text("signature"), Text(pm.signature or "", style="dim"))
|
|
142
|
-
if ctx.show_ids:
|
|
143
|
-
t.add_row(Text("comp_id"), Text(pm.comp_id or "", style="dim"))
|
|
144
|
-
t.add_row(Text("updated"), Text(pm.last_updated.isoformat(), style="dim"))
|
|
145
|
-
|
|
146
|
-
# Section: logic
|
|
147
|
-
t.add_row(Text("Logic", style="italic dim"), Text(""))
|
|
148
|
-
t.add_row(Text("iml_valid"), _badge(pm.is_iml_valid))
|
|
149
|
-
if pm.iml_error:
|
|
150
|
-
t.add_row(Text("iml_error"), Text(pm.iml_error, style="red"))
|
|
151
|
-
|
|
152
|
-
# Section: connections
|
|
153
|
-
t.add_row(Text("Connections", style="italic dim"), Text(""))
|
|
154
|
-
t.add_row(Text("linked artifacts"), Text(str(pm.links.total)))
|
|
155
|
-
t.add_row(Text("test/log traces"), Text(f"{pm.links.test_traces}/{pm.links.log_traces}"))
|
|
156
|
-
t.add_row(Text("doc/src refs"), Text(f"{pm.links.doc_refs}/{pm.links.src_code_refs}"))
|
|
157
|
-
if pm.links.unresolved_ids:
|
|
158
|
-
t.add_row(Text("unresolved"), Text(str(pm.links.unresolved_ids), style="yellow"))
|
|
159
|
-
|
|
160
|
-
blocks: list[RenderableType] = [t]
|
|
161
|
-
|
|
162
|
-
if ctx.show_code:
|
|
163
|
-
blocks.append(Text(""))
|
|
164
|
-
blocks.append(
|
|
165
|
-
_code_block(
|
|
166
|
-
title="iml",
|
|
167
|
-
code=(pm.iml or "(* empty *)"),
|
|
168
|
-
lang="ocaml",
|
|
169
|
-
)
|
|
170
|
-
)
|
|
171
|
-
else:
|
|
172
|
-
snip = _snippet(pm.iml or pm.src_code, limit=120)
|
|
173
|
-
blocks.append(Text(""))
|
|
174
|
-
blocks.append(Text(f"iml: {snip}" if snip else "iml: ∅", style="dim"))
|
|
175
|
-
|
|
176
|
-
return Panel(
|
|
177
|
-
Group(*blocks),
|
|
178
|
-
title=f"[bold]Transition[/bold]: {pm.name or '-'}",
|
|
179
|
-
border_style="green",
|
|
180
|
-
)
|
|
@@ -1,90 +0,0 @@
|
|
|
1
|
-
#
|
|
2
|
-
# Imandra Inc.
|
|
3
|
-
#
|
|
4
|
-
# speclogician/presentation/renderers/recommendations.py
|
|
5
|
-
#
|
|
6
|
-
|
|
7
|
-
|
|
8
|
-
from __future__ import annotations
|
|
9
|
-
|
|
10
|
-
from rich import box
|
|
11
|
-
from rich.console import Group
|
|
12
|
-
from rich.panel import Panel
|
|
13
|
-
from rich.table import Table
|
|
14
|
-
from rich.text import Text
|
|
15
|
-
|
|
16
|
-
from speclogician.presentation.ctx import RenderCtx
|
|
17
|
-
from speclogician.presentation.models.recommendations import RecommendationsPM, RecommendationPM
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
def _kind_style(kind: str) -> str:
|
|
21
|
-
k = (kind or "").lower()
|
|
22
|
-
if k == "error":
|
|
23
|
-
return "red"
|
|
24
|
-
if k == "warning":
|
|
25
|
-
return "yellow"
|
|
26
|
-
if k == "info":
|
|
27
|
-
return "cyan"
|
|
28
|
-
return "green" # next
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
def _header(pm: RecommendationsPM) -> Text:
|
|
32
|
-
parts = []
|
|
33
|
-
if pm.num_error:
|
|
34
|
-
parts.append(Text(f"{pm.num_error} error", style="red"))
|
|
35
|
-
if pm.num_warning:
|
|
36
|
-
parts.append(Text(f"{pm.num_warning} warning", style="yellow"))
|
|
37
|
-
if pm.num_next:
|
|
38
|
-
parts.append(Text(f"{pm.num_next} next", style="green"))
|
|
39
|
-
if pm.num_info:
|
|
40
|
-
parts.append(Text(f"{pm.num_info} info", style="cyan"))
|
|
41
|
-
|
|
42
|
-
if not parts:
|
|
43
|
-
return Text("No recommendations", style="dim")
|
|
44
|
-
|
|
45
|
-
out = Text(" • ").join(parts)
|
|
46
|
-
return out
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
def _render_item(r: RecommendationPM, *, show_priority: bool) -> list[Text]:
|
|
50
|
-
style = _kind_style(r.kind)
|
|
51
|
-
left = Text(r.kind.upper(), style=f"bold {style}")
|
|
52
|
-
if show_priority:
|
|
53
|
-
left.append(f" p{r.priority}", style="dim")
|
|
54
|
-
body = Text(r.text)
|
|
55
|
-
return [left, body]
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
def render_recommendations(pm: RecommendationsPM, *, ctx: RenderCtx) -> Panel:
|
|
59
|
-
b = box.MINIMAL if ctx.compact else box.SIMPLE
|
|
60
|
-
|
|
61
|
-
if pm.count == 0:
|
|
62
|
-
body = Text("— none —", style="dim")
|
|
63
|
-
return Panel(body, title="Recommendations", border_style="dim", box=b)
|
|
64
|
-
|
|
65
|
-
show_priority = ctx.show_ids # cheap reuse: if ids are shown, show pri too
|
|
66
|
-
|
|
67
|
-
t = Table(
|
|
68
|
-
box=b,
|
|
69
|
-
pad_edge=False,
|
|
70
|
-
show_edge=False,
|
|
71
|
-
expand=True,
|
|
72
|
-
show_header=False,
|
|
73
|
-
)
|
|
74
|
-
t.add_column(style="dim", no_wrap=True)
|
|
75
|
-
t.add_column(no_wrap=False)
|
|
76
|
-
|
|
77
|
-
# In compact mode, show fewer items (but keep deterministic)
|
|
78
|
-
items = pm.items
|
|
79
|
-
if ctx.compact and len(items) > 8:
|
|
80
|
-
items = items[:8]
|
|
81
|
-
|
|
82
|
-
for r in items:
|
|
83
|
-
left, body = _render_item(r, show_priority=show_priority)
|
|
84
|
-
t.add_row(left, body)
|
|
85
|
-
|
|
86
|
-
blocks = [t]
|
|
87
|
-
# show a small header line if useful
|
|
88
|
-
blocks.insert(0, _header(pm))
|
|
89
|
-
|
|
90
|
-
return Panel(Group(*blocks), title="Recommendations", border_style="cyan", box=b)
|
|
@@ -1,94 +0,0 @@
|
|
|
1
|
-
#
|
|
2
|
-
# Imandra Inc.
|
|
3
|
-
#
|
|
4
|
-
# speclogician/presentation/renderers/scenario.py
|
|
5
|
-
#
|
|
6
|
-
|
|
7
|
-
from __future__ import annotations
|
|
8
|
-
|
|
9
|
-
from rich import box
|
|
10
|
-
from rich.panel import Panel
|
|
11
|
-
from rich.table import Table
|
|
12
|
-
from rich.text import Text
|
|
13
|
-
|
|
14
|
-
from speclogician.presentation.ctx import RenderCtx
|
|
15
|
-
from speclogician.presentation.models.scenario import ScenarioPM
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
def _status_style(kind: str) -> str:
|
|
19
|
-
k = (kind or "").lower()
|
|
20
|
-
if k == "valid":
|
|
21
|
-
return "green"
|
|
22
|
-
if k == "missing":
|
|
23
|
-
return "yellow"
|
|
24
|
-
if k == "inconsistent":
|
|
25
|
-
return "red"
|
|
26
|
-
return "dim"
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
def _section(label: str) -> Text:
|
|
30
|
-
return Text(label, style="italic magenta")
|
|
31
|
-
|
|
32
|
-
|
|
33
|
-
def _bool_badge(v: bool) -> Text:
|
|
34
|
-
return Text("✓" if v else "✗", style=("green" if v else "red"))
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
def _names_block(items: list[str], *, empty: str = "—") -> Text:
|
|
38
|
-
"""
|
|
39
|
-
Render a list of names as plain styled text (no Syntax, no black background).
|
|
40
|
-
"""
|
|
41
|
-
if not items:
|
|
42
|
-
return Text(empty, style="dim")
|
|
43
|
-
|
|
44
|
-
out = Text()
|
|
45
|
-
for i, name in enumerate(items):
|
|
46
|
-
if i:
|
|
47
|
-
out.append("\n")
|
|
48
|
-
out.append("• ", style="dim")
|
|
49
|
-
out.append(name, style="cyan")
|
|
50
|
-
return out
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
def render_scenario(pm: ScenarioPM, *, ctx: RenderCtx) -> Panel:
|
|
54
|
-
status_style = _status_style(pm.status.kind)
|
|
55
|
-
|
|
56
|
-
title = Text.assemble(
|
|
57
|
-
("Scenario: ", "bold"),
|
|
58
|
-
(pm.name or "(unnamed)", "cyan"),
|
|
59
|
-
)
|
|
60
|
-
|
|
61
|
-
b = box.MINIMAL if ctx.compact else box.SIMPLE
|
|
62
|
-
t = Table(
|
|
63
|
-
show_header=False,
|
|
64
|
-
box=b,
|
|
65
|
-
pad_edge=False,
|
|
66
|
-
show_edge=False,
|
|
67
|
-
expand=False,
|
|
68
|
-
)
|
|
69
|
-
t.add_column(style="italic dim", no_wrap=True)
|
|
70
|
-
t.add_column(no_wrap=False)
|
|
71
|
-
|
|
72
|
-
# optional id
|
|
73
|
-
if ctx.show_ids:
|
|
74
|
-
t.add_row("comp_id", Text(pm.comp_id, style="dim"))
|
|
75
|
-
|
|
76
|
-
# Predicates
|
|
77
|
-
t.add_row(_section("Predicates"), Text(""))
|
|
78
|
-
t.add_row(" given", _names_block(pm.given))
|
|
79
|
-
t.add_row(" when", _names_block(pm.when))
|
|
80
|
-
t.add_row(" then", _names_block(pm.then))
|
|
81
|
-
|
|
82
|
-
# Checks
|
|
83
|
-
t.add_row(_section("Checks"), Text(""))
|
|
84
|
-
t.add_row(" given consistent", _bool_badge(pm.given_preds_consistent))
|
|
85
|
-
t.add_row(" when consistent", _bool_badge(pm.when_preds_consistent))
|
|
86
|
-
t.add_row(" all consistent", _bool_badge(pm.all_preds_consistent))
|
|
87
|
-
|
|
88
|
-
# Missing components
|
|
89
|
-
if getattr(ctx, "show_missing_components", False) and pm.status.kind == "missing":
|
|
90
|
-
t.add_row(_section("Missing"), Text(""))
|
|
91
|
-
t.add_row(" predicates", _names_block(pm.status.missing_preds))
|
|
92
|
-
t.add_row(" transitions", _names_block(pm.status.missing_trans))
|
|
93
|
-
|
|
94
|
-
return Panel(t, title=title, border_style=status_style)
|
|
@@ -1,59 +0,0 @@
|
|
|
1
|
-
#
|
|
2
|
-
# Imandra Inc.
|
|
3
|
-
#
|
|
4
|
-
# speclogician/presentation/renderers/scenario_complement.py
|
|
5
|
-
#
|
|
6
|
-
|
|
7
|
-
from __future__ import annotations
|
|
8
|
-
|
|
9
|
-
from rich.console import Group
|
|
10
|
-
from rich.panel import Panel
|
|
11
|
-
from rich.text import Text
|
|
12
|
-
|
|
13
|
-
from speclogician.presentation.ctx import RenderCtx
|
|
14
|
-
from speclogician.presentation.models.scenario_complement import ScenarioComplementPM
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
def render_scenario_complement(pm: ScenarioComplementPM, ctx: RenderCtx):
|
|
18
|
-
# Header summary
|
|
19
|
-
hdr = Text()
|
|
20
|
-
hdr.append("Regions: ")
|
|
21
|
-
hdr.append(str(pm.count_regions), style="bold")
|
|
22
|
-
|
|
23
|
-
if not pm.regions_preview:
|
|
24
|
-
return Panel(
|
|
25
|
-
Group(hdr, Text("— no regions (or not computed yet) —")),
|
|
26
|
-
title="Scenario Complement",
|
|
27
|
-
)
|
|
28
|
-
|
|
29
|
-
lines = []
|
|
30
|
-
for r in pm.regions_preview:
|
|
31
|
-
# One-liner summary
|
|
32
|
-
line = Text()
|
|
33
|
-
line.append(r.fp, style="bold")
|
|
34
|
-
line.append(" ")
|
|
35
|
-
line.append(f"constraints={r.num_constraints}")
|
|
36
|
-
|
|
37
|
-
# If we have extra details, add small indented lines
|
|
38
|
-
blocks = [line]
|
|
39
|
-
if r.invariant:
|
|
40
|
-
blocks.append(Text(f" inv: {r.invariant}"))
|
|
41
|
-
if r.constraints_preview:
|
|
42
|
-
blocks.append(Text(f" c0: {r.constraints_preview[0]}"))
|
|
43
|
-
for c in r.constraints_preview[1:]:
|
|
44
|
-
blocks.append(Text(f" {c}"))
|
|
45
|
-
if r.model_eval:
|
|
46
|
-
blocks.append(Text(f" eval: {r.model_eval}"))
|
|
47
|
-
if r.model:
|
|
48
|
-
blocks.append(Text(f" model: {r.model}"))
|
|
49
|
-
|
|
50
|
-
lines.append(Group(*blocks))
|
|
51
|
-
|
|
52
|
-
tail = Text()
|
|
53
|
-
if pm.count_regions > len(pm.regions_preview):
|
|
54
|
-
tail.append(f"(showing {len(pm.regions_preview)} of {pm.count_regions})", style="dim")
|
|
55
|
-
|
|
56
|
-
return Panel(
|
|
57
|
-
Group(hdr, *lines, tail),
|
|
58
|
-
title="Scenario Complement",
|
|
59
|
-
)
|