moai-adk 0.9.0__py3-none-any.whl → 0.15.0__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 (186) hide show
  1. moai_adk/cli/commands/init.py +14 -2
  2. moai_adk/cli/commands/update.py +214 -56
  3. moai_adk/core/issue_creator.py +2 -2
  4. moai_adk/core/project/detector.py +201 -12
  5. moai_adk/core/project/initializer.py +62 -1
  6. moai_adk/core/project/phase_executor.py +48 -6
  7. moai_adk/core/tags/ci_validator.py +34 -4
  8. moai_adk/core/tags/pre_commit_validator.py +40 -2
  9. moai_adk/core/tags/reporter.py +2 -3
  10. moai_adk/core/tags/validator.py +1 -1
  11. moai_adk/core/template_engine.py +20 -5
  12. moai_adk/templates/.claude/agents/alfred/backend-expert.md +319 -0
  13. moai_adk/templates/.claude/agents/alfred/devops-expert.md +464 -0
  14. moai_adk/templates/.claude/agents/alfred/doc-syncer.md +1 -1
  15. moai_adk/templates/.claude/agents/alfred/frontend-expert.md +357 -0
  16. moai_adk/templates/.claude/agents/alfred/git-manager.md +2 -2
  17. moai_adk/templates/.claude/agents/alfred/implementation-planner.md +76 -3
  18. moai_adk/templates/.claude/agents/alfred/project-manager.md +49 -10
  19. moai_adk/templates/.claude/agents/alfred/quality-gate.md +3 -3
  20. moai_adk/templates/.claude/agents/alfred/spec-builder.md +108 -3
  21. moai_adk/templates/.claude/agents/alfred/tag-agent.md +74 -0
  22. moai_adk/templates/.claude/agents/alfred/tdd-implementer.md +107 -5
  23. moai_adk/templates/.claude/agents/alfred/trust-checker.md +2 -2
  24. moai_adk/templates/.claude/agents/alfred/ui-ux-expert.md +571 -0
  25. moai_adk/templates/.claude/commands/alfred/0-project.md +465 -129
  26. moai_adk/templates/.claude/commands/alfred/1-plan.md +139 -65
  27. moai_adk/templates/.claude/commands/alfred/2-run.md +214 -50
  28. moai_adk/templates/.claude/commands/alfred/3-sync.md +372 -46
  29. moai_adk/templates/.claude/commands/alfred/9-feedback.md +1 -1
  30. moai_adk/templates/.claude/hooks/alfred/core/project.py +25 -27
  31. moai_adk/templates/.claude/hooks/alfred/core/timeout.py +136 -0
  32. moai_adk/templates/.claude/hooks/alfred/core/ttl_cache.py +108 -0
  33. moai_adk/templates/.claude/hooks/alfred/core/version_cache.py +4 -4
  34. moai_adk/templates/.claude/hooks/alfred/handlers/__init__.py +29 -0
  35. moai_adk/templates/.claude/hooks/alfred/post_tool__log_changes.py +11 -19
  36. moai_adk/templates/.claude/hooks/alfred/pre_tool__auto_checkpoint.py +11 -19
  37. moai_adk/templates/.claude/hooks/alfred/session_end__cleanup.py +11 -19
  38. moai_adk/templates/.claude/hooks/alfred/session_start__show_project_info.py +10 -18
  39. moai_adk/templates/.claude/hooks/alfred/shared/core/__init__.py +2 -2
  40. moai_adk/templates/.claude/hooks/alfred/shared/core/checkpoint.py +3 -3
  41. moai_adk/templates/.claude/hooks/alfred/shared/core/context.py +5 -5
  42. moai_adk/templates/.claude/hooks/alfred/shared/core/project.py +40 -41
  43. moai_adk/templates/.claude/hooks/alfred/shared/core/tags.py +55 -23
  44. moai_adk/templates/.claude/hooks/alfred/shared/core/version_cache.py +4 -4
  45. moai_adk/templates/.claude/hooks/alfred/shared/handlers/notification.py +132 -3
  46. moai_adk/templates/.claude/hooks/alfred/shared/handlers/session.py +9 -10
  47. moai_adk/templates/.claude/hooks/alfred/shared/handlers/tool.py +3 -6
  48. moai_adk/templates/.claude/hooks/alfred/shared/handlers/user.py +19 -0
  49. moai_adk/templates/.claude/hooks/alfred/user_prompt__jit_load_docs.py +14 -22
  50. moai_adk/templates/.claude/hooks/alfred/utils/__init__.py +1 -0
  51. moai_adk/templates/.claude/hooks/alfred/utils/timeout.py +161 -0
  52. moai_adk/templates/.claude/settings.json +5 -5
  53. moai_adk/templates/.claude/skills/moai-alfred-agent-guide/SKILL.md +70 -0
  54. moai_adk/templates/.claude/skills/moai-alfred-agent-guide/examples.md +62 -0
  55. moai_adk/templates/{.moai/memory/CLAUDE-AGENTS-GUIDE.md → .claude/skills/moai-alfred-agent-guide/reference.md} +34 -0
  56. moai_adk/templates/.claude/skills/moai-alfred-config-schema/SKILL.md +56 -0
  57. moai_adk/templates/.claude/skills/moai-alfred-config-schema/examples.md +28 -0
  58. moai_adk/templates/.claude/skills/moai-alfred-config-schema/reference.md +444 -0
  59. moai_adk/templates/.claude/skills/moai-alfred-context-budget/SKILL.md +62 -0
  60. moai_adk/templates/.claude/skills/moai-alfred-context-budget/examples.md +28 -0
  61. moai_adk/templates/.claude/skills/moai-alfred-context-budget/reference.md +405 -0
  62. moai_adk/templates/.claude/skills/moai-alfred-dev-guide/SKILL.md +51 -0
  63. moai_adk/templates/.claude/skills/moai-alfred-dev-guide/examples.md +355 -0
  64. moai_adk/templates/.claude/skills/moai-alfred-dev-guide/reference.md +239 -0
  65. moai_adk/templates/.claude/skills/moai-alfred-expertise-detection/SKILL.md +323 -0
  66. moai_adk/templates/.claude/skills/moai-alfred-expertise-detection/examples.md +286 -0
  67. moai_adk/templates/.claude/skills/moai-alfred-expertise-detection/reference.md +126 -0
  68. moai_adk/templates/.claude/skills/moai-alfred-gitflow-policy/SKILL.md +74 -0
  69. moai_adk/templates/.claude/skills/moai-alfred-gitflow-policy/examples.md +4 -0
  70. moai_adk/templates/.claude/skills/moai-alfred-gitflow-policy/reference.md +269 -0
  71. moai_adk/templates/.claude/skills/moai-alfred-issue-labels/SKILL.md +19 -0
  72. moai_adk/templates/.claude/skills/moai-alfred-issue-labels/examples.md +4 -0
  73. moai_adk/templates/.claude/skills/moai-alfred-persona-roles/SKILL.md +198 -0
  74. moai_adk/templates/.claude/skills/moai-alfred-persona-roles/examples.md +431 -0
  75. moai_adk/templates/.claude/skills/moai-alfred-persona-roles/reference.md +141 -0
  76. moai_adk/templates/.claude/skills/moai-alfred-practices/SKILL.md +89 -0
  77. moai_adk/templates/.claude/skills/moai-alfred-practices/examples.md +122 -0
  78. moai_adk/templates/.claude/skills/moai-alfred-proactive-suggestions/SKILL.md +508 -0
  79. moai_adk/templates/.claude/skills/moai-alfred-proactive-suggestions/examples.md +481 -0
  80. moai_adk/templates/.claude/skills/moai-alfred-proactive-suggestions/reference.md +100 -0
  81. moai_adk/templates/.claude/skills/moai-alfred-reporting/SKILL.md +273 -0
  82. moai_adk/templates/.claude/skills/moai-alfred-rules/SKILL.md +77 -0
  83. moai_adk/templates/.claude/skills/moai-alfred-rules/examples.md +265 -0
  84. moai_adk/templates/.claude/skills/moai-alfred-session-state/SKILL.md +19 -0
  85. moai_adk/templates/.claude/skills/moai-alfred-session-state/examples.md +4 -0
  86. moai_adk/templates/.claude/skills/moai-alfred-session-state/reference.md +84 -0
  87. moai_adk/templates/.claude/skills/{moai-spec-authoring → moai-alfred-spec-authoring}/SKILL.md +5 -5
  88. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-extended/SKILL.md +115 -0
  89. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-extended/examples.md +4 -0
  90. moai_adk/templates/.claude/skills/moai-alfred-spec-metadata-extended/reference.md +348 -0
  91. moai_adk/templates/.claude/skills/moai-alfred-todowrite-pattern/SKILL.md +19 -0
  92. moai_adk/templates/.claude/skills/moai-alfred-todowrite-pattern/examples.md +4 -0
  93. moai_adk/templates/.claude/skills/moai-alfred-todowrite-pattern/reference.md +211 -0
  94. moai_adk/templates/.claude/skills/moai-alfred-workflow/SKILL.md +288 -0
  95. moai_adk/templates/.claude/skills/moai-cc-skill-descriptions/SKILL.md +19 -0
  96. moai_adk/templates/.claude/skills/moai-cc-skill-descriptions/examples.md +4 -0
  97. moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/SKILL.md +3 -3
  98. moai_adk/templates/.claude/skills/moai-design-systems/SKILL.md +802 -0
  99. moai_adk/templates/.claude/skills/moai-design-systems/examples.md +1238 -0
  100. moai_adk/templates/.claude/skills/moai-design-systems/reference.md +673 -0
  101. moai_adk/templates/.claude/skills/moai-domain-frontend/SKILL.md +17 -13
  102. moai_adk/templates/.claude/skills/moai-lang-go/SKILL.md +15 -12
  103. moai_adk/templates/.claude/skills/moai-lang-java/SKILL.md +14 -12
  104. moai_adk/templates/.claude/skills/moai-lang-php/SKILL.md +14 -11
  105. moai_adk/templates/.claude/skills/moai-lang-python/SKILL.md +10 -8
  106. moai_adk/templates/.claude/skills/moai-lang-rust/SKILL.md +15 -12
  107. moai_adk/templates/.claude/skills/moai-lang-scala/SKILL.md +13 -11
  108. moai_adk/templates/.claude/skills/moai-lang-typescript/SKILL.md +16 -10
  109. moai_adk/templates/.claude/skills/moai-project-documentation.md +622 -0
  110. moai_adk/templates/.git-hooks/pre-push +143 -0
  111. moai_adk/templates/.github/workflows/c-tag-validation.yml +11 -0
  112. moai_adk/templates/.github/workflows/cpp-tag-validation.yml +11 -0
  113. moai_adk/templates/.github/workflows/csharp-tag-validation.yml +11 -0
  114. moai_adk/templates/.github/workflows/dart-tag-validation.yml +11 -0
  115. moai_adk/templates/.github/workflows/go-tag-validation.yml +130 -0
  116. moai_adk/templates/.github/workflows/java-tag-validation.yml +11 -0
  117. moai_adk/templates/.github/workflows/javascript-tag-validation.yml +135 -0
  118. moai_adk/templates/.github/workflows/kotlin-tag-validation.yml +11 -0
  119. moai_adk/templates/.github/workflows/moai-gitflow.yml +182 -25
  120. moai_adk/templates/.github/workflows/moai-release-pipeline.yml +35 -29
  121. moai_adk/templates/.github/workflows/php-tag-validation.yml +11 -0
  122. moai_adk/templates/.github/workflows/python-tag-validation.yml +118 -0
  123. moai_adk/templates/.github/workflows/release.yml +76 -7
  124. moai_adk/templates/.github/workflows/ruby-tag-validation.yml +11 -0
  125. moai_adk/templates/.github/workflows/rust-tag-validation.yml +11 -0
  126. moai_adk/templates/.github/workflows/shell-tag-validation.yml +11 -0
  127. moai_adk/templates/.github/workflows/spec-issue-sync.yml +208 -41
  128. moai_adk/templates/.github/workflows/swift-tag-validation.yml +11 -0
  129. moai_adk/templates/.github/workflows/tag-report.yml +269 -0
  130. moai_adk/templates/.github/workflows/tag-validation.yml +186 -0
  131. moai_adk/templates/.github/workflows/typescript-tag-validation.yml +154 -0
  132. moai_adk/templates/.moai/config.json +3 -1
  133. moai_adk/templates/CLAUDE.md +940 -45
  134. moai_adk/templates/workflows/go-tag-validation.yml +30 -0
  135. moai_adk/templates/workflows/javascript-tag-validation.yml +41 -0
  136. moai_adk/templates/workflows/python-tag-validation.yml +42 -0
  137. moai_adk/templates/workflows/typescript-tag-validation.yml +31 -0
  138. moai_adk/utils/banner.py +5 -5
  139. {moai_adk-0.9.0.dist-info → moai_adk-0.15.0.dist-info}/METADATA +1166 -455
  140. {moai_adk-0.9.0.dist-info → moai_adk-0.15.0.dist-info}/RECORD +169 -109
  141. moai_adk/templates/.claude/hooks/alfred/alfred_hooks.py +0 -209
  142. moai_adk/templates/.claude/hooks/alfred/notification__handle_events.py +0 -102
  143. moai_adk/templates/.claude/hooks/alfred/stop__handle_interrupt.py +0 -102
  144. moai_adk/templates/.claude/hooks/alfred/subagent_stop__handle_subagent_end.py +0 -102
  145. moai_adk/templates/.claude/output-styles/alfred/agentic-coding.md +0 -640
  146. moai_adk/templates/.claude/output-styles/alfred/moai-adk-learning.md +0 -696
  147. moai_adk/templates/.claude/output-styles/alfred/study-with-alfred.md +0 -474
  148. moai_adk/templates/.github/ISSUE_TEMPLATE/spec.yml +0 -176
  149. moai_adk/templates/.github/PULL_REQUEST_TEMPLATE.md +0 -69
  150. moai_adk/templates/.moai/memory/DEVELOPMENT-GUIDE.md +0 -344
  151. moai_adk/templates/.moai/memory/SPEC-METADATA.md +0 -356
  152. moai_adk/templates/.moai/memory/gitflow-protection-policy.md +0 -330
  153. moai_adk/templates/.moai/project/product.md +0 -161
  154. moai_adk/templates/.moai/project/structure.md +0 -156
  155. moai_adk/templates/.moai/project/tech.md +0 -227
  156. moai_adk/templates/README.md +0 -256
  157. moai_adk/templates/__init__.py +0 -2
  158. /moai_adk/templates/{.moai/memory/ISSUE-LABEL-MAPPING.md → .claude/skills/moai-alfred-issue-labels/reference.md} +0 -0
  159. /moai_adk/templates/{.moai/memory/CLAUDE-PRACTICES.md → .claude/skills/moai-alfred-practices/reference.md} +0 -0
  160. /moai_adk/templates/{.moai/memory/CLAUDE-RULES.md → .claude/skills/moai-alfred-rules/reference.md} +0 -0
  161. /moai_adk/templates/.claude/skills/{moai-spec-authoring → moai-alfred-spec-authoring}/README.md +0 -0
  162. /moai_adk/templates/.claude/skills/{moai-spec-authoring → moai-alfred-spec-authoring}/examples/validate-spec.sh +0 -0
  163. /moai_adk/templates/.claude/skills/{moai-spec-authoring → moai-alfred-spec-authoring}/examples.md +0 -0
  164. /moai_adk/templates/.claude/skills/{moai-spec-authoring → moai-alfred-spec-authoring}/reference.md +0 -0
  165. /moai_adk/templates/{.moai/memory/SKILLS-DESCRIPTION-POLICY.md → .claude/skills/moai-cc-skill-descriptions/reference.md} +0 -0
  166. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/CHECKLIST.md +0 -0
  167. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/EXAMPLES.md +0 -0
  168. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/INTERACTIVE-DISCOVERY.md +0 -0
  169. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/METADATA.md +0 -0
  170. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/PARALLEL-ANALYSIS-REPORT.md +0 -0
  171. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/PYTHON-VERSION-MATRIX.md +0 -0
  172. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/SKILL-FACTORY-WORKFLOW.md +0 -0
  173. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/SKILL-UPDATE-ADVISOR.md +0 -0
  174. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/STEP-BY-STEP-GUIDE.md +0 -0
  175. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/STRUCTURE.md +0 -0
  176. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/WEB-RESEARCH.md +0 -0
  177. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/reference.md +0 -0
  178. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/scripts/generate-structure.sh +0 -0
  179. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/scripts/validate-skill.sh +0 -0
  180. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/templates/SKILL_TEMPLATE.md +0 -0
  181. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/templates/examples-template.md +0 -0
  182. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/templates/reference-template.md +0 -0
  183. /moai_adk/templates/.claude/skills/{moai-skill-factory → moai-cc-skill-factory}/templates/scripts-template.sh +0 -0
  184. {moai_adk-0.9.0.dist-info → moai_adk-0.15.0.dist-info}/WHEEL +0 -0
  185. {moai_adk-0.9.0.dist-info → moai_adk-0.15.0.dist-info}/entry_points.txt +0 -0
  186. {moai_adk-0.9.0.dist-info → moai_adk-0.15.0.dist-info}/licenses/LICENSE +0 -0
