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.
Files changed (147) hide show
  1. elspais/__init__.py +1 -10
  2. elspais/{sponsors/__init__.py → associates.py} +102 -56
  3. elspais/cli.py +366 -69
  4. elspais/commands/__init__.py +9 -3
  5. elspais/commands/analyze.py +118 -169
  6. elspais/commands/changed.py +12 -23
  7. elspais/commands/config_cmd.py +10 -13
  8. elspais/commands/edit.py +33 -13
  9. elspais/commands/example_cmd.py +319 -0
  10. elspais/commands/hash_cmd.py +161 -183
  11. elspais/commands/health.py +1177 -0
  12. elspais/commands/index.py +98 -115
  13. elspais/commands/init.py +99 -22
  14. elspais/commands/reformat_cmd.py +41 -433
  15. elspais/commands/rules_cmd.py +2 -2
  16. elspais/commands/trace.py +443 -324
  17. elspais/commands/validate.py +193 -411
  18. elspais/config/__init__.py +799 -5
  19. elspais/{core/content_rules.py → content_rules.py} +20 -2
  20. elspais/docs/cli/assertions.md +67 -0
  21. elspais/docs/cli/commands.md +304 -0
  22. elspais/docs/cli/config.md +262 -0
  23. elspais/docs/cli/format.md +66 -0
  24. elspais/docs/cli/git.md +45 -0
  25. elspais/docs/cli/health.md +190 -0
  26. elspais/docs/cli/hierarchy.md +60 -0
  27. elspais/docs/cli/ignore.md +72 -0
  28. elspais/docs/cli/mcp.md +245 -0
  29. elspais/docs/cli/quickstart.md +58 -0
  30. elspais/docs/cli/traceability.md +89 -0
  31. elspais/docs/cli/validation.md +96 -0
  32. elspais/graph/GraphNode.py +383 -0
  33. elspais/graph/__init__.py +40 -0
  34. elspais/graph/annotators.py +927 -0
  35. elspais/graph/builder.py +1886 -0
  36. elspais/graph/deserializer.py +248 -0
  37. elspais/graph/factory.py +284 -0
  38. elspais/graph/metrics.py +127 -0
  39. elspais/graph/mutations.py +161 -0
  40. elspais/graph/parsers/__init__.py +156 -0
  41. elspais/graph/parsers/code.py +213 -0
  42. elspais/graph/parsers/comments.py +112 -0
  43. elspais/graph/parsers/config_helpers.py +29 -0
  44. elspais/graph/parsers/heredocs.py +225 -0
  45. elspais/graph/parsers/journey.py +131 -0
  46. elspais/graph/parsers/remainder.py +79 -0
  47. elspais/graph/parsers/requirement.py +347 -0
  48. elspais/graph/parsers/results/__init__.py +6 -0
  49. elspais/graph/parsers/results/junit_xml.py +229 -0
  50. elspais/graph/parsers/results/pytest_json.py +313 -0
  51. elspais/graph/parsers/test.py +305 -0
  52. elspais/graph/relations.py +78 -0
  53. elspais/graph/serialize.py +216 -0
  54. elspais/html/__init__.py +8 -0
  55. elspais/html/generator.py +731 -0
  56. elspais/html/templates/trace_view.html.j2 +2151 -0
  57. elspais/mcp/__init__.py +45 -29
  58. elspais/mcp/__main__.py +5 -1
  59. elspais/mcp/file_mutations.py +138 -0
  60. elspais/mcp/server.py +1998 -244
  61. elspais/testing/__init__.py +3 -3
  62. elspais/testing/config.py +3 -0
  63. elspais/testing/mapper.py +1 -1
  64. elspais/testing/scanner.py +301 -12
  65. elspais/utilities/__init__.py +1 -0
  66. elspais/utilities/docs_loader.py +115 -0
  67. elspais/utilities/git.py +607 -0
  68. elspais/{core → utilities}/hasher.py +8 -22
  69. elspais/utilities/md_renderer.py +189 -0
  70. elspais/{core → utilities}/patterns.py +56 -51
  71. elspais/utilities/reference_config.py +626 -0
  72. elspais/validation/__init__.py +19 -0
  73. elspais/validation/format.py +264 -0
  74. {elspais-0.11.2.dist-info → elspais-0.43.5.dist-info}/METADATA +7 -4
  75. elspais-0.43.5.dist-info/RECORD +80 -0
  76. elspais/config/defaults.py +0 -179
  77. elspais/config/loader.py +0 -494
  78. elspais/core/__init__.py +0 -21
  79. elspais/core/git.py +0 -346
  80. elspais/core/models.py +0 -320
  81. elspais/core/parser.py +0 -639
  82. elspais/core/rules.py +0 -509
  83. elspais/mcp/context.py +0 -172
  84. elspais/mcp/serializers.py +0 -112
  85. elspais/reformat/__init__.py +0 -50
  86. elspais/reformat/detector.py +0 -112
  87. elspais/reformat/hierarchy.py +0 -247
  88. elspais/reformat/line_breaks.py +0 -218
  89. elspais/reformat/prompts.py +0 -133
  90. elspais/reformat/transformer.py +0 -266
  91. elspais/trace_view/__init__.py +0 -55
  92. elspais/trace_view/coverage.py +0 -183
  93. elspais/trace_view/generators/__init__.py +0 -12
  94. elspais/trace_view/generators/base.py +0 -334
  95. elspais/trace_view/generators/csv.py +0 -118
  96. elspais/trace_view/generators/markdown.py +0 -170
  97. elspais/trace_view/html/__init__.py +0 -33
  98. elspais/trace_view/html/generator.py +0 -1140
  99. elspais/trace_view/html/templates/base.html +0 -283
  100. elspais/trace_view/html/templates/components/code_viewer_modal.html +0 -14
  101. elspais/trace_view/html/templates/components/file_picker_modal.html +0 -20
  102. elspais/trace_view/html/templates/components/legend_modal.html +0 -69
  103. elspais/trace_view/html/templates/components/review_panel.html +0 -118
  104. elspais/trace_view/html/templates/partials/review/help/help-panel.json +0 -244
  105. elspais/trace_view/html/templates/partials/review/help/onboarding.json +0 -77
  106. elspais/trace_view/html/templates/partials/review/help/tooltips.json +0 -237
  107. elspais/trace_view/html/templates/partials/review/review-comments.js +0 -928
  108. elspais/trace_view/html/templates/partials/review/review-data.js +0 -961
  109. elspais/trace_view/html/templates/partials/review/review-help.js +0 -679
  110. elspais/trace_view/html/templates/partials/review/review-init.js +0 -177
  111. elspais/trace_view/html/templates/partials/review/review-line-numbers.js +0 -429
  112. elspais/trace_view/html/templates/partials/review/review-packages.js +0 -1029
  113. elspais/trace_view/html/templates/partials/review/review-position.js +0 -540
  114. elspais/trace_view/html/templates/partials/review/review-resize.js +0 -115
  115. elspais/trace_view/html/templates/partials/review/review-status.js +0 -659
  116. elspais/trace_view/html/templates/partials/review/review-sync.js +0 -992
  117. elspais/trace_view/html/templates/partials/review-styles.css +0 -2238
  118. elspais/trace_view/html/templates/partials/scripts.js +0 -1741
  119. elspais/trace_view/html/templates/partials/styles.css +0 -1756
  120. elspais/trace_view/models.py +0 -378
  121. elspais/trace_view/review/__init__.py +0 -63
  122. elspais/trace_view/review/branches.py +0 -1142
  123. elspais/trace_view/review/models.py +0 -1200
  124. elspais/trace_view/review/position.py +0 -591
  125. elspais/trace_view/review/server.py +0 -1032
  126. elspais/trace_view/review/status.py +0 -455
  127. elspais/trace_view/review/storage.py +0 -1343
  128. elspais/trace_view/scanning.py +0 -213
  129. elspais/trace_view/specs/README.md +0 -84
  130. elspais/trace_view/specs/tv-d00001-template-architecture.md +0 -36
  131. elspais/trace_view/specs/tv-d00002-css-extraction.md +0 -37
  132. elspais/trace_view/specs/tv-d00003-js-extraction.md +0 -43
  133. elspais/trace_view/specs/tv-d00004-build-embedding.md +0 -40
  134. elspais/trace_view/specs/tv-d00005-test-format.md +0 -78
  135. elspais/trace_view/specs/tv-d00010-review-data-models.md +0 -33
  136. elspais/trace_view/specs/tv-d00011-review-storage.md +0 -33
  137. elspais/trace_view/specs/tv-d00012-position-resolution.md +0 -33
  138. elspais/trace_view/specs/tv-d00013-git-branches.md +0 -31
  139. elspais/trace_view/specs/tv-d00014-review-api-server.md +0 -31
  140. elspais/trace_view/specs/tv-d00015-status-modifier.md +0 -27
  141. elspais/trace_view/specs/tv-d00016-js-integration.md +0 -33
  142. elspais/trace_view/specs/tv-p00001-html-generator.md +0 -33
  143. elspais/trace_view/specs/tv-p00002-review-system.md +0 -29
  144. elspais-0.11.2.dist-info/RECORD +0 -101
  145. {elspais-0.11.2.dist-info → elspais-0.43.5.dist-info}/WHEEL +0 -0
  146. {elspais-0.11.2.dist-info → elspais-0.43.5.dist-info}/entry_points.txt +0 -0
  147. {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
- )