moai-adk 0.8.0__py3-none-any.whl → 0.8.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.

Potentially problematic release.


This version of moai-adk might be problematic. Click here for more details.

Files changed (94) hide show
  1. moai_adk/cli/commands/update.py +15 -4
  2. moai_adk/core/issue_creator.py +309 -0
  3. moai_adk/core/tags/__init__.py +87 -0
  4. moai_adk/core/tags/ci_validator.py +435 -0
  5. moai_adk/core/tags/cli.py +283 -0
  6. moai_adk/core/tags/generator.py +109 -0
  7. moai_adk/core/tags/inserter.py +99 -0
  8. moai_adk/core/tags/mapper.py +126 -0
  9. moai_adk/core/tags/parser.py +76 -0
  10. moai_adk/core/tags/pre_commit_validator.py +355 -0
  11. moai_adk/core/tags/reporter.py +959 -0
  12. moai_adk/core/tags/tags.py +149 -0
  13. moai_adk/core/tags/validator.py +897 -0
  14. moai_adk/core/template_engine.py +253 -0
  15. moai_adk/templates/.claude/agents/alfred/cc-manager.md +25 -2
  16. moai_adk/templates/.claude/agents/alfred/debug-helper.md +24 -12
  17. moai_adk/templates/.claude/agents/alfred/doc-syncer.md +19 -12
  18. moai_adk/templates/.claude/agents/alfred/git-manager.md +45 -14
  19. moai_adk/templates/.claude/agents/alfred/implementation-planner.md +19 -12
  20. moai_adk/templates/.claude/agents/alfred/project-manager.md +29 -2
  21. moai_adk/templates/.claude/agents/alfred/quality-gate.md +25 -2
  22. moai_adk/templates/.claude/agents/alfred/skill-factory.md +30 -2
  23. moai_adk/templates/.claude/agents/alfred/spec-builder.md +26 -11
  24. moai_adk/templates/.claude/agents/alfred/tag-agent.md +30 -8
  25. moai_adk/templates/.claude/agents/alfred/tdd-implementer.md +27 -12
  26. moai_adk/templates/.claude/agents/alfred/trust-checker.md +25 -2
  27. moai_adk/templates/.claude/commands/alfred/0-project.md +5 -0
  28. moai_adk/templates/.claude/commands/alfred/1-plan.md +17 -4
  29. moai_adk/templates/.claude/commands/alfred/2-run.md +7 -0
  30. moai_adk/templates/.claude/commands/alfred/3-sync.md +6 -0
  31. moai_adk/templates/.claude/commands/alfred/9-feedback.md +149 -0
  32. moai_adk/templates/.claude/hooks/alfred/.moai/cache/version-check.json +9 -0
  33. moai_adk/templates/.claude/hooks/alfred/README.md +258 -145
  34. moai_adk/templates/.claude/hooks/alfred/TROUBLESHOOTING.md +471 -0
  35. moai_adk/templates/.claude/hooks/alfred/alfred_hooks.py +92 -57
  36. moai_adk/templates/.claude/hooks/alfred/core/version_cache.py +198 -0
  37. moai_adk/templates/.claude/hooks/alfred/notification__handle_events.py +102 -0
  38. moai_adk/templates/.claude/hooks/alfred/post_tool__log_changes.py +102 -0
  39. moai_adk/templates/.claude/hooks/alfred/pre_tool__auto_checkpoint.py +108 -0
  40. moai_adk/templates/.claude/hooks/alfred/session_end__cleanup.py +102 -0
  41. moai_adk/templates/.claude/hooks/alfred/session_start__show_project_info.py +102 -0
  42. moai_adk/templates/.claude/hooks/alfred/{core → shared/core}/project.py +271 -15
  43. moai_adk/templates/.claude/hooks/alfred/shared/core/version_cache.py +198 -0
  44. moai_adk/templates/.claude/hooks/alfred/{handlers → shared/handlers}/session.py +21 -7
  45. moai_adk/templates/.claude/hooks/alfred/stop__handle_interrupt.py +102 -0
  46. moai_adk/templates/.claude/hooks/alfred/subagent_stop__handle_subagent_end.py +102 -0
  47. moai_adk/templates/.claude/hooks/alfred/user_prompt__jit_load_docs.py +120 -0
  48. moai_adk/templates/.claude/settings.json +5 -5
  49. moai_adk/templates/.claude/skills/moai-foundation-ears/SKILL.md +9 -6
  50. moai_adk/templates/.claude/skills/moai-spec-authoring/README.md +56 -56
  51. moai_adk/templates/.claude/skills/moai-spec-authoring/SKILL.md +101 -100
  52. moai_adk/templates/.claude/skills/moai-spec-authoring/examples/validate-spec.sh +3 -3
  53. moai_adk/templates/.claude/skills/moai-spec-authoring/examples.md +219 -219
  54. moai_adk/templates/.claude/skills/moai-spec-authoring/reference.md +287 -287
  55. moai_adk/templates/.github/ISSUE_TEMPLATE/spec.yml +6 -6
  56. moai_adk/templates/.github/PULL_REQUEST_TEMPLATE.md +1 -1
  57. moai_adk/templates/.github/workflows/moai-gitflow.yml +22 -16
  58. moai_adk/templates/.github/workflows/moai-release-create.yml +100 -0
  59. moai_adk/templates/.github/workflows/moai-release-pipeline.yml +182 -0
  60. moai_adk/templates/.github/workflows/release.yml +49 -0
  61. moai_adk/templates/.github/workflows/spec-issue-sync.yml +10 -6
  62. moai_adk/templates/.github/workflows/tag-report.yml +261 -0
  63. moai_adk/templates/.github/workflows/tag-validation.yml +176 -0
  64. moai_adk/templates/.moai/config.json +18 -1
  65. moai_adk/templates/.moai/docs/quick-issue-creation-guide.md +219 -0
  66. moai_adk/templates/.moai/hooks/install.sh +79 -0
  67. moai_adk/templates/.moai/hooks/pre-commit.sh +66 -0
  68. moai_adk/templates/.moai/memory/ISSUE-LABEL-MAPPING.md +150 -0
  69. moai_adk/templates/CLAUDE.md +39 -40
  70. moai_adk/templates/src/moai_adk/core/__init__.py +5 -0
  71. moai_adk/templates/src/moai_adk/core/tags/__init__.py +87 -0
  72. moai_adk/templates/src/moai_adk/core/tags/ci_validator.py +435 -0
  73. moai_adk/templates/src/moai_adk/core/tags/cli.py +283 -0
  74. moai_adk/templates/src/moai_adk/core/tags/pre_commit_validator.py +355 -0
  75. moai_adk/templates/src/moai_adk/core/tags/reporter.py +959 -0
  76. moai_adk/templates/src/moai_adk/core/tags/validator.py +897 -0
  77. {moai_adk-0.8.0.dist-info → moai_adk-0.8.2.dist-info}/METADATA +348 -1
  78. {moai_adk-0.8.0.dist-info → moai_adk-0.8.2.dist-info}/RECORD +89 -52
  79. moai_adk/templates/.claude/hooks/alfred/HOOK_SCHEMA_VALIDATION.md +0 -313
  80. moai_adk/templates/.claude/hooks/alfred/test_hook_output.py +0 -175
  81. moai_adk/templates/.moai/memory/config-schema.md +0 -444
  82. moai_adk/templates/.moai/memory/gitflow-protection-policy.md +0 -220
  83. moai_adk/templates/.moai/memory/spec-metadata.md +0 -356
  84. /moai_adk/templates/.claude/hooks/alfred/{core → shared/core}/__init__.py +0 -0
  85. /moai_adk/templates/.claude/hooks/alfred/{core → shared/core}/checkpoint.py +0 -0
  86. /moai_adk/templates/.claude/hooks/alfred/{core → shared/core}/context.py +0 -0
  87. /moai_adk/templates/.claude/hooks/alfred/{core → shared/core}/tags.py +0 -0
  88. /moai_adk/templates/.claude/hooks/alfred/{handlers → shared/handlers}/__init__.py +0 -0
  89. /moai_adk/templates/.claude/hooks/alfred/{handlers → shared/handlers}/notification.py +0 -0
  90. /moai_adk/templates/.claude/hooks/alfred/{handlers → shared/handlers}/tool.py +0 -0
  91. /moai_adk/templates/.claude/hooks/alfred/{handlers → shared/handlers}/user.py +0 -0
  92. {moai_adk-0.8.0.dist-info → moai_adk-0.8.2.dist-info}/WHEEL +0 -0
  93. {moai_adk-0.8.0.dist-info → moai_adk-0.8.2.dist-info}/entry_points.txt +0 -0
  94. {moai_adk-0.8.0.dist-info → moai_adk-0.8.2.dist-info}/licenses/LICENSE +0 -0
