elspais 0.11.0__py3-none-any.whl → 0.11.2__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 (53) hide show
  1. elspais/__init__.py +1 -1
  2. elspais/cli.py +75 -23
  3. elspais/commands/analyze.py +5 -6
  4. elspais/commands/changed.py +2 -6
  5. elspais/commands/config_cmd.py +4 -4
  6. elspais/commands/edit.py +32 -36
  7. elspais/commands/hash_cmd.py +24 -18
  8. elspais/commands/index.py +8 -7
  9. elspais/commands/init.py +4 -4
  10. elspais/commands/reformat_cmd.py +32 -43
  11. elspais/commands/rules_cmd.py +6 -2
  12. elspais/commands/trace.py +23 -19
  13. elspais/commands/validate.py +8 -10
  14. elspais/config/defaults.py +7 -1
  15. elspais/core/content_rules.py +0 -1
  16. elspais/core/git.py +4 -10
  17. elspais/core/parser.py +55 -56
  18. elspais/core/patterns.py +2 -6
  19. elspais/core/rules.py +10 -15
  20. elspais/mcp/__init__.py +2 -0
  21. elspais/mcp/context.py +1 -0
  22. elspais/mcp/serializers.py +1 -1
  23. elspais/mcp/server.py +54 -39
  24. elspais/reformat/__init__.py +13 -13
  25. elspais/reformat/detector.py +9 -16
  26. elspais/reformat/hierarchy.py +8 -7
  27. elspais/reformat/line_breaks.py +36 -38
  28. elspais/reformat/prompts.py +22 -12
  29. elspais/reformat/transformer.py +43 -41
  30. elspais/sponsors/__init__.py +0 -2
  31. elspais/testing/__init__.py +1 -1
  32. elspais/testing/result_parser.py +25 -21
  33. elspais/trace_view/__init__.py +4 -3
  34. elspais/trace_view/coverage.py +5 -5
  35. elspais/trace_view/generators/__init__.py +1 -1
  36. elspais/trace_view/generators/base.py +17 -12
  37. elspais/trace_view/generators/csv.py +2 -6
  38. elspais/trace_view/generators/markdown.py +3 -8
  39. elspais/trace_view/html/__init__.py +4 -2
  40. elspais/trace_view/html/generator.py +423 -289
  41. elspais/trace_view/models.py +25 -0
  42. elspais/trace_view/review/__init__.py +21 -18
  43. elspais/trace_view/review/branches.py +114 -121
  44. elspais/trace_view/review/models.py +232 -237
  45. elspais/trace_view/review/position.py +53 -71
  46. elspais/trace_view/review/server.py +264 -288
  47. elspais/trace_view/review/status.py +43 -58
  48. elspais/trace_view/review/storage.py +48 -72
  49. {elspais-0.11.0.dist-info → elspais-0.11.2.dist-info}/METADATA +12 -9
  50. {elspais-0.11.0.dist-info → elspais-0.11.2.dist-info}/RECORD +53 -53
  51. {elspais-0.11.0.dist-info → elspais-0.11.2.dist-info}/WHEEL +0 -0
  52. {elspais-0.11.0.dist-info → elspais-0.11.2.dist-info}/entry_points.txt +0 -0
  53. {elspais-0.11.0.dist-info → elspais-0.11.2.dist-info}/licenses/LICENSE +0 -0
@@ -9,14 +9,11 @@ requirement parsing, implementation scanning, and output generation.
9
9
  from pathlib import Path
10
10
  from typing import Dict, List, Optional
11
11
 
12
- from elspais.config.loader import find_config_file, load_config, get_spec_directories
13
12
  from elspais.config.defaults import DEFAULT_CONFIG
13
+ from elspais.config.loader import find_config_file, get_spec_directories, load_config
14
+ from elspais.core.git import get_git_changes
14
15
  from elspais.core.parser import RequirementParser
15
16
  from elspais.core.patterns import PatternConfig
