@atlashub/smartstack-cli 1.35.0 → 1.37.0
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.
- package/package.json +1 -1
- package/templates/skills/_shared.md +7 -7
- package/templates/skills/application/steps/step-01-navigation.md +226 -43
- package/templates/skills/application/steps/step-03-roles.md +160 -38
- package/templates/skills/application/steps/step-04-backend.md +126 -19
- package/templates/skills/application/steps/step-05-frontend.md +4 -1
- package/templates/skills/application/templates-backend.md +8 -8
- package/templates/skills/application/templates-frontend.md +8 -8
- package/templates/skills/application/templates-seed.md +200 -1
- package/templates/skills/gitflow/_shared.md +188 -53
- package/templates/skills/gitflow/phases/abort.md +28 -16
- package/templates/skills/gitflow/phases/cleanup.md +13 -9
- package/templates/skills/gitflow/phases/status.md +16 -17
- package/templates/skills/gitflow/steps/step-commit.md +11 -5
- package/templates/skills/gitflow/steps/step-finish.md +43 -33
- package/templates/skills/gitflow/steps/step-init.md +7 -2
- package/templates/skills/gitflow/steps/step-merge.md +24 -10
- package/templates/skills/gitflow/steps/step-pr.md +42 -28
- package/templates/skills/gitflow/steps/step-start.md +19 -13
- package/templates/skills/gitflow/templates/config.json +7 -4
- package/templates/skills/ralph-loop/SKILL.md +57 -11
- package/templates/skills/ralph-loop/steps/step-00-init.md +170 -30
- package/templates/skills/ralph-loop/steps/step-01-task.md +243 -40
- package/templates/skills/ralph-loop/steps/step-02-execute.md +142 -24
- package/templates/skills/ralph-loop/steps/step-03-commit.md +140 -36
- package/templates/skills/ralph-loop/steps/step-04-check.md +128 -44
- package/templates/skills/ralph-loop/steps/step-05-report.md +175 -88
|
@@ -16,9 +16,12 @@ Create tags for releases/hotfixes, merge back to develop, clean up worktree and
|
|
|
16
16
|
|
|
17
17
|
## EXECUTION SEQUENCE:
|
|
18
18
|
|
|
19
|
-
### 1. Determine Branch Context
|
|
19
|
+
### 1. Load Config and Determine Branch Context
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
+
# Load GitFlow config (sets GF_* variables)
|
|
23
|
+
read_gitflow_config || { echo "❌ Run /gitflow init first."; exit 1; }
|
|
24
|
+
|
|
22
25
|
# Get current or specified branch
|
|
23
26
|
BRANCH=${1:-$(git rev-parse --abbrev-ref HEAD)}
|
|
24
27
|
BRANCH_TYPE=$(echo $BRANCH | cut -d'/' -f1)
|
|
@@ -27,8 +30,8 @@ BRANCH_NAME=$(echo $BRANCH | cut -d'/' -f2)
|
|
|
27
30
|
# Validate branch type
|
|
28
31
|
case "$BRANCH_TYPE" in
|
|
29
32
|
feature|release|hotfix) ;;
|
|
30
|
-
|
|
31
|
-
echo "❌ Cannot finish
|
|
33
|
+
$GF_MAIN_BRANCH|$GF_DEVELOP_BRANCH)
|
|
34
|
+
echo "❌ Cannot finish $GF_MAIN_BRANCH or $GF_DEVELOP_BRANCH branch"
|
|
32
35
|
STOP
|
|
33
36
|
;;
|
|
34
37
|
*)
|
|
@@ -46,12 +49,12 @@ git fetch origin
|
|
|
46
49
|
# Check if branch was merged
|
|
47
50
|
case "$BRANCH_TYPE" in
|
|
48
51
|
feature)
|
|
49
|
-
MERGED=$(git branch -r --merged origin
|
|
50
|
-
TARGET="
|
|
52
|
+
MERGED=$(git branch -r --merged origin/$GF_DEVELOP_BRANCH | grep "$BRANCH" | wc -l)
|
|
53
|
+
TARGET="$GF_DEVELOP_BRANCH"
|
|
51
54
|
;;
|
|
52
55
|
release|hotfix)
|
|
53
|
-
MERGED=$(git branch -r --merged origin
|
|
54
|
-
TARGET="
|
|
56
|
+
MERGED=$(git branch -r --merged origin/$GF_MAIN_BRANCH | grep "$BRANCH" | wc -l)
|
|
57
|
+
TARGET="$GF_MAIN_BRANCH"
|
|
55
58
|
;;
|
|
56
59
|
esac
|
|
57
60
|
|
|
@@ -74,8 +77,8 @@ esac
|
|
|
74
77
|
|
|
75
78
|
```bash
|
|
76
79
|
if [ "$BRANCH_TYPE" = "release" ] || [ "$BRANCH_TYPE" = "hotfix" ]; then
|
|
77
|
-
# Get version
|
|
78
|
-
VERSION
|
|
80
|
+
# Get version from config (already loaded)
|
|
81
|
+
VERSION="$GF_VERSION"
|
|
79
82
|
|
|
80
83
|
# For hotfix, increment patch
|
|
81
84
|
if [ "$BRANCH_TYPE" = "hotfix" ]; then
|
|
@@ -95,8 +98,8 @@ if [ "$BRANCH_TYPE" = "release" ] || [ "$BRANCH_TYPE" = "hotfix" ]; then
|
|
|
95
98
|
}
|
|
96
99
|
|
|
97
100
|
# Create tag on main
|
|
98
|
-
git checkout
|
|
99
|
-
git pull origin
|
|
101
|
+
git checkout $GF_MAIN_BRANCH
|
|
102
|
+
git pull origin $GF_MAIN_BRANCH
|
|
100
103
|
git tag -a "$TAG_NAME" -m "$BRANCH_TYPE: $BRANCH_NAME"
|
|
101
104
|
git push origin "$TAG_NAME"
|
|
102
105
|
|
|
@@ -108,13 +111,13 @@ fi
|
|
|
108
111
|
|
|
109
112
|
```bash
|
|
110
113
|
if [ "$BRANCH_TYPE" = "release" ] || [ "$BRANCH_TYPE" = "hotfix" ]; then
|
|
111
|
-
echo "Merging $TAG_NAME back to
|
|
114
|
+
echo "Merging $TAG_NAME back to $GF_DEVELOP_BRANCH..."
|
|
112
115
|
|
|
113
|
-
git checkout
|
|
114
|
-
git pull origin
|
|
116
|
+
git checkout $GF_DEVELOP_BRANCH
|
|
117
|
+
git pull origin $GF_DEVELOP_BRANCH
|
|
115
118
|
|
|
116
119
|
# Merge with merge commit (preserve history)
|
|
117
|
-
git merge
|
|
120
|
+
git merge $GF_MAIN_BRANCH -m "Merge $TAG_NAME back to $GF_DEVELOP_BRANCH"
|
|
118
121
|
|
|
119
122
|
# Handle conflicts
|
|
120
123
|
CONFLICTS=$(git diff --name-only --diff-filter=U | wc -l)
|
|
@@ -125,48 +128,55 @@ if [ "$BRANCH_TYPE" = "release" ] || [ "$BRANCH_TYPE" = "hotfix" ]; then
|
|
|
125
128
|
# Options: resolve, abort
|
|
126
129
|
}
|
|
127
130
|
|
|
128
|
-
git push origin
|
|
131
|
+
git push origin $GF_DEVELOP_BRANCH
|
|
129
132
|
|
|
130
133
|
# CRITICAL: Verify push and update tracking refs
|
|
131
|
-
git fetch origin
|
|
134
|
+
git fetch origin $GF_DEVELOP_BRANCH:refs/remotes/origin/$GF_DEVELOP_BRANCH --force --quiet
|
|
132
135
|
LOCAL_SHA=$(git rev-parse HEAD)
|
|
133
|
-
REMOTE_SHA=$(git rev-parse origin
|
|
136
|
+
REMOTE_SHA=$(git rev-parse origin/$GF_DEVELOP_BRANCH)
|
|
134
137
|
if [ "$LOCAL_SHA" = "$REMOTE_SHA" ]; then
|
|
135
138
|
echo "✅ Push verified - local/remote in sync"
|
|
136
139
|
else
|
|
137
140
|
echo "⚠️ Push verification FAILED"
|
|
138
141
|
echo " Local: $LOCAL_SHA"
|
|
139
142
|
echo " Remote: $REMOTE_SHA"
|
|
140
|
-
echo " → Try: git push origin
|
|
143
|
+
echo " → Try: git push origin $GF_DEVELOP_BRANCH --force-with-lease"
|
|
141
144
|
fi
|
|
142
145
|
|
|
143
|
-
echo "✅ Merged back to
|
|
146
|
+
echo "✅ Merged back to $GF_DEVELOP_BRANCH"
|
|
144
147
|
fi
|
|
145
148
|
```
|
|
146
149
|
|
|
147
|
-
### 5. Update Version (Release
|
|
150
|
+
### 5. Update Version (Release and Hotfix)
|
|
148
151
|
|
|
149
152
|
```bash
|
|
150
|
-
if [ "$BRANCH_TYPE" = "release" ]; then
|
|
151
|
-
# Increment minor version for next development
|
|
153
|
+
if [ "$BRANCH_TYPE" = "release" ] || [ "$BRANCH_TYPE" = "hotfix" ]; then
|
|
152
154
|
MAJOR=$(echo $VERSION | cut -d'.' -f1)
|
|
153
155
|
MINOR=$(echo $VERSION | cut -d'.' -f2)
|
|
154
|
-
|
|
156
|
+
PATCH=$(echo $VERSION | cut -d'.' -f3)
|
|
157
|
+
|
|
158
|
+
if [ "$BRANCH_TYPE" = "release" ]; then
|
|
159
|
+
# Release: increment minor, reset patch
|
|
160
|
+
NEXT_VERSION="$MAJOR.$((MINOR + 1)).0"
|
|
161
|
+
else
|
|
162
|
+
# Hotfix: increment patch (patch was already bumped for the tag, bump again for next dev)
|
|
163
|
+
NEXT_VERSION="$MAJOR.$MINOR.$((PATCH + 2))"
|
|
164
|
+
fi
|
|
155
165
|
|
|
156
|
-
# Update config
|
|
157
|
-
sed -i "s/\"current\": \"
|
|
166
|
+
# Update config (using resolved config path)
|
|
167
|
+
sed -i "s/\"current\": \".*\"/\"current\": \"$NEXT_VERSION\"/" "$GF_CONFIG_FILE"
|
|
158
168
|
|
|
159
169
|
# Update source files
|
|
160
170
|
# csproj, package.json, etc.
|
|
161
171
|
|
|
162
172
|
git add -A
|
|
163
173
|
git commit -m "chore: bump version to $NEXT_VERSION for development"
|
|
164
|
-
git push origin
|
|
174
|
+
git push origin $GF_DEVELOP_BRANCH
|
|
165
175
|
|
|
166
176
|
# CRITICAL: Verify push and update tracking refs
|
|
167
|
-
git fetch origin
|
|
177
|
+
git fetch origin $GF_DEVELOP_BRANCH:refs/remotes/origin/$GF_DEVELOP_BRANCH --force --quiet
|
|
168
178
|
LOCAL_SHA=$(git rev-parse HEAD)
|
|
169
|
-
REMOTE_SHA=$(git rev-parse origin
|
|
179
|
+
REMOTE_SHA=$(git rev-parse origin/$GF_DEVELOP_BRANCH)
|
|
170
180
|
if [ "$LOCAL_SHA" = "$REMOTE_SHA" ]; then
|
|
171
181
|
echo "✅ Push verified - local/remote in sync"
|
|
172
182
|
else
|
|
@@ -182,14 +192,14 @@ fi
|
|
|
182
192
|
### 6. Clean Up Worktree
|
|
183
193
|
|
|
184
194
|
```bash
|
|
185
|
-
# Find worktree for this branch
|
|
186
|
-
WORKTREE_PATH=$(git worktree list | grep "
|
|
195
|
+
# Find worktree for this branch (use --porcelain for reliable parsing)
|
|
196
|
+
WORKTREE_PATH=$(git worktree list --porcelain | grep -B2 "branch refs/heads/$BRANCH" | grep "^worktree " | sed 's/^worktree //')
|
|
187
197
|
|
|
188
198
|
if [ -n "$WORKTREE_PATH" ] && [ -d "$WORKTREE_PATH" ]; then
|
|
189
199
|
echo "Removing worktree: $WORKTREE_PATH"
|
|
190
200
|
|
|
191
|
-
# Make sure we're not in the worktree
|
|
192
|
-
cd $(git rev-parse --show-toplevel)
|
|
201
|
+
# Make sure we're not in the worktree directory
|
|
202
|
+
cd "$GF_DEVELOP_PATH" 2>/dev/null || cd "$(git rev-parse --show-toplevel)"
|
|
193
203
|
|
|
194
204
|
git worktree remove "$WORKTREE_PATH" --force 2>/dev/null || {
|
|
195
205
|
rm -rf "$WORKTREE_PATH"
|
|
@@ -452,6 +452,7 @@ mkdir -p "$DEVELOP_PATH/.claude/gitflow/{plans,logs,cache,backup}"
|
|
|
452
452
|
"version": "2.0.0",
|
|
453
453
|
"repository": {
|
|
454
454
|
"name": "{PROJECT_NAME}",
|
|
455
|
+
"rootFolder": "{ROOT_FOLDER}",
|
|
455
456
|
"nameVariants": {
|
|
456
457
|
"pascalCaseDot": "{PascalCase.Dot}",
|
|
457
458
|
"pascalCase": "{PascalCase}",
|
|
@@ -459,7 +460,7 @@ mkdir -p "$DEVELOP_PATH/.claude/gitflow/{plans,logs,cache,backup}"
|
|
|
459
460
|
"snakeCase": "{snake_case}",
|
|
460
461
|
"displayName": "{Display Name}"
|
|
461
462
|
},
|
|
462
|
-
"
|
|
463
|
+
"defaultBranch": "main",
|
|
463
464
|
"remoteUrl": "{REPO_URL}"
|
|
464
465
|
},
|
|
465
466
|
"git": {
|
|
@@ -494,7 +495,8 @@ mkdir -p "$DEVELOP_PATH/.claude/gitflow/{plans,logs,cache,backup}"
|
|
|
494
495
|
"efcore": {
|
|
495
496
|
"enabled": true,
|
|
496
497
|
"validateOnCommit": true,
|
|
497
|
-
"blockDestructive": true
|
|
498
|
+
"blockDestructive": true,
|
|
499
|
+
"migrationNaming": "{context}_v{version}_{sequence}_{Description}"
|
|
498
500
|
},
|
|
499
501
|
"workflow": {
|
|
500
502
|
"push": {
|
|
@@ -504,6 +506,9 @@ mkdir -p "$DEVELOP_PATH/.claude/gitflow/{plans,logs,cache,backup}"
|
|
|
504
506
|
"autoLabels": true,
|
|
505
507
|
"requireReview": true
|
|
506
508
|
}
|
|
509
|
+
},
|
|
510
|
+
"language": {
|
|
511
|
+
"code": "{GF_LANG}"
|
|
507
512
|
}
|
|
508
513
|
}
|
|
509
514
|
```
|
|
@@ -16,19 +16,33 @@ Run through review checklist and merge the pull request with appropriate strateg
|
|
|
16
16
|
|
|
17
17
|
## EXECUTION SEQUENCE:
|
|
18
18
|
|
|
19
|
-
### 1. Load PR Context
|
|
19
|
+
### 1. Load Config and PR Context
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
+
# Load GitFlow config (sets GF_* variables)
|
|
23
|
+
read_gitflow_config || { echo "❌ Run /gitflow init first."; exit 1; }
|
|
24
|
+
|
|
22
25
|
CURRENT=$(git rev-parse --abbrev-ref HEAD)
|
|
23
|
-
GIT_PROVIDER
|
|
26
|
+
GIT_PROVIDER="$GF_PROVIDER"
|
|
27
|
+
|
|
28
|
+
# Try loading persisted PR state first
|
|
29
|
+
CONFIG_DIR=$(dirname "$GF_CONFIG_FILE")
|
|
30
|
+
PR_STATE_FILE="$CONFIG_DIR/cache/pr-state.json"
|
|
31
|
+
if [ -f "$PR_STATE_FILE" ]; then
|
|
32
|
+
PR_NUMBER=$(grep -oP '"pr_number":\s*"\K[^"]+' "$PR_STATE_FILE" | head -1)
|
|
33
|
+
TARGET_BRANCH=$(grep -oP '"target_branch":\s*"\K[^"]+' "$PR_STATE_FILE" | head -1)
|
|
34
|
+
echo "✓ Loaded PR state from cache: PR #$PR_NUMBER → $TARGET_BRANCH"
|
|
35
|
+
fi
|
|
24
36
|
|
|
25
|
-
#
|
|
26
|
-
if [ "$
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
37
|
+
# Fallback: query provider if no cached state
|
|
38
|
+
if [ -z "$PR_NUMBER" ]; then
|
|
39
|
+
if [ "$GIT_PROVIDER" = "github" ]; then
|
|
40
|
+
PR_NUMBER=$(gh pr list --head "$CURRENT" --json number --jq '.[0].number')
|
|
41
|
+
PR_STATUS=$(gh pr view $PR_NUMBER --json state,mergeable,reviews --jq '.')
|
|
42
|
+
elif [ "$GIT_PROVIDER" = "azuredevops" ]; then
|
|
43
|
+
PR_NUMBER=$(az repos pr list --source-branch "$CURRENT" --query "[0].pullRequestId" -o tsv)
|
|
44
|
+
PR_STATUS=$(az repos pr show --id $PR_NUMBER --query "{status:status,mergeStatus:mergeStatus}")
|
|
45
|
+
fi
|
|
32
46
|
fi
|
|
33
47
|
|
|
34
48
|
[ -z "$PR_NUMBER" ] && {
|
|
@@ -125,7 +139,7 @@ case "$BRANCH_TYPE" in
|
|
|
125
139
|
release|hotfix)
|
|
126
140
|
MERGE_STRATEGY="merge"
|
|
127
141
|
DELETE_BRANCH=true
|
|
128
|
-
MERGE_BACK="
|
|
142
|
+
MERGE_BACK="$GF_DEVELOP_BRANCH"
|
|
129
143
|
;;
|
|
130
144
|
esac
|
|
131
145
|
```
|
|
@@ -16,23 +16,21 @@ Create a pull request with proper target, title, and description based on branch
|
|
|
16
16
|
|
|
17
17
|
## EXECUTION SEQUENCE:
|
|
18
18
|
|
|
19
|
-
### 1. Detect
|
|
19
|
+
### 1. Load Config and Detect Provider
|
|
20
20
|
|
|
21
21
|
```bash
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
[[ "$
|
|
22
|
+
# Load GitFlow config (sets GF_* variables)
|
|
23
|
+
read_gitflow_config || { echo "❌ Run /gitflow init first."; exit 1; }
|
|
24
|
+
|
|
25
|
+
GIT_PROVIDER="$GF_PROVIDER"
|
|
26
|
+
|
|
27
|
+
# Extract Azure DevOps details if needed
|
|
28
|
+
if [ "$GIT_PROVIDER" = "azuredevops" ]; then
|
|
29
|
+
[[ "$GF_REMOTE_URL" =~ dev\.azure\.com/([^/]+)/([^/]+)/_git/([^/]+) ]] && {
|
|
30
30
|
AZURE_ORG="${BASH_REMATCH[1]}"
|
|
31
31
|
AZURE_PROJECT="${BASH_REMATCH[2]}"
|
|
32
32
|
AZURE_REPO="${BASH_REMATCH[3]}"
|
|
33
33
|
}
|
|
34
|
-
else
|
|
35
|
-
GIT_PROVIDER="unknown"
|
|
36
34
|
fi
|
|
37
35
|
```
|
|
38
36
|
|
|
@@ -42,10 +40,10 @@ fi
|
|
|
42
40
|
CURRENT=$(git rev-parse --abbrev-ref HEAD)
|
|
43
41
|
|
|
44
42
|
case "$CURRENT" in
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
*)
|
|
43
|
+
${GF_FEATURE_PREFIX}*) TARGET_BRANCH="$GF_DEVELOP_BRANCH" ;;
|
|
44
|
+
${GF_RELEASE_PREFIX}*) TARGET_BRANCH="$GF_MAIN_BRANCH" ;;
|
|
45
|
+
${GF_HOTFIX_PREFIX}*) TARGET_BRANCH="$GF_MAIN_BRANCH" ;;
|
|
46
|
+
*) TARGET_BRANCH="$GF_DEVELOP_BRANCH" ;;
|
|
49
47
|
esac
|
|
50
48
|
```
|
|
51
49
|
|
|
@@ -90,16 +88,26 @@ EXISTING_PR=$(gh pr list --head "$CURRENT" --json number --jq '.[0].number' 2>/d
|
|
|
90
88
|
### 4. Run Pre-PR Checks
|
|
91
89
|
|
|
92
90
|
```bash
|
|
93
|
-
# Build check
|
|
91
|
+
# Build check (multi-runtime detection)
|
|
94
92
|
echo "Running build check..."
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
# Migration check
|
|
101
|
-
echo "Checking migrations..."
|
|
102
|
-
dotnet ef migrations list 2>&1 || echo "No migrations or EF Core not configured"
|
|
93
|
+
if [ -f "*.sln" ] || ls *.csproj 2>/dev/null | head -1 > /dev/null; then
|
|
94
|
+
dotnet build --no-restore 2>&1 || {
|
|
95
|
+
echo "❌ .NET build failed. Fix before creating PR."
|
|
96
|
+
STOP
|
|
97
|
+
}
|
|
98
|
+
# Migration check
|
|
99
|
+
echo "Checking migrations..."
|
|
100
|
+
dotnet ef migrations list 2>&1 || echo "No migrations or EF Core not configured"
|
|
101
|
+
elif [ -f "package.json" ]; then
|
|
102
|
+
npm run build 2>&1 || {
|
|
103
|
+
echo "❌ npm build failed. Fix before creating PR."
|
|
104
|
+
STOP
|
|
105
|
+
}
|
|
106
|
+
elif [ -f "requirements.txt" ] || [ -f "pyproject.toml" ]; then
|
|
107
|
+
echo "Python project detected — skipping build check"
|
|
108
|
+
else
|
|
109
|
+
echo "⚠️ No known build system detected — skipping build check"
|
|
110
|
+
fi
|
|
103
111
|
```
|
|
104
112
|
|
|
105
113
|
### 5. Generate PR Content
|
|
@@ -112,7 +120,7 @@ BRANCH_TYPE=$(echo $CURRENT | cut -d'/' -f1)
|
|
|
112
120
|
case "$BRANCH_TYPE" in
|
|
113
121
|
feature) TITLE="feat: $BRANCH_NAME" ;;
|
|
114
122
|
hotfix) TITLE="fix: $BRANCH_NAME" ;;
|
|
115
|
-
release) TITLE="release: v$
|
|
123
|
+
release) TITLE="release: v$GF_VERSION" ;;
|
|
116
124
|
esac
|
|
117
125
|
```
|
|
118
126
|
|
|
@@ -187,13 +195,19 @@ fi
|
|
|
187
195
|
### 8. Store PR Info
|
|
188
196
|
|
|
189
197
|
```bash
|
|
190
|
-
#
|
|
198
|
+
# Persist PR info for merge step (uses config path for portability)
|
|
199
|
+
CONFIG_DIR=$(dirname "$GF_CONFIG_FILE")
|
|
200
|
+
cat > "$CONFIG_DIR/cache/pr-state.json" << EOF
|
|
191
201
|
{
|
|
192
|
-
"pr_number": $PR_NUMBER,
|
|
202
|
+
"pr_number": "$PR_NUMBER",
|
|
193
203
|
"pr_url": "$PR_URL",
|
|
204
|
+
"source_branch": "$CURRENT",
|
|
194
205
|
"target_branch": "$TARGET_BRANCH",
|
|
195
|
-
"git_provider": "$GIT_PROVIDER"
|
|
206
|
+
"git_provider": "$GIT_PROVIDER",
|
|
207
|
+
"created_at": "$(date -u +%Y-%m-%dT%H:%M:%SZ)"
|
|
196
208
|
}
|
|
209
|
+
EOF
|
|
210
|
+
echo "✓ PR state saved to $CONFIG_DIR/cache/pr-state.json"
|
|
197
211
|
```
|
|
198
212
|
|
|
199
213
|
### 9. Summary
|
|
@@ -31,18 +31,22 @@ Create a new feature/release/hotfix branch with optional worktree setup.
|
|
|
31
31
|
|
|
32
32
|
## EXECUTION SEQUENCE:
|
|
33
33
|
|
|
34
|
-
### 1. Analyze Context
|
|
34
|
+
### 1. Load Config and Analyze Context
|
|
35
35
|
|
|
36
36
|
```bash
|
|
37
|
+
# Load GitFlow config (sets GF_* variables)
|
|
38
|
+
# See _shared.md → READ_GITFLOW_CONFIG for all variables
|
|
39
|
+
read_gitflow_config || { echo "❌ Run /gitflow init first."; exit 1; }
|
|
40
|
+
|
|
37
41
|
CURRENT_BRANCH=$(git branch --show-current)
|
|
38
42
|
git fetch origin --quiet
|
|
39
43
|
|
|
40
|
-
# Version
|
|
41
|
-
VERSION
|
|
44
|
+
# Version from config
|
|
45
|
+
VERSION="$GF_VERSION"
|
|
42
46
|
LAST_TAG=$(git describe --tags --abbrev=0 2>/dev/null || echo "none")
|
|
43
47
|
|
|
44
48
|
# Develop ahead of main?
|
|
45
|
-
DEVELOP_AHEAD=$(git rev-list --count origin
|
|
49
|
+
DEVELOP_AHEAD=$(git rev-list --count origin/$GF_MAIN_BRANCH..origin/$GF_DEVELOP_BRANCH 2>/dev/null || echo "0")
|
|
46
50
|
|
|
47
51
|
# Working directory status
|
|
48
52
|
DIRTY=$(git status --porcelain | wc -l)
|
|
@@ -129,17 +133,17 @@ esac
|
|
|
129
133
|
|
|
130
134
|
### 6. Create Branch and Worktree
|
|
131
135
|
|
|
132
|
-
**Read worktree mode from config:**
|
|
136
|
+
**Read worktree mode from config (already loaded by read_gitflow_config):**
|
|
133
137
|
```bash
|
|
134
|
-
WORKTREE_MODE
|
|
138
|
+
WORKTREE_MODE="$GF_WORKTREE_MODE"
|
|
135
139
|
```
|
|
136
140
|
|
|
137
|
-
**Mode: organized**
|
|
141
|
+
**Mode: organized (uses absolute paths from config)**
|
|
138
142
|
```bash
|
|
139
143
|
case "$branch_type" in
|
|
140
|
-
feature) WORKTREE_PATH="
|
|
141
|
-
release) WORKTREE_PATH="
|
|
142
|
-
hotfix) WORKTREE_PATH="
|
|
144
|
+
feature) WORKTREE_PATH="$GF_FEATURES_PATH/$BRANCH_NAME" ;;
|
|
145
|
+
release) WORKTREE_PATH="$GF_RELEASES_PATH/v$VERSION" ;;
|
|
146
|
+
hotfix) WORKTREE_PATH="$GF_HOTFIXES_PATH/$BRANCH_NAME" ;;
|
|
143
147
|
esac
|
|
144
148
|
|
|
145
149
|
mkdir -p "$(dirname $WORKTREE_PATH)"
|
|
@@ -181,13 +185,15 @@ API_DIR=$(find "$WORKTREE_PATH" -type d -name "*.Api" -path "*/src/*" | head -1)
|
|
|
181
185
|
WEB_DIR=$(find "$WORKTREE_PATH" -type d -name "*-web" -path "*/web/*" | head -1)
|
|
182
186
|
|
|
183
187
|
# Generate unique ports based on branch name hash (to avoid conflicts between worktrees)
|
|
184
|
-
|
|
188
|
+
# Use shasum (portable across macOS/Linux/Windows Git Bash) with md5sum fallback
|
|
189
|
+
HASH=$(echo "$BRANCH_NAME" | shasum 2>/dev/null || echo "$BRANCH_NAME" | md5sum 2>/dev/null || echo "$BRANCH_NAME" | cksum)
|
|
190
|
+
HASH=$(echo "$HASH" | cut -c1-4)
|
|
185
191
|
HASH_NUM=$((16#$HASH % 100))
|
|
186
192
|
API_PORT=$((5200 + HASH_NUM))
|
|
187
193
|
WEB_PORT=$((5300 + HASH_NUM))
|
|
188
194
|
|
|
189
|
-
# Project
|
|
190
|
-
PROJECT_NAME=$(
|
|
195
|
+
# Project name from config (not from pwd)
|
|
196
|
+
PROJECT_NAME=$(echo "$GF_PROJECT_NAME" | tr '[:upper:]' '[:lower:]')
|
|
191
197
|
DB_NAME=$(echo "${PROJECT_NAME}_${branch_type}_${BRANCH_NAME}" | cut -c1-63)
|
|
192
198
|
```
|
|
193
199
|
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
"version": "2.0.0",
|
|
3
3
|
"repository": {
|
|
4
4
|
"name": "",
|
|
5
|
+
"rootFolder": "",
|
|
5
6
|
"nameVariants": {
|
|
6
7
|
"pascalCaseDot": "",
|
|
7
8
|
"pascalCase": "",
|
|
@@ -13,7 +14,7 @@
|
|
|
13
14
|
"remoteUrl": ""
|
|
14
15
|
},
|
|
15
16
|
"git": {
|
|
16
|
-
"provider": "
|
|
17
|
+
"provider": "",
|
|
17
18
|
"branches": {
|
|
18
19
|
"main": "main",
|
|
19
20
|
"develop": "develop"
|
|
@@ -28,9 +29,11 @@
|
|
|
28
29
|
"enabled": true,
|
|
29
30
|
"mode": "organized",
|
|
30
31
|
"structure": {
|
|
31
|
-
"
|
|
32
|
-
"
|
|
33
|
-
"
|
|
32
|
+
"main": "",
|
|
33
|
+
"develop": "",
|
|
34
|
+
"features": "",
|
|
35
|
+
"releases": "",
|
|
36
|
+
"hotfixes": ""
|
|
34
37
|
}
|
|
35
38
|
},
|
|
36
39
|
"versioning": {
|
|
@@ -111,7 +111,7 @@ The loop only stops when this exact tag is output or max iterations reached.
|
|
|
111
111
|
1. Parse flags and task description
|
|
112
112
|
2. Verify MCP servers are available (MANDATORY)
|
|
113
113
|
3. Initialize .ralph/ structure and state files
|
|
114
|
-
4. Load current task from prd.json (or create initial
|
|
114
|
+
4. Load current task from prd.json (or create initial task breakdown with categories, dependencies, and acceptance criteria)
|
|
115
115
|
5. Execute ONE task per iteration
|
|
116
116
|
6. Commit changes, update progress
|
|
117
117
|
7. Check completion criteria
|
|
@@ -131,6 +131,10 @@ The loop only stops when this exact tag is output or max iterations reached.
|
|
|
131
131
|
| `{current_iteration}` | number | Current iteration count |
|
|
132
132
|
| `{tasks_completed}` | number | Number of tasks completed |
|
|
133
133
|
| `{tasks_total}` | number | Total tasks in prd.json |
|
|
134
|
+
| `{task_status}` | string | Current task status (pending/in_progress/completed/failed/skipped/blocked) |
|
|
135
|
+
| `{task_category}` | string | Task category (domain/application/infrastructure/api/frontend/i18n/test/validation) |
|
|
136
|
+
| `{files_created}` | string[] | Files created during current task |
|
|
137
|
+
| `{files_modified}` | string[] | Files modified during current task |
|
|
134
138
|
|
|
135
139
|
</state_variables>
|
|
136
140
|
|
|
@@ -190,19 +194,58 @@ Before ANY work, verify MCP servers:
|
|
|
190
194
|
**prd.json structure:**
|
|
191
195
|
```json
|
|
192
196
|
{
|
|
197
|
+
"$version": "2.0.0",
|
|
193
198
|
"feature": "{task_description}",
|
|
194
|
-
"
|
|
195
|
-
"
|
|
196
|
-
"
|
|
197
|
-
"
|
|
199
|
+
"status": "in_progress",
|
|
200
|
+
"created": "2026-01-30T15:00:00.000Z",
|
|
201
|
+
"updated_at": "2026-01-30T16:30:00.000Z",
|
|
202
|
+
"metadata": {
|
|
203
|
+
"cli_version": "1.36.0",
|
|
204
|
+
"branch": "feature/user-auth",
|
|
205
|
+
"project_path": "/path/to/project",
|
|
206
|
+
"mcp_servers": { "smartstack": true, "context7": true }
|
|
207
|
+
},
|
|
208
|
+
"config": {
|
|
209
|
+
"max_iterations": 50,
|
|
210
|
+
"completion_promise": "COMPLETE",
|
|
211
|
+
"current_iteration": 1
|
|
212
|
+
},
|
|
213
|
+
"source": {
|
|
214
|
+
"type": "ba-handoff",
|
|
215
|
+
"handoff_path": "path/to/4-development-handoff.md",
|
|
216
|
+
"frd_path": null,
|
|
217
|
+
"brd_path": null
|
|
218
|
+
},
|
|
198
219
|
"tasks": [
|
|
199
|
-
{
|
|
200
|
-
|
|
201
|
-
|
|
220
|
+
{
|
|
221
|
+
"id": 1,
|
|
222
|
+
"description": "Create User entity in Domain layer",
|
|
223
|
+
"status": "pending",
|
|
224
|
+
"category": "domain",
|
|
225
|
+
"dependencies": [],
|
|
226
|
+
"acceptance_criteria": "Entity compiles, properties match handoff spec",
|
|
227
|
+
"started_at": null,
|
|
228
|
+
"completed_at": null,
|
|
229
|
+
"iteration": null,
|
|
230
|
+
"commit_hash": null,
|
|
231
|
+
"files_changed": { "created": [], "modified": [] },
|
|
232
|
+
"validation": null,
|
|
233
|
+
"error": null
|
|
234
|
+
}
|
|
235
|
+
],
|
|
236
|
+
"history": []
|
|
202
237
|
}
|
|
203
238
|
```
|
|
204
239
|
|
|
205
|
-
>
|
|
240
|
+
> **Schema v2 notes:**
|
|
241
|
+
> - `$version`: Schema version for forward migration
|
|
242
|
+
> - `status` (top-level): `pending` | `in_progress` | `completed` | `failed` | `partial`
|
|
243
|
+
> - `source.type`: `ba-handoff` | `direct` | `feature-full` — `null` when tasks are created directly by Ralph Loop
|
|
244
|
+
> - `task.status`: `pending` | `in_progress` | `completed` | `failed` | `skipped` | `blocked`
|
|
245
|
+
> - `task.category`: `domain` | `application` | `infrastructure` | `api` | `frontend` | `i18n` | `test` | `validation` | `other`
|
|
246
|
+
> - `task.dependencies`: Array of task IDs that must be `completed` before this task can start
|
|
247
|
+
> - `history`: Structured iteration journal (replaces unstructured progress.txt for traceability)
|
|
248
|
+
> - **Backward compatibility**: step-00 auto-migrates v1 prd.json (with `passes` boolean) to v2 format
|
|
206
249
|
</file_structure>
|
|
207
250
|
|
|
208
251
|
<execution_rules>
|
|
@@ -217,11 +260,14 @@ Before ANY work, verify MCP servers:
|
|
|
217
260
|
|
|
218
261
|
<success_criteria>
|
|
219
262
|
|
|
220
|
-
- All tasks in prd.json have `
|
|
263
|
+
- All tasks in prd.json have `status: "completed"` (or `"skipped"`)
|
|
264
|
+
- No tasks with `status: "blocked"` remain
|
|
221
265
|
- MCP validations pass
|
|
222
|
-
- Git commits atomic per task
|
|
266
|
+
- Git commits atomic per task with `commit_hash` tracked
|
|
267
|
+
- `history[]` contains entry for every completed task
|
|
223
268
|
- Completion promise output when genuinely complete
|
|
224
269
|
- Final report generated in `.ralph/reports/`
|
|
270
|
+
- `prd.json` top-level `status` set to `"completed"` or `"partial"`
|
|
225
271
|
</success_criteria>
|
|
226
272
|
|
|
227
273
|
<available_commands>
|