@@ -274,6 +274,10 @@ def _get_project_config_version(project_path: Path) -> str:
274
274
  Raises:
275
275
  ValueError: If config.json exists but cannot be parsed
276
276
  """
277
+ def _is_placeholder(value: str) -> bool:
278
+ """Check if value contains unsubstituted template placeholders."""
279
+ return isinstance(value, str) and value.startswith("{{") and value.endswith("}}")
280
+
277
281
  config_path = project_path / ".moai" / "config.json"
278
282
 
279
283
  if not config_path.exists():
@@ -284,15 +288,15 @@ def _get_project_config_version(project_path: Path) -> str:
284
288
  config_data = json.loads(config_path.read_text(encoding="utf-8"))
285
289
  # Check for template_version in project section
286
290
  template_version = config_data.get("project", {}).get("template_version")
287
- if template_version:
291
+ if template_version and not _is_placeholder(template_version):
288
292
  return template_version
289
293
 
290
294
  # Fallback to moai version if no template_version exists
291
295
  moai_version = config_data.get("moai", {}).get("version")
292
- if moai_version:
296
+ if moai_version and not _is_placeholder(moai_version):
293
297
  return moai_version
294
298
 
295
- # If neither exists, this is a new/old project
299
+ # If values are placeholders or don't exist, treat as uninitialized (0.0.0 triggers sync)
296
300
  return "0.0.0"
297
301
  except json.JSONDecodeError as e:
298
302
  raise ValueError(f"Failed to parse project config.json: {e}") from e
@@ -796,7 +800,14 @@ def update(path: str, force: bool, check: bool, templates_only: bool, yes: bool)
796
800
  console.print(f" Package template: {package_config_version}")
797
801
  console.print(f" Project config: {project_config_version}")
798
802
 
799
- config_comparison = _compare_versions(package_config_version, project_config_version)
803
+ try:
804
+ config_comparison = _compare_versions(package_config_version, project_config_version)
805
+ except version.InvalidVersion as e:
806
+ # Handle invalid version strings (e.g., unsubstituted template placeholders, corrupted configs)
807
+ console.print(f"[yellow]⚠ Invalid version format in config: {e}[/yellow]")
808
+ console.print("[cyan]ℹ️ Forcing template sync to repair configuration...[/cyan]")
809
+ # Force template sync by treating project version as outdated
810
+ config_comparison = 1 # package_config_version > project_config_version
800
811
 
801
812
  # If versions are equal, no sync needed
802
813
  if config_comparison <= 0:
@@ -0,0 +1,309 @@
1
+ """
2
+ GitHub Issue Creator for MoAI-ADK quick issue reporting.
3
+
4
+ Enables users to quickly create GitHub Issues with standardized templates
5
+ using `/alfred:9-feedback` interactive dialog.
6
+
7
+ @TAG:ISSUE-CREATOR-001 - GitHub issue creation system
8
+ @TAG:QUICK-REPORTING-001 - Quick issue reporting functionality
9
+ """
10
+
11
+ import subprocess
12
+ from dataclasses import dataclass
13
+ from enum import Enum
14
+ from typing import Any, Dict, List, Optional
15
+
16
+
17
+ class IssueType(Enum):
18
+ """Supported GitHub issue types."""
19
+ BUG = "bug"
20
+ FEATURE = "feature"
21
+ IMPROVEMENT = "improvement"
22
+ QUESTION = "question"
23
+
24
+
25
+ class IssuePriority(Enum):
26
+ """Issue priority levels."""
27
+ CRITICAL = "critical"
28
+ HIGH = "high"
29
+ MEDIUM = "medium"
30
+ LOW = "low"
31
+
32
+
33
+ @dataclass
34
+ class IssueConfig:
35
+ """Configuration for issue creation."""
36
+ issue_type: IssueType
37
+ title: str
38
+ description: str
39
+ priority: IssuePriority = IssuePriority.MEDIUM
40
+ category: Optional[str] = None
41
+ assignees: Optional[List[str]] = None
42
+ custom_labels: Optional[List[str]] = None
43
+
44
+
45
+ class GitHubIssueCreator:
46
+ """
47
+ Creates GitHub Issues using the `gh` CLI.
48
+
49
+ Supports:
50
+ - Multiple issue types (bug, feature, improvement, question)
51
+ - Priority levels and categories
52
+ - Standard templates for each type
53
+ - Label automation
54
+ - Priority emoji indicators
55
+ """
56
+
57
+ # Label mapping for issue types
58
+ LABEL_MAP = {
59
+ IssueType.BUG: ["bug", "reported"],
60
+ IssueType.FEATURE: ["feature-request", "enhancement"],
61
+ IssueType.IMPROVEMENT: ["improvement", "enhancement"],
62
+ IssueType.QUESTION: ["question", "help-wanted"],
63
+ }
64
+
65
+ # Priority emoji
66
+ PRIORITY_EMOJI = {
67
+ IssuePriority.CRITICAL: "🔴",
68
+ IssuePriority.HIGH: "🟠",
69
+ IssuePriority.MEDIUM: "🟡",
70
+ IssuePriority.LOW: "🟢",
71
+ }
72
+
73
+ # Issue type emoji
74
+ TYPE_EMOJI = {
75
+ IssueType.BUG: "🐛",
76
+ IssueType.FEATURE: "✨",
77
+ IssueType.IMPROVEMENT: "⚡",
78
+ IssueType.QUESTION: "❓",
79
+ }
80
+
81
+ def __init__(self, github_token: Optional[str] = None):
82
+ """
83
+ Initialize the GitHub Issue Creator.
84
+
85
+ Args:
86
+ github_token: GitHub API token. If not provided, uses GITHUB_TOKEN env var.
87
+ """
88
+ self.github_token = github_token
89
+ self._check_gh_cli()
90
+
91
+ def _check_gh_cli(self) -> None:
92
+ """
93
+ Check if `gh` CLI is installed and accessible.
94
+
95
+ Raises:
96
+ RuntimeError: If `gh` CLI is not found or not authenticated.
97
+ """
98
+ try:
99
+ result = subprocess.run(
100
+ ["gh", "auth", "status"],
101
+ capture_output=True,
102
+ text=True,
103
+ timeout=5
104
+ )
105
+ if result.returncode != 0:
106
+ raise RuntimeError(
107
+ "GitHub CLI (gh) is not authenticated. "
108
+ "Run `gh auth login` to authenticate."
109
+ )
110
+ except FileNotFoundError:
111
+ raise RuntimeError(
112
+ "GitHub CLI (gh) is not installed. "
113
+ "Please install it: https://cli.github.com"
114
+ )
115
+
116
+ def create_issue(self, config: IssueConfig) -> Dict[str, Any]:
117
+ """
118
+ Create a GitHub issue with the given configuration.
119
+
120
+ Args:
121
+ config: Issue configuration
122
+
123
+ Returns:
124
+ Dictionary containing issue creation result:
125
+ {
126
+ "success": bool,
127
+ "issue_number": int,
128
+ "issue_url": str,
129
+ "message": str
130
+ }
131
+
132
+ Raises:
133
+ RuntimeError: If issue creation fails
134
+ """
135
+ # Build title with emoji and priority
136
+ emoji = self.TYPE_EMOJI.get(config.issue_type, "📋")
137
+ priority_emoji = self.PRIORITY_EMOJI.get(config.priority, "")
138
+ full_title = f"{emoji} [{config.issue_type.value.upper()}] {config.title}"
139
+ if priority_emoji:
140
+ full_title = f"{priority_emoji} {full_title}"
141
+
142
+ # Build body with template
143
+ body = self._build_body(config)
144
+
145
+ # Collect labels
146
+ labels = self.LABEL_MAP.get(config.issue_type, []).copy()
147
+ if config.priority:
148
+ labels.append(f"priority-{config.priority.value}")
149
+ if config.category:
150
+ labels.append(f"category-{config.category.lower().replace(' ', '-')}")
151
+ if config.custom_labels:
152
+ labels.extend(config.custom_labels)
153
+
154
+ # Build gh command
155
+ gh_command = [
156
+ "gh", "issue", "create",
157
+ "--title", full_title,
158
+ "--body", body,
159
+ ]
160
+
161
+ # Add labels
162
+ if labels:
163
+ gh_command.extend(["--label", ",".join(set(labels))])
164
+
165
+ # Add assignees if provided
166
+ if config.assignees:
167
+ gh_command.extend(["--assignee", ",".join(config.assignees)])
168
+
169
+ try:
170
+ result = subprocess.run(
171
+ gh_command,
172
+ capture_output=True,
173
+ text=True,
174
+ timeout=30
175
+ )
176
+
177
+ if result.returncode != 0:
178
+ error_msg = result.stderr or result.stdout
179
+ raise RuntimeError(f"Failed to create GitHub issue: {error_msg}")
180
+
181
+ # Parse issue URL from output
182
+ issue_url = result.stdout.strip()
183
+ issue_number = self._extract_issue_number(issue_url)
184
+
185
+ return {
186
+ "success": True,
187
+ "issue_number": issue_number,
188
+ "issue_url": issue_url,
189
+ "message": f"✅ GitHub Issue #{issue_number} created successfully",
190
+ "title": full_title,
191
+ "labels": labels,
192
+ }
193
+
194
+ except subprocess.TimeoutExpired:
195
+ raise RuntimeError("GitHub issue creation timed out")
196
+ except Exception as e:
197
+ raise RuntimeError(f"Error creating GitHub issue: {e}")
198
+
199
+ def _build_body(self, config: IssueConfig) -> str:
200
+ """
201
+ Build the issue body based on issue type.
202
+
203
+ Args:
204
+ config: Issue configuration
205
+
206
+ Returns:
207
+ Formatted issue body
208
+ """
209
+ body = config.description
210
+
211
+ # Add metadata footer
212
+ footer = "\n\n---\n\n"
213
+ footer += f"**Type**: {config.issue_type.value} \n"
214
+ footer += f"**Priority**: {config.priority.value} \n"
215
+ if config.category:
216
+ footer += f"**Category**: {config.category} \n"
217
+ footer += f"**Created via**: `/alfred:9-feedback`"
218
+
219
+ return body + footer
220
+
221
+ @staticmethod
222
+ def _extract_issue_number(url: str) -> int:
223
+ """
224
+ Extract issue number from GitHub URL.
225
+
226
+ Args:
227
+ url: GitHub issue URL
228
+
229
+ Returns:
230
+ Issue number
231
+
232
+ Raises:
233
+ ValueError: If unable to extract issue number
234
+ """
235
+ try:
236
+ # URL format: https://github.com/owner/repo/issues/123
237
+ return int(url.strip().split("/")[-1])
238
+ except (ValueError, IndexError):
239
+ raise ValueError(f"Unable to extract issue number from URL: {url}")
240
+
241
+ def format_result(self, result: Dict[str, Any]) -> str:
242
+ """
243
+ Format the issue creation result for display.
244
+
245
+ Args:
246
+ result: Issue creation result
247
+
248
+ Returns:
249
+ Formatted result string
250
+ """
251
+ if result["success"]:
252
+ output = f"{result['message']}\n"
253
+ output += f"📋 Title: {result['title']}\n"
254
+ output += f"🔗 URL: {result['issue_url']}\n"
255
+ if result.get("labels"):
256
+ output += f"🏷️ Labels: {', '.join(result['labels'])}\n"
257
+ return output
258
+ else:
259
+ return f"❌ Failed to create issue: {result.get('message', 'Unknown error')}"
260
+
261
+
262
+ class IssueCreatorFactory:
263
+ """
264
+ Factory for creating issue creators with predefined configurations.
265
+ """
266
+
267
+ @staticmethod
268
+ def create_bug_issue(title: str, description: str, priority: IssuePriority = IssuePriority.HIGH) -> IssueConfig:
269
+ """Create a bug report issue configuration."""
270
+ return IssueConfig(
271
+ issue_type=IssueType.BUG,
272
+ title=title,
273
+ description=description,
274
+ priority=priority,
275
+ category="Bug Report",
276
+ )
277
+
278
+ @staticmethod
279
+ def create_feature_issue(title: str, description: str, priority: IssuePriority = IssuePriority.MEDIUM) -> IssueConfig:
280
+ """Create a feature request issue configuration."""
281
+ return IssueConfig(
282
+ issue_type=IssueType.FEATURE,
283
+ title=title,
284
+ description=description,
285
+ priority=priority,
286
+ category="Feature Request",
287
+ )
288
+
289
+ @staticmethod
290
+ def create_improvement_issue(title: str, description: str, priority: IssuePriority = IssuePriority.MEDIUM) -> IssueConfig:
291
+ """Create an improvement issue configuration."""
292
+ return IssueConfig(
293
+ issue_type=IssueType.IMPROVEMENT,
294
+ title=title,
295
+ description=description,
296
+ priority=priority,
297
+ category="Improvement",
298
+ )
299
+
300
+ @staticmethod
301
+ def create_question_issue(title: str, description: str, priority: IssuePriority = IssuePriority.LOW) -> IssueConfig:
302
+ """Create a question/discussion issue configuration."""
303
+ return IssueConfig(
304
+ issue_type=IssueType.QUESTION,
305
+ title=title,
306
+ description=description,
307
+ priority=priority,
308
+ category="Question",
309
+ )
@@ -0,0 +1,87 @@
1
+ #!/usr/bin/env python3
2
+ # @CODE:DOC-TAG-004 | TAG validation core module (Components 1, 2, 3 & 4)
3
+ """TAG validation and management for MoAI-ADK
4
+
5
+ This module provides TAG validation functionality for:
6
+ - Pre-commit hook validation (Component 1)
7
+ - CI/CD pipeline validation (Component 2)
8
+ - Central validation system (Component 3)
9
+ - Documentation & Reporting (Component 4)
10
+ - TAG format checking
11
+ - Duplicate detection
12
+ - Orphan detection
13
+ - Chain integrity validation
14
+ """
15
+
16
+ # Component 1: Pre-commit validator
17
+ from .pre_commit_validator import (
18
+ PreCommitValidator,
19
+ ValidationResult,
20
+ ValidationError,
21
+ ValidationWarning,
22
+ )
23
+
24
+ # Component 2: CI/CD validator
25
+ from .ci_validator import CIValidator
26
+
27
+ # Component 3: Central validation system
28
+ from .validator import (
29
+ ValidationConfig,
30
+ TagValidator,
31
+ DuplicateValidator,
32
+ OrphanValidator,
33
+ ChainValidator,
34
+ FormatValidator,
35
+ CentralValidator,
36
+ CentralValidationResult,
37
+ ValidationIssue,
38
+ ValidationStatistics,
39
+ )
40
+
41
+ # Component 4: Documentation & Reporting
42
+ from .reporter import (
43
+ TagInventory,
44
+ TagMatrix,
45
+ InventoryGenerator,
46
+ MatrixGenerator,
47
+ CoverageAnalyzer,
48
+ StatisticsGenerator,
49
+ ReportFormatter,
50
+ ReportGenerator,
51
+ CoverageMetrics,
52
+ StatisticsReport,
53
+ ReportResult,
54
+ )
55
+
56
+ __all__ = [
57
+ # Component 1
58
+ "PreCommitValidator",
59
+ "ValidationResult",
60
+ "ValidationError",
61
+ "ValidationWarning",
62
+ # Component 2
63
+ "CIValidator",
64
+ # Component 3
65
+ "ValidationConfig",
66
+ "TagValidator",
67
+ "DuplicateValidator",
68
+ "OrphanValidator",
69
+ "ChainValidator",
70
+ "FormatValidator",
71
+ "CentralValidator",
72
+ "CentralValidationResult",
73
+ "ValidationIssue",
74
+ "ValidationStatistics",
75
+ # Component 4
76
+ "TagInventory",
77
+ "TagMatrix",
78
+ "InventoryGenerator",
79
+ "MatrixGenerator",
80
+ "CoverageAnalyzer",
81
+ "StatisticsGenerator",
82
+ "ReportFormatter",
83
+ "ReportGenerator",
84
+ "CoverageMetrics",
85
+ "StatisticsReport",
86
+ "ReportResult",
87
+ ]