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,102 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Imandra Inc.
|
|
3
|
+
#
|
|
4
|
+
# speclogician/presentation/models/state_instance_summary.py
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from pydantic import BaseModel
|
|
10
|
+
from typing import Optional
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class StateInstanceSummaryPM(BaseModel):
|
|
14
|
+
# -----------------
|
|
15
|
+
# metadata
|
|
16
|
+
# -----------------
|
|
17
|
+
created_at: Optional[str] = None
|
|
18
|
+
|
|
19
|
+
# -----------------
|
|
20
|
+
# changes
|
|
21
|
+
# -----------------
|
|
22
|
+
num_changes: int = 0
|
|
23
|
+
|
|
24
|
+
# -----------------
|
|
25
|
+
# Domain model (base)
|
|
26
|
+
# -----------------
|
|
27
|
+
base_status: Optional[str] = None
|
|
28
|
+
base_has_state: Optional[bool] = None
|
|
29
|
+
base_has_action: Optional[bool] = None
|
|
30
|
+
|
|
31
|
+
# -----------------
|
|
32
|
+
# Domain model (state predicates)
|
|
33
|
+
# -----------------
|
|
34
|
+
num_state_preds_total: Optional[int] = None
|
|
35
|
+
num_state_preds_matched: Optional[int] = None
|
|
36
|
+
num_state_preds_valid_logic: Optional[int] = None
|
|
37
|
+
num_state_preds_errored: Optional[int] = None
|
|
38
|
+
|
|
39
|
+
# -----------------
|
|
40
|
+
# Domain model (action predicates)
|
|
41
|
+
# -----------------
|
|
42
|
+
num_action_preds_total: Optional[int] = None
|
|
43
|
+
num_action_preds_matched: Optional[int] = None
|
|
44
|
+
num_action_preds_valid_logic: Optional[int] = None
|
|
45
|
+
num_action_preds_errored: Optional[int] = None
|
|
46
|
+
|
|
47
|
+
# -----------------
|
|
48
|
+
# Domain model (predicate totals)
|
|
49
|
+
# -----------------
|
|
50
|
+
num_preds_total: Optional[int] = None
|
|
51
|
+
num_preds_matched: Optional[int] = None
|
|
52
|
+
num_preds_valid_logic: Optional[int] = None
|
|
53
|
+
num_preds_errored: Optional[int] = None
|
|
54
|
+
|
|
55
|
+
# -----------------
|
|
56
|
+
# Domain model (transitions)
|
|
57
|
+
# -----------------
|
|
58
|
+
num_trans_total: Optional[int] = None
|
|
59
|
+
num_trans_matched: Optional[int] = None
|
|
60
|
+
num_trans_valid_logic: Optional[int] = None
|
|
61
|
+
num_trans_errored: Optional[int] = None
|
|
62
|
+
|
|
63
|
+
# -----------------
|
|
64
|
+
# Scenarios
|
|
65
|
+
# -----------------
|
|
66
|
+
num_sc_total: Optional[int] = None
|
|
67
|
+
num_sc_missing: Optional[int] = None
|
|
68
|
+
num_sc_matched: Optional[int] = None
|
|
69
|
+
num_sc_inconsistent: Optional[int] = None
|
|
70
|
+
|
|
71
|
+
# -----------------
|
|
72
|
+
# Conflicts (spec-level)
|
|
73
|
+
# -----------------
|
|
74
|
+
num_sc_conflicted: Optional[int] = None
|
|
75
|
+
num_sc_overlap: Optional[int] = None
|
|
76
|
+
num_sc_consumed: Optional[int] = None
|
|
77
|
+
|
|
78
|
+
# -----------------
|
|
79
|
+
# Test traces
|
|
80
|
+
# -----------------
|
|
81
|
+
num_test_traces_total: Optional[int] = None
|
|
82
|
+
num_test_traces_matched: Optional[int] = None
|
|
83
|
+
num_test_traces_logic_good: Optional[int] = None
|
|
84
|
+
|
|
85
|
+
# -----------------
|
|
86
|
+
# Log traces
|
|
87
|
+
# -----------------
|
|
88
|
+
num_log_traces_total: Optional[int] = None
|
|
89
|
+
num_log_traces_matched: Optional[int] = None
|
|
90
|
+
num_log_traces_logic_good: Optional[int] = None
|
|
91
|
+
|
|
92
|
+
# -----------------
|
|
93
|
+
# Source code artifacts
|
|
94
|
+
# -----------------
|
|
95
|
+
num_src_code_arts_total: Optional[int] = None
|
|
96
|
+
num_src_code_arts_matched: Optional[int] = None
|
|
97
|
+
|
|
98
|
+
# -----------------
|
|
99
|
+
# Doc artifacts
|
|
100
|
+
# -----------------
|
|
101
|
+
num_doc_arts_total: Optional[int] = None
|
|
102
|
+
num_doc_arts_matched: Optional[int] = None
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Imandra Inc.
|
|
3
|
+
#
|
|
4
|
+
# speclogician/presentation/models/trace.py
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from typing import Literal
|
|
10
|
+
from pydantic import BaseModel
|
|
11
|
+
|
|
12
|
+
|
|
13
|
+
class TraceIMLValidityPM(BaseModel):
|
|
14
|
+
iml_valid: str # "unknown" | "valid" | "invalid"
|
|
15
|
+
err: str | None = None
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
class TraceCorePM(BaseModel):
|
|
19
|
+
art_id: str
|
|
20
|
+
given: str
|
|
21
|
+
when: str | None = None
|
|
22
|
+
then: str | None = None
|
|
23
|
+
time: str = ""
|
|
24
|
+
iml_validity: TraceIMLValidityPM
|
|
25
|
+
|
|
26
|
+
|
|
27
|
+
class TestTracePM(BaseModel):
|
|
28
|
+
kind: Literal["test_trace"] = "test_trace"
|
|
29
|
+
core: TraceCorePM
|
|
30
|
+
|
|
31
|
+
name: str
|
|
32
|
+
filepath: str = ""
|
|
33
|
+
language: str | None = None
|
|
34
|
+
contents: str | None = None # optional / heavy
|
|
35
|
+
|
|
36
|
+
|
|
37
|
+
class LogTracePM(BaseModel):
|
|
38
|
+
kind: Literal["log_trace"] = "log_trace"
|
|
39
|
+
core: TraceCorePM
|
|
40
|
+
|
|
41
|
+
filename: str
|
|
42
|
+
contents: str | None = None # optional / heavy
|
|
@@ -0,0 +1,50 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Imandra Inc.
|
|
3
|
+
#
|
|
4
|
+
# speclogician/presentation/preview/cli.py
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import json
|
|
10
|
+
import typer
|
|
11
|
+
|
|
12
|
+
from speclogician.presentation.ctx import RenderCtx
|
|
13
|
+
from speclogician.presentation.preview.registry import get, list_previews
|
|
14
|
+
from speclogician.presentation.preview.fixtures import register_fixtures
|
|
15
|
+
from speclogician.utils import console # your rich console
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
app = typer.Typer(help="Preview PM renderers using synthetic fixtures.")
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@app.command("list")
|
|
22
|
+
def list_cmd() -> None:
|
|
23
|
+
register_fixtures()
|
|
24
|
+
for spec in sorted(list_previews(), key=lambda s: s.name):
|
|
25
|
+
console.print(f"[bold]{spec.name}[/bold] variants={', '.join(spec.variants)}")
|
|
26
|
+
|
|
27
|
+
|
|
28
|
+
@app.command("show")
|
|
29
|
+
def show_cmd(
|
|
30
|
+
name: str = typer.Argument(..., help="Preview name (see: preview list)"),
|
|
31
|
+
variant: str = typer.Argument("typical", help="Variant: typical|minimal|edge"),
|
|
32
|
+
json_only: bool = typer.Option(False, "--json", help="Dump PM as JSON instead of rendering."),
|
|
33
|
+
compact: bool = typer.Option(False, "--compact", help="Use compact rendering."),
|
|
34
|
+
) -> None:
|
|
35
|
+
register_fixtures()
|
|
36
|
+
|
|
37
|
+
ctx = RenderCtx(compact=compact)
|
|
38
|
+
spec = get(name)
|
|
39
|
+
|
|
40
|
+
if variant not in spec.variants:
|
|
41
|
+
raise typer.BadParameter(f"Unknown variant '{variant}'. Choose one of: {', '.join(spec.variants)}")
|
|
42
|
+
|
|
43
|
+
pm = spec.make(ctx, variant)
|
|
44
|
+
|
|
45
|
+
if json_only:
|
|
46
|
+
# Pydantic v2
|
|
47
|
+
typer.echo(json.dumps(pm.model_dump(), indent=2, default=str))
|
|
48
|
+
raise typer.Exit(0)
|
|
49
|
+
|
|
50
|
+
console.print(spec.render(pm, ctx))
|
|
@@ -0,0 +1,205 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Imandra Inc.
|
|
3
|
+
#
|
|
4
|
+
# speclogician/presentation/preview/fixtures/__init__.py
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from speclogician.presentation.preview.registry import PreviewSpec, register
|
|
10
|
+
|
|
11
|
+
from . import state_diff
|
|
12
|
+
from . import state_instance_summary
|
|
13
|
+
from . import trace
|
|
14
|
+
from . import data_artifact
|
|
15
|
+
from . import artifact_container
|
|
16
|
+
from . import predicate
|
|
17
|
+
from . import scenario
|
|
18
|
+
from . import domain_model
|
|
19
|
+
from . import instances_list
|
|
20
|
+
from . import spec
|
|
21
|
+
from . import smart_find
|
|
22
|
+
from . import state_instance
|
|
23
|
+
|
|
24
|
+
|
|
25
|
+
def register_fixtures() -> None:
|
|
26
|
+
|
|
27
|
+
# ------------------------------------------------------------------
|
|
28
|
+
# State-level fixtures (already present)
|
|
29
|
+
# ------------------------------------------------------------------
|
|
30
|
+
|
|
31
|
+
register(
|
|
32
|
+
PreviewSpec(
|
|
33
|
+
name="state-diff",
|
|
34
|
+
variants=("typical", "minimal", "edge"),
|
|
35
|
+
make=state_diff.make_state_diff_pm,
|
|
36
|
+
render=state_diff.render,
|
|
37
|
+
)
|
|
38
|
+
)
|
|
39
|
+
|
|
40
|
+
register(
|
|
41
|
+
PreviewSpec(
|
|
42
|
+
name="state-instance-summary",
|
|
43
|
+
variants=("typical", "minimal", "edge"),
|
|
44
|
+
make=state_instance_summary.make_state_instance_summary_pm,
|
|
45
|
+
render=state_instance_summary.render,
|
|
46
|
+
)
|
|
47
|
+
)
|
|
48
|
+
|
|
49
|
+
# ------------------------------------------------------------------
|
|
50
|
+
# Trace fixtures
|
|
51
|
+
# ------------------------------------------------------------------
|
|
52
|
+
|
|
53
|
+
register(
|
|
54
|
+
PreviewSpec(
|
|
55
|
+
name="test-trace",
|
|
56
|
+
variants=("typical", "minimal", "edge"),
|
|
57
|
+
make=trace.make_test_trace_pm,
|
|
58
|
+
render=trace.render_test,
|
|
59
|
+
)
|
|
60
|
+
)
|
|
61
|
+
|
|
62
|
+
register(
|
|
63
|
+
PreviewSpec(
|
|
64
|
+
name="log-trace",
|
|
65
|
+
variants=("typical", "minimal", "edge"),
|
|
66
|
+
make=trace.make_log_trace_pm,
|
|
67
|
+
render=trace.render_log,
|
|
68
|
+
)
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
# ------------------------------------------------------------------
|
|
72
|
+
# Data artifact fixtures
|
|
73
|
+
# ------------------------------------------------------------------
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
register(
|
|
77
|
+
PreviewSpec(
|
|
78
|
+
name="doc-ref",
|
|
79
|
+
variants=("typical", "minimal", "edge"),
|
|
80
|
+
make=data_artifact.make_doc_ref_pm,
|
|
81
|
+
render=data_artifact.render_doc,
|
|
82
|
+
)
|
|
83
|
+
)
|
|
84
|
+
|
|
85
|
+
register(
|
|
86
|
+
PreviewSpec(
|
|
87
|
+
name="src-code-ref",
|
|
88
|
+
variants=("typical", "minimal", "edge"),
|
|
89
|
+
make=data_artifact.make_src_code_ref_pm,
|
|
90
|
+
render=data_artifact.render_src,
|
|
91
|
+
)
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
# ------------------------------------------------------------------
|
|
95
|
+
# Artifact container fixtures
|
|
96
|
+
# ------------------------------------------------------------------
|
|
97
|
+
|
|
98
|
+
register(
|
|
99
|
+
PreviewSpec(
|
|
100
|
+
name="artifact-container",
|
|
101
|
+
variants=("typical", "minimal", "edge"),
|
|
102
|
+
make=artifact_container.make_artifact_container_pm,
|
|
103
|
+
render=artifact_container.render,
|
|
104
|
+
)
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
# ------------------------------------------------------------------
|
|
108
|
+
# Predicate/Transition fixtures
|
|
109
|
+
# ------------------------------------------------------------------
|
|
110
|
+
|
|
111
|
+
register(
|
|
112
|
+
PreviewSpec(
|
|
113
|
+
name="predicate",
|
|
114
|
+
variants=("typical", "minimal", "edge"),
|
|
115
|
+
make=predicate.make_predicate_pm,
|
|
116
|
+
render=predicate.render_predicate,
|
|
117
|
+
)
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
register(
|
|
121
|
+
PreviewSpec(
|
|
122
|
+
name="transition",
|
|
123
|
+
variants=("typical", "minimal", "edge"),
|
|
124
|
+
make=predicate.make_transition_pm,
|
|
125
|
+
render=predicate.render_transition,
|
|
126
|
+
)
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
# ------------------------------------------------------------------
|
|
130
|
+
# Scenario fixture
|
|
131
|
+
# ------------------------------------------------------------------
|
|
132
|
+
|
|
133
|
+
register(
|
|
134
|
+
PreviewSpec(
|
|
135
|
+
name="scenario",
|
|
136
|
+
variants=("typical", "minimal", "edge"),
|
|
137
|
+
make=scenario.make_scenario_pm,
|
|
138
|
+
render=scenario.render,
|
|
139
|
+
)
|
|
140
|
+
)
|
|
141
|
+
|
|
142
|
+
# ------------------------------------------------------------------
|
|
143
|
+
# DomainModel fixture
|
|
144
|
+
# ------------------------------------------------------------------
|
|
145
|
+
|
|
146
|
+
register(
|
|
147
|
+
PreviewSpec(
|
|
148
|
+
name="domain-model",
|
|
149
|
+
variants=("typical", "minimal", "edge"),
|
|
150
|
+
make=domain_model.make_domain_model_pm,
|
|
151
|
+
render=domain_model.render,
|
|
152
|
+
)
|
|
153
|
+
)
|
|
154
|
+
|
|
155
|
+
# ------------------------------------------------------------------
|
|
156
|
+
# InstancesList fixture
|
|
157
|
+
# ------------------------------------------------------------------
|
|
158
|
+
|
|
159
|
+
register(
|
|
160
|
+
PreviewSpec(
|
|
161
|
+
name="instances-list",
|
|
162
|
+
variants=("typical", "minimal", "edge"),
|
|
163
|
+
make=instances_list.make_instances_list_pm,
|
|
164
|
+
render=instances_list.render,
|
|
165
|
+
)
|
|
166
|
+
)
|
|
167
|
+
|
|
168
|
+
# ------------------------------------------------------------------
|
|
169
|
+
# Spec fixture
|
|
170
|
+
# ------------------------------------------------------------------
|
|
171
|
+
|
|
172
|
+
register(
|
|
173
|
+
PreviewSpec(
|
|
174
|
+
name="spec",
|
|
175
|
+
variants=("typical", "minimal", "edge"),
|
|
176
|
+
make=spec.make_spec_pm,
|
|
177
|
+
render=spec.render,
|
|
178
|
+
)
|
|
179
|
+
)
|
|
180
|
+
|
|
181
|
+
# ------------------------------------------------------------------
|
|
182
|
+
# SmartFind
|
|
183
|
+
# ------------------------------------------------------------------
|
|
184
|
+
register(
|
|
185
|
+
PreviewSpec(
|
|
186
|
+
name="smart-find",
|
|
187
|
+
variants=("typical", "minimal", "edge"),
|
|
188
|
+
make=smart_find.make_smart_find_pm,
|
|
189
|
+
render=smart_find.render,
|
|
190
|
+
)
|
|
191
|
+
)
|
|
192
|
+
|
|
193
|
+
|
|
194
|
+
# ------------------------------------------------------------------
|
|
195
|
+
# SmartFind
|
|
196
|
+
# ------------------------------------------------------------------
|
|
197
|
+
|
|
198
|
+
register(
|
|
199
|
+
PreviewSpec(
|
|
200
|
+
name="state-instance",
|
|
201
|
+
variants=("typical", "minimal", "edge"),
|
|
202
|
+
make=state_instance.make_state_instance_pm,
|
|
203
|
+
render=state_instance.render,
|
|
204
|
+
)
|
|
205
|
+
)
|
|
@@ -0,0 +1,150 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Imandra Inc.
|
|
3
|
+
#
|
|
4
|
+
# speclogician/presentation/preview/fixtures/artifact_container.py
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
from speclogician.presentation.ctx import RenderCtx
|
|
9
|
+
|
|
10
|
+
from speclogician.presentation.models.container import (
|
|
11
|
+
ArtifactContainerPM,
|
|
12
|
+
ArtifactContainerCountsPM,
|
|
13
|
+
ArtifactContainerItemsPM,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
# reuse existing fixtures
|
|
17
|
+
from speclogician.presentation.preview.fixtures.trace import (
|
|
18
|
+
minimal_test_trace_pm,
|
|
19
|
+
typical_test_trace_pm,
|
|
20
|
+
edge_test_trace_pm,
|
|
21
|
+
minimal_log_trace_pm,
|
|
22
|
+
typical_log_trace_pm,
|
|
23
|
+
edge_log_trace_pm,
|
|
24
|
+
)
|
|
25
|
+
|
|
26
|
+
from speclogician.presentation.preview.fixtures.data_artifact import (
|
|
27
|
+
minimal_doc_ref_pm,
|
|
28
|
+
typical_doc_ref_pm,
|
|
29
|
+
edge_doc_ref_pm,
|
|
30
|
+
minimal_src_code_ref_pm,
|
|
31
|
+
typical_src_code_ref_pm,
|
|
32
|
+
edge_src_code_ref_pm,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
# -----------------------------------------------------------------------------
|
|
37
|
+
# helpers
|
|
38
|
+
# -----------------------------------------------------------------------------
|
|
39
|
+
|
|
40
|
+
def _counts_from_items(items: ArtifactContainerItemsPM) -> ArtifactContainerCountsPM:
|
|
41
|
+
# totals
|
|
42
|
+
num_test_total = len(items.test_traces)
|
|
43
|
+
num_log_total = len(items.log_traces)
|
|
44
|
+
num_doc_total = len(items.doc_refs)
|
|
45
|
+
num_src_total = len(items.src_code_refs)
|
|
46
|
+
|
|
47
|
+
# matched / logic_good are not explicitly present on PMs yet,
|
|
48
|
+
# so we keep these deterministic for fixtures. You can refine
|
|
49
|
+
# this later once you encode matched flags in PMs.
|
|
50
|
+
def _half(n: int) -> int:
|
|
51
|
+
return 0 if n == 0 else max(1, n // 2)
|
|
52
|
+
|
|
53
|
+
return ArtifactContainerCountsPM(
|
|
54
|
+
num_test_traces_total=num_test_total,
|
|
55
|
+
num_test_traces_matched=_half(num_test_total),
|
|
56
|
+
num_test_traces_logic_good=_half(num_test_total),
|
|
57
|
+
|
|
58
|
+
num_log_traces_total=num_log_total,
|
|
59
|
+
num_log_traces_matched=_half(num_log_total),
|
|
60
|
+
num_log_traces_logic_good=_half(num_log_total),
|
|
61
|
+
|
|
62
|
+
num_src_code_arts_total=num_src_total,
|
|
63
|
+
num_src_code_arts_matched=_half(num_src_total),
|
|
64
|
+
|
|
65
|
+
num_doc_arts_total=num_doc_total,
|
|
66
|
+
num_doc_arts_matched=_half(num_doc_total),
|
|
67
|
+
)
|
|
68
|
+
|
|
69
|
+
|
|
70
|
+
# -----------------------------------------------------------------------------
|
|
71
|
+
# main fixture entrypoint (matches PreviewSpec.make signature)
|
|
72
|
+
# -----------------------------------------------------------------------------
|
|
73
|
+
|
|
74
|
+
def make_artifact_container_pm(ctx: RenderCtx, variant: str = "typical") -> ArtifactContainerPM:
|
|
75
|
+
v = (variant or "typical").lower().strip()
|
|
76
|
+
|
|
77
|
+
# -------------------------
|
|
78
|
+
# minimal
|
|
79
|
+
# -------------------------
|
|
80
|
+
if v == "minimal":
|
|
81
|
+
items = ArtifactContainerItemsPM(
|
|
82
|
+
test_traces=[],
|
|
83
|
+
log_traces=[],
|
|
84
|
+
doc_refs=[],
|
|
85
|
+
src_code_refs=[],
|
|
86
|
+
)
|
|
87
|
+
return ArtifactContainerPM(
|
|
88
|
+
counts=_counts_from_items(items),
|
|
89
|
+
items=items,
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
# -------------------------
|
|
93
|
+
# edge (stress: long content, many items)
|
|
94
|
+
# -------------------------
|
|
95
|
+
if v == "edge":
|
|
96
|
+
items = ArtifactContainerItemsPM(
|
|
97
|
+
test_traces=[
|
|
98
|
+
edge_test_trace_pm(),
|
|
99
|
+
typical_test_trace_pm(with_contents=True, invalid=True),
|
|
100
|
+
typical_test_trace_pm(with_contents=False, invalid=False),
|
|
101
|
+
],
|
|
102
|
+
log_traces=[
|
|
103
|
+
edge_log_trace_pm(),
|
|
104
|
+
typical_log_trace_pm(with_contents=True, invalid=True),
|
|
105
|
+
],
|
|
106
|
+
doc_refs=[
|
|
107
|
+
edge_doc_ref_pm(),
|
|
108
|
+
typical_doc_ref_pm(),
|
|
109
|
+
],
|
|
110
|
+
src_code_refs=[
|
|
111
|
+
edge_src_code_ref_pm(),
|
|
112
|
+
typical_src_code_ref_pm(),
|
|
113
|
+
],
|
|
114
|
+
)
|
|
115
|
+
return ArtifactContainerPM(
|
|
116
|
+
counts=_counts_from_items(items),
|
|
117
|
+
items=items,
|
|
118
|
+
)
|
|
119
|
+
|
|
120
|
+
# -------------------------
|
|
121
|
+
# typical
|
|
122
|
+
# -------------------------
|
|
123
|
+
items = ArtifactContainerItemsPM(
|
|
124
|
+
test_traces=[
|
|
125
|
+
typical_test_trace_pm(with_contents=False, invalid=False),
|
|
126
|
+
typical_test_trace_pm(with_contents=True, invalid=True),
|
|
127
|
+
],
|
|
128
|
+
log_traces=[
|
|
129
|
+
typical_log_trace_pm(with_contents=False, invalid=False),
|
|
130
|
+
],
|
|
131
|
+
doc_refs=[
|
|
132
|
+
typical_doc_ref_pm(),
|
|
133
|
+
],
|
|
134
|
+
src_code_refs=[
|
|
135
|
+
typical_src_code_ref_pm(),
|
|
136
|
+
],
|
|
137
|
+
)
|
|
138
|
+
return ArtifactContainerPM(
|
|
139
|
+
counts=_counts_from_items(items),
|
|
140
|
+
items=items,
|
|
141
|
+
)
|
|
142
|
+
|
|
143
|
+
|
|
144
|
+
# -----------------------------------------------------------------------------
|
|
145
|
+
# renderer adapter (matches other fixtures style)
|
|
146
|
+
# -----------------------------------------------------------------------------
|
|
147
|
+
|
|
148
|
+
def render(pm: ArtifactContainerPM, ctx : RenderCtx):
|
|
149
|
+
from speclogician.presentation.renderers.container import render_artifact_container
|
|
150
|
+
return render_artifact_container(pm, ctx=ctx)
|
|
@@ -0,0 +1,144 @@
|
|
|
1
|
+
#
|
|
2
|
+
# Imandra Inc.
|
|
3
|
+
#
|
|
4
|
+
# speclogician/presentation/preview/fixtures/data_artifact.py
|
|
5
|
+
#
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
from speclogician.presentation.ctx import RenderCtx
|
|
10
|
+
from speclogician.presentation.models.data_artifact import DataArtifactCorePM, DocRefPM, SrcCodeRefPM
|
|
11
|
+
from speclogician.presentation.renderers.data_artifact import (
|
|
12
|
+
render_doc_ref,
|
|
13
|
+
render_src_code_ref,
|
|
14
|
+
)
|
|
15
|
+
|
|
16
|
+
# -----------------------------------------------------------------------------
|
|
17
|
+
# Shared helpers
|
|
18
|
+
# -----------------------------------------------------------------------------
|
|
19
|
+
|
|
20
|
+
def _core(*, art_id: str) -> DataArtifactCorePM:
|
|
21
|
+
return DataArtifactCorePM(art_id=art_id)
|
|
22
|
+
|
|
23
|
+
|
|
24
|
+
# -----------------------------------------------------------------------------
|
|
25
|
+
# DocRefPM fixtures
|
|
26
|
+
# -----------------------------------------------------------------------------
|
|
27
|
+
|
|
28
|
+
def minimal_doc_ref_pm() -> DocRefPM:
|
|
29
|
+
return DocRefPM(
|
|
30
|
+
core=_core(art_id="00000000-0000-0000-0000-000000000000"),
|
|
31
|
+
text="",
|
|
32
|
+
meta=None,
|
|
33
|
+
)
|
|
34
|
+
|
|
35
|
+
|
|
36
|
+
def typical_doc_ref_pm() -> DocRefPM:
|
|
37
|
+
return DocRefPM(
|
|
38
|
+
core=_core(art_id="11111111-1111-1111-1111-111111111111"),
|
|
39
|
+
text="Order must be rejected if quantity exceeds max order size.",
|
|
40
|
+
meta="spec:order_limits; source=confluence; section=Risk Checks",
|
|
41
|
+
)
|
|
42
|
+
|
|
43
|
+
|
|
44
|
+
def edge_doc_ref_pm() -> DocRefPM:
|
|
45
|
+
return DocRefPM(
|
|
46
|
+
core=_core(art_id="99999999-9999-9999-9999-999999999999"),
|
|
47
|
+
text=(
|
|
48
|
+
"A very long doc note that should wrap nicely and still be readable. "
|
|
49
|
+
"It may contain bullet-like text, punctuation, and ‘quoted’ phrases.\n\n"
|
|
50
|
+
"- Must preserve meaning\n"
|
|
51
|
+
"- Must keep formatting\n"
|
|
52
|
+
"- Should not overflow tables\n"
|
|
53
|
+
),
|
|
54
|
+
meta=(
|
|
55
|
+
"url=https://example.com/really/long/path/to/a/doc\n"
|
|
56
|
+
"tags=risk,limits,edge-case\n"
|
|
57
|
+
"owner=QA\n"
|
|
58
|
+
),
|
|
59
|
+
)
|
|
60
|
+
|
|
61
|
+
|
|
62
|
+
def make_doc_ref_pm(ctx: RenderCtx, variant: str) -> DocRefPM:
|
|
63
|
+
match variant:
|
|
64
|
+
case "minimal":
|
|
65
|
+
return minimal_doc_ref_pm()
|
|
66
|
+
case "edge":
|
|
67
|
+
return edge_doc_ref_pm()
|
|
68
|
+
case _:
|
|
69
|
+
return typical_doc_ref_pm()
|
|
70
|
+
|
|
71
|
+
|
|
72
|
+
# -----------------------------------------------------------------------------
|
|
73
|
+
# SrcCodeRefPM fixtures
|
|
74
|
+
# -----------------------------------------------------------------------------
|
|
75
|
+
|
|
76
|
+
def minimal_src_code_ref_pm() -> SrcCodeRefPM:
|
|
77
|
+
return SrcCodeRefPM(
|
|
78
|
+
core=_core(art_id="00000000-0000-0000-0000-000000000000"),
|
|
79
|
+
src_code="",
|
|
80
|
+
language=None,
|
|
81
|
+
file_path=None,
|
|
82
|
+
iml_code=None,
|
|
83
|
+
meta=None,
|
|
84
|
+
)
|
|
85
|
+
|
|
86
|
+
|
|
87
|
+
def typical_src_code_ref_pm(*, with_iml: bool = True) -> SrcCodeRefPM:
|
|
88
|
+
return SrcCodeRefPM(
|
|
89
|
+
core=_core(art_id="22222222-2222-2222-2222-222222222222"),
|
|
90
|
+
src_code=(
|
|
91
|
+
"def check_qty(order):\n"
|
|
92
|
+
" return order.qty <= 10000\n"
|
|
93
|
+
),
|
|
94
|
+
language="python",
|
|
95
|
+
file_path="risk/checks/order_limits.py",
|
|
96
|
+
iml_code=(
|
|
97
|
+
"let check_qty (o: order) : bool = o.qty <= 10000"
|
|
98
|
+
if with_iml
|
|
99
|
+
else None
|
|
100
|
+
),
|
|
101
|
+
meta="repo=speclogician; commit=abc123; kind=snippet",
|
|
102
|
+
)
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def edge_src_code_ref_pm() -> SrcCodeRefPM:
|
|
106
|
+
return SrcCodeRefPM(
|
|
107
|
+
core=_core(art_id="aaaaaaaa-aaaa-aaaa-aaaa-aaaaaaaaaaaa"),
|
|
108
|
+
src_code=(
|
|
109
|
+
"class RiskEngine:\n"
|
|
110
|
+
" def check(self, order, market_data, limits):\n"
|
|
111
|
+
" # extremely long snippet to stress wrapping\n"
|
|
112
|
+
+ (" # line\n" * 60)
|
|
113
|
+
+ " return True\n"
|
|
114
|
+
),
|
|
115
|
+
language="python",
|
|
116
|
+
file_path=("very/long/path/" * 6) + "risk_engine.py",
|
|
117
|
+
iml_code=(
|
|
118
|
+
"type order = { qty : int }\n"
|
|
119
|
+
"let check (o: order) : bool = o.qty > 0\n"
|
|
120
|
+
+ ("(* comment *)\n" * 40)
|
|
121
|
+
),
|
|
122
|
+
meta=(
|
|
123
|
+
"repo=monorepo\n"
|
|
124
|
+
"component=risk_engine\n"
|
|
125
|
+
"note=this meta is multi-line to stress rendering\n"
|
|
126
|
+
),
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
|
|
130
|
+
def make_src_code_ref_pm(ctx: RenderCtx, variant: str) -> SrcCodeRefPM:
|
|
131
|
+
match variant:
|
|
132
|
+
case "minimal":
|
|
133
|
+
return minimal_src_code_ref_pm()
|
|
134
|
+
case "edge":
|
|
135
|
+
return edge_src_code_ref_pm()
|
|
136
|
+
case _:
|
|
137
|
+
return typical_src_code_ref_pm()
|
|
138
|
+
|
|
139
|
+
def render_doc(pm: DocRefPM, ctx: RenderCtx):
|
|
140
|
+
return render_doc_ref(pm, ctx=ctx)
|
|
141
|
+
|
|
142
|
+
|
|
143
|
+
def render_src(pm: SrcCodeRefPM, ctx: RenderCtx):
|
|
144
|
+
return render_src_code_ref(pm, ctx=ctx)
|