elspais 0.11.1__py3-none-any.whl → 0.43.5__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.
- elspais/__init__.py +2 -11
- elspais/{sponsors/__init__.py → associates.py} +102 -58
- elspais/cli.py +395 -79
- elspais/commands/__init__.py +9 -3
- elspais/commands/analyze.py +121 -173
- elspais/commands/changed.py +15 -30
- elspais/commands/config_cmd.py +13 -16
- elspais/commands/edit.py +60 -44
- elspais/commands/example_cmd.py +319 -0
- elspais/commands/hash_cmd.py +167 -183
- elspais/commands/health.py +1177 -0
- elspais/commands/index.py +98 -114
- elspais/commands/init.py +103 -26
- elspais/commands/reformat_cmd.py +41 -444
- elspais/commands/rules_cmd.py +7 -3
- elspais/commands/trace.py +444 -321
- elspais/commands/validate.py +195 -415
- elspais/config/__init__.py +799 -5
- elspais/{core/content_rules.py → content_rules.py} +20 -3
- elspais/docs/cli/assertions.md +67 -0
- elspais/docs/cli/commands.md +304 -0
- elspais/docs/cli/config.md +262 -0
- elspais/docs/cli/format.md +66 -0
- elspais/docs/cli/git.md +45 -0
- elspais/docs/cli/health.md +190 -0
- elspais/docs/cli/hierarchy.md +60 -0
- elspais/docs/cli/ignore.md +72 -0
- elspais/docs/cli/mcp.md +245 -0
- elspais/docs/cli/quickstart.md +58 -0
- elspais/docs/cli/traceability.md +89 -0
- elspais/docs/cli/validation.md +96 -0
- elspais/graph/GraphNode.py +383 -0
- elspais/graph/__init__.py +40 -0
- elspais/graph/annotators.py +927 -0
- elspais/graph/builder.py +1886 -0
- elspais/graph/deserializer.py +248 -0
- elspais/graph/factory.py +284 -0
- elspais/graph/metrics.py +127 -0
- elspais/graph/mutations.py +161 -0
- elspais/graph/parsers/__init__.py +156 -0
- elspais/graph/parsers/code.py +213 -0
- elspais/graph/parsers/comments.py +112 -0
- elspais/graph/parsers/config_helpers.py +29 -0
- elspais/graph/parsers/heredocs.py +225 -0
- elspais/graph/parsers/journey.py +131 -0
- elspais/graph/parsers/remainder.py +79 -0
- elspais/graph/parsers/requirement.py +347 -0
- elspais/graph/parsers/results/__init__.py +6 -0
- elspais/graph/parsers/results/junit_xml.py +229 -0
- elspais/graph/parsers/results/pytest_json.py +313 -0
- elspais/graph/parsers/test.py +305 -0
- elspais/graph/relations.py +78 -0
- elspais/graph/serialize.py +216 -0
- elspais/html/__init__.py +8 -0
- elspais/html/generator.py +731 -0
- elspais/html/templates/trace_view.html.j2 +2151 -0
- elspais/mcp/__init__.py +47 -29
- elspais/mcp/__main__.py +5 -1
- elspais/mcp/file_mutations.py +138 -0
- elspais/mcp/server.py +2016 -247
- elspais/testing/__init__.py +4 -4
- elspais/testing/config.py +3 -0
- elspais/testing/mapper.py +1 -1
- elspais/testing/result_parser.py +25 -21
- elspais/testing/scanner.py +301 -12
- elspais/utilities/__init__.py +1 -0
- elspais/utilities/docs_loader.py +115 -0
- elspais/utilities/git.py +607 -0
- elspais/{core → utilities}/hasher.py +8 -22
- elspais/utilities/md_renderer.py +189 -0
- elspais/{core → utilities}/patterns.py +58 -57
- elspais/utilities/reference_config.py +626 -0
- elspais/validation/__init__.py +19 -0
- elspais/validation/format.py +264 -0
- {elspais-0.11.1.dist-info → elspais-0.43.5.dist-info}/METADATA +7 -4
- elspais-0.43.5.dist-info/RECORD +80 -0
- elspais/config/defaults.py +0 -173
- elspais/config/loader.py +0 -494
- elspais/core/__init__.py +0 -21
- elspais/core/git.py +0 -352
- elspais/core/models.py +0 -320
- elspais/core/parser.py +0 -640
- elspais/core/rules.py +0 -514
- elspais/mcp/context.py +0 -171
- elspais/mcp/serializers.py +0 -112
- elspais/reformat/__init__.py +0 -50
- elspais/reformat/detector.py +0 -119
- elspais/reformat/hierarchy.py +0 -246
- elspais/reformat/line_breaks.py +0 -220
- elspais/reformat/prompts.py +0 -123
- elspais/reformat/transformer.py +0 -264
- elspais/trace_view/__init__.py +0 -54
- elspais/trace_view/coverage.py +0 -183
- elspais/trace_view/generators/__init__.py +0 -12
- elspais/trace_view/generators/base.py +0 -329
- elspais/trace_view/generators/csv.py +0 -122
- elspais/trace_view/generators/markdown.py +0 -175
- elspais/trace_view/html/__init__.py +0 -31
- elspais/trace_view/html/generator.py +0 -1006
- elspais/trace_view/html/templates/base.html +0 -283
- elspais/trace_view/html/templates/components/code_viewer_modal.html +0 -14
- elspais/trace_view/html/templates/components/file_picker_modal.html +0 -20
- elspais/trace_view/html/templates/components/legend_modal.html +0 -69
- elspais/trace_view/html/templates/components/review_panel.html +0 -118
- elspais/trace_view/html/templates/partials/review/help/help-panel.json +0 -244
- elspais/trace_view/html/templates/partials/review/help/onboarding.json +0 -77
- elspais/trace_view/html/templates/partials/review/help/tooltips.json +0 -237
- elspais/trace_view/html/templates/partials/review/review-comments.js +0 -928
- elspais/trace_view/html/templates/partials/review/review-data.js +0 -961
- elspais/trace_view/html/templates/partials/review/review-help.js +0 -679
- elspais/trace_view/html/templates/partials/review/review-init.js +0 -177
- elspais/trace_view/html/templates/partials/review/review-line-numbers.js +0 -429
- elspais/trace_view/html/templates/partials/review/review-packages.js +0 -1029
- elspais/trace_view/html/templates/partials/review/review-position.js +0 -540
- elspais/trace_view/html/templates/partials/review/review-resize.js +0 -115
- elspais/trace_view/html/templates/partials/review/review-status.js +0 -659
- elspais/trace_view/html/templates/partials/review/review-sync.js +0 -992
- elspais/trace_view/html/templates/partials/review-styles.css +0 -2238
- elspais/trace_view/html/templates/partials/scripts.js +0 -1741
- elspais/trace_view/html/templates/partials/styles.css +0 -1756
- elspais/trace_view/models.py +0 -353
- elspais/trace_view/review/__init__.py +0 -60
- elspais/trace_view/review/branches.py +0 -1149
- elspais/trace_view/review/models.py +0 -1205
- elspais/trace_view/review/position.py +0 -609
- elspais/trace_view/review/server.py +0 -1056
- elspais/trace_view/review/status.py +0 -470
- elspais/trace_view/review/storage.py +0 -1367
- elspais/trace_view/scanning.py +0 -213
- elspais/trace_view/specs/README.md +0 -84
- elspais/trace_view/specs/tv-d00001-template-architecture.md +0 -36
- elspais/trace_view/specs/tv-d00002-css-extraction.md +0 -37
- elspais/trace_view/specs/tv-d00003-js-extraction.md +0 -43
- elspais/trace_view/specs/tv-d00004-build-embedding.md +0 -40
- elspais/trace_view/specs/tv-d00005-test-format.md +0 -78
- elspais/trace_view/specs/tv-d00010-review-data-models.md +0 -33
- elspais/trace_view/specs/tv-d00011-review-storage.md +0 -33
- elspais/trace_view/specs/tv-d00012-position-resolution.md +0 -33
- elspais/trace_view/specs/tv-d00013-git-branches.md +0 -31
- elspais/trace_view/specs/tv-d00014-review-api-server.md +0 -31
- elspais/trace_view/specs/tv-d00015-status-modifier.md +0 -27
- elspais/trace_view/specs/tv-d00016-js-integration.md +0 -33
- elspais/trace_view/specs/tv-p00001-html-generator.md +0 -33
- elspais/trace_view/specs/tv-p00002-review-system.md +0 -29
- elspais-0.11.1.dist-info/RECORD +0 -101
- {elspais-0.11.1.dist-info → elspais-0.43.5.dist-info}/WHEEL +0 -0
- {elspais-0.11.1.dist-info → elspais-0.43.5.dist-info}/entry_points.txt +0 -0
- {elspais-0.11.1.dist-info → elspais-0.43.5.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,216 @@
|
|
|
1
|
+
"""Graph Serialization - Export TraceGraph to various formats.
|
|
2
|
+
|
|
3
|
+
This module provides functions to serialize TraceGraph and GraphNode
|
|
4
|
+
to JSON-compatible dicts, markdown, and CSV formats.
|
|
5
|
+
"""
|
|
6
|
+
|
|
7
|
+
from __future__ import annotations
|
|
8
|
+
|
|
9
|
+
import csv
|
|
10
|
+
import io
|
|
11
|
+
from typing import TYPE_CHECKING, Any
|
|
12
|
+
|
|
13
|
+
if TYPE_CHECKING:
|
|
14
|
+
from elspais.graph.builder import TraceGraph
|
|
15
|
+
from elspais.graph.GraphNode import GraphNode
|
|
16
|
+
|
|
17
|
+
|
|
18
|
+
def serialize_node(node: GraphNode) -> dict[str, Any]:
|
|
19
|
+
"""Serialize a GraphNode to a JSON-compatible dict.
|
|
20
|
+
|
|
21
|
+
Args:
|
|
22
|
+
node: The node to serialize.
|
|
23
|
+
|
|
24
|
+
Returns:
|
|
25
|
+
Dict suitable for JSON serialization.
|
|
26
|
+
"""
|
|
27
|
+
|
|
28
|
+
result: dict[str, Any] = {
|
|
29
|
+
"id": node.id,
|
|
30
|
+
"kind": node.kind.name,
|
|
31
|
+
"label": node.get_label(),
|
|
32
|
+
"uuid": node.uuid,
|
|
33
|
+
"content": node.get_all_content(),
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
# Include source location if present
|
|
37
|
+
if node.source:
|
|
38
|
+
result["source"] = {
|
|
39
|
+
"path": node.source.path,
|
|
40
|
+
"line": node.source.line,
|
|
41
|
+
"end_line": node.source.end_line,
|
|
42
|
+
}
|
|
43
|
+
if node.source.repo:
|
|
44
|
+
result["source"]["repo"] = node.source.repo
|
|
45
|
+
|
|
46
|
+
# Include child IDs
|
|
47
|
+
children = list(node.iter_children())
|
|
48
|
+
if children:
|
|
49
|
+
result["children"] = [child.id for child in children]
|
|
50
|
+
|
|
51
|
+
# Include parent IDs
|
|
52
|
+
parents = list(node.iter_parents())
|
|
53
|
+
if parents:
|
|
54
|
+
result["parents"] = [parent.id for parent in parents]
|
|
55
|
+
|
|
56
|
+
# Include metrics
|
|
57
|
+
if node._metrics:
|
|
58
|
+
result["metrics"] = dict(node._metrics)
|
|
59
|
+
|
|
60
|
+
# Include outgoing edges
|
|
61
|
+
edges = list(node.iter_outgoing_edges())
|
|
62
|
+
if edges:
|
|
63
|
+
result["edges"] = [
|
|
64
|
+
{
|
|
65
|
+
"target": edge.target.id,
|
|
66
|
+
"kind": edge.kind.name,
|
|
67
|
+
}
|
|
68
|
+
for edge in edges
|
|
69
|
+
]
|
|
70
|
+
|
|
71
|
+
return result
|
|
72
|
+
|
|
73
|
+
|
|
74
|
+
def serialize_graph(graph: TraceGraph) -> dict[str, Any]:
|
|
75
|
+
"""Serialize a TraceGraph to a JSON-compatible dict.
|
|
76
|
+
|
|
77
|
+
Args:
|
|
78
|
+
graph: The graph to serialize.
|
|
79
|
+
|
|
80
|
+
Returns:
|
|
81
|
+
Dict with nodes, roots, and metadata.
|
|
82
|
+
"""
|
|
83
|
+
|
|
84
|
+
# Serialize all nodes and count by kind in single pass
|
|
85
|
+
nodes = {}
|
|
86
|
+
kind_counts: dict[str, int] = {}
|
|
87
|
+
for node in graph.all_nodes():
|
|
88
|
+
nodes[node.id] = serialize_node(node)
|
|
89
|
+
kind_name = node.kind.name
|
|
90
|
+
kind_counts[kind_name] = kind_counts.get(kind_name, 0) + 1
|
|
91
|
+
|
|
92
|
+
roots = list(graph.iter_roots())
|
|
93
|
+
return {
|
|
94
|
+
"nodes": nodes,
|
|
95
|
+
"roots": [root.id for root in roots],
|
|
96
|
+
"metadata": {
|
|
97
|
+
"node_count": len(nodes),
|
|
98
|
+
"root_count": len(roots),
|
|
99
|
+
"repo_root": str(graph.repo_root),
|
|
100
|
+
"by_kind": kind_counts,
|
|
101
|
+
},
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
|
|
105
|
+
def to_markdown(graph: TraceGraph) -> str:
|
|
106
|
+
"""Generate a markdown traceability matrix from graph.
|
|
107
|
+
|
|
108
|
+
Args:
|
|
109
|
+
graph: The TraceGraph to render.
|
|
110
|
+
|
|
111
|
+
Returns:
|
|
112
|
+
Markdown string with traceability matrix.
|
|
113
|
+
"""
|
|
114
|
+
from elspais.graph import NodeKind
|
|
115
|
+
|
|
116
|
+
lines = [
|
|
117
|
+
"# Traceability Matrix",
|
|
118
|
+
"",
|
|
119
|
+
"| ID | Level | Title | Status | Implements |",
|
|
120
|
+
"|-----|-------|-------|--------|------------|",
|
|
121
|
+
]
|
|
122
|
+
|
|
123
|
+
# Get requirements only
|
|
124
|
+
requirements = list(graph.nodes_by_kind(NodeKind.REQUIREMENT))
|
|
125
|
+
|
|
126
|
+
# Sort by ID
|
|
127
|
+
requirements.sort(key=lambda n: n.id)
|
|
128
|
+
|
|
129
|
+
for node in requirements:
|
|
130
|
+
req_id = node.id
|
|
131
|
+
level = node.get_field("level", "")
|
|
132
|
+
title = node.get_label() or ""
|
|
133
|
+
status = node.get_field("status", "")
|
|
134
|
+
|
|
135
|
+
# Get implements from incoming edges (what this node implements)
|
|
136
|
+
implements = []
|
|
137
|
+
for edge in node.iter_incoming_edges():
|
|
138
|
+
from elspais.graph.relations import EdgeKind
|
|
139
|
+
|
|
140
|
+
if edge.kind == EdgeKind.IMPLEMENTS:
|
|
141
|
+
implements.append(edge.source.id)
|
|
142
|
+
|
|
143
|
+
implements_str = ", ".join(implements) if implements else "-"
|
|
144
|
+
|
|
145
|
+
lines.append(f"| {req_id} | {level} | {title} | {status} | {implements_str} |")
|
|
146
|
+
|
|
147
|
+
lines.append("")
|
|
148
|
+
return "\n".join(lines)
|
|
149
|
+
|
|
150
|
+
|
|
151
|
+
def to_csv(graph: TraceGraph) -> str:
|
|
152
|
+
"""Generate a CSV export from graph.
|
|
153
|
+
|
|
154
|
+
Args:
|
|
155
|
+
graph: The TraceGraph to export.
|
|
156
|
+
|
|
157
|
+
Returns:
|
|
158
|
+
CSV string with requirement data.
|
|
159
|
+
"""
|
|
160
|
+
from elspais.graph import NodeKind
|
|
161
|
+
|
|
162
|
+
output = io.StringIO()
|
|
163
|
+
writer = csv.writer(output, quoting=csv.QUOTE_MINIMAL)
|
|
164
|
+
|
|
165
|
+
# Header
|
|
166
|
+
writer.writerow(
|
|
167
|
+
[
|
|
168
|
+
"id",
|
|
169
|
+
"level",
|
|
170
|
+
"label",
|
|
171
|
+
"status",
|
|
172
|
+
"file_path",
|
|
173
|
+
"line",
|
|
174
|
+
"hash",
|
|
175
|
+
"implements",
|
|
176
|
+
]
|
|
177
|
+
)
|
|
178
|
+
|
|
179
|
+
# Get requirements only
|
|
180
|
+
requirements = list(graph.nodes_by_kind(NodeKind.REQUIREMENT))
|
|
181
|
+
requirements.sort(key=lambda n: n.id)
|
|
182
|
+
|
|
183
|
+
for node in requirements:
|
|
184
|
+
file_path = node.source.path if node.source else ""
|
|
185
|
+
line = node.source.line if node.source else ""
|
|
186
|
+
|
|
187
|
+
# Get implements from incoming edges (what this node implements)
|
|
188
|
+
implements = []
|
|
189
|
+
for edge in node.iter_incoming_edges():
|
|
190
|
+
from elspais.graph.relations import EdgeKind
|
|
191
|
+
|
|
192
|
+
if edge.kind == EdgeKind.IMPLEMENTS:
|
|
193
|
+
implements.append(edge.source.id)
|
|
194
|
+
|
|
195
|
+
writer.writerow(
|
|
196
|
+
[
|
|
197
|
+
node.id,
|
|
198
|
+
node.get_field("level", ""),
|
|
199
|
+
node.get_label(),
|
|
200
|
+
node.get_field("status", ""),
|
|
201
|
+
file_path,
|
|
202
|
+
line,
|
|
203
|
+
node.get_field("hash", ""),
|
|
204
|
+
"; ".join(implements),
|
|
205
|
+
]
|
|
206
|
+
)
|
|
207
|
+
|
|
208
|
+
return output.getvalue()
|
|
209
|
+
|
|
210
|
+
|
|
211
|
+
__all__ = [
|
|
212
|
+
"serialize_node",
|
|
213
|
+
"serialize_graph",
|
|
214
|
+
"to_markdown",
|
|
215
|
+
"to_csv",
|
|
216
|
+
]
|