@@ -3,7 +3,7 @@ name: 📋 SPEC Issue Sync
3
3
  on:
4
4
  pull_request:
5
5
  paths:
6
- - '{{SPEC_DIR}}/SPEC-*/spec.md'
6
+ - '.moai/specs/SPEC-*/spec.md'
7
7
  types: [opened, synchronize]
8
8
 
9
9
  permissions:
@@ -25,33 +25,62 @@ jobs:
25
25
 
26
26
  - name: Find and parse SPEC file
27
27
  id: spec
28
+ env:
29
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
28
30
  run: |
29
31
  set -x # Enable debug mode
30
32
 
31
- # Debug: Show current directory and files
32
- echo "=== Debug: Current directory ==="
33
- pwd
34
- ls -la
33
+ echo "=== STEP 1: Get PR branch name ==="
34
+ branch_name="${{ github.head_ref }}"
35
+ echo "Branch: $branch_name"
35
36
 
36
- echo "=== Debug: Looking for {{SPEC_DIR}} ==="
37
- ls -la {{SPEC_DIR}}/ 2>&1 || echo "{{SPEC_DIR}}/ directory not found"
37
+ echo ""
38
+ echo "=== STEP 2: Get changed files from PR ==="
39
+ # Get list of changed files from PR
40
+ changed_files=$(gh pr view ${{ github.event.pull_request.number }} --json files --jq '.files[].path' 2>&1)
41
+
42
+ if [ $? -ne 0 ]; then
43
+ echo "⚠️ Failed to fetch PR files, falling back to git diff"
44
+ changed_files=$(git diff --name-only origin/main HEAD 2>&1)
45
+ fi
38
46
 
