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
elspais/cli.py CHANGED
@@ -15,7 +15,9 @@ from elspais.commands import (
15
15
  changed,
16
16
  config_cmd,
17
17
  edit,
18
+ example_cmd,
18
19
  hash_cmd,
20
+ health,
19
21
  index,
20
22
  init,
21
23
  reformat_cmd,
@@ -40,8 +42,17 @@ Examples:
40
42
  elspais hash update # Update all requirement hashes
41
43
  elspais changed # Show uncommitted spec changes
42
44
  elspais analyze hierarchy # Show requirement hierarchy tree
43
- elspais config show # View current configuration
44
- elspais init # Create .elspais.toml configuration
45
+
46
+ Configuration:
47
+ elspais init # Create .elspais.toml in current directory
48
+ elspais config path # Show config file location
49
+ elspais config show # View all settings
50
+ elspais config --help # Configuration guide with examples
51
+
52
+ Documentation:
53
+ elspais example # Quick requirement format reference
54
+ elspais example --full # Full specification document
55
+ elspais completion # Shell tab-completion setup
45
56
 
46
57
  For detailed command help: elspais <command> --help
47
58
  """,
@@ -104,13 +115,12 @@ Common rules to skip:
104
115
  validate_parser.add_argument(
105
116
  "--fix",
106
117
  action="store_true",
107
- help="Auto-fix fixable issues",
118
+ help="Auto-fix issues that can be corrected programmatically (hashes, status)",
108
119
  )
109
120
  validate_parser.add_argument(
110
- "--core-repo",
111
- type=Path,
112
- help="Path to core repository (for associated repo validation)",
113
- metavar="PATH",
121
+ "--dry-run",
122
+ action="store_true",
123
+ help="Show what would be fixed without making changes (use with --fix)",
114
124
  )
115
125
  validate_parser.add_argument(
116
126
  "--skip-rule",
@@ -124,21 +134,59 @@ Common rules to skip:
124
134
  action="store_true",
125
135
  help="Output requirements as JSON (hht_diary compatible format)",
126
136
  )
127
- validate_parser.add_argument(
128
- "--tests",
137
+ # NOTE: --tests, --no-tests, --mode removed (dead code - never implemented)
138
+
139
+ # health command
140
+ health_parser = subparsers.add_parser(
141
+ "health",
142
+ help="Check repository and configuration health",
143
+ formatter_class=argparse.RawDescriptionHelpFormatter,
144
+ epilog="""
145
+ Examples:
146
+ elspais health # Run all health checks
147
+ elspais health --config # Check config only
148
+ elspais health --spec # Check spec files only
149
+ elspais health --code # Check code references only
150
+ elspais health --tests # Check test mappings only
151
+ elspais health -j # Output JSON for tooling
152
+ elspais health -v # Verbose output with details
153
+
154
+ Checks performed:
155
+ CONFIG: TOML syntax, required fields, pattern tokens, hierarchy rules, paths
156
+ SPEC: File parsing, duplicate IDs, reference resolution, orphans
157
+ CODE: Code→REQ reference validation, coverage statistics
158
+ TESTS: Test→REQ mappings, result status, coverage statistics
159
+ """,
160
+ )
161
+ health_parser.add_argument(
162
+ "--config",
163
+ dest="config_only",
129
164
  action="store_true",
130
- help="Force test scanning even if disabled in config",
165
+ help="Run configuration checks only",
131
166
  )
132
- validate_parser.add_argument(
133
- "--no-tests",
167
+ health_parser.add_argument(
168
+ "--spec",
169
+ dest="spec_only",
134
170
  action="store_true",
135
- help="Skip test scanning",
171
+ help="Run spec file checks only",
136
172
  )
137
- validate_parser.add_argument(
138
- "--mode",
139
- choices=["core", "combined"],
140
- default="combined",
141
- help="Scope: core (this repo only), combined (include sponsor repos)",
173
+ health_parser.add_argument(
174
+ "--code",
175
+ dest="code_only",
176
+ action="store_true",
177
+ help="Run code reference checks only",
178
+ )
179
+ health_parser.add_argument(
180
+ "--tests",
181
+ dest="tests_only",
182
+ action="store_true",
183
+ help="Run test mapping checks only",
184
+ )
185
+ health_parser.add_argument(
186
+ "-j",
187
+ "--json",
188
+ action="store_true",
189
+ help="Output as JSON",
142
190
  )
143
191
 
144
192
  # trace command
@@ -184,23 +232,19 @@ Common rules to skip:
184
232
  action="store_true",
185
233
  help="Start review server (requires trace-review extra)",
186
234
  )
235
+ # NOTE: --port, --mode, --sponsor, --graph removed (dead code - never implemented)
236
+ # Graph-based trace options
187
237
  trace_parser.add_argument(
188
- "--port",
189
- type=int,
190
- default=8080,
191
- help="Port for review server (default: 8080)",
192
- )
193
- trace_parser.add_argument(
194
- "--mode",
195
- choices=["core", "sponsor", "combined"],
196
- default="core",
197
- help="Report mode: core, sponsor, or combined (default: core)",
238
+ "--graph-json",
239
+ action="store_true",
240
+ help="Output graph structure as JSON",
198
241
  )
199
242
  trace_parser.add_argument(
200
- "--sponsor",
201
- help="Sponsor name for sponsor-specific reports",
202
- metavar="NAME",
243
+ "--report",
244
+ choices=["minimal", "standard", "full"],
245
+ help="Report preset to use (default: standard)",
203
246
  )
247
+ # NOTE: --depth removed (dead code - never implemented)
204
248
 
205
249
  # hash command
206
250
  hash_parser = subparsers.add_parser(
@@ -320,6 +364,38 @@ Common rules to skip:
320
364
  action="store_true",
321
365
  help="Overwrite existing configuration",
322
366
  )
367
+ init_parser.add_argument(
368
+ "--template",
369
+ action="store_true",
370
+ help="Create an example requirement file in spec/",
371
+ )
372
+
373
+ # example command
374
+ example_parser = subparsers.add_parser(
375
+ "example",
376
+ help="Display requirement format examples and templates",
377
+ formatter_class=argparse.RawDescriptionHelpFormatter,
378
+ epilog="""
379
+ Subcommands:
380
+ elspais example Quick reference (default)
381
+ elspais example requirement Full requirement template with all sections
382
+ elspais example journey User journey template
383
+ elspais example assertion Assertion rules and examples
384
+ elspais example ids Show ID patterns from current config
385
+ elspais example --full Display spec/requirements-spec.md (if exists)
386
+ """,
387
+ )
388
+ example_parser.add_argument(
389
+ "example_type",
390
+ nargs="?",
391
+ choices=["requirement", "journey", "assertion", "ids"],
392
+ help="Example type to display",
393
+ )
394
+ example_parser.add_argument(
395
+ "--full",
396
+ action="store_true",
397
+ help="Display the full requirements specification file",
398
+ )
323
399
 
324
400
  # edit command
325
401
  edit_parser = subparsers.add_parser(
@@ -334,7 +410,7 @@ Examples:
334
410
  elspais edit --from-json edits.json
335
411
 
336
412
  JSON batch format:
337
- {"edits": [{"req_id": "...", "status": "...", "implements": [...]}]}
413
+ [{"req_id": "...", "status": "...", "implements": [...]}]
338
414
  """,
339
415
  )
