moai-adk 0.5.6__py3-none-any.whl → 0.6.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.
- moai_adk/__main__.py +1 -1
- moai_adk/core/project/phase_executor.py +4 -1
- moai_adk/templates/.claude/commands/alfred/1-plan.md +13 -13
- moai_adk/templates/.github/ISSUE_TEMPLATE/spec.yml +176 -0
- moai_adk/templates/.github/workflows/spec-issue-sync.yml +167 -0
- moai_adk/templates/.moai/memory/CONFIG-SCHEMA.md +444 -0
- moai_adk/templates/.moai/memory/gitflow-protection-policy.md +220 -0
- moai_adk/templates/.moai/memory/spec-metadata.md +356 -0
- {moai_adk-0.5.6.dist-info → moai_adk-0.6.0.dist-info}/METADATA +115 -2
- {moai_adk-0.5.6.dist-info → moai_adk-0.6.0.dist-info}/RECORD +13 -8
- {moai_adk-0.5.6.dist-info → moai_adk-0.6.0.dist-info}/WHEEL +0 -0
- {moai_adk-0.5.6.dist-info → moai_adk-0.6.0.dist-info}/entry_points.txt +0 -0
- {moai_adk-0.5.6.dist-info → moai_adk-0.6.0.dist-info}/licenses/LICENSE +0 -0
moai_adk/__main__.py
CHANGED
|
@@ -38,7 +38,7 @@ def show_logo() -> None:
|
|
|
38
38
|
console.print(__version__, style="cyan bold")
|
|
39
39
|
console.print()
|
|
40
40
|
console.print(" Tip: Run ", style="yellow", end="")
|
|
41
|
-
console.print("
|
|
41
|
+
console.print("uv run moai-adk --help", style="cyan", end="")
|
|
42
42
|
console.print(" to see available commands", style="yellow")
|
|
43
43
|
|
|
44
44
|
|
|
@@ -191,7 +191,10 @@ class PhaseExecutor:
|
|
|
191
191
|
# Ensure project section exists and set defaults
|
|
192
192
|
if "project" not in config:
|
|
193
193
|
config["project"] = {}
|
|
194
|
-
|
|
194
|
+
# Type guard for mypy
|
|
195
|
+
project_config = config["project"]
|
|
196
|
+
if isinstance(project_config, dict):
|
|
197
|
+
project_config["optimized"] = False # Default value
|
|
195
198
|
|
|
196
199
|
# Write config.json
|
|
197
200
|
config_path = project_path / ".moai" / "config.json"
|
|
@@ -5,19 +5,19 @@ description: "Planning (brainstorming, plan writing, design discussion) + Branch
|
|
|
5
5
|
# - ko: "계획 수립 (브레인스토밍, 설계 논의) + 브랜치/PR 생성"
|
|
6
6
|
# - ja: "計画策定(ブレインストーミング、設計議論)+ ブランチ/PR作成"
|
|
7
7
|
# - zh: "规划(头脑风暴、设计讨论)+ 分支/PR创建"
|
|
8
|
-
argument-hint:
|
|
8
|
+
argument-hint: Title 1 Title 2 ... | SPEC-ID modifications
|
|
9
9
|
allowed-tools:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
10
|
+
- Read
|
|
11
|
+
- Write
|
|
12
|
+
- Edit
|
|
13
|
+
- MultiEdit
|
|
14
|
+
- Grep
|
|
15
|
+
- Glob
|
|
16
|
+
- TodoWrite
|
|
17
|
+
- Bash(git:*)
|
|
18
|
+
- Bash(gh:*)
|
|
19
|
+
- Bash(rg:*)
|
|
20
|
+
- Bash(mkdir:*)
|
|
21
21
|
---
|
|
22
22
|
|
|
23
23
|
# 🏗️ MoAI-ADK Step 1: Establish a plan (Plan) - Always make a plan first and then proceed.
|
|
@@ -29,7 +29,7 @@ allowed-tools:
|
|
|
29
29
|
|
|
30
30
|
**Plan for**: $ARGUMENTS
|
|
31
31
|
|
|
32
|
-
## 💡 Planning philosophy:
|
|
32
|
+
## 💡 Planning philosophy: "Always make a plan first and then proceed."
|
|
33
33
|
|
|
34
34
|
`/alfred:1-plan` is a general-purpose command that **creates a plan**, rather than simply “creating” a SPEC document.
|
|
35
35
|
|
|
@@ -0,0 +1,176 @@
|
|
|
1
|
+
name: 📋 SPEC Document
|
|
2
|
+
description: Create a new SPEC document for feature planning
|
|
3
|
+
title: "[SPEC-] "
|
|
4
|
+
labels: ["spec", "planning"]
|
|
5
|
+
assignees: []
|
|
6
|
+
|
|
7
|
+
body:
|
|
8
|
+
- type: markdown
|
|
9
|
+
attributes:
|
|
10
|
+
value: |
|
|
11
|
+
## 📋 SPEC Metadata
|
|
12
|
+
|
|
13
|
+
Fill out the SPEC details below. This will be synchronized with the SPEC document and GitHub Issue.
|
|
14
|
+
|
|
15
|
+
- type: input
|
|
16
|
+
id: spec-id
|
|
17
|
+
attributes:
|
|
18
|
+
label: SPEC ID
|
|
19
|
+
description: "Format: DOMAIN-###. Example: AUTH-001, API-DESIGN-001"
|
|
20
|
+
placeholder: "AUTH-001"
|
|
21
|
+
validations:
|
|
22
|
+
required: true
|
|
23
|
+
|
|
24
|
+
- type: input
|
|
25
|
+
id: spec-title
|
|
26
|
+
attributes:
|
|
27
|
+
label: SPEC Title
|
|
28
|
+
description: "Brief description of the specification"
|
|
29
|
+
placeholder: "JWT-based authentication system"
|
|
30
|
+
validations:
|
|
31
|
+
required: true
|
|
32
|
+
|
|
33
|
+
- type: dropdown
|
|
34
|
+
id: priority
|
|
35
|
+
attributes:
|
|
36
|
+
label: Priority
|
|
37
|
+
description: "Feature priority level"
|
|
38
|
+
options:
|
|
39
|
+
- "critical"
|
|
40
|
+
- "high"
|
|
41
|
+
- "medium"
|
|
42
|
+
- "low"
|
|
43
|
+
validations:
|
|
44
|
+
required: true
|
|
45
|
+
|
|
46
|
+
- type: dropdown
|
|
47
|
+
id: category
|
|
48
|
+
attributes:
|
|
49
|
+
label: Category
|
|
50
|
+
description: "SPEC category"
|
|
51
|
+
options:
|
|
52
|
+
- "API"
|
|
53
|
+
- "Backend"
|
|
54
|
+
- "Frontend"
|
|
55
|
+
- "Infrastructure"
|
|
56
|
+
- "Security"
|
|
57
|
+
- "Testing"
|
|
58
|
+
- "DevOps"
|
|
59
|
+
- "Documentation"
|
|
60
|
+
- "Performance"
|
|
61
|
+
- "Other"
|
|
62
|
+
validations:
|
|
63
|
+
required: true
|
|
64
|
+
|
|
65
|
+
- type: textarea
|
|
66
|
+
id: ubiquitous-requirements
|
|
67
|
+
attributes:
|
|
68
|
+
label: "Ubiquitous Requirements"
|
|
69
|
+
description: "Statements that apply universally to the system"
|
|
70
|
+
placeholder: |
|
|
71
|
+
- The system must provide JWT-based authentication
|
|
72
|
+
- The system must support token expiration
|
|
73
|
+
value: "### Ubiquitous\n"
|
|
74
|
+
validations:
|
|
75
|
+
required: true
|
|
76
|
+
|
|
77
|
+
- type: textarea
|
|
78
|
+
id: event-requirements
|
|
79
|
+
attributes:
|
|
80
|
+
label: "Event-driven Requirements (WHEN)"
|
|
81
|
+
description: "Event-triggered requirements in EARS format"
|
|
82
|
+
placeholder: |
|
|
83
|
+
- WHEN the user submits login credentials, the system must validate them against the database
|
|
84
|
+
- WHEN credentials are valid, the system must issue a JWT token with expiration
|
|
85
|
+
value: "### Event-driven (WHEN)\n"
|
|
86
|
+
validations:
|
|
87
|
+
required: false
|
|
88
|
+
|
|
89
|
+
- type: textarea
|
|
90
|
+
id: state-requirements
|
|
91
|
+
attributes:
|
|
92
|
+
label: "State-driven Requirements (WHILE)"
|
|
93
|
+
description: "State-based requirements in EARS format"
|
|
94
|
+
placeholder: |
|
|
95
|
+
- WHILE the token is unexpired, the system must allow access to protected resources
|
|
96
|
+
- WHILE the user is logged in, the system must track the session
|
|
97
|
+
value: "### State-driven (WHILE)\n"
|
|
98
|
+
validations:
|
|
99
|
+
required: false
|
|
100
|
+
|
|
101
|
+
- type: textarea
|
|
102
|
+
id: optional-requirements
|
|
103
|
+
attributes:
|
|
104
|
+
label: "Optional Requirements (WHERE)"
|
|
105
|
+
description: "Optional features and capabilities"
|
|
106
|
+
placeholder: |
|
|
107
|
+
- WHERE the user requests token refresh, the system can issue a new token
|
|
108
|
+
- WHERE OAuth2 is available, the system can support social login
|
|
109
|
+
value: "### Optional (WHERE)\n"
|
|
110
|
+
validations:
|
|
111
|
+
required: false
|
|
112
|
+
|
|
113
|
+
- type: textarea
|
|
114
|
+
id: constraints
|
|
115
|
+
attributes:
|
|
116
|
+
label: "Constraints (IF)"
|
|
117
|
+
description: "System constraints and conditions"
|
|
118
|
+
placeholder: |
|
|
119
|
+
- IF the token has expired, the system must return 401 Unauthorized
|
|
120
|
+
- IF the password is incorrect, the system must reject the login attempt
|
|
121
|
+
value: "### Constraints (IF)\n"
|
|
122
|
+
validations:
|
|
123
|
+
required: false
|
|
124
|
+
|
|
125
|
+
- type: textarea
|
|
126
|
+
id: acceptance-criteria
|
|
127
|
+
attributes:
|
|
128
|
+
label: "Acceptance Criteria (Given-When-Then)"
|
|
129
|
+
description: "At least 2-3 test scenarios"
|
|
130
|
+
placeholder: |
|
|
131
|
+
**Scenario 1: Successful Login**
|
|
132
|
+
- Given a user with valid credentials exists
|
|
133
|
+
- When the user submits their credentials
|
|
134
|
+
- Then the system returns a valid JWT token
|
|
135
|
+
|
|
136
|
+
**Scenario 2: Token Expiration**
|
|
137
|
+
- Given a user with an expired token
|
|
138
|
+
- When the user tries to access a protected resource
|
|
139
|
+
- Then the system returns a 401 Unauthorized response
|
|
140
|
+
value: "## Acceptance Criteria\n\n"
|
|
141
|
+
validations:
|
|
142
|
+
required: true
|
|
143
|
+
|
|
144
|
+
- type: textarea
|
|
145
|
+
id: dependencies
|
|
146
|
+
attributes:
|
|
147
|
+
label: "Dependencies"
|
|
148
|
+
description: "Related SPECs, tasks, or blockers"
|
|
149
|
+
placeholder: |
|
|
150
|
+
- Related: SPEC-SECURITY-001
|
|
151
|
+
- Blocks: SPEC-API-DESIGN-001
|
|
152
|
+
- Depends on: SPEC-DATABASE-001
|
|
153
|
+
validations:
|
|
154
|
+
required: false
|
|
155
|
+
|
|
156
|
+
- type: textarea
|
|
157
|
+
id: notes
|
|
158
|
+
attributes:
|
|
159
|
+
label: "Additional Notes"
|
|
160
|
+
description: "Technical notes, assumptions, or context"
|
|
161
|
+
placeholder: |
|
|
162
|
+
- Consider token refresh token rotation
|
|
163
|
+
- JWT payload should be minimal for performance
|
|
164
|
+
- Consider rate limiting on login attempts
|
|
165
|
+
validations:
|
|
166
|
+
required: false
|
|
167
|
+
|
|
168
|
+
- type: markdown
|
|
169
|
+
attributes:
|
|
170
|
+
value: |
|
|
171
|
+
## 📚 Reference
|
|
172
|
+
|
|
173
|
+
- **SPEC Metadata Guide**: See `.moai/memory/spec-metadata.md`
|
|
174
|
+
- **EARS Syntax Guide**: See `.moai/memory/development-guide.md`
|
|
175
|
+
- **Acceptance Criteria**: Use Given-When-Then (Gherkin) format
|
|
176
|
+
- **@TAG System**: @SPEC, @TEST, @CODE, @DOC traceability
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
name: 📋 SPEC Issue Sync
|
|
2
|
+
|
|
3
|
+
on:
|
|
4
|
+
pull_request:
|
|
5
|
+
paths:
|
|
6
|
+
- '.moai/specs/SPEC-*/spec.md'
|
|
7
|
+
types: [opened, synchronize]
|
|
8
|
+
|
|
9
|
+
permissions:
|
|
10
|
+
issues: write
|
|
11
|
+
pull-requests: write
|
|
12
|
+
contents: read
|
|
13
|
+
|
|
14
|
+
jobs:
|
|
15
|
+
sync-spec-to-issue:
|
|
16
|
+
runs-on: ubuntu-latest
|
|
17
|
+
name: 🔄 Sync SPEC to GitHub Issue
|
|
18
|
+
|
|
19
|
+
steps:
|
|
20
|
+
- name: Checkout code
|
|
21
|
+
uses: actions/checkout@v4
|
|
22
|
+
with:
|
|
23
|
+
fetch-depth: 0
|
|
24
|
+
ref: ${{ github.event.pull_request.head.sha }}
|
|
25
|
+
|
|
26
|
+
- name: Find and parse SPEC file
|
|
27
|
+
id: spec
|
|
28
|
+
run: |
|
|
29
|
+
set -x # Enable debug mode
|
|
30
|
+
|
|
31
|
+
# Debug: Show current directory and files
|
|
32
|
+
echo "=== Debug: Current directory ==="
|
|
33
|
+
pwd
|
|
34
|
+
ls -la
|
|
35
|
+
|
|
36
|
+
echo "=== Debug: Looking for .moai/specs ==="
|
|
37
|
+
ls -la .moai/ 2>&1 || echo ".moai/ directory not found"
|
|
38
|
+
|
|
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"
|
|
42
|
+
|
|
43
|
+
spec_file=$(find .moai/specs -name "spec.md" -type f 2>&1 | head -1)
|
|
44
|
+
echo "Found spec_file: [$spec_file]"
|
|
45
|
+
|
|
46
|
+
if [ -z "$spec_file" ]; then
|
|
47
|
+
echo "⚠️ No SPEC file found in .moai/specs"
|
|
48
|
+
echo "Exiting gracefully (this is expected if no SPEC files changed)"
|
|
49
|
+
exit 0
|
|
50
|
+
fi
|
|
51
|
+
|
|
52
|
+
echo "✅ Found SPEC file: $spec_file"
|
|
53
|
+
echo "spec_file=$spec_file" >> $GITHUB_OUTPUT
|
|
54
|
+
|
|
55
|
+
# Extract YAML metadata using grep
|
|
56
|
+
spec_id=$(grep "^id:" "$spec_file" | sed 's/^id: *//' | tr -d ' "')
|
|
57
|
+
spec_version=$(grep "^version:" "$spec_file" | sed 's/^version: *//' | tr -d ' "')
|
|
58
|
+
spec_status=$(grep "^status:" "$spec_file" | sed 's/^status: *//' | tr -d ' "')
|
|
59
|
+
spec_priority=$(grep "^priority:" "$spec_file" | sed 's/^priority: *//' | tr -d ' "')
|
|
60
|
+
|
|
61
|
+
# Extract title from H1 heading
|
|
62
|
+
spec_title=$(grep "^# @SPEC:" "$spec_file" | sed 's/^# @SPEC:[^:]*: //')
|
|
63
|
+
|
|
64
|
+
echo "✅ Extracted SPEC metadata:"
|
|
65
|
+
echo " ID: $spec_id"
|
|
66
|
+
echo " Title: $spec_title"
|
|
67
|
+
echo " Version: $spec_version"
|
|
68
|
+
echo " Status: $spec_status"
|
|
69
|
+
echo " Priority: $spec_priority"
|
|
70
|
+
|
|
71
|
+
echo "spec_id=$spec_id" >> $GITHUB_OUTPUT
|
|
72
|
+
echo "spec_version=$spec_version" >> $GITHUB_OUTPUT
|
|
73
|
+
echo "spec_status=$spec_status" >> $GITHUB_OUTPUT
|
|
74
|
+
echo "spec_priority=$spec_priority" >> $GITHUB_OUTPUT
|
|
75
|
+
echo "spec_title=$spec_title" >> $GITHUB_OUTPUT
|
|
76
|
+
|
|
77
|
+
- name: Create GitHub Issue
|
|
78
|
+
if: steps.spec.outputs.spec_id
|
|
79
|
+
id: create-issue
|
|
80
|
+
env:
|
|
81
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
82
|
+
run: |
|
|
83
|
+
spec_id="${{ steps.spec.outputs.spec_id }}"
|
|
84
|
+
spec_version="${{ steps.spec.outputs.spec_version }}"
|
|
85
|
+
spec_title="${{ steps.spec.outputs.spec_title }}"
|
|
86
|
+
spec_status="${{ steps.spec.outputs.spec_status }}"
|
|
87
|
+
spec_priority="${{ steps.spec.outputs.spec_priority }}"
|
|
88
|
+
spec_file="${{ steps.spec.outputs.spec_file }}"
|
|
89
|
+
|
|
90
|
+
# Read SPEC content (skip YAML frontmatter: 9 lines + 1 blank = 10 lines total)
|
|
91
|
+
# Start reading from line 11
|
|
92
|
+
spec_content=$(tail -n +11 "$spec_file")
|
|
93
|
+
|
|
94
|
+
# Create issue body using GitHub Actions recommended pattern
|
|
95
|
+
# Reference: https://docs.github.com/en/actions/using-workflows/workflow-commands-for-github-actions
|
|
96
|
+
{
|
|
97
|
+
echo "## SPEC Metadata"
|
|
98
|
+
echo ""
|
|
99
|
+
echo "| Field | Value |"
|
|
100
|
+
echo "|-------|-------|"
|
|
101
|
+
echo "| **ID** | $spec_id |"
|
|
102
|
+
echo "| **Version** | $spec_version |"
|
|
103
|
+
echo "| **Status** | $spec_status |"
|
|
104
|
+
echo "| **Priority** | $spec_priority |"
|
|
105
|
+
echo ""
|
|
106
|
+
echo "## SPEC Document"
|
|
107
|
+
echo ""
|
|
108
|
+
echo "$spec_content"
|
|
109
|
+
echo ""
|
|
110
|
+
echo "---"
|
|
111
|
+
echo ""
|
|
112
|
+
echo "📎 **Branch**: \`feature/$spec_id\`"
|
|
113
|
+
echo "🔗 **PR**: #${{ github.event.pull_request.number }}"
|
|
114
|
+
echo "📝 **Auto-synced**: This issue is automatically synchronized from the SPEC document"
|
|
115
|
+
} > /tmp/issue_body.txt
|
|
116
|
+
|
|
117
|
+
echo "📋 Creating GitHub Issue..."
|
|
118
|
+
echo " Title: [SPEC-$spec_id] $spec_title (v$spec_version)"
|
|
119
|
+
echo " Body file: /tmp/issue_body.txt"
|
|
120
|
+
wc -l /tmp/issue_body.txt
|
|
121
|
+
|
|
122
|
+
# Create issue with labels using body-file
|
|
123
|
+
issue_output=$(gh issue create \
|
|
124
|
+
--title "[SPEC-$spec_id] $spec_title (v$spec_version)" \
|
|
125
|
+
--body-file /tmp/issue_body.txt \
|
|
126
|
+
--label "spec" \
|
|
127
|
+
--label "planning" \
|
|
128
|
+
--label "$spec_priority" 2>&1)
|
|
129
|
+
|
|
130
|
+
echo "$issue_output" | tee /tmp/issue_output.txt
|
|
131
|
+
|
|
132
|
+
# Extract issue number from output
|
|
133
|
+
issue_num=$(echo "$issue_output" | grep -oE '/issues/[0-9]+' | grep -oE '[0-9]+' | head -1)
|
|
134
|
+
|
|
135
|
+
if [ -z "$issue_num" ]; then
|
|
136
|
+
echo "⚠️ Could not extract issue number from output"
|
|
137
|
+
echo "Full output:"
|
|
138
|
+
cat /tmp/issue_output.txt
|
|
139
|
+
exit 1
|
|
140
|
+
fi
|
|
141
|
+
|
|
142
|
+
echo "issue_number=$issue_num" >> $GITHUB_OUTPUT
|
|
143
|
+
echo "✅ Created issue #$issue_num"
|
|
144
|
+
|
|
145
|
+
- name: Add PR comment
|
|
146
|
+
if: steps.create-issue.outputs.issue_number
|
|
147
|
+
env:
|
|
148
|
+
GH_TOKEN: ${{ secrets.GITHUB_TOKEN }}
|
|
149
|
+
run: |
|
|
150
|
+
issue_num="${{ steps.create-issue.outputs.issue_number }}"
|
|
151
|
+
spec_id="${{ steps.spec.outputs.spec_id }}"
|
|
152
|
+
spec_title="${{ steps.spec.outputs.spec_title }}"
|
|
153
|
+
|
|
154
|
+
# Create PR comment body using same pattern
|
|
155
|
+
{
|
|
156
|
+
echo "✅ **SPEC GitHub Issue Created**"
|
|
157
|
+
echo ""
|
|
158
|
+
echo "This SPEC has been synchronized to GitHub Issue."
|
|
159
|
+
echo ""
|
|
160
|
+
echo "📋 **Issue**: [#$issue_num - SPEC-$spec_id: $spec_title](../issues/$issue_num)"
|
|
161
|
+
echo "🔗 **SPEC File**: \`.moai/specs/SPEC-$spec_id/spec.md\`"
|
|
162
|
+
echo ""
|
|
163
|
+
echo "The issue will be automatically updated as you modify the SPEC document."
|
|
164
|
+
} > /tmp/pr_comment.txt
|
|
165
|
+
|
|
166
|
+
gh pr comment ${{ github.event.pull_request.number }} --body-file /tmp/pr_comment.txt
|
|
167
|
+
echo "✅ Added PR comment linking to issue #$issue_num"
|