39
- # Find SPEC files in the PR
40
- echo "=== Debug: Searching for SPEC files ==="
41
- find . -name "spec.md" -type f 2>&1 || echo "find command failed"
47
+ echo "Changed files:"
48
+ echo "$changed_files"
42
49
 
43
- spec_file=$(find {{SPEC_DIR}} -name "spec.md" -type f 2>&1 | head -1)
44
- echo "Found spec_file: [$spec_file]"
50
+ echo ""
51
+ echo "=== STEP 3: Find SPEC files that were actually changed ==="
52
+ # Find spec files that were actually modified in this PR
53
+ spec_files=$(echo "$changed_files" | grep -E '\.moai/specs/SPEC-.*/spec\.md$' || true)
45
54
 
46
- if [ -z "$spec_file" ]; then
47
- echo "⚠️ No SPEC file found in {{SPEC_DIR}}"
55
+ if [ -z "$spec_files" ]; then
56
+ echo "⚠️ No SPEC file changes detected in this PR"
48
57
  echo "Exiting gracefully (this is expected if no SPEC files changed)"
49
58
  exit 0
50
59
  fi
51
60
 
52
- echo "Found SPEC file: $spec_file"
61
+ echo "Found SPEC files:"
62
+ echo "$spec_files"
63
+
64
+ # Count SPEC files
65
+ spec_file_count=$(echo "$spec_files" | wc -l)
66
+ echo "Count: $spec_file_count"
67
+
68
+ if [ "$spec_file_count" -gt 1 ]; then
69
+ echo ""
70
+ echo "⚠️ WARNING: Multiple SPEC files detected in this PR"
71
+ echo " This is unusual. Using first SPEC file."
72
+ echo " Files:"
73
+ echo "$spec_files" | sed 's/^/ /'
74
+ fi
75
+
76
+ # Select first SPEC file
77
+ spec_file=$(echo "$spec_files" | head -1)
78
+ echo ""
79
+ echo "✅ Selected SPEC file: $spec_file"
53
80
  echo "spec_file=$spec_file" >> $GITHUB_OUTPUT