340
416
  edit_parser.add_argument(
@@ -377,6 +453,39 @@ JSON batch format:
377
453
  config_parser = subparsers.add_parser(
378
454
  "config",
379
455
  help="View and modify configuration (show, get, set, ...)",
456
+ formatter_class=argparse.RawDescriptionHelpFormatter,
457
+ epilog="""
458
+ Configuration File:
459
+ elspais looks for .elspais.toml in the current directory or parent directories.
460
+ Create one with: elspais init
461
+
462
+ Location: elspais config path
463
+ View all: elspais config show
464
+
465
+ Quick Start (.elspais.toml):
466
+ [project]
467
+ name = "my-project"
468
+ spec_dir = "spec" # Where requirement files live
469
+
470
+ [patterns]
471
+ prefix = "REQ" # Requirement ID prefix
472
+ separator = "-" # ID separator (REQ-p00001)
473
+
474
+ [rules]
475
+ strict_mode = false # Strict implements semantics
476
+
477
+ [rules.hierarchy]
478
+ allowed = ["dev -> ops, prd", "ops -> prd"]
479
+
480
+ Common Commands:
481
+ elspais config show # View current config
482
+ elspais config get patterns.prefix
483
+ elspais config set project.name "MyApp"
484
+ elspais config path # Show config file location
485
+
486
+ Full Documentation:
487
+ See docs/configuration.md for all options.
488
+ """,
380
489
  )
381
490
  config_subparsers = config_parser.add_subparsers(dest="config_action")
382
491
 
@@ -494,51 +603,105 @@ JSON batch format:
494
603
  help="Content rule file name (e.g., 'AI-AGENT.md')",
495
604
  )
