@atlashub/smartstack-cli 2.9.0 → 3.1.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/.documentation/agents.html +1 -371
- package/.documentation/business-analyse.html +81 -17
- package/.documentation/cli-commands.html +1 -1
- package/.documentation/commands.html +1 -1
- package/.documentation/efcore.html +1 -1
- package/.documentation/gitflow.html +1 -1
- package/.documentation/hooks.html +27 -66
- package/.documentation/index.html +166 -166
- package/.documentation/init.html +6 -7
- package/.documentation/installation.html +1 -1
- package/.documentation/ralph-loop.html +1 -9
- package/.documentation/test-web.html +15 -39
- package/dist/index.js +23 -16
- package/dist/index.js.map +1 -1
- package/dist/mcp-entry.mjs +1302 -223
- package/dist/mcp-entry.mjs.map +1 -1
- package/package.json +1 -1
- package/templates/agents/efcore/db-deploy.md +1 -1
- package/templates/agents/efcore/migration.md +26 -10
- package/templates/agents/efcore/rebase-snapshot.md +24 -7
- package/templates/agents/efcore/squash.md +73 -57
- package/templates/agents/gitflow/commit.md +138 -18
- package/templates/agents/gitflow/exec.md +1 -1
- package/templates/agents/gitflow/finish.md +79 -62
- package/templates/agents/gitflow/init-clone.md +186 -0
- package/templates/agents/gitflow/init-detect.md +137 -0
- package/templates/agents/gitflow/init-validate.md +210 -0
- package/templates/agents/gitflow/init.md +231 -74
- package/templates/agents/gitflow/merge.md +115 -33
- package/templates/agents/gitflow/pr.md +151 -46
- package/templates/agents/gitflow/start.md +76 -33
- package/templates/agents/gitflow/status.md +41 -71
- package/templates/hooks/appsettings-guard.sh +76 -0
- package/templates/hooks/ef-migration-check.md +1 -1
- package/templates/hooks/hooks.json +9 -0
- package/templates/project/appsettings.json.template +8 -2
- package/templates/project/test-frontend/msw/handlers.ts +58 -0
- package/templates/project/test-frontend/msw/server.ts +25 -0
- package/templates/project/test-frontend/setup.ts +16 -0
- package/templates/project/test-frontend/test-utils.tsx +59 -0
- package/templates/project/test-frontend/vitest.config.ts +31 -0
- package/templates/skills/_resources/config-safety.md +61 -0
- package/templates/skills/_resources/formatting-guide.md +2 -2
- package/templates/skills/application/SKILL.md +12 -3
- package/templates/skills/application/steps/step-04-backend.md +21 -0
- package/templates/skills/application/steps/step-07-tests.md +259 -120
- package/templates/skills/business-analyse/SKILL.md +57 -28
- package/templates/skills/business-analyse/_shared.md +70 -39
- package/templates/skills/business-analyse/html/ba-interactive.html +2596 -0
- package/templates/skills/business-analyse/questionnaire/00-application.md +123 -131
- package/templates/skills/business-analyse/questionnaire/01-context.md +173 -24
- package/templates/skills/business-analyse/questionnaire/02-stakeholders.md +170 -50
- package/templates/skills/business-analyse/questionnaire/03-scope.md +154 -48
- package/templates/skills/business-analyse/questionnaire/10-documentation.md +1 -1
- package/templates/skills/business-analyse/questionnaire/14-risk-assumptions.md +135 -0
- package/templates/skills/business-analyse/questionnaire/15-success-metrics.md +136 -0
- package/templates/skills/business-analyse/questionnaire.md +55 -46
- package/templates/skills/business-analyse/steps/step-00-init.md +24 -2
- package/templates/skills/business-analyse/steps/step-01-cadrage.md +31 -20
- package/templates/skills/business-analyse/steps/step-03-specify.md +58 -0
- package/templates/skills/business-analyse/steps/step-05-handoff.md +301 -1
- package/templates/skills/business-analyse/steps/step-06-extract.md +518 -0
- package/templates/skills/check-version/SKILL.md +1 -1
- package/templates/skills/efcore/steps/db/step-deploy.md +22 -3
- package/templates/skills/efcore/steps/db/step-reset.md +27 -4
- package/templates/skills/efcore/steps/db/step-seed.md +46 -2
- package/templates/skills/efcore/steps/db/step-status.md +14 -0
- package/templates/skills/efcore/steps/migration/step-01-check.md +31 -5
- package/templates/skills/efcore/steps/migration/step-02-create.md +20 -4
- package/templates/skills/efcore/steps/rebase-snapshot/step-03-create.md +60 -0
- package/templates/skills/efcore/steps/shared/step-00-init.md +47 -8
- package/templates/skills/efcore/steps/squash/step-03-create.md +27 -5
- package/templates/skills/gitflow/SKILL.md +91 -29
- package/templates/skills/gitflow/_shared.md +144 -2
- package/templates/skills/gitflow/phases/status.md +11 -1
- package/templates/skills/gitflow/steps/step-commit.md +1 -1
- package/templates/skills/gitflow/steps/step-init.md +202 -39
- package/templates/skills/gitflow/steps/step-pr.md +17 -5
- package/templates/skills/gitflow/templates/config.json +10 -1
- package/templates/skills/ralph-loop/SKILL.md +22 -15
- package/templates/skills/ralph-loop/steps/step-01-task.md +89 -4
- package/templates/skills/ralph-loop/steps/step-02-execute.md +408 -23
- package/templates/skills/ralph-loop/steps/step-03-commit.md +84 -2
- package/templates/skills/ralph-loop/steps/step-04-check.md +235 -6
- package/templates/skills/ralph-loop/steps/step-05-report.md +115 -0
- package/templates/skills/validate-feature/SKILL.md +83 -0
- package/templates/skills/validate-feature/steps/step-01-compile.md +38 -0
- package/templates/skills/validate-feature/steps/step-02-unit-tests.md +45 -0
- package/templates/skills/validate-feature/steps/step-03-integration-tests.md +53 -0
- package/templates/skills/validate-feature/steps/step-04-api-smoke.md +157 -0
|
@@ -4,6 +4,95 @@
|
|
|
4
4
|
|
|
5
5
|
---
|
|
6
6
|
|
|
7
|
+
## DETECT_PLATFORM
|
|
8
|
+
|
|
9
|
+
Detects the current platform (WSL, Windows, macOS, Linux) and shell environment.
|
|
10
|
+
Must be called before any path operations.
|
|
11
|
+
|
|
12
|
+
```bash
|
|
13
|
+
detect_platform() {
|
|
14
|
+
# WSL detection (highest priority - WSL reports as Linux but needs path translation)
|
|
15
|
+
if [ -f /proc/version ] && grep -qi "microsoft\|wsl" /proc/version 2>/dev/null; then
|
|
16
|
+
GF_PLATFORM="wsl"
|
|
17
|
+
GF_SHELL="bash"
|
|
18
|
+
elif [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "mingw"* ]] || [[ "$OSTYPE" == "cygwin" ]]; then
|
|
19
|
+
GF_PLATFORM="windows"
|
|
20
|
+
GF_SHELL="gitbash"
|
|
21
|
+
elif [[ -n "$WINDIR" ]] || [[ -n "$SystemRoot" ]]; then
|
|
22
|
+
GF_PLATFORM="windows"
|
|
23
|
+
GF_SHELL="powershell"
|
|
24
|
+
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
|
25
|
+
GF_PLATFORM="macos"
|
|
26
|
+
GF_SHELL="zsh"
|
|
27
|
+
elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
|
28
|
+
GF_PLATFORM="linux"
|
|
29
|
+
GF_SHELL="bash"
|
|
30
|
+
else
|
|
31
|
+
GF_PLATFORM="unknown"
|
|
32
|
+
GF_SHELL="bash"
|
|
33
|
+
fi
|
|
34
|
+
}
|
|
35
|
+
```
|
|
36
|
+
|
|
37
|
+
---
|
|
38
|
+
|
|
39
|
+
## NORMALIZE_PATH
|
|
40
|
+
|
|
41
|
+
Path translation functions for cross-platform compatibility (Windows ↔ WSL ↔ POSIX).
|
|
42
|
+
|
|
43
|
+
```bash
|
|
44
|
+
# Translates a path to the format expected by the CURRENT platform
|
|
45
|
+
normalize_path_for_platform() {
|
|
46
|
+
local input_path="$1"
|
|
47
|
+
case "$GF_PLATFORM" in
|
|
48
|
+
wsl)
|
|
49
|
+
# Windows path → WSL path: D:\foo\bar or D:/foo/bar → /mnt/d/foo/bar
|
|
50
|
+
if [[ "$input_path" =~ ^[A-Za-z]:[\\/] ]]; then
|
|
51
|
+
local drive=$(echo "${input_path:0:1}" | tr '[:upper:]' '[:lower:]')
|
|
52
|
+
local rest="${input_path:2}"
|
|
53
|
+
rest="${rest//\\//}"
|
|
54
|
+
echo "/mnt/$drive$rest"
|
|
55
|
+
else
|
|
56
|
+
echo "$input_path"
|
|
57
|
+
fi
|
|
58
|
+
;;
|
|
59
|
+
*)
|
|
60
|
+
# Normalize backslashes to forward slashes
|
|
61
|
+
echo "${input_path//\\//}"
|
|
62
|
+
;;
|
|
63
|
+
esac
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
# Translates a path to storage-neutral format for config.json (forward slashes, drive letter)
|
|
67
|
+
normalize_path_for_storage() {
|
|
68
|
+
local input_path="$1"
|
|
69
|
+
case "$GF_PLATFORM" in
|
|
70
|
+
wsl)
|
|
71
|
+
# WSL path → Windows-style for config: /mnt/d/foo/bar → D:/foo/bar
|
|
72
|
+
if [[ "$input_path" =~ ^/mnt/([a-z])/(.*) ]]; then
|
|
73
|
+
local drive=$(echo "${BASH_REMATCH[1]}" | tr '[:lower:]' '[:upper:]')
|
|
74
|
+
echo "${drive}:/${BASH_REMATCH[2]}"
|
|
75
|
+
else
|
|
76
|
+
echo "$input_path"
|
|
77
|
+
fi
|
|
78
|
+
;;
|
|
79
|
+
*)
|
|
80
|
+
# Normalize backslashes to forward slashes
|
|
81
|
+
echo "${input_path//\\//}"
|
|
82
|
+
;;
|
|
83
|
+
esac
|
|
84
|
+
}
|
|
85
|
+
|
|
86
|
+
# Returns current directory in platform-appropriate format
|
|
87
|
+
get_current_dir() {
|
|
88
|
+
local raw_pwd
|
|
89
|
+
raw_pwd="$(pwd)"
|
|
90
|
+
normalize_path_for_platform "$raw_pwd"
|
|
91
|
+
}
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
7
96
|
## DETECT_PROVIDER
|
|
8
97
|
|
|
9
98
|
Detects GitHub or Azure DevOps from remote URL.
|
|
@@ -83,12 +172,18 @@ Reads GitFlow configuration from config.json. Exposes all variables needed by st
|
|
|
83
172
|
|
|
84
173
|
```bash
|
|
85
174
|
read_gitflow_config() {
|
|
175
|
+
# Detect platform first (needed for path translation)
|
|
176
|
+
detect_platform
|
|
177
|
+
|
|
86
178
|
local CONFIG_FILE
|
|
87
179
|
CONFIG_FILE=$(resolve_gitflow_config_path) || {
|
|
88
180
|
echo "❌ GitFlow config not found. Run /gitflow init first."
|
|
89
181
|
return 1
|
|
90
182
|
}
|
|
91
183
|
|
|
184
|
+
# Config version
|
|
185
|
+
GF_CONFIG_VERSION=$(grep -oP '"version":\s*"\K[^"]+' "$CONFIG_FILE" | head -1)
|
|
186
|
+
|
|
92
187
|
# Repository
|
|
93
188
|
GF_PROJECT_NAME=$(grep -oP '"name":\s*"\K[^"]+' "$CONFIG_FILE" | head -1)
|
|
94
189
|
GF_ROOT_FOLDER=$(grep -oP '"rootFolder":\s*"\K[^"]+' "$CONFIG_FILE" | head -1)
|
|
@@ -119,6 +214,14 @@ read_gitflow_config() {
|
|
|
119
214
|
GF_VERSION=$(grep -oP '"current":\s*"\K[^"]+' "$CONFIG_FILE" | head -1)
|
|
120
215
|
GF_TAG_PREFIX=$(grep -oP '"tagPrefix":\s*"\K[^"]+' "$CONFIG_FILE" | head -1)
|
|
121
216
|
|
|
217
|
+
# Platform (v2.1.0+, optional)
|
|
218
|
+
GF_CONFIG_PLATFORM=$(grep -oP '"detected":\s*"\K[^"]+' "$CONFIG_FILE" | head -1)
|
|
219
|
+
GF_CONFIG_PLATFORM=${GF_CONFIG_PLATFORM:-$GF_PLATFORM}
|
|
220
|
+
|
|
221
|
+
# Workspace (v2.1.0+, optional)
|
|
222
|
+
GF_WORKSPACE_PATH=$(grep -A1 '"workspace"' "$CONFIG_FILE" | grep -oP '"path":\s*"\K[^"]+' | head -1)
|
|
223
|
+
GF_WORKSPACE_NAME=$(grep -A2 '"workspace"' "$CONFIG_FILE" | grep -oP '"name":\s*"\K[^"]+' | head -1)
|
|
224
|
+
|
|
122
225
|
# Defaults for missing values
|
|
123
226
|
GF_LANG=${GF_LANG:-en}
|
|
124
227
|
GF_WORKTREE_MODE=${GF_WORKTREE_MODE:-organized}
|
|
@@ -130,6 +233,16 @@ read_gitflow_config() {
|
|
|
130
233
|
GF_TAG_PREFIX=${GF_TAG_PREFIX:-v}
|
|
131
234
|
GF_VERSION=${GF_VERSION:-0.1.0}
|
|
132
235
|
|
|
236
|
+
# Translate all stored paths to current platform format
|
|
237
|
+
# This ensures WSL paths are /mnt/d/... and Windows paths use forward slashes
|
|
238
|
+
GF_ROOT_FOLDER=$(normalize_path_for_platform "$GF_ROOT_FOLDER")
|
|
239
|
+
GF_MAIN_PATH=$(normalize_path_for_platform "$GF_MAIN_PATH")
|
|
240
|
+
GF_DEVELOP_PATH=$(normalize_path_for_platform "$GF_DEVELOP_PATH")
|
|
241
|
+
GF_FEATURES_PATH=$(normalize_path_for_platform "$GF_FEATURES_PATH")
|
|
242
|
+
GF_RELEASES_PATH=$(normalize_path_for_platform "$GF_RELEASES_PATH")
|
|
243
|
+
GF_HOTFIXES_PATH=$(normalize_path_for_platform "$GF_HOTFIXES_PATH")
|
|
244
|
+
[ -n "$GF_WORKSPACE_PATH" ] && GF_WORKSPACE_PATH=$(normalize_path_for_platform "$GF_WORKSPACE_PATH")
|
|
245
|
+
|
|
133
246
|
# Export config file path for steps that need to update it
|
|
134
247
|
GF_CONFIG_FILE="$CONFIG_FILE"
|
|
135
248
|
}
|
|
@@ -201,6 +314,26 @@ cleanup_worktree_for_branch() {
|
|
|
201
314
|
|
|
202
315
|
---
|
|
203
316
|
|
|
317
|
+
## RESOLVE_WORKSPACE
|
|
318
|
+
|
|
319
|
+
Resolves the workspace JSON file by walking up the directory tree.
|
|
320
|
+
|
|
321
|
+
```bash
|
|
322
|
+
resolve_workspace_path() {
|
|
323
|
+
local dir="$(pwd)"
|
|
324
|
+
while [ "$dir" != "/" ] && [ "$dir" != "." ]; do
|
|
325
|
+
[ -f "$dir/.smartstack-workspace.json" ] && {
|
|
326
|
+
echo "$dir/.smartstack-workspace.json"
|
|
327
|
+
return 0
|
|
328
|
+
}
|
|
329
|
+
dir=$(dirname "$dir")
|
|
330
|
+
done
|
|
331
|
+
return 1
|
|
332
|
+
}
|
|
333
|
+
```
|
|
334
|
+
|
|
335
|
+
---
|
|
336
|
+
|
|
204
337
|
## SYNC_REMOTE
|
|
205
338
|
|
|
206
339
|
Syncs with remote and displays status.
|
|
@@ -221,11 +354,20 @@ sync_with_remote() {
|
|
|
221
354
|
|
|
222
355
|
## CONFIG_TEMPLATE
|
|
223
356
|
|
|
224
|
-
GitFlow configuration JSON template v2.
|
|
357
|
+
GitFlow configuration JSON template v2.1.0 (aligned with `templates/config.json`).
|
|
225
358
|
|
|
226
359
|
```json
|
|
227
360
|
{
|
|
228
|
-
"version": "2.
|
|
361
|
+
"version": "2.1.0",
|
|
362
|
+
"platform": {
|
|
363
|
+
"detected": "",
|
|
364
|
+
"shell": "",
|
|
365
|
+
"detectedAt": ""
|
|
366
|
+
},
|
|
367
|
+
"workspace": {
|
|
368
|
+
"path": "",
|
|
369
|
+
"name": ""
|
|
370
|
+
},
|
|
229
371
|
"repository": {
|
|
230
372
|
"name": "",
|
|
231
373
|
"rootFolder": "",
|
|
@@ -16,12 +16,18 @@ Display complete GitFlow state including branches, worktrees, remotes, and pendi
|
|
|
16
16
|
### 1. Load Config and Repository Info
|
|
17
17
|
|
|
18
18
|
```bash
|
|
19
|
-
#
|
|
19
|
+
# Detect platform first (needed for path translation)
|
|
20
|
+
detect_platform
|
|
21
|
+
|
|
22
|
+
# Load GitFlow config (sets GF_* variables, translates paths for current platform)
|
|
20
23
|
read_gitflow_config || { echo "❌ Run /gitflow init first."; exit 1; }
|
|
21
24
|
|
|
22
25
|
REPO_NAME="$GF_PROJECT_NAME"
|
|
23
26
|
CURRENT=$(git rev-parse --abbrev-ref HEAD)
|
|
24
27
|
GIT_PROVIDER="$GF_PROVIDER"
|
|
28
|
+
|
|
29
|
+
# Workspace info (v2.1.0+)
|
|
30
|
+
WS_FILE=$(resolve_workspace_path 2>/dev/null)
|
|
25
31
|
```
|
|
26
32
|
|
|
27
33
|
### 2. Branch Status
|
|
@@ -99,7 +105,11 @@ fi
|
|
|
99
105
|
╠══════════════════════════════════════════════════════════════════╣
|
|
100
106
|
║ Repository: {REPO_NAME} ║
|
|
101
107
|
║ Provider: {GIT_PROVIDER} ║
|
|
108
|
+
║ Platform: {GF_PLATFORM} ({GF_SHELL}) ║
|
|
102
109
|
║ Current: {CURRENT} ║
|
|
110
|
+
{if WS_FILE}
|
|
111
|
+
║ Workspace: {dirname(WS_FILE)} ║
|
|
112
|
+
{endif}
|
|
103
113
|
╠══════════════════════════════════════════════════════════════════╣
|
|
104
114
|
|
|
105
115
|
## Main Branches
|
|
@@ -36,6 +36,22 @@ Set up GitFlow configuration with bare repository, worktrees, and branches.
|
|
|
36
36
|
### 1. Detect Environment (for defaults only)
|
|
37
37
|
|
|
38
38
|
```bash
|
|
39
|
+
# PLATFORM DETECTION (required for correct path handling on WSL/Windows/macOS/Linux)
|
|
40
|
+
if [ -f /proc/version ] && grep -qi "microsoft\|wsl" /proc/version 2>/dev/null; then
|
|
41
|
+
GF_PLATFORM="wsl"; GF_SHELL="bash"
|
|
42
|
+
elif [[ "$OSTYPE" == "msys" ]] || [[ "$OSTYPE" == "mingw"* ]] || [[ "$OSTYPE" == "cygwin" ]]; then
|
|
43
|
+
GF_PLATFORM="windows"; GF_SHELL="gitbash"
|
|
44
|
+
elif [[ -n "$WINDIR" ]] || [[ -n "$SystemRoot" ]]; then
|
|
45
|
+
GF_PLATFORM="windows"; GF_SHELL="powershell"
|
|
46
|
+
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
|
47
|
+
GF_PLATFORM="macos"; GF_SHELL="zsh"
|
|
48
|
+
elif [[ "$OSTYPE" == "linux-gnu"* ]]; then
|
|
49
|
+
GF_PLATFORM="linux"; GF_SHELL="bash"
|
|
50
|
+
else
|
|
51
|
+
GF_PLATFORM="unknown"; GF_SHELL="bash"
|
|
52
|
+
fi
|
|
53
|
+
echo "Platform: $GF_PLATFORM ($GF_SHELL)"
|
|
54
|
+
|
|
39
55
|
# Check if we're in a git repository
|
|
40
56
|
IS_GIT_REPO=$(git rev-parse --git-dir 2>/dev/null && echo "true" || echo "false")
|
|
41
57
|
|
|
@@ -405,54 +421,84 @@ AskUserQuestion:
|
|
|
405
421
|
|
|
406
422
|
### 8. Create Directory Structure
|
|
407
423
|
|
|
408
|
-
**⛔
|
|
424
|
+
**⛔ CRITICAL: Use ABSOLUTE PATHS for ALL operations. NEVER use `cd` (it does not persist between Bash calls).**
|
|
425
|
+
**⛔ Use `git -C <path>` or `GIT_DIR=<path>` instead of `cd` + `git`.**
|
|
409
426
|
|
|
427
|
+
**Path normalization for WSL:**
|
|
410
428
|
```bash
|
|
411
|
-
|
|
412
|
-
|
|
413
|
-
#
|
|
414
|
-
|
|
415
|
-
|
|
416
|
-
|
|
417
|
-
|
|
418
|
-
|
|
419
|
-
|
|
420
|
-
|
|
429
|
+
# If on WSL, translate Windows paths to /mnt/ format
|
|
430
|
+
# normalize_path_for_platform() from _shared.md handles this
|
|
431
|
+
# Example: D:/projects/MyApp → /mnt/d/projects/MyApp
|
|
432
|
+
PROJECT_BASE="{ROOT_FOLDER}" # Must be already normalized for current platform
|
|
433
|
+
```
|
|
434
|
+
|
|
435
|
+
**⛔ Create the COMPLETE structure with absolute paths:**
|
|
436
|
+
|
|
437
|
+
```bash
|
|
438
|
+
PROJECT_BASE="{ROOT_FOLDER}"
|
|
439
|
+
|
|
440
|
+
# Create subdirectories (absolute paths)
|
|
441
|
+
mkdir -p "$PROJECT_BASE/features" "$PROJECT_BASE/releases" "$PROJECT_BASE/hotfixes"
|
|
442
|
+
|
|
443
|
+
# Create bare repository if not exists (absolute path, no cd)
|
|
444
|
+
if [ ! -d "$PROJECT_BASE/.bare" ]; then
|
|
445
|
+
git clone --bare "{REPO_URL}" "$PROJECT_BASE/.bare"
|
|
446
|
+
|
|
447
|
+
# Configure bare repo for worktrees (using git -C, no cd)
|
|
448
|
+
git -C "$PROJECT_BASE/.bare" config core.bare false
|
|
449
|
+
git -C "$PROJECT_BASE/.bare" config core.worktree ..
|
|
421
450
|
fi
|
|
422
451
|
|
|
423
|
-
# Create
|
|
424
|
-
|
|
452
|
+
# Create .git pseudo-file pointing to .bare
|
|
453
|
+
echo "gitdir: ./.bare" > "$PROJECT_BASE/.git"
|
|
425
454
|
|
|
426
|
-
# Organized mode: numbered main folders
|
|
455
|
+
# Organized mode: numbered main folders (absolute paths, GIT_DIR instead of cd)
|
|
427
456
|
if [ "$WORKTREE_MODE" = "organized" ]; then
|
|
428
|
-
|
|
429
|
-
|
|
457
|
+
[ ! -d "$PROJECT_BASE/01-Main" ] && \
|
|
458
|
+
GIT_DIR="$PROJECT_BASE/.bare" git worktree add "$PROJECT_BASE/01-Main" main
|
|
430
459
|
|
|
431
|
-
|
|
432
|
-
|
|
460
|
+
[ ! -d "$PROJECT_BASE/02-Develop" ] && \
|
|
461
|
+
GIT_DIR="$PROJECT_BASE/.bare" git worktree add "$PROJECT_BASE/02-Develop" develop
|
|
433
462
|
fi
|
|
434
463
|
|
|
435
|
-
# Simple mode: named folders
|
|
464
|
+
# Simple mode: named folders (absolute paths)
|
|
436
465
|
if [ "$WORKTREE_MODE" = "simple" ]; then
|
|
437
|
-
[ ! -d "main" ] &&
|
|
438
|
-
|
|
466
|
+
[ ! -d "$PROJECT_BASE/main" ] && \
|
|
467
|
+
GIT_DIR="$PROJECT_BASE/.bare" git worktree add "$PROJECT_BASE/main" main
|
|
468
|
+
|
|
469
|
+
[ ! -d "$PROJECT_BASE/develop" ] && \
|
|
470
|
+
GIT_DIR="$PROJECT_BASE/.bare" git worktree add "$PROJECT_BASE/develop" develop
|
|
439
471
|
fi
|
|
440
472
|
|
|
441
|
-
# Create gitflow config directory (
|
|
442
|
-
|
|
443
|
-
mkdir -p "$
|
|
473
|
+
# Create gitflow config directory (absolute paths)
|
|
474
|
+
DEVELOP_DIR=$([ "$WORKTREE_MODE" = "organized" ] && echo "02-Develop" || echo "develop")
|
|
475
|
+
mkdir -p "$PROJECT_BASE/$DEVELOP_DIR/.claude/gitflow/plans"
|
|
476
|
+
mkdir -p "$PROJECT_BASE/$DEVELOP_DIR/.claude/gitflow/logs"
|
|
477
|
+
mkdir -p "$PROJECT_BASE/$DEVELOP_DIR/.claude/gitflow/cache"
|
|
478
|
+
mkdir -p "$PROJECT_BASE/$DEVELOP_DIR/.claude/gitflow/backup"
|
|
444
479
|
```
|
|
445
480
|
|
|
446
481
|
### 9. Create Configuration
|
|
447
482
|
|
|
448
|
-
**Write `.claude/gitflow/config.json` in develop worktree
|
|
483
|
+
**Write `.claude/gitflow/config.json` in develop worktree.**
|
|
484
|
+
|
|
485
|
+
**⛔ IMPORTANT: Store paths using `normalize_path_for_storage()` format (Windows-style: `D:/path/to/folder`).** The `read_gitflow_config()` in `_shared.md` translates them to platform format at read time. This ensures WSL and Windows can share the same config.
|
|
449
486
|
|
|
450
487
|
```json
|
|
451
488
|
{
|
|
452
|
-
"version": "2.
|
|
489
|
+
"version": "2.1.0",
|
|
490
|
+
"platform": {
|
|
491
|
+
"detected": "{GF_PLATFORM}",
|
|
492
|
+
"shell": "{GF_SHELL}",
|
|
493
|
+
"detectedAt": "{ISO_DATE}"
|
|
494
|
+
},
|
|
495
|
+
"workspace": {
|
|
496
|
+
"path": "{WORKSPACE_DIR_STORAGE_FORMAT}",
|
|
497
|
+
"name": ""
|
|
498
|
+
},
|
|
453
499
|
"repository": {
|
|
454
500
|
"name": "{PROJECT_NAME}",
|
|
455
|
-
"rootFolder": "{
|
|
501
|
+
"rootFolder": "{ROOT_FOLDER_STORAGE_FORMAT}",
|
|
456
502
|
"nameVariants": {
|
|
457
503
|
"pascalCaseDot": "{PascalCase.Dot}",
|
|
458
504
|
"pascalCase": "{PascalCase}",
|
|
@@ -479,11 +525,11 @@ mkdir -p "$DEVELOP_PATH/.claude/gitflow/{plans,logs,cache,backup}"
|
|
|
479
525
|
"enabled": true,
|
|
480
526
|
"mode": "{WORKTREE_MODE}",
|
|
481
527
|
"structure": {
|
|
482
|
-
"main": "{
|
|
483
|
-
"develop": "{
|
|
484
|
-
"features": "{
|
|
485
|
-
"releases": "{
|
|
486
|
-
"hotfixes": "{
|
|
528
|
+
"main": "{ROOT_FOLDER_STORAGE_FORMAT}/01-Main",
|
|
529
|
+
"develop": "{ROOT_FOLDER_STORAGE_FORMAT}/02-Develop",
|
|
530
|
+
"features": "{ROOT_FOLDER_STORAGE_FORMAT}/features",
|
|
531
|
+
"releases": "{ROOT_FOLDER_STORAGE_FORMAT}/releases",
|
|
532
|
+
"hotfixes": "{ROOT_FOLDER_STORAGE_FORMAT}/hotfixes"
|
|
487
533
|
}
|
|
488
534
|
},
|
|
489
535
|
"versioning": {
|
|
@@ -513,21 +559,60 @@ mkdir -p "$DEVELOP_PATH/.claude/gitflow/{plans,logs,cache,backup}"
|
|
|
513
559
|
}
|
|
514
560
|
```
|
|
515
561
|
|
|
562
|
+
**Path storage convention:**
|
|
563
|
+
- `{ROOT_FOLDER_STORAGE_FORMAT}` = result of `normalize_path_for_storage("{ROOT_FOLDER}")`
|
|
564
|
+
- On WSL: `/mnt/d/projects/MyApp` → stored as `D:/projects/MyApp`
|
|
565
|
+
- On Windows: `D:\projects\MyApp` → stored as `D:/projects/MyApp`
|
|
566
|
+
- On Linux/macOS: `/home/user/projects/MyApp` → stored as-is
|
|
567
|
+
|
|
516
568
|
### 10. Detect Version
|
|
517
569
|
|
|
570
|
+
**⛔ Use absolute paths with `git -C`, no `cd`.**
|
|
571
|
+
|
|
518
572
|
```bash
|
|
519
|
-
|
|
520
|
-
cd "$DEVELOP_PATH"
|
|
573
|
+
DEVELOP_FULL_PATH="$PROJECT_BASE/$DEVELOP_DIR"
|
|
521
574
|
|
|
522
575
|
# Priority: csproj > Directory.Build.props > package.json > VERSION > tag
|
|
523
|
-
VERSION=$(grep -oP '<Version>\K[^<]+'
|
|
524
|
-
[ -z "$VERSION" ] && VERSION=$(grep -oP '<Version>\K[^<]+' Directory.Build.props 2>/dev/null)
|
|
525
|
-
[ -z "$VERSION" ] && VERSION=$(grep -oP '"version":\s*"\K[^"]+' package.json 2>/dev/null)
|
|
526
|
-
[ -z "$VERSION" ] && VERSION=$(cat VERSION 2>/dev/null)
|
|
527
|
-
[ -z "$VERSION" ] && VERSION=$(git describe --tags --abbrev=0 2>/dev/null | sed 's/^v//')
|
|
576
|
+
VERSION=$(grep -oP '<Version>\K[^<]+' "$DEVELOP_FULL_PATH"/*.csproj 2>/dev/null | head -1)
|
|
577
|
+
[ -z "$VERSION" ] && VERSION=$(grep -oP '<Version>\K[^<]+' "$DEVELOP_FULL_PATH/Directory.Build.props" 2>/dev/null)
|
|
578
|
+
[ -z "$VERSION" ] && VERSION=$(grep -oP '"version":\s*"\K[^"]+' "$DEVELOP_FULL_PATH/package.json" 2>/dev/null)
|
|
579
|
+
[ -z "$VERSION" ] && VERSION=$(cat "$DEVELOP_FULL_PATH/VERSION" 2>/dev/null)
|
|
580
|
+
[ -z "$VERSION" ] && VERSION=$(git -C "$DEVELOP_FULL_PATH" describe --tags --abbrev=0 2>/dev/null | sed 's/^v//')
|
|
528
581
|
[ -z "$VERSION" ] && VERSION="0.1.0"
|
|
529
582
|
```
|
|
530
583
|
|
|
584
|
+
### 10b. Post-Init Validation
|
|
585
|
+
|
|
586
|
+
**⛔ MANDATORY: Verify the structure was created correctly.**
|
|
587
|
+
|
|
588
|
+
```bash
|
|
589
|
+
PROJECT_BASE="{ROOT_FOLDER}"
|
|
590
|
+
MAIN_DIR=$([ "$WORKTREE_MODE" = "organized" ] && echo "01-Main" || echo "main")
|
|
591
|
+
DEVELOP_DIR=$([ "$WORKTREE_MODE" = "organized" ] && echo "02-Develop" || echo "develop")
|
|
592
|
+
ERRORS=0
|
|
593
|
+
|
|
594
|
+
# Verify bare repo
|
|
595
|
+
[ -f "$PROJECT_BASE/.bare/HEAD" ] && echo "✓ .bare/HEAD OK" || { echo "❌ .bare/HEAD missing"; ERRORS=$((ERRORS+1)); }
|
|
596
|
+
|
|
597
|
+
# Verify worktrees on correct branches
|
|
598
|
+
MAIN_BRANCH=$(git -C "$PROJECT_BASE/$MAIN_DIR" branch --show-current 2>/dev/null)
|
|
599
|
+
[ "$MAIN_BRANCH" = "main" ] && echo "✓ $MAIN_DIR on main" || { echo "❌ $MAIN_DIR on '$MAIN_BRANCH', expected 'main'"; ERRORS=$((ERRORS+1)); }
|
|
600
|
+
|
|
601
|
+
DEVELOP_BRANCH=$(git -C "$PROJECT_BASE/$DEVELOP_DIR" branch --show-current 2>/dev/null)
|
|
602
|
+
[ "$DEVELOP_BRANCH" = "develop" ] && echo "✓ $DEVELOP_DIR on develop" || { echo "❌ $DEVELOP_DIR on '$DEVELOP_BRANCH', expected 'develop'"; ERRORS=$((ERRORS+1)); }
|
|
603
|
+
|
|
604
|
+
# Verify directories
|
|
605
|
+
for subdir in features releases hotfixes; do
|
|
606
|
+
[ -d "$PROJECT_BASE/$subdir" ] && echo "✓ $subdir/ OK" || { echo "❌ $subdir/ missing"; ERRORS=$((ERRORS+1)); }
|
|
607
|
+
done
|
|
608
|
+
|
|
609
|
+
# Verify config directory
|
|
610
|
+
[ -d "$PROJECT_BASE/$DEVELOP_DIR/.claude/gitflow" ] && echo "✓ .claude/gitflow/ OK" || { echo "❌ .claude/gitflow/ missing"; ERRORS=$((ERRORS+1)); }
|
|
611
|
+
|
|
612
|
+
echo ""
|
|
613
|
+
[ "$ERRORS" -eq 0 ] && echo "VALIDATION: ALL CHECKS PASSED" || echo "VALIDATION: $ERRORS error(s) detected - check output above"
|
|
614
|
+
```
|
|
615
|
+
|
|
531
616
|
### 11. Summary
|
|
532
617
|
|
|
533
618
|
```
|
|
@@ -538,7 +623,9 @@ VERSION=$(grep -oP '<Version>\K[^<]+' *.csproj 2>/dev/null | head -1)
|
|
|
538
623
|
║ Root: {ROOT_FOLDER} ║
|
|
539
624
|
║ Remote: {REPO_URL} ║
|
|
540
625
|
║ Provider: {GIT_PROVIDER} ║
|
|
626
|
+
║ Platform: {GF_PLATFORM} ({GF_SHELL}) ║
|
|
541
627
|
║ Version: {VERSION} ║
|
|
628
|
+
║ Config: v2.1.0 ║
|
|
542
629
|
╠══════════════════════════════════════════════════════════════════╣
|
|
543
630
|
║ Structure: ║
|
|
544
631
|
║ ├── .bare/ (git bare repository) ║
|
|
@@ -548,6 +635,8 @@ VERSION=$(grep -oP '<Version>\K[^<]+' *.csproj 2>/dev/null | head -1)
|
|
|
548
635
|
║ ├── releases/ (release worktrees) ✅ ║
|
|
549
636
|
║ └── hotfixes/ (hotfix worktrees) ✅ ║
|
|
550
637
|
╠══════════════════════════════════════════════════════════════════╣
|
|
638
|
+
║ Validation: {ERRORS == 0 ? "ALL CHECKS PASSED" : "errors"} ║
|
|
639
|
+
╠══════════════════════════════════════════════════════════════════╣
|
|
551
640
|
{if SIBLING_PROJECTS not empty}
|
|
552
641
|
║ Workspace: {WORKSPACE_DIR} ║
|
|
553
642
|
║ GitFlow projects: {#SIBLING_PROJECTS + 1} (including this one) ║
|
|
@@ -598,3 +687,77 @@ Before completing init, verify:
|
|
|
598
687
|
## NEXT STEP:
|
|
599
688
|
|
|
600
689
|
Init is standalone. User should `cd 02-Develop` then run `/gitflow -f <feature-name>`.
|
|
690
|
+
|
|
691
|
+
---
|
|
692
|
+
|
|
693
|
+
## WORKSPACE MODE (`--workspace`)
|
|
694
|
+
|
|
695
|
+
When called with `init --workspace`, batch-initialize all repos in a workspace.
|
|
696
|
+
|
|
697
|
+
### Workspace Execution Sequence:
|
|
698
|
+
|
|
699
|
+
1. **Ask workspace directory:**
|
|
700
|
+
```yaml
|
|
701
|
+
AskUserQuestion:
|
|
702
|
+
- header: "Workspace"
|
|
703
|
+
question: "Where is the workspace root? (parent directory containing all repos)"
|
|
704
|
+
options:
|
|
705
|
+
- label: "Use parent folder (Recommended)"
|
|
706
|
+
description: "{DETECTED_FOLDER}/"
|
|
707
|
+
- label: "Custom path"
|
|
708
|
+
description: "Specify a different location"
|
|
709
|
+
multiSelect: false
|
|
710
|
+
```
|
|
711
|
+
|
|
712
|
+
2. **Detect or ask for repos:**
|
|
713
|
+
```yaml
|
|
714
|
+
AskUserQuestion:
|
|
715
|
+
- header: "Repos"
|
|
716
|
+
question: "How to identify repositories to initialize?"
|
|
717
|
+
options:
|
|
718
|
+
- label: "Detect from folders (Recommended)"
|
|
719
|
+
description: "Scan workspace for git repositories"
|
|
720
|
+
- label: "Enter URLs"
|
|
721
|
+
description: "Provide a list of repository URLs"
|
|
722
|
+
multiSelect: false
|
|
723
|
+
```
|
|
724
|
+
|
|
725
|
+
3. **Create `.smartstack-workspace.json`:**
|
|
726
|
+
```json
|
|
727
|
+
{
|
|
728
|
+
"version": "1.0.0",
|
|
729
|
+
"name": "{WORKSPACE_NAME}",
|
|
730
|
+
"createdAt": "{ISO_DATE}",
|
|
731
|
+
"updatedAt": "{ISO_DATE}",
|
|
732
|
+
"platform": {
|
|
733
|
+
"detected": "{GF_PLATFORM}",
|
|
734
|
+
"shell": "{GF_SHELL}"
|
|
735
|
+
},
|
|
736
|
+
"repositories": [],
|
|
737
|
+
"defaults": {
|
|
738
|
+
"provider": "{GIT_PROVIDER}",
|
|
739
|
+
"worktreeMode": "organized",
|
|
740
|
+
"language": "en"
|
|
741
|
+
}
|
|
742
|
+
}
|
|
743
|
+
```
|
|
744
|
+
|
|
745
|
+
4. **Loop: For each repo, run Steps 1-10b with workspace defaults pre-populated.**
|
|
746
|
+
- Skip questions where workspace defaults apply (provider, worktree mode)
|
|
747
|
+
- Add each repo to `workspace.json` after successful init
|
|
748
|
+
|
|
749
|
+
5. **Display global summary:**
|
|
750
|
+
```
|
|
751
|
+
╔══════════════════════════════════════════════════════════════════╗
|
|
752
|
+
║ WORKSPACE INITIALIZED ║
|
|
753
|
+
╠══════════════════════════════════════════════════════════════════╣
|
|
754
|
+
║ Workspace: {WORKSPACE_DIR} ║
|
|
755
|
+
║ Platform: {GF_PLATFORM} ({GF_SHELL}) ║
|
|
756
|
+
║ Repos: {REPO_COUNT} initialized ║
|
|
757
|
+
╠══════════════════════════════════════════════════════════════════╣
|
|
758
|
+
{for each REPO}
|
|
759
|
+
║ ✅ {REPO_NAME} ║
|
|
760
|
+
║ 01-Main/ ✓ 02-Develop/ ✓ config.json ✓ ║
|
|
761
|
+
{end for}
|
|
762
|
+
╚══════════════════════════════════════════════════════════════════╝
|
|
763
|
+
```
|
|
@@ -38,13 +38,25 @@ fi
|
|
|
38
38
|
|
|
39
39
|
```bash
|
|
40
40
|
CURRENT=$(git rev-parse --abbrev-ref HEAD)
|
|
41
|
+
BRANCH_TYPE=$(echo $CURRENT | cut -d'/' -f1)
|
|
42
|
+
|
|
43
|
+
# CRITICAL: Verify config was loaded
|
|
44
|
+
if [ -z "$GF_MAIN_BRANCH" ] || [ -z "$GF_DEVELOP_BRANCH" ]; then
|
|
45
|
+
echo "❌ GitFlow config not loaded properly"
|
|
46
|
+
echo "→ Variables GF_MAIN_BRANCH and GF_DEVELOP_BRANCH are empty"
|
|
47
|
+
exit 1
|
|
48
|
+
fi
|
|
41
49
|
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
50
|
+
# Determine target branch based on type (using config values)
|
|
51
|
+
case "$BRANCH_TYPE" in
|
|
52
|
+
feature) TARGET_BRANCH="$GF_DEVELOP_BRANCH" ;;
|
|
53
|
+
release) TARGET_BRANCH="$GF_MAIN_BRANCH" ;;
|
|
54
|
+
hotfix) TARGET_BRANCH="$GF_MAIN_BRANCH" ;;
|
|
55
|
+
*) TARGET_BRANCH="$GF_DEVELOP_BRANCH" ;;
|
|
47
56
|
esac
|
|
57
|
+
|
|
58
|
+
echo "✓ Branch: $CURRENT (type: $BRANCH_TYPE)"
|
|
59
|
+
echo "✓ Target: $TARGET_BRANCH"
|
|
48
60
|
```
|
|
49
61
|
|
|
50
62
|
### 3. Check Prerequisites
|
|
@@ -109,22 +109,27 @@ The loop only stops when this exact tag is output or max iterations reached.
|
|
|
109
109
|
|
|
110
110
|
<workflow>
|
|
111
111
|
**Standard flow (single module):**
|
|
112
|
-
1. Parse flags and task description
|
|
113
|
-
2. Verify MCP servers are available (MANDATORY)
|
|
114
|
-
3. Initialize .ralph/ structure and state files
|
|
115
|
-
4. Load current task from prd.json
|
|
116
|
-
5. Execute
|
|
117
|
-
6. Commit changes, update progress
|
|
118
|
-
7. Check completion
|
|
119
|
-
8.
|
|
112
|
+
1. Parse flags and task description (step-00)
|
|
113
|
+
2. Verify MCP servers are available (step-00, MANDATORY)
|
|
114
|
+
3. Initialize .ralph/ structure and state files (step-00)
|
|
115
|
+
4. Load current task from prd.json — create task breakdown if new (step-01, READ ONCE)
|
|
116
|
+
5. Execute first task (step-02, READ ONCE)
|
|
117
|
+
6. Commit changes, update progress (step-03, READ ONCE)
|
|
118
|
+
7. Check completion → enter COMPACT LOOP (step-04)
|
|
119
|
+
8. **COMPACT LOOP** (step-04 section 5, NO re-reading step files):
|
|
120
|
+
- Find eligible tasks → batch by category (max 5)
|
|
121
|
+
- Execute batch inline
|
|
122
|
+
- Commit batch
|
|
123
|
+
- Re-check completion → loop or finish
|
|
124
|
+
9. When complete: generate final report (step-05)
|
|
120
125
|
|
|
121
126
|
**Multi-module flow (from BA handoff):**
|
|
122
127
|
1-3. Same as standard flow
|
|
123
128
|
4. Detect `prd-*.json` files → create `modules-queue.json`
|
|
124
129
|
5. Copy current module's prd to `prd.json`
|
|
125
|
-
6. Execute all tasks for current module
|
|
126
|
-
7. When module complete: advance to next module in queue
|
|
127
|
-
8. Repeat steps 5-7 for each module
|
|
130
|
+
6. Execute all tasks for current module via COMPACT LOOP
|
|
131
|
+
7. When module complete: advance to next module in queue (step-04 section 3)
|
|
132
|
+
8. Repeat steps 5-7 for each module (step-01 is re-read ONLY for module transitions)
|
|
128
133
|
9. When all modules done: generate cross-module report
|
|
129
134
|
</workflow>
|
|
130
135
|
|
|
@@ -279,12 +284,14 @@ Before ANY work, verify MCP servers:
|
|
|
279
284
|
|
|
280
285
|
<execution_rules>
|
|
281
286
|
|
|
282
|
-
- **Load
|
|
283
|
-
- **VERIFY MCP FIRST** - Never skip MCP validation
|
|
284
|
-
- **
|
|
285
|
-
- **COMMIT AFTER EACH
|
|
287
|
+
- **Load step files ONCE** - Step files are read only on FIRST iteration. After that, use the COMPACT LOOP in step-04 section 5.
|
|
288
|
+
- **VERIFY MCP FIRST** - Never skip MCP validation at init
|
|
289
|
+
- **BATCH same-category tasks** - Execute up to 5 tasks of the same category per iteration (reduces loop iterations from 30+ to ~8)
|
|
290
|
+
- **COMMIT AFTER EACH BATCH** - One commit per batch, not per individual task
|
|
286
291
|
- **UPDATE progress.txt** - Persist learnings
|
|
287
292
|
- **NEVER fake completion** - Only output promise when truly done
|
|
293
|
+
- **NEVER STOP THE LOOP** - The loop is AUTONOMOUS. DO NOT pause between iterations. DO NOT wait for user input. Only stop on: completion, max iterations, dead-end, or explicit user interruption. Stopping for any other reason wastes context and causes re-reads.
|
|
294
|
+
- **COMPACT OUTPUT** - During loop iterations, use 1-2 lines per task. Save verbose output for the final report.
|
|
288
295
|
</execution_rules>
|
|
289
296
|
|
|
290
297
|
<success_criteria>
|