54
81
 
82
+ echo ""
83
+ echo "=== STEP 4: Extract YAML metadata ==="
55
84
  # Extract YAML metadata using grep
56
85
  spec_id=$(grep "^id:" "$spec_file" | sed 's/^id: *//' | tr -d ' "')
57
86
  spec_version=$(grep "^version:" "$spec_file" | sed 's/^version: *//' | tr -d ' "')
@@ -59,11 +88,7 @@ jobs:
59
88
  spec_priority=$(grep "^priority:" "$spec_file" | sed 's/^priority: *//' | tr -d ' "')
60
89
 
61
90
  # Extract title from H1 heading
62
- {% if ENABLE_TAG_SYSTEM -%}
63
91
  spec_title=$(grep "^# @SPEC:" "$spec_file" | sed 's/^# @SPEC:[^:]*: //')
64
- {% else -%}
65
- spec_title=$(grep "^# " "$spec_file" | head -1 | sed 's/^# //')
66
- {% endif -%}
67
92
 
68
93
  echo "✅ Extracted SPEC metadata:"
69
94
  echo " ID: $spec_id"
@@ -72,13 +97,93 @@ jobs:
72
97
  echo " Status: $spec_status"
73
98
  echo " Priority: $spec_priority"
74
99
 
100
+ echo ""
101
+ echo "=== STEP 5: Validate SPEC status ==="
102
+ # Skip if SPEC is already completed (historical document)
103
+ if [ "$spec_status" = "completed" ]; then
104
+ echo "⚠️ SPEC status is 'completed' (historical document)"
105
+ echo " Skipping issue creation for completed SPEC"
106
+ exit 0
107
+ fi
108
+
109
+ echo "✅ SPEC status is valid (not completed)"
110
+
111
+ echo ""
112
+ echo "=== STEP 6: Validate branch name matches SPEC ID ==="
113
+ # Extract SPEC ID from branch name (feature/SPEC-UPDATE-REFACTOR-002 -> UPDATE-REFACTOR-002)
114
+ branch_spec_id=$(echo "$branch_name" | grep -oE 'SPEC-[A-Z0-9_-]+' | sed 's/^SPEC-//' || true)
115
+
116
+ if [ -n "$branch_spec_id" ]; then
117
+ if [ "$branch_spec_id" != "$spec_id" ]; then
118
+ echo "⚠️ WARNING: Branch name mismatch!"
119
+ echo " Branch SPEC ID: $branch_spec_id"
120
+ echo " File SPEC ID: $spec_id"
121
+ echo " Continuing anyway (might be intentional)"
122
+ else
123
+ echo "✅ Branch name matches SPEC ID"
124
+ fi
125
+ else
126
+ echo "⚠️ Could not extract SPEC ID from branch name"
127
+ echo " Branch: $branch_name"
128
+ echo " Continuing anyway"
129
+ fi
130
+
131
+ echo ""
132
+ echo "=== STEP 7: Output all variables ==="
75
133
  echo "spec_id=$spec_id" >> $GITHUB_OUTPUT