16
- from elspais.core.git import get_git_changes, GitChangeInfo
17
-
18
- from elspais.trace_view.models import TraceViewRequirement, GitChangeInfo as TVGitChangeInfo
19
- from elspais.trace_view.scanning import scan_implementation_files
20
17
  from elspais.trace_view.coverage import (
21
18
  calculate_coverage,
22
19
  generate_coverage_report,
@@ -24,6 +21,9 @@ from elspais.trace_view.coverage import (
24
21
  )
25
22
  from elspais.trace_view.generators.csv import generate_csv, generate_planning_csv
26
23
  from elspais.trace_view.generators.markdown import generate_markdown
24
+ from elspais.trace_view.models import GitChangeInfo as TVGitChangeInfo
25
+ from elspais.trace_view.models import TraceViewRequirement
26
+ from elspais.trace_view.scanning import scan_implementation_files
27
27
 
28
28
 
29
29
  class TraceViewGenerator:
@@ -93,7 +93,7 @@ class TraceViewGenerator:
93
93
 
94
94
  # Parse requirements
95
95
  if not quiet:
96
- print(f"Scanning for requirements...")
96
+ print("Scanning for requirements...")
97
97
  self._parse_requirements(quiet)
98
98
 
99
99
  if not self.requirements:
@@ -187,9 +187,7 @@ class TraceViewGenerator:
187
187
 
188
188
  # Report branch changes vs main
189
189
  if not quiet and git_changes.branch_changed_files:
190
- spec_branch = [
191
- f for f in git_changes.branch_changed_files if f.startswith("spec/")
192
- ]
190
+ spec_branch = [f for f in git_changes.branch_changed_files if f.startswith("spec/")]
193
191
  if spec_branch:
194
192
  print(f"Spec files changed vs main: {len(spec_branch)}")
195
193
 
@@ -298,7 +296,9 @@ class TraceViewGenerator:
298
296
  cycle_count += 1
299
297
 
300
298
  if not quiet and cycle_count > 0:
301
- print(f" Warning: {cycle_count} requirements marked as cyclic (shown as orphaned items)")
299
+ print(
300
+ f" Warning: {cycle_count} requirements marked as cyclic (shown as orphaned items)"
301
+ )
302
302
 
303
303
  def _calculate_base_path(self, output_file: Path):
304
304
  """Calculate relative path from output file location to repo root."""
@@ -320,8 +320,13 @@ class TraceViewGenerator:
320
320
 
321
321
  def generate_planning_csv(self) -> str:
322
322
  """Generate planning CSV with actionable requirements."""
323
- get_status = lambda req_id: get_implementation_status(self.requirements, req_id)
324
- calc_coverage = lambda req_id: calculate_coverage(self.requirements, req_id)
323
+
324
+ def get_status(req_id):
325
+ return get_implementation_status(self.requirements, req_id)
326
+
327
+ def calc_coverage(req_id):
328
+ return calculate_coverage(self.requirements, req_id)
329
+
325
330
  return generate_planning_csv(self.requirements, get_status, calc_coverage)
326
331
 
327
332
  def generate_coverage_report(self) -> str:
@@ -90,14 +90,10 @@ def generate_planning_csv(
90
90
  writer = csv.writer(output)
91
91
 
92
92
  # Header
93
- writer.writerow(
94
- ["REQ ID", "Title", "Level", "Status", "Impl Status", "Coverage", "Code Refs"]
95
- )
93
+ writer.writerow(["REQ ID", "Title", "Level", "Status", "Impl Status", "Coverage", "Code Refs"])
96
94
 
97
95
  # Filter to actionable requirements (Active or Draft status)
98
- actionable_reqs = [
99
- req for req in requirements.values() if req.status in ["Active", "Draft"]
100
- ]
96
+ actionable_reqs = [req for req in requirements.values() if req.status in ["Active", "Draft"]]
101
97
 
102
98
  # Sort by ID
103
99
  actionable_reqs.sort(key=lambda r: r.id)
@@ -8,8 +8,8 @@ import sys
8
8
  from datetime import datetime
9
9
  from typing import Dict, List, Optional
10
10
 
11
- from elspais.trace_view.models import TraceViewRequirement
12
11
  from elspais.trace_view.coverage import count_by_level, find_orphaned_requirements
12
+ from elspais.trace_view.models import TraceViewRequirement
13
13
 
14
14
 
15
15
  def generate_legend_markdown() -> str:
@@ -83,9 +83,7 @@ def generate_markdown(
83
83
  lines.append("\n## Orphaned Requirements\n")
84
84
  lines.append("*(Requirements not linked from any parent)*\n")
85
85
  for req in orphaned:
86
- lines.append(
87
- f"- **REQ-{req.id}**: {req.title} ({req.level}) - {req.display_filename}"
88
- )
86
+ lines.append(f"- **REQ-{req.id}**: {req.title} ({req.level}) - {req.display_filename}")
89
87
 
90
88
  return "\n".join(lines)
91
89
 
@@ -117,10 +115,7 @@ def format_req_tree_md(
117
115
  cycle_path = ancestor_path + [req.id]
118
116
  cycle_str = " -> ".join([f"REQ-{rid}" for rid in cycle_path])
119
117
  print(f"Warning: CYCLE DETECTED: {cycle_str}", file=sys.stderr)
120
- return (
121
- " " * indent
122
- + f"- **CYCLE DETECTED**: REQ-{req.id} (path: {cycle_str})"
123
- )
118
+ return " " * indent + f"- **CYCLE DETECTED**: REQ-{req.id} (path: {cycle_str})"
124
119
 
125
120
  # Safety depth limit
126
121
  MAX_DEPTH = 50
@@ -5,9 +5,11 @@ elspais.trace_view.html - Interactive HTML generation.
5
5
  Requires: pip install elspais[trace-view]
6
6
  """
7
7
 
8
+
8
9
  def _check_jinja2():
9
10
  try:
10
11
  import jinja2 # noqa: F401
12
+
11
13
  return True
12
14
  except ImportError:
13
15
  return False
@@ -17,6 +19,7 @@ JINJA2_AVAILABLE = _check_jinja2()
17
19
 
18
20
  if JINJA2_AVAILABLE:
19
21
  from elspais.trace_view.html.generator import HTMLGenerator
22
+
20
23
  __all__ = ["HTMLGenerator", "JINJA2_AVAILABLE"]
21
24
  else:
22
25
  __all__ = ["JINJA2_AVAILABLE"]
@@ -26,6 +29,5 @@ else:
26
29
 
27
30
  def __init__(self, *args, **kwargs):
28
31
  raise ImportError(
29
- "HTMLGenerator requires Jinja2. "
30
- "Install with: pip install elspais[trace-view]"
32
+ "HTMLGenerator requires Jinja2. " "Install with: pip install elspais[trace-view]"
31
33
  )