elspais 0.11.2__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 +1 -10
- elspais/{sponsors/__init__.py → associates.py} +102 -56
- elspais/cli.py +366 -69
- elspais/commands/__init__.py +9 -3
- elspais/commands/analyze.py +118 -169
- elspais/commands/changed.py +12 -23
- elspais/commands/config_cmd.py +10 -13
- elspais/commands/edit.py +33 -13
- elspais/commands/example_cmd.py +319 -0
- elspais/commands/hash_cmd.py +161 -183
- elspais/commands/health.py +1177 -0
- elspais/commands/index.py +98 -115
- elspais/commands/init.py +99 -22
- elspais/commands/reformat_cmd.py +41 -433
- elspais/commands/rules_cmd.py +2 -2
- elspais/commands/trace.py +443 -324
- elspais/commands/validate.py +193 -411
- elspais/config/__init__.py +799 -5
- elspais/{core/content_rules.py → content_rules.py} +20 -2
- 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 +45 -29
- elspais/mcp/__main__.py +5 -1
- elspais/mcp/file_mutations.py +138 -0
- elspais/mcp/server.py +1998 -244
- elspais/testing/__init__.py +3 -3
- elspais/testing/config.py +3 -0
- elspais/testing/mapper.py +1 -1
- 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 +56 -51
- elspais/utilities/reference_config.py +626 -0
- elspais/validation/__init__.py +19 -0
- elspais/validation/format.py +264 -0
- {elspais-0.11.2.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 -179
- elspais/config/loader.py +0 -494
- elspais/core/__init__.py +0 -21
- elspais/core/git.py +0 -346
- elspais/core/models.py +0 -320
- elspais/core/parser.py +0 -639
- elspais/core/rules.py +0 -509
- elspais/mcp/context.py +0 -172
- elspais/mcp/serializers.py +0 -112
- elspais/reformat/__init__.py +0 -50
- elspais/reformat/detector.py +0 -112
- elspais/reformat/hierarchy.py +0 -247
- elspais/reformat/line_breaks.py +0 -218
- elspais/reformat/prompts.py +0 -133
- elspais/reformat/transformer.py +0 -266
- elspais/trace_view/__init__.py +0 -55
- elspais/trace_view/coverage.py +0 -183
- elspais/trace_view/generators/__init__.py +0 -12
- elspais/trace_view/generators/base.py +0 -334
- elspais/trace_view/generators/csv.py +0 -118
- elspais/trace_view/generators/markdown.py +0 -170
- elspais/trace_view/html/__init__.py +0 -33
- elspais/trace_view/html/generator.py +0 -1140
- 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 -378
- elspais/trace_view/review/__init__.py +0 -63
- elspais/trace_view/review/branches.py +0 -1142
- elspais/trace_view/review/models.py +0 -1200
- elspais/trace_view/review/position.py +0 -591
- elspais/trace_view/review/server.py +0 -1032
- elspais/trace_view/review/status.py +0 -455
- elspais/trace_view/review/storage.py +0 -1343
- 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.2.dist-info/RECORD +0 -101
- {elspais-0.11.2.dist-info → elspais-0.43.5.dist-info}/WHEEL +0 -0
- {elspais-0.11.2.dist-info → elspais-0.43.5.dist-info}/entry_points.txt +0 -0
- {elspais-0.11.2.dist-info → elspais-0.43.5.dist-info}/licenses/LICENSE +0 -0
|
@@ -1,170 +0,0 @@
|
|
|
1
|
-
"""
|
|
2
|
-
elspais.trace_view.generators.markdown - Markdown generation.
|
|
3
|
-
|
|
4
|
-
Provides functions to generate markdown traceability matrices.
|
|
5
|
-
"""
|
|
6
|
-
|
|
7
|
-
import sys
|
|
8
|
-
from datetime import datetime
|
|
9
|
-
from typing import Dict, List, Optional
|
|
10
|
-
|
|
11
|
-
from elspais.trace_view.coverage import count_by_level, find_orphaned_requirements
|
|
12
|
-
from elspais.trace_view.models import TraceViewRequirement
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
def generate_legend_markdown() -> str:
|
|
16
|
-
"""Generate markdown legend section.
|
|
17
|
-
|
|
18
|
-
Returns:
|
|
19
|
-
Markdown string with legend explaining symbols
|
|
20
|
-
"""
|
|
21
|
-
return """## Legend
|
|
22
|
-
|
|
23
|
-
**Requirement Status:**
|
|
24
|
-
- Active requirement
|
|
25
|
-
- Draft requirement
|
|
26
|
-
- Deprecated requirement
|
|
27
|
-
|
|
28
|
-
**Traceability:**
|
|
29
|
-
- Has implementation file(s)
|
|
30
|
-
- No implementation found
|
|
31
|
-
|
|
32
|
-
**Interactive (HTML only):**
|
|
33
|
-
- Expandable (has child requirements)
|
|
34
|
-
- Collapsed (click to expand)
|
|
35
|
-
"""
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
def generate_markdown(
|
|
39
|
-
requirements: Dict[str, TraceViewRequirement],
|
|
40
|
-
base_path: str = "",
|
|
41
|
-
) -> str:
|
|
42
|
-
"""Generate markdown traceability matrix.
|
|
43
|
-
|
|
44
|
-
Args:
|
|
45
|
-
requirements: Dict mapping requirement ID to TraceViewRequirement
|
|
46
|
-
base_path: Base path for links (e.g., '../' for files in subdirectory)
|
|
47
|
-
|
|
48
|
-
Returns:
|
|
49
|
-
Complete markdown traceability matrix
|
|
50
|
-
"""
|
|
51
|
-
lines = []
|
|
52
|
-
lines.append("# Requirements Traceability Matrix")
|
|
53
|
-
lines.append(f"\n**Generated**: {datetime.now().strftime('%Y-%m-%d %H:%M:%S')}")
|
|
54
|
-
lines.append(f"**Total Requirements**: {len(requirements)}\n")
|
|
55
|
-
|
|
56
|
-
# Summary by level (using active counts, excluding deprecated)
|
|
57
|
-
by_level = count_by_level(requirements)
|
|
58
|
-
lines.append("## Summary\n")
|
|
59
|
-
lines.append(f"- **PRD Requirements**: {by_level['active']['PRD']}")
|
|
60
|
-
lines.append(f"- **OPS Requirements**: {by_level['active']['OPS']}")
|
|
61
|
-
lines.append(f"- **DEV Requirements**: {by_level['active']['DEV']}\n")
|
|
62
|
-
|
|
63
|
-
# Add legend
|
|
64
|
-
lines.append(generate_legend_markdown())
|
|
65
|
-
|
|
66
|
-
# Full traceability tree
|
|
67
|
-
lines.append("## Traceability Tree\n")
|
|
68
|
-
|
|
69
|
-
# Start with top-level PRD requirements
|
|
70
|
-
prd_reqs = [req for req in requirements.values() if req.level == "PRD"]
|
|
71
|
-
prd_reqs.sort(key=lambda r: r.id)
|
|
72
|
-
|
|
73
|
-
for prd_req in prd_reqs:
|
|
74
|
-
lines.append(
|
|
75
|
-
format_req_tree_md(
|
|
76
|
-
prd_req, requirements, indent=0, ancestor_path=[], base_path=base_path
|
|
77
|
-
)
|
|
78
|
-
)
|
|
79
|
-
|
|
80
|
-
# Orphaned ops/dev requirements
|
|
81
|
-
orphaned = find_orphaned_requirements(requirements)
|
|
82
|
-
if orphaned:
|
|
83
|
-
lines.append("\n## Orphaned Requirements\n")
|
|
84
|
-
lines.append("*(Requirements not linked from any parent)*\n")
|
|
85
|
-
for req in orphaned:
|
|
86
|
-
lines.append(f"- **REQ-{req.id}**: {req.title} ({req.level}) - {req.display_filename}")
|
|
87
|
-
|
|
88
|
-
return "\n".join(lines)
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
def format_req_tree_md(
|
|
92
|
-
req: TraceViewRequirement,
|
|
93
|
-
requirements: Dict[str, TraceViewRequirement],
|
|
94
|
-
indent: int,
|
|
95
|
-
ancestor_path: Optional[List[str]] = None,
|
|
96
|
-
base_path: str = "",
|
|
97
|
-
) -> str:
|
|
98
|
-
"""Format requirement and its children as markdown tree.
|
|
99
|
-
|
|
100
|
-
Args:
|
|
101
|
-
req: The requirement to format
|
|
102
|
-
requirements: Dict mapping requirement ID to TraceViewRequirement
|
|
103
|
-
indent: Current indentation level
|
|
104
|
-
ancestor_path: List of requirement IDs in the current traversal path (for cycle detection)
|
|
105
|
-
base_path: Base path for links
|
|
106
|
-
|
|
107
|
-
Returns:
|
|
108
|
-
Formatted markdown string
|
|
109
|
-
"""
|
|
110
|
-
if ancestor_path is None:
|
|
111
|
-
ancestor_path = []
|
|
112
|
-
|
|
113
|
-
# Cycle detection: check if this requirement is already in our traversal path
|
|
114
|
-
if req.id in ancestor_path:
|
|
115
|
-
cycle_path = ancestor_path + [req.id]
|
|
116
|
-
cycle_str = " -> ".join([f"REQ-{rid}" for rid in cycle_path])
|
|
117
|
-
print(f"Warning: CYCLE DETECTED: {cycle_str}", file=sys.stderr)
|
|
118
|
-
return " " * indent + f"- **CYCLE DETECTED**: REQ-{req.id} (path: {cycle_str})"
|
|
119
|
-
|
|
120
|
-
# Safety depth limit
|
|
121
|
-
MAX_DEPTH = 50
|
|
122
|
-
if indent > MAX_DEPTH:
|
|
123
|
-
print(f"Warning: MAX DEPTH ({MAX_DEPTH}) exceeded at REQ-{req.id}", file=sys.stderr)
|
|
124
|
-
return " " * indent + f"- **MAX DEPTH EXCEEDED**: REQ-{req.id}"
|
|
125
|
-
|
|
126
|
-
lines = []
|
|
127
|
-
prefix = " " * indent
|
|
128
|
-
|
|
129
|
-
# Format current requirement
|
|
130
|
-
status_indicator = {
|
|
131
|
-
"Active": "[Active]",
|
|
132
|
-
"Draft": "[Draft]",
|
|
133
|
-
"Deprecated": "[Deprecated]",
|
|
134
|
-
}
|
|
135
|
-
indicator = status_indicator.get(req.status, "[?]")
|
|
136
|
-
|
|
137
|
-
# Create link to source file with REQ anchor
|
|
138
|
-
if req.external_spec_path:
|
|
139
|
-
req_link = f"[REQ-{req.id}](file://{req.external_spec_path}#REQ-{req.id})"
|
|
140
|
-
else:
|
|
141
|
-
spec_subpath = "spec/roadmap" if req.is_roadmap else "spec"
|
|
142
|
-
req_link = f"[REQ-{req.id}]({base_path}{spec_subpath}/{req.file_path.name}#REQ-{req.id})"
|
|
143
|
-
|
|
144
|
-
lines.append(
|
|
145
|
-
f"{prefix}- {indicator} **{req_link}**: {req.title}\n"
|
|
146
|
-
f"{prefix} - Level: {req.level} | Status: {req.status}\n"
|
|
147
|
-
f"{prefix} - File: {req.display_filename}:{req.line_number}"
|
|
148
|
-
)
|
|
149
|
-
|
|
150
|
-
# Format implementation files as nested list with clickable links
|
|
151
|
-
if req.implementation_files:
|
|
152
|
-
lines.append(f"{prefix} - **Implemented in**:")
|
|
153
|
-
for file_path, line_num in req.implementation_files:
|
|
154
|
-
# Create markdown link to file with line number anchor
|
|
155
|
-
link = f"[{file_path}:{line_num}]({base_path}{file_path}#L{line_num})"
|
|
156
|
-
lines.append(f"{prefix} - {link}")
|
|
157
|
-
|
|
158
|
-
# Find and format children
|
|
159
|
-
children = [r for r in requirements.values() if req.id in r.implements]
|
|
160
|
-
children.sort(key=lambda r: r.id)
|
|
161
|
-
|
|
162
|
-
if children:
|
|
163
|
-
# Add current req to path before recursing into children
|
|
164
|
-
current_path = ancestor_path + [req.id]
|
|
165
|
-
for child in children:
|
|
166
|
-
lines.append(
|
|
167
|
-
format_req_tree_md(child, requirements, indent + 1, current_path, base_path)
|
|
168
|
-
)
|
|
169
|
-
|
|
170
|
-
return "\n".join(lines)
|
|
@@ -1,33 +0,0 @@
|
|
|
1
|
-
# Implements: REQ-int-d00002-B (HTML generation requires jinja2)
|
|
2
|
-
"""
|
|
3
|
-
elspais.trace_view.html - Interactive HTML generation.
|
|
4
|
-
|
|
5
|
-
Requires: pip install elspais[trace-view]
|
|
6
|
-
"""
|
|
7
|
-
|
|
8
|
-
|
|
9
|
-
def _check_jinja2():
|
|
10
|
-
try:
|
|
11
|
-
import jinja2 # noqa: F401
|
|
12
|
-
|
|
13
|
-
return True
|
|
14
|
-
except ImportError:
|
|
15
|
-
return False
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
JINJA2_AVAILABLE = _check_jinja2()
|
|
19
|
-
|
|
20
|
-
if JINJA2_AVAILABLE:
|
|
21
|
-
from elspais.trace_view.html.generator import HTMLGenerator
|
|
22
|
-
|
|
23
|
-
__all__ = ["HTMLGenerator", "JINJA2_AVAILABLE"]
|
|
24
|
-
else:
|
|
25
|
-
__all__ = ["JINJA2_AVAILABLE"]
|
|
26
|
-
|
|
27
|
-
class HTMLGenerator:
|
|
28
|
-
"""Placeholder when jinja2 is not installed."""
|
|
29
|
-
|
|
30
|
-
def __init__(self, *args, **kwargs):
|
|
31
|
-
raise ImportError(
|
|
32
|
-
"HTMLGenerator requires Jinja2. " "Install with: pip install elspais[trace-view]"
|
|
33
|
-
)
|