76
134
  echo "spec_version=$spec_version" >> $GITHUB_OUTPUT
77
135
  echo "spec_status=$spec_status" >> $GITHUB_OUTPUT
78
136
  echo "spec_priority=$spec_priority" >> $GITHUB_OUTPUT
79
137
  echo "spec_title=$spec_title" >> $GITHUB_OUTPUT
80
138
 
81
- - name: Create GitHub Issue
139
+ - name: Check for existing issue
140
+ if: steps.spec.outputs.spec_id
141
+ id: check-issue
142
+ env:
143
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
144
+ run: |
145
+ spec_id="${{ steps.spec.outputs.spec_id }}"
146
+
147
+ echo "=== Checking for existing issue ==="
148
+ echo "Searching for existing GitHub issue with SPEC-$spec_id..."
149
+
150
+ # PRIMARY: Search with label filter (efficient)
151
+ echo " Attempt 1: Searching with 'spec' label filter..."
152
+ existing_issue=$(gh issue list \
153
+ --label "spec" \
154
+ --state all \
155
+ --search "[SPEC-$spec_id]" \
156
+ --json number,title,state \
157
+ --jq '.[] | select(.title | contains("[SPEC-'$spec_id']")) | .number' \
158
+ 2>/dev/null | head -1)
159
+
160
+ # FALLBACK: Search without label filter (in case labels missing)
161
+ if [ -z "$existing_issue" ]; then
162
+ echo " Attempt 2: Searching WITHOUT label filter (fallback for missing labels)..."
163
+ existing_issue=$(gh issue list \
164
+ --state all \
165
+ --search "[SPEC-$spec_id]" \
166
+ --json number,title,state,labels \
167
+ --jq '.[] | select(.title | contains("[SPEC-'$spec_id']")) | .number' \
168
+ 2>/dev/null | head -1)
169
+
170
+ if [ -n "$existing_issue" ]; then
171
+ echo " ⚠️ Found issue without 'spec' label, adding labels..."
172
+ # Add missing labels to existing issue
173
+ gh issue edit "$existing_issue" --add-label "spec,planning" 2>/dev/null || true
174
+ fi
175
+ fi
176
+
177
+ if [ -n "$existing_issue" ]; then
178
+ echo "✅ Found existing issue: #$existing_issue"
179
+ echo "issue_exists=true" >> $GITHUB_OUTPUT
180
+ echo "issue_number=$existing_issue" >> $GITHUB_OUTPUT
181
+ else
182
+ echo "📋 No existing issue found for SPEC-$spec_id"
183
+ echo "issue_exists=false" >> $GITHUB_OUTPUT
184
+ fi
185
+
186
+ - name: Create or Update GitHub Issue
82
187
  if: steps.spec.outputs.spec_id
83
188
  id: create-issue
84
189
  env:
@@ -90,6 +195,8 @@ jobs:
90
195
  spec_status="${{ steps.spec.outputs.spec_status }}"
91
196
  spec_priority="${{ steps.spec.outputs.spec_priority }}"
92
197
  spec_file="${{ steps.spec.outputs.spec_file }}"
198
+ issue_exists="${{ steps.check-issue.outputs.issue_exists }}"
199
+ existing_issue="${{ steps.check-issue.outputs.issue_number }}"
93
200
 
94
201
  # Read SPEC content (skip YAML frontmatter: 9 lines + 1 blank = 10 lines total)
95
202
  # Start reading from line 11
@@ -118,33 +225,93 @@ jobs:
118
225
  echo "📝 **Auto-synced**: This issue is automatically synchronized from the SPEC document"
119
226
  } > /tmp/issue_body.txt
120
227
 
121
- echo "📋 Creating GitHub Issue..."
122
- echo " Title: [SPEC-$spec_id] $spec_title (v$spec_version)"
123
- echo " Body file: /tmp/issue_body.txt"
124
- wc -l /tmp/issue_body.txt
228
+ if [ "$issue_exists" = "true" ]; then
229
+ echo "📝 Updating existing issue #$existing_issue..."
230
+ echo " Title: [SPEC-$spec_id] $spec_title (v$spec_version)"
231
+ echo " Labels: spec, planning, $spec_priority"
125
232
 
126
- # Create issue with labels using body-file
127
- issue_output=$(gh issue create \
128
- --title "[SPEC-$spec_id] $spec_title (v$spec_version)" \
129
- --body-file /tmp/issue_body.txt \
130
- --label "spec" \
131
- --label "planning" \
132
- --label "$spec_priority" 2>&1)
233
+ # Update existing issue with new content and ensure proper labels
234
+ gh issue edit "$existing_issue" \
235
+ --title "[SPEC-$spec_id] $spec_title (v$spec_version)" \
236
+ --body-file /tmp/issue_body.txt \
237
+ --add-label "spec,planning,$spec_priority" \
238
+ --state open
239
+
240
+ issue_num=$existing_issue
241
+ echo "✅ Updated issue #$issue_num with latest SPEC version"
242
+ else
243
+ echo "📋 Creating new GitHub Issue..."
244
+ echo " Title: [SPEC-$spec_id] $spec_title (v$spec_version)"
245
+ echo " Body file: /tmp/issue_body.txt"
246
+ wc -l /tmp/issue_body.txt
247
+
248
+ # Create issue with labels using body-file
249
+ issue_output=$(gh issue create \
250
+ --title "[SPEC-$spec_id] $spec_title (v$spec_version)" \
251
+ --body-file /tmp/issue_body.txt \
252
+ --label "spec" \
253
+ --label "planning" \
254
+ --label "$spec_priority" 2>&1)
133
255
 
134
- echo "$issue_output" | tee /tmp/issue_output.txt
256
+ echo "$issue_output" | tee /tmp/issue_output.txt
135
257
 
136
- # Extract issue number from output
137
- issue_num=$(echo "$issue_output" | grep -oE '/issues/[0-9]+' | grep -oE '[0-9]+' | head -1)
258
+ # Extract issue number from output
259
+ issue_num=$(echo "$issue_output" | grep -oE '/issues/[0-9]+' | grep -oE '[0-9]+' | head -1)
138
260
 
139
- if [ -z "$issue_num" ]; then
140
- echo "⚠️ Could not extract issue number from output"
141
- echo "Full output:"
142
- cat /tmp/issue_output.txt
143
- exit 1
261
+ if [ -z "$issue_num" ]; then
262
+ echo "⚠️ Could not extract issue number from output"
263
+ echo "Full output:"
264
+ cat /tmp/issue_output.txt
265
+ exit 1
266
+ fi
267
+
268
+ echo "✅ Created issue #$issue_num"
144
269
  fi
145
270
 
146
271
  echo "issue_number=$issue_num" >> $GITHUB_OUTPUT
147
- echo "✅ Created issue #$issue_num"
272
+
273
+ - name: Validate SPEC issue labels
274
+ if: steps.create-issue.outputs.issue_number
275
+ id: validate-labels
276
+ env:
277
+ GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
278
+ run: |
279
+ issue_num="${{ steps.create-issue.outputs.issue_number }}"
280
+ spec_priority="${{ steps.spec.outputs.spec_priority }}"
281
+
282
+ echo "🔍 Validating SPEC issue #$issue_num labels..."
283
+
284
+ # Get current labels
285
+ current_labels=$(gh issue view $issue_num --json labels --jq '.labels[].name' | tr '\n' ',' | sed 's/,$//')
286
+ echo "Current labels: $current_labels"
287
+
288
+ # Check for mandatory labels
289
+ needs_update=false
290
+
291
+ if [[ ! "$current_labels" =~ "spec" ]]; then
292
+ echo "⚠️ Missing 'spec' label, adding..."
293
+ gh issue edit $issue_num --add-label "spec"
294
+ needs_update=true
295
+ fi
296
+
297
+ if [[ ! "$current_labels" =~ "planning" ]]; then
298
+ echo "⚠️ Missing 'planning' label, adding..."
299
+ gh issue edit $issue_num --add-label "planning"
300
+ needs_update=true
301
+ fi
302
+
303
+ # Check for priority label
304
+ if [[ ! "$current_labels" =~ (critical|high|medium|low) ]]; then
305
+ echo "⚠️ No priority label found, adding '$spec_priority' as default"
306
+ gh issue edit $issue_num --add-label "$spec_priority"
307
+ needs_update=true
308
+ fi
309
+
310
+ if [ "$needs_update" = true ]; then
311
+ echo "✅ SPEC labels validated and corrected"
312
+ else
313
+ echo "✅ SPEC labels already valid"
314
+ fi
148
315
 
149
316
  - name: Add PR comment
150
317
  if: steps.create-issue.outputs.issue_number
@@ -162,7 +329,7 @@ jobs:
162
329
  echo "This SPEC has been synchronized to GitHub Issue."
163
330
  echo ""
164
331
  echo "📋 **Issue**: [#$issue_num - SPEC-$spec_id: $spec_title](../issues/$issue_num)"
165
- echo "🔗 **SPEC File**: \`{{SPEC_DIR}}/SPEC-$spec_id/spec.md\`"
332
+ echo "🔗 **SPEC File**: \`.moai/specs/SPEC-$spec_id/spec.md\`"
166
333
  echo ""
167
334
  echo "The issue will be automatically updated as you modify the SPEC document."
168
335
  } > /tmp/pr_comment.txt