496
605
 
497
- # reformat-with-claude command
498
- reformat_parser = subparsers.add_parser(
606
+ # reformat-with-claude command (NOT YET IMPLEMENTED - placeholder for future feature)
607
+ subparsers.add_parser(
499
608
  "reformat-with-claude",
500
- help="Reformat requirements using AI (Acceptance Criteria -> Assertions)",
501
- )
502
- reformat_parser.add_argument(
503
- "--start-req",
504
- help="Starting requirement ID (default: all PRD requirements)",
505
- metavar="ID",
506
- )
507
- reformat_parser.add_argument(
508
- "--depth",
509
- type=int,
510
- help="Maximum traversal depth (default: unlimited)",
609
+ help="[NOT IMPLEMENTED] Reformat requirements using AI (Acceptance Criteria -> Assertions)",
511
610
  )
512
- reformat_parser.add_argument(
513
- "--dry-run",
514
- action="store_true",
515
- help="Preview changes without applying",
516
- )
517
- reformat_parser.add_argument(
518
- "--backup",
519
- action="store_true",
520
- help="Create .bak files before editing",
611
+ # NOTE: All arguments removed - command not yet implemented
612
+ # See src/elspais/commands/reformat_cmd.py for planned features
613
+
614
+ # docs command - comprehensive user documentation
615
+ docs_parser = subparsers.add_parser(
616
+ "docs",
617
+ help="Read the user guide (topics: quickstart, format, hierarchy, ...)",
618
+ formatter_class=argparse.RawDescriptionHelpFormatter,
619
+ epilog="""
620
+ Available Topics:
621
+ quickstart Getting started with elspais (default)
622
+ format Requirement file format and structure
623
+ hierarchy PRD → OPS → DEV levels and implements
624
+ assertions Writing testable assertions with SHALL
625
+ traceability Linking requirements to code and tests
626
+ validation Running validation and fixing issues
627
+ git Change detection and git integration
628
+ config Configuration file reference
629
+ mcp MCP server for AI integration
630
+ all Show complete documentation
631
+
632
+ Examples:
633
+ elspais docs # Quick start guide
634
+ elspais docs format # Requirement format reference
635
+ elspais docs all # Complete documentation
636
+ elspais docs all --no-pager # Disable pager
637
+ """,
521
638
  )
522
- reformat_parser.add_argument(
523
- "--force",
639
+ docs_parser.add_argument(
640
+ "topic",
641
+ nargs="?",
642
+ default="quickstart",
643
+ choices=[
644
+ "quickstart",
645
+ "format",
646
+ "hierarchy",
647
+ "assertions",
648
+ "traceability",
649
+ "validation",
650
+ "git",
651
+ "config",
652
+ "commands",
653
+ "health",
654
+ "mcp",
655
+ "all",
656
+ ],
657
+ help="Documentation topic (default: quickstart)",
658
+ )
659
+ docs_parser.add_argument(
660
+ "--plain",
524
661
  action="store_true",
525
- help="Reformat even if already in new format",
662
+ help="Plain text output (no ANSI colors)",
526
663
  )
527
- reformat_parser.add_argument(
528
- "--fix-line-breaks",
664
+ docs_parser.add_argument(
665
+ "--no-pager",
529
666
  action="store_true",
530
- help="Normalize line breaks (remove extra blank lines)",
667
+ help="Disable paging (print directly to stdout)",
531
668
  )
532
- reformat_parser.add_argument(
533
- "--line-breaks-only",
534
- action="store_true",
535
- help="Only fix line breaks, skip AI-based reformatting",
669
+
670
+ # completion command - shell tab-completion setup
671
+ completion_parser = subparsers.add_parser(
672
+ "completion",
673
+ help="Generate shell tab-completion scripts",
674
+ formatter_class=argparse.RawDescriptionHelpFormatter,
675
+ epilog="""
676
+ Shell Completion Setup:
677
+
678
+ First, install the completion extra:
679
+ pip install elspais[completion]
680
+
681
+ Bash (add to ~/.bashrc):
682
+ eval "$(register-python-argcomplete elspais)"
683
+
684
+ Zsh (add to ~/.zshrc):
685
+ autoload -U bashcompinit
686
+ bashcompinit
687
+ eval "$(register-python-argcomplete elspais)"
688
+
689
+ Fish (add to ~/.config/fish/config.fish):
690
+ register-python-argcomplete --shell fish elspais | source
691
+
692
+ Tcsh (add to ~/.tcshrc):
693
+ eval `register-python-argcomplete --shell tcsh elspais`
694
+
695
+ Global activation (for all argcomplete-enabled tools):
696
+ activate-global-python-argcomplete
697
+
698
+ After adding the appropriate line, restart your shell or source the config file.
699
+ """,
536
700
  )
537
- reformat_parser.add_argument(
538
- "--mode",
539
- choices=["combined", "core-only", "local-only"],
540
- default="combined",
541
- help="Which repos to include in hierarchy (default: combined)",
701
+ completion_parser.add_argument(
702
+ "--shell",
703
+ choices=["bash", "zsh", "fish", "tcsh"],
704
+ help="Generate script for specific shell",
542
705
  )
543
706
 
544
707
  # mcp command
@@ -606,6 +769,17 @@ def main(argv: Optional[List[str]] = None) -> int:
606
769
  Exit code (0 for success, non-zero for failure)
607
770
  """
608
771
  parser = create_parser()
772
+
773
+ # Enable shell tab-completion if argcomplete is installed
774
+ # Install with: pip install elspais[completion]
775
+ # Then activate: eval "$(register-python-argcomplete elspais)"
776
+ try:
777
+ import argcomplete
778
+
779
+ argcomplete.autocomplete(parser)
780
+ except ImportError:
781
+ pass
782
+
609
783
  args = parser.parse_args(argv)
610
784
 
611
785
  # Handle no command
@@ -613,10 +787,28 @@ def main(argv: Optional[List[str]] = None) -> int:
613
787
  parser.print_help()
614
788
  return 0
615
789
 
790
+ # Auto-detect git repository root and change to it
791
+ # This ensures elspais works the same from any subdirectory
792
+ import os
793
+
794
+ from elspais.config import find_git_root
795
+
796
+ original_cwd = Path.cwd()
797
+ git_root = find_git_root(original_cwd)
798
+
799
+ if git_root and git_root != original_cwd:
800
+ os.chdir(git_root)
801
+ if args.verbose:
802
+ print(f"Working from repository root: {git_root}", file=sys.stderr)
803
+ elif not git_root and args.verbose:
804
+ print("Warning: Not in a git repository", file=sys.stderr)
805
+
616
806
  try:
617
807
  # Dispatch to command handlers
618
808
  if args.command == "validate":
619
809
  return validate.run(args)
810
+ elif args.command == "health":
811
+ return health.run(args)
620
812
  elif args.command == "trace":
621
813
  return trace.run(args)
622
814
  elif args.command == "hash":
@@ -631,6 +823,8 @@ def main(argv: Optional[List[str]] = None) -> int:
631
823
  return version_command(args)
632
824
  elif args.command == "init":
633
825
  return init.run(args)
826
+ elif args.command == "example":
827
+ return example_cmd.run(args)
634
828
  elif args.command == "edit":
635
829
  return edit.run(args)
636
830
  elif args.command == "config":
@@ -639,6 +833,10 @@ def main(argv: Optional[List[str]] = None) -> int:
639
833
  return rules_cmd.run(args)
640
834
  elif args.command == "reformat-with-claude":
641
835
  return reformat_cmd.run(args)
836
+ elif args.command == "docs":
837
+ return docs_command(args)
838
+ elif args.command == "completion":
839
+ return completion_command(args)
642
840
  elif args.command == "mcp":
643
841
  return mcp_command(args)
644
842
  else:
@@ -655,6 +853,105 @@ def main(argv: Optional[List[str]] = None) -> int:
655
853
  return 1
656
854
 
657
855
 
856
+ def docs_command(args: argparse.Namespace) -> int:
857
+ """Handle docs command - display user documentation from markdown files."""
858
+ import pydoc
859
+
860
+ from elspais.utilities.docs_loader import load_all_topics, load_topic
861
+ from elspais.utilities.md_renderer import render_markdown
862
+
863
+ topic = args.topic
864
+ use_pager = not args.no_pager and sys.stdout.isatty()
865
+ use_color = not args.plain and sys.stdout.isatty()
866
+
867
+ # Load content from markdown files
868
+ if topic == "all":
869
+ content = load_all_topics()
870
+ else:
871
+ content = load_topic(topic)
872
+
873
+ if content is None:
874
+ print(f"Error: Documentation not found for topic '{topic}'", file=sys.stderr)
875
+ print("Documentation files may not be installed correctly.", file=sys.stderr)
876
+ return 1
877
+
878
+ # Render markdown to ANSI and display
879
+ output = render_markdown(content, use_color=use_color)
880
+
881
+ if use_pager:
882
+ pydoc.pager(output)
883
+ else:
884
+ print(output)
885
+
886
+ return 0
887
+
888
+
889
+ def completion_command(args: argparse.Namespace) -> int:
890
+ """Handle completion command - generate shell completion scripts."""
891
+ import importlib.util
892
+
893
+ if importlib.util.find_spec("argcomplete") is None:
894
+ print("Error: argcomplete not installed.", file=sys.stderr)
895
+ print("Install with: pip install elspais[completion]", file=sys.stderr)
896
+ return 1
897
+
898
+ shell = args.shell
899
+
900
+ if shell:
901
+ # Generate script for specific shell
902
+ import subprocess
903
+
904
+ shell_flag = f"--shell={shell}" if shell in ("fish", "tcsh") else ""
905
+ cmd = ["register-python-argcomplete"]
906
+ if shell_flag:
907
+ cmd.append(shell_flag)
908
+ cmd.append("elspais")
909
+
910
+ try:
911
+ result = subprocess.run(cmd, capture_output=True, text=True)
912
+ if result.returncode == 0:
913
+ print(result.stdout)
914
+ else:
915
+ print(f"Error generating completion script: {result.stderr}", file=sys.stderr)
916
+ return 1
917
+ except FileNotFoundError:
918
+ print("Error: register-python-argcomplete not found.", file=sys.stderr)
919
+ print("Make sure argcomplete is properly installed.", file=sys.stderr)
920
+ return 1
921
+ else:
922
+ # Show setup instructions
923
+ print(
924
+ """
925
+ Shell Completion Setup for elspais
926
+ ===================================
927
+
928
+ Bash (add to ~/.bashrc):
929
+ eval "$(register-python-argcomplete elspais)"
930
+
931
+ Zsh (add to ~/.zshrc):
932
+ autoload -U bashcompinit
933
+ bashcompinit
934
+ eval "$(register-python-argcomplete elspais)"
935
+
936
+ Fish (add to ~/.config/fish/config.fish):
937
+ register-python-argcomplete --shell fish elspais | source
938
+
939
+ Tcsh (add to ~/.tcshrc):
940
+ eval `register-python-argcomplete --shell tcsh elspais`
941
+
942
+ Generate script for a specific shell:
943
+ elspais completion --shell bash
944
+ elspais completion --shell zsh
945
+ elspais completion --shell fish
946
+ elspais completion --shell tcsh
947
+
948
+ After adding the line, restart your shell or source the config file.
949
+ """
950
+ )
951
+
952
+ return 0
953
+
954
+
658
955
  def version_command(args: argparse.Namespace) -> int:
659
956
  """Handle version command."""
660
957
  print(f"elspais {__version__}")
@@ -3,10 +3,16 @@ elspais.commands - CLI command implementations
3
3
  """
4
4
 
5
5
  __all__ = [
6
- "validate",
7
- "trace",
6
+ "analyze",
7
+ "changed",
8
+ "config_cmd",
9
+ "edit",
10
+ "example_cmd",
8
11
  "hash_cmd",
9
12
  "index",
10
- "analyze",
11
13
  "init",
14
+ "reformat_cmd",
15
+ "rules_cmd",
16
+ "trace",
17
+ "validate",
12
18
  ]