doit-toolkit-cli 0.1.10__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.
Potentially problematic release.
This version of doit-toolkit-cli might be problematic. Click here for more details.
- doit_cli/__init__.py +1356 -0
- doit_cli/cli/__init__.py +26 -0
- doit_cli/cli/analytics_command.py +616 -0
- doit_cli/cli/context_command.py +213 -0
- doit_cli/cli/diagram_command.py +304 -0
- doit_cli/cli/fixit_command.py +641 -0
- doit_cli/cli/hooks_command.py +211 -0
- doit_cli/cli/init_command.py +613 -0
- doit_cli/cli/memory_command.py +293 -0
- doit_cli/cli/roadmapit_command.py +10 -0
- doit_cli/cli/status_command.py +117 -0
- doit_cli/cli/sync_prompts_command.py +248 -0
- doit_cli/cli/validate_command.py +196 -0
- doit_cli/cli/verify_command.py +204 -0
- doit_cli/cli/workflow_mixin.py +224 -0
- doit_cli/cli/xref_command.py +555 -0
- doit_cli/formatters/__init__.py +8 -0
- doit_cli/formatters/base.py +38 -0
- doit_cli/formatters/json_formatter.py +126 -0
- doit_cli/formatters/markdown_formatter.py +97 -0
- doit_cli/formatters/rich_formatter.py +257 -0
- doit_cli/main.py +51 -0
- doit_cli/models/__init__.py +139 -0
- doit_cli/models/agent.py +74 -0
- doit_cli/models/analytics_models.py +384 -0
- doit_cli/models/context_config.py +464 -0
- doit_cli/models/crossref_models.py +182 -0
- doit_cli/models/diagram_models.py +363 -0
- doit_cli/models/fixit_models.py +355 -0
- doit_cli/models/hook_config.py +125 -0
- doit_cli/models/project.py +91 -0
- doit_cli/models/results.py +121 -0
- doit_cli/models/search_models.py +228 -0
- doit_cli/models/status_models.py +195 -0
- doit_cli/models/sync_models.py +146 -0
- doit_cli/models/template.py +77 -0
- doit_cli/models/validation_models.py +175 -0
- doit_cli/models/workflow_models.py +319 -0
- doit_cli/prompts/__init__.py +5 -0
- doit_cli/prompts/fixit_prompts.py +344 -0
- doit_cli/prompts/interactive.py +390 -0
- doit_cli/rules/__init__.py +5 -0
- doit_cli/rules/builtin_rules.py +160 -0
- doit_cli/services/__init__.py +79 -0
- doit_cli/services/agent_detector.py +168 -0
- doit_cli/services/analytics_service.py +218 -0
- doit_cli/services/architecture_generator.py +290 -0
- doit_cli/services/backup_service.py +204 -0
- doit_cli/services/config_loader.py +113 -0
- doit_cli/services/context_loader.py +1123 -0
- doit_cli/services/coverage_calculator.py +142 -0
- doit_cli/services/crossref_service.py +237 -0
- doit_cli/services/cycle_time_calculator.py +134 -0
- doit_cli/services/date_inferrer.py +349 -0
- doit_cli/services/diagram_service.py +337 -0
- doit_cli/services/drift_detector.py +109 -0
- doit_cli/services/entity_parser.py +301 -0
- doit_cli/services/er_diagram_generator.py +197 -0
- doit_cli/services/fixit_service.py +699 -0
- doit_cli/services/github_service.py +192 -0
- doit_cli/services/hook_manager.py +258 -0
- doit_cli/services/hook_validator.py +528 -0
- doit_cli/services/input_validator.py +322 -0
- doit_cli/services/memory_search.py +527 -0
- doit_cli/services/mermaid_validator.py +334 -0
- doit_cli/services/prompt_transformer.py +91 -0
- doit_cli/services/prompt_writer.py +133 -0
- doit_cli/services/query_interpreter.py +428 -0
- doit_cli/services/report_exporter.py +219 -0
- doit_cli/services/report_generator.py +256 -0
- doit_cli/services/requirement_parser.py +112 -0
- doit_cli/services/roadmap_summarizer.py +209 -0
- doit_cli/services/rule_engine.py +443 -0
- doit_cli/services/scaffolder.py +215 -0
- doit_cli/services/score_calculator.py +172 -0
- doit_cli/services/section_parser.py +204 -0
- doit_cli/services/spec_scanner.py +327 -0
- doit_cli/services/state_manager.py +355 -0
- doit_cli/services/status_reporter.py +143 -0
- doit_cli/services/task_parser.py +347 -0
- doit_cli/services/template_manager.py +710 -0
- doit_cli/services/template_reader.py +158 -0
- doit_cli/services/user_journey_generator.py +214 -0
- doit_cli/services/user_story_parser.py +232 -0
- doit_cli/services/validation_service.py +188 -0
- doit_cli/services/validator.py +232 -0
- doit_cli/services/velocity_tracker.py +173 -0
- doit_cli/services/workflow_engine.py +405 -0
- doit_cli/templates/agent-file-template.md +28 -0
- doit_cli/templates/checklist-template.md +39 -0
- doit_cli/templates/commands/doit.checkin.md +363 -0
- doit_cli/templates/commands/doit.constitution.md +187 -0
- doit_cli/templates/commands/doit.documentit.md +485 -0
- doit_cli/templates/commands/doit.fixit.md +181 -0
- doit_cli/templates/commands/doit.implementit.md +265 -0
- doit_cli/templates/commands/doit.planit.md +262 -0
- doit_cli/templates/commands/doit.reviewit.md +355 -0
- doit_cli/templates/commands/doit.roadmapit.md +389 -0
- doit_cli/templates/commands/doit.scaffoldit.md +458 -0
- doit_cli/templates/commands/doit.specit.md +521 -0
- doit_cli/templates/commands/doit.taskit.md +304 -0
- doit_cli/templates/commands/doit.testit.md +277 -0
- doit_cli/templates/config/context.yaml +134 -0
- doit_cli/templates/config/hooks.yaml +93 -0
- doit_cli/templates/config/validation-rules.yaml +64 -0
- doit_cli/templates/github-issue-templates/epic.yml +78 -0
- doit_cli/templates/github-issue-templates/feature.yml +116 -0
- doit_cli/templates/github-issue-templates/task.yml +129 -0
- doit_cli/templates/hooks/.gitkeep +0 -0
- doit_cli/templates/hooks/post-commit.sh +25 -0
- doit_cli/templates/hooks/post-merge.sh +75 -0
- doit_cli/templates/hooks/pre-commit.sh +17 -0
- doit_cli/templates/hooks/pre-push.sh +18 -0
- doit_cli/templates/memory/completed_roadmap.md +50 -0
- doit_cli/templates/memory/constitution.md +125 -0
- doit_cli/templates/memory/roadmap.md +61 -0
- doit_cli/templates/plan-template.md +146 -0
- doit_cli/templates/scripts/bash/check-prerequisites.sh +166 -0
- doit_cli/templates/scripts/bash/common.sh +156 -0
- doit_cli/templates/scripts/bash/create-new-feature.sh +297 -0
- doit_cli/templates/scripts/bash/setup-plan.sh +61 -0
- doit_cli/templates/scripts/bash/update-agent-context.sh +675 -0
- doit_cli/templates/scripts/powershell/check-prerequisites.ps1 +148 -0
- doit_cli/templates/scripts/powershell/common.ps1 +137 -0
- doit_cli/templates/scripts/powershell/create-new-feature.ps1 +283 -0
- doit_cli/templates/scripts/powershell/setup-plan.ps1 +61 -0
- doit_cli/templates/scripts/powershell/update-agent-context.ps1 +406 -0
- doit_cli/templates/spec-template.md +159 -0
- doit_cli/templates/tasks-template.md +313 -0
- doit_cli/templates/vscode-settings.json +14 -0
- doit_toolkit_cli-0.1.10.dist-info/METADATA +324 -0
- doit_toolkit_cli-0.1.10.dist-info/RECORD +135 -0
- doit_toolkit_cli-0.1.10.dist-info/WHEEL +4 -0
- doit_toolkit_cli-0.1.10.dist-info/entry_points.txt +2 -0
- doit_toolkit_cli-0.1.10.dist-info/licenses/LICENSE +21 -0
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
"""CLI commands for Git hook management."""
|
|
2
|
+
|
|
3
|
+
import sys
|
|
4
|
+
|
|
5
|
+
import typer
|
|
6
|
+
from rich.console import Console
|
|
7
|
+
|
|
8
|
+
from ..services.hook_manager import HookManager
|
|
9
|
+
from ..services.hook_validator import HookValidator
|
|
10
|
+
|
|
11
|
+
console = Console()
|
|
12
|
+
|
|
13
|
+
# Create the hooks command group
|
|
14
|
+
hooks_app = typer.Typer(
|
|
15
|
+
name="hooks",
|
|
16
|
+
help="Manage Git hooks for workflow enforcement.",
|
|
17
|
+
no_args_is_help=True,
|
|
18
|
+
)
|
|
19
|
+
|
|
20
|
+
|
|
21
|
+
@hooks_app.command("install")
|
|
22
|
+
def install_hooks(
|
|
23
|
+
backup: bool = typer.Option(
|
|
24
|
+
False, "--backup", "-b", help="Backup existing hooks before installing"
|
|
25
|
+
),
|
|
26
|
+
force: bool = typer.Option(
|
|
27
|
+
False, "--force", "-f", help="Overwrite existing hooks without prompting"
|
|
28
|
+
),
|
|
29
|
+
) -> None:
|
|
30
|
+
"""Install pre-commit and pre-push Git hooks."""
|
|
31
|
+
manager = HookManager()
|
|
32
|
+
|
|
33
|
+
# Check if in git repo
|
|
34
|
+
if not manager.is_git_repo():
|
|
35
|
+
console.print("[red]Error: Not a Git repository.[/red]")
|
|
36
|
+
console.print("Run 'git init' first to initialize a Git repository.")
|
|
37
|
+
raise typer.Exit(1)
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
installed, skipped = manager.install_hooks(backup=backup, force=force)
|
|
41
|
+
|
|
42
|
+
if installed:
|
|
43
|
+
console.print("[green]Successfully installed hooks:[/green]")
|
|
44
|
+
for hook in installed:
|
|
45
|
+
console.print(f" - {hook}")
|
|
46
|
+
|
|
47
|
+
if skipped:
|
|
48
|
+
console.print("\n[yellow]Skipped hooks (already exist):[/yellow]")
|
|
49
|
+
for hook in skipped:
|
|
50
|
+
console.print(f" - {hook}")
|
|
51
|
+
console.print("\nUse --backup to backup existing hooks, or --force to overwrite.")
|
|
52
|
+
|
|
53
|
+
if not installed and not skipped:
|
|
54
|
+
console.print("[yellow]No hooks to install.[/yellow]")
|
|
55
|
+
|
|
56
|
+
except RuntimeError as e:
|
|
57
|
+
console.print(f"[red]Error: {e}[/red]")
|
|
58
|
+
raise typer.Exit(1)
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
@hooks_app.command("uninstall")
|
|
62
|
+
def uninstall_hooks() -> None:
|
|
63
|
+
"""Remove installed Git hooks."""
|
|
64
|
+
manager = HookManager()
|
|
65
|
+
|
|
66
|
+
removed = manager.uninstall_hooks()
|
|
67
|
+
|
|
68
|
+
if removed:
|
|
69
|
+
console.print("[green]Successfully removed hooks:[/green]")
|
|
70
|
+
for hook in removed:
|
|
71
|
+
console.print(f" - {hook}")
|
|
72
|
+
else:
|
|
73
|
+
console.print("[yellow]No doit hooks found to remove.[/yellow]")
|
|
74
|
+
|
|
75
|
+
|
|
76
|
+
@hooks_app.command("status")
|
|
77
|
+
def hooks_status() -> None:
|
|
78
|
+
"""Show current hook installation and configuration status."""
|
|
79
|
+
from ..models.hook_config import HookConfig
|
|
80
|
+
|
|
81
|
+
manager = HookManager()
|
|
82
|
+
config = HookConfig.load_default()
|
|
83
|
+
|
|
84
|
+
console.print("[bold]Git Hooks Status[/bold]")
|
|
85
|
+
console.print("=" * 40)
|
|
86
|
+
|
|
87
|
+
if not manager.is_git_repo():
|
|
88
|
+
console.print("[red]Not a Git repository[/red]")
|
|
89
|
+
raise typer.Exit(1)
|
|
90
|
+
|
|
91
|
+
installed = manager.get_installed_hooks()
|
|
92
|
+
|
|
93
|
+
console.print("\n[bold]Installed Hooks:[/bold]")
|
|
94
|
+
if installed:
|
|
95
|
+
for hook in installed:
|
|
96
|
+
console.print(f" [green]\u2713[/green] {hook}")
|
|
97
|
+
else:
|
|
98
|
+
console.print(" [dim]No doit hooks installed[/dim]")
|
|
99
|
+
|
|
100
|
+
# Show configuration
|
|
101
|
+
config_path = HookConfig.get_default_config_path()
|
|
102
|
+
console.print(f"\n[bold]Configuration:[/bold] {config_path}")
|
|
103
|
+
|
|
104
|
+
pre_commit_status = "[green]enabled[/green]" if config.pre_commit.enabled else "[red]disabled[/red]"
|
|
105
|
+
pre_push_status = "[green]enabled[/green]" if config.pre_push.enabled else "[red]disabled[/red]"
|
|
106
|
+
bypass_status = "[green]enabled[/green]" if config.logging.log_bypasses else "[red]disabled[/red]"
|
|
107
|
+
|
|
108
|
+
console.print(f" Pre-commit validation: {pre_commit_status}")
|
|
109
|
+
console.print(f" Pre-push validation: {pre_push_status}")
|
|
110
|
+
console.print(f" Bypass logging: {bypass_status}")
|
|
111
|
+
|
|
112
|
+
# Show exempt branches
|
|
113
|
+
if config.pre_commit.exempt_branches:
|
|
114
|
+
console.print(f"\n[bold]Exempt Branches:[/bold] {', '.join(config.pre_commit.exempt_branches)}")
|
|
115
|
+
|
|
116
|
+
# Show exempt paths
|
|
117
|
+
if config.pre_commit.exempt_paths:
|
|
118
|
+
console.print(f"[bold]Exempt Paths:[/bold] {', '.join(config.pre_commit.exempt_paths)}")
|
|
119
|
+
|
|
120
|
+
console.print("\n[dim]Use 'doit hooks install' to install hooks[/dim]")
|
|
121
|
+
|
|
122
|
+
|
|
123
|
+
@hooks_app.command("restore")
|
|
124
|
+
def restore_hooks(
|
|
125
|
+
timestamp: str = typer.Option(
|
|
126
|
+
None, "--timestamp", "-t", help="Specific backup timestamp to restore"
|
|
127
|
+
),
|
|
128
|
+
) -> None:
|
|
129
|
+
"""Restore previously backed up hooks."""
|
|
130
|
+
manager = HookManager()
|
|
131
|
+
|
|
132
|
+
try:
|
|
133
|
+
restored = manager.restore_hooks(timestamp=timestamp)
|
|
134
|
+
|
|
135
|
+
if restored:
|
|
136
|
+
console.print("[green]Successfully restored hooks:[/green]")
|
|
137
|
+
for hook in restored:
|
|
138
|
+
console.print(f" - {hook}")
|
|
139
|
+
else:
|
|
140
|
+
console.print("[yellow]No hooks were restored.[/yellow]")
|
|
141
|
+
|
|
142
|
+
except RuntimeError as e:
|
|
143
|
+
console.print(f"[red]Error: {e}[/red]")
|
|
144
|
+
raise typer.Exit(1)
|
|
145
|
+
|
|
146
|
+
|
|
147
|
+
@hooks_app.command("validate")
|
|
148
|
+
def validate_hook(
|
|
149
|
+
hook_type: str = typer.Argument(
|
|
150
|
+
..., help="Type of hook to validate (pre-commit or pre-push)"
|
|
151
|
+
),
|
|
152
|
+
) -> None:
|
|
153
|
+
"""Validate workflow compliance for the specified hook type."""
|
|
154
|
+
valid_types = ["pre-commit", "pre-push"]
|
|
155
|
+
if hook_type not in valid_types:
|
|
156
|
+
console.print(f"[red]Invalid hook type: {hook_type}[/red]")
|
|
157
|
+
console.print(f"Valid types: {', '.join(valid_types)}")
|
|
158
|
+
raise typer.Exit(1)
|
|
159
|
+
|
|
160
|
+
validator = HookValidator()
|
|
161
|
+
|
|
162
|
+
if hook_type == "pre-commit":
|
|
163
|
+
result = validator.validate_pre_commit()
|
|
164
|
+
else:
|
|
165
|
+
result = validator.validate_pre_push()
|
|
166
|
+
|
|
167
|
+
if result.success:
|
|
168
|
+
# Silent success for normal workflow
|
|
169
|
+
sys.exit(0)
|
|
170
|
+
else:
|
|
171
|
+
# Show error and suggestion
|
|
172
|
+
console.print(f"[red]\u2717 {hook_type.title().replace('-', '-')} validation failed[/red]")
|
|
173
|
+
console.print()
|
|
174
|
+
console.print(result.message)
|
|
175
|
+
if result.suggestion:
|
|
176
|
+
console.print()
|
|
177
|
+
console.print(f"[dim]{result.suggestion}[/dim]")
|
|
178
|
+
sys.exit(1)
|
|
179
|
+
|
|
180
|
+
|
|
181
|
+
@hooks_app.command("report")
|
|
182
|
+
def hooks_report() -> None:
|
|
183
|
+
"""Show bypass audit log report."""
|
|
184
|
+
validator = HookValidator()
|
|
185
|
+
events = validator.get_bypass_report()
|
|
186
|
+
|
|
187
|
+
console.print("[bold]Hook Bypass Report[/bold]")
|
|
188
|
+
console.print("=" * 40)
|
|
189
|
+
|
|
190
|
+
if not events:
|
|
191
|
+
console.print("\n[dim]No bypass events recorded.[/dim]")
|
|
192
|
+
console.print("[dim]Bypass events are logged when --no-verify is used.[/dim]")
|
|
193
|
+
return
|
|
194
|
+
|
|
195
|
+
console.print(f"\n[bold]Total bypasses:[/bold] {len(events)}")
|
|
196
|
+
console.print()
|
|
197
|
+
|
|
198
|
+
for event in events:
|
|
199
|
+
timestamp = event.get("timestamp", "Unknown")
|
|
200
|
+
hook = event.get("hook", "Unknown")
|
|
201
|
+
branch = event.get("branch", "Unknown")
|
|
202
|
+
user = event.get("user", "Unknown")
|
|
203
|
+
commit = event.get("commit", "")
|
|
204
|
+
|
|
205
|
+
line = f"[dim]{timestamp}[/dim] | [yellow]{hook}[/yellow] | branch: {branch}"
|
|
206
|
+
if commit:
|
|
207
|
+
line += f" | commit: {commit}"
|
|
208
|
+
if user:
|
|
209
|
+
line += f" | user: {user}"
|
|
210
|
+
|
|
211
|
+
console.print(line)
|