@@ -0,0 +1,11 @@
1
+ name: Swift TAG Validation
2
+ on:
3
+ push:
4
+ branches: [ develop, main ]
5
+ jobs:
6
+ validate-tags:
7
+ runs-on: ubuntu-latest
8
+ steps:
9
+ - uses: actions/checkout@v3
10
+ - name: Validate Swift TAGs
11
+ run: echo "Validating Swift TAGs"
@@ -0,0 +1,269 @@
1
+ # @CODE:DOC-TAG-004 | Component 4: Automated TAG reporting workflow
2
+ name: TAG Report Generation
3
+
4
+ on:
5
+ # Scheduled: Daily at 09:00 UTC
6
+ schedule:
7
+ - cron: '0 9 * * *'
8
+
9
+ # Event: Push to main/develop
10
+ push:
11
+ branches:
12
+ - main
13
+ - develop
14
+
15
+ # Manual: Workflow dispatch
16
+ workflow_dispatch:
17
+ inputs:
18
+ output_format:
19
+ description: 'Report format (all|inventory|matrix|statistics)'
20
+ required: false
21
+ default: 'all'
22
+
23
+ jobs:
24
+ generate-tag-reports:
25
+ name: Generate TAG Reports
26
+ runs-on: ubuntu-latest
27
+
28
+ permissions:
29
+ contents: write # Required to commit reports back to repo
30
+ pull-requests: write # Required to comment on PRs
31
+
32
+ strategy:
33
+ matrix:
34
+ python-version: ["3.11", "3.12", "3.13"]
35
+
36
+ steps:
37
+ - name: Checkout repository
38
+ uses: actions/checkout@v4
39
+ with:
40
+ fetch-depth: 0 # Full history for accurate file modification times
41
+
42
+ - name: Setup Python
43
+ uses: actions/setup-python@v5
44
+ with:
45
+ python-version: ${{ matrix.python-version }}
46
+
47
+ - name: Install uv
48
+ uses: astral-sh/setup-uv@v5
49
+ with:
50
+ version: "latest"
51
+
52
+ - name: Install MoAI-ADK
53
+ run: |
54
+ uv pip install --system -e .
55
+ uv pip install --system requests
56
+
57
+ - name: Create reports directory
58
+ run: |
59
+ mkdir -p docs/reports
60
+ echo "Reports will be generated in docs/reports/"
61
+
62
+ - name: Generate TAG Inventory
63
+ run: |
64
+ python -c "
65
+ from moai_adk.core.tags.reporter import ReportGenerator
66
+
67
+ generator = ReportGenerator()
68
+ inventory = generator.generate_inventory_report('.')
69
+
70
+ with open('docs/reports/tag-inventory.md', 'w') as f:
71
+ f.write(inventory)
72
+
73
+ print('✅ Generated tag-inventory.md')
74
+ "
75
+
76
+ - name: Generate TAG Coverage Matrix
77
+ run: |
78
+ python -c "
79
+ from moai_adk.core.tags.reporter import ReportGenerator
80
+
81
+ generator = ReportGenerator()
82
+ matrix = generator.generate_matrix_report('.')
83
+
84
+ with open('docs/reports/tag-matrix.md', 'w') as f:
85
+ f.write(matrix)
86
+
87
+ print('✅ Generated tag-matrix.md')
88
+ "
89
+
90
+ - name: Generate TAG Statistics
91
+ run: |
92
+ python -c "
93
+ from moai_adk.core.tags.reporter import ReportGenerator
94
+
95
+ generator = ReportGenerator()
96
+ stats = generator.generate_statistics_report('.')
97
+
98
+ with open('docs/reports/tag-statistics.json', 'w') as f:
99
+ f.write(stats)
100
+
101
+ print('✅ Generated tag-statistics.json')
102
+ "
103
+
104
+ - name: Generate combined report
105
+ run: |
106
+ python -c "
107
+ from moai_adk.core.tags.reporter import ReportGenerator
108
+ from pathlib import Path
109
+ import json
110
+
111
+ generator = ReportGenerator()
112
+ result = generator.generate_all_reports('.', 'docs/reports')
113
+
114
+ if result.success:
115
+ print(f'✅ All reports generated successfully')
116
+ print(f' - Inventory: {result.inventory_path}')
117
+ print(f' - Matrix: {result.matrix_path}')
118
+ print(f' - Statistics: {result.statistics_path}')
119
+
120
+ # Read statistics for summary
121
+ stats = json.loads(result.statistics_path.read_text())
122
+ print(f'')
123
+ print(f'📊 Summary:')
124
+ print(f' - Total TAGs: {stats[\"total_tags\"]}')
125
+ print(f' - By Type: SPEC={stats[\"by_type\"].get(\"SPEC\", 0)}, CODE={stats[\"by_type\"].get(\"CODE\", 0)}, TEST={stats[\"by_type\"].get(\"TEST\", 0)}, DOC={stats[\"by_type\"].get(\"DOC\", 0)}')
126
+ print(f' - Coverage: {stats[\"coverage\"].get(\"overall_percentage\", 0)}%')
127
+ else:
128
+ print(f'❌ Report generation failed: {result.error_message}')
129
+ exit(1)
130
+ "
131
+
132
+ - name: Check for changes
133
+ id: git_status
134
+ run: |
135
+ if [ -n "$(git status --porcelain docs/reports/)" ]; then
136
+ echo "changes=true" >> $GITHUB_OUTPUT
137
+ echo "📝 TAG reports have changed"
138
+ else
139
+ echo "changes=false" >> $GITHUB_OUTPUT
140
+ echo "✅ TAG reports unchanged (no commit needed)"
141
+ fi
142
+
143
+ - name: Commit reports
144
+ if: steps.git_status.outputs.changes == 'true'
145
+ run: |
146
+ git config --global user.name 'github-actions[bot]'
147
+ git config --global user.email 'github-actions[bot]@users.noreply.github.com'
148
+ git add docs/reports/
149
+ git commit -m "docs(tags): Update TAG reports [automated]
150
+
151
+ - Updated tag-inventory.md
152
+ - Updated tag-matrix.md
153
+ - Updated tag-statistics.json
154
+
155
+ Generated by: GitHub Actions workflow (tag-report.yml)
156
+ Triggered: ${{ github.event_name }}
157
+ Commit: ${{ github.sha }}
158
+
159
+ 🤖 Generated with MoAI-ADK TAG Reporting System
160
+ "
161
+ git push
162
+
163
+ - name: Create GitHub Release Notes
164
+ if: github.ref == 'refs/heads/main' && steps.git_status.outputs.changes == 'true'
165
+ run: |
166
+ echo "📊 TAG System Health Report" > report_summary.md
167
+ echo "" >> report_summary.md
168
+ echo "Generated: $(date -u +'%Y-%m-%d %H:%M:%S UTC')" >> report_summary.md
169
+ echo "" >> report_summary.md
170
+
171
+ # Extract key metrics from statistics
172
+ python -c "
173
+ import json
174
+ from pathlib import Path
175
+
176
+ stats = json.loads(Path('docs/reports/tag-statistics.json').read_text())
177
+
178
+ print(f'## Summary')
179
+ print(f'')
180
+ print(f'- **Total TAGs**: {stats[\"total_tags\"]}')
181
+ print(f'- **By Type**:')
182
+ print(f' - SPEC: {stats[\"by_type\"].get(\"SPEC\", 0)}')
183
+ print(f' - CODE: {stats[\"by_type\"].get(\"CODE\", 0)}')
184
+ print(f' - TEST: {stats[\"by_type\"].get(\"TEST\", 0)}')
185
+ print(f' - DOC: {stats[\"by_type\"].get(\"DOC\", 0)}')
186
+ print(f'')
187
+ print(f'## Coverage')
188
+ print(f'')
189
+ print(f'- **Overall**: {stats[\"coverage\"].get(\"overall_percentage\", 0)}%')
190
+ print(f'- **SPEC → CODE**: {stats[\"coverage\"].get(\"spec_to_code\", 0)}%')
191
+ print(f'- **CODE → TEST**: {stats[\"coverage\"].get(\"code_to_test\", 0)}%')
192
+ print(f'')
193
+ print(f'## Issues')
194
+ print(f'')
195
+ print(f'- **Orphan TAGs**: {stats[\"issues\"].get(\"orphan_count\", 0)}')
196
+ print(f'- **Incomplete Chains**: {stats[\"issues\"].get(\"incomplete_chains\", 0)}')
197
+ print(f'')
198
+ print(f'## Reports')
199
+ print(f'')
200
+ print(f'- [TAG Inventory](./docs/reports/tag-inventory.md)')
201
+ print(f'- [Coverage Matrix](./docs/reports/tag-matrix.md)')
202
+ print(f'- [Statistics (JSON)](./docs/reports/tag-statistics.json)')
203
+ " >> report_summary.md
204
+
205
+ cat report_summary.md
206
+
207
+ - name: Upload reports as artifacts
208
+ uses: actions/upload-artifact@v4
209
+ with:
210
+ name: tag-reports-${{ github.sha }}
211
+ path: docs/reports/
212
+ retention-days: 90
213
+
214
+ - name: Post summary to GitHub Actions UI
215
+ run: |
216
+ echo "## 📊 TAG Report Generation Complete" >> $GITHUB_STEP_SUMMARY
217
+ echo "" >> $GITHUB_STEP_SUMMARY
218
+
219
+ python -c "
220
+ import json
221
+ from pathlib import Path
222
+
223
+ stats = json.loads(Path('docs/reports/tag-statistics.json').read_text())
224
+
225
+ print(f'### Summary')
226
+ print(f'')
227
+ print(f'| Metric | Value |')
228
+ print(f'|--------|-------|')
229
+ print(f'| Total TAGs | {stats[\"total_tags\"]} |')
230
+ print(f'| SPEC | {stats[\"by_type\"].get(\"SPEC\", 0)} |')
231
+ print(f'| CODE | {stats[\"by_type\"].get(\"CODE\", 0)} |')
232
+ print(f'| TEST | {stats[\"by_type\"].get(\"TEST\", 0)} |')
233
+ print(f'| DOC | {stats[\"by_type\"].get(\"DOC\", 0)} |')
234
+ print(f'| Overall Coverage | {stats[\"coverage\"].get(\"overall_percentage\", 0)}% |')
235
+ print(f'| Orphan TAGs | {stats[\"issues\"].get(\"orphan_count\", 0)} |')
236
+ print(f'| Incomplete Chains | {stats[\"issues\"].get(\"incomplete_chains\", 0)} |')
237
+ print(f'')
238
+ print(f'### Generated Files')
239
+ print(f'')
240
+ print(f'- ✅ tag-inventory.md')
241
+ print(f'- ✅ tag-matrix.md')
242
+ print(f'- ✅ tag-statistics.json')
243
+ " >> $GITHUB_STEP_SUMMARY
244
+
245
+ - name: Fail workflow if issues detected (optional)
246
+ if: always()
247
+ run: |
248
+ python -c "
249
+ import json
250
+ from pathlib import Path
251
+ import sys
252
+
253
+ stats = json.loads(Path('docs/reports/tag-statistics.json').read_text())
254
+
255
+ orphan_count = stats['issues'].get('orphan_count', 0)
256
+ incomplete_count = stats['issues'].get('incomplete_chains', 0)
257
+
258
+ # Optional: Fail workflow if too many issues
259
+ # Uncomment to enable strict validation
260
+ # if orphan_count > 10 or incomplete_count > 10:
261
+ # print(f'❌ Too many TAG issues detected!')
262
+ # print(f' Orphans: {orphan_count}')
263
+ # print(f' Incomplete: {incomplete_count}')
264
+ # sys.exit(1)
265
+
266
+ print(f'✅ TAG system health check passed')
267
+ print(f' Orphans: {orphan_count}')
268
+ print(f' Incomplete: {incomplete_count}')
269
+ "