@atlashub/smartstack-cli 2.9.0 → 3.0.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/business-analyse.html +81 -17
- 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 +65 -33
- package/templates/agents/gitflow/pr.md +93 -49
- 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/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 +2622 -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 +1 -0
- package/templates/skills/business-analyse/steps/step-05-handoff.md +103 -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/templates/config.json +10 -1
- package/templates/skills/ralph-loop/steps/step-03-commit.md +2 -2
- 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
|
+
```
|
|
@@ -44,7 +44,7 @@ Task {current_task_id}/{tasks_total} - Iteration {current_iteration}
|
|
|
44
44
|
Category: {current_task_category}
|
|
45
45
|
{current_module ? "Module: " + current_module : ""}
|
|
46
46
|
|
|
47
|
-
Co-Authored-By: Claude Opus 4.
|
|
47
|
+
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
48
48
|
EOF
|
|
49
49
|
)"
|
|
50
50
|
```
|
|
@@ -189,7 +189,7 @@ Iteration {current_iteration} complete
|
|
|
189
189
|
Status: {task.status}
|
|
190
190
|
{current_module ? "Module: " + current_module : ""}
|
|
191
191
|
|
|
192
|
-
Co-Authored-By: Claude Opus 4.
|
|
192
|
+
Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
|
|
193
193
|
EOF
|
|
194
194
|
)"
|
|
195
195
|
```
|
|
@@ -0,0 +1,83 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: validate-feature
|
|
3
|
+
description: Validate that a scaffolded feature works end-to-end (compile, test, API smoke test)
|
|
4
|
+
version: 1.0.0
|
|
5
|
+
author: SmartStack
|
|
6
|
+
tags: [testing, validation, smoke-test, integration]
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
# /validate-feature
|
|
10
|
+
|
|
11
|
+
## PURPOSE
|
|
12
|
+
|
|
13
|
+
Validates that a scaffolded SmartStack feature **actually works** by running:
|
|
14
|
+
1. Compilation check (`dotnet build`)
|
|
15
|
+
2. Unit tests (`dotnet test`)
|
|
16
|
+
3. Integration tests (`dotnet test --filter`)
|
|
17
|
+
4. API smoke test (start API, hit CRUD endpoints, verify responses)
|
|
18
|
+
|
|
19
|
+
## WHEN TO USE
|
|
20
|
+
|
|
21
|
+
- After running `/application` to scaffold a new feature
|
|
22
|
+
- After making changes to backend code (controllers, services, entities)
|
|
23
|
+
- Before committing to verify nothing is broken
|
|
24
|
+
- As a confidence check that the full stack works
|
|
25
|
+
|
|
26
|
+
## USAGE
|
|
27
|
+
|
|
28
|
+
```
|
|
29
|
+
/validate-feature {EntityName}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
**Examples:**
|
|
33
|
+
```
|
|
34
|
+
/validate-feature Product
|
|
35
|
+
/validate-feature Order
|
|
36
|
+
/validate-feature UserProfile
|
|
37
|
+
```
|
|
38
|
+
|
|
39
|
+
## PARAMETERS
|
|
40
|
+
|
|
41
|
+
| Parameter | Required | Description |
|
|
42
|
+
|-----------|----------|-------------|
|
|
43
|
+
| `{entity_name}` | YES | PascalCase entity name to validate |
|
|
44
|
+
|
|
45
|
+
## PREREQUISITES
|
|
46
|
+
|
|
47
|
+
- The solution must compile
|
|
48
|
+
- Test project must exist with infrastructure (SmartStackTestFactory, IntegrationTestBase)
|
|
49
|
+
- Entity must have been scaffolded (controller, service, entity files exist)
|
|
50
|
+
|
|
51
|
+
## EXECUTION
|
|
52
|
+
|
|
53
|
+
This skill follows a 4-step sequential workflow:
|
|
54
|
+
|
|
55
|
+
| Step | File | Description | Blocking |
|
|
56
|
+
|------|------|-------------|----------|
|
|
57
|
+
| 1 | `steps/step-01-compile.md` | Build the full solution | YES |
|
|
58
|
+
| 2 | `steps/step-02-unit-tests.md` | Run unit tests | YES |
|
|
59
|
+
| 3 | `steps/step-03-integration-tests.md` | Run integration tests | YES |
|
|
60
|
+
| 4 | `steps/step-04-api-smoke.md` | Start API and test CRUD endpoints | YES |
|
|
61
|
+
|
|
62
|
+
Each step must PASS before proceeding to the next.
|
|
63
|
+
|
|
64
|
+
## OUTPUT
|
|
65
|
+
|
|
66
|
+
A validation report showing pass/fail for each check:
|
|
67
|
+
|
|
68
|
+
```
|
|
69
|
+
## Feature Validation: {EntityName}
|
|
70
|
+
|
|
71
|
+
| Check | Result |
|
|
72
|
+
|-------|--------|
|
|
73
|
+
| Solution build | PASS |
|
|
74
|
+
| Unit tests (X passed) | PASS |
|
|
75
|
+
| Integration tests (X passed) | PASS |
|
|
76
|
+
| API smoke: GET /api/{entity} | PASS (200) |
|
|
77
|
+
| API smoke: POST /api/{entity} | PASS (201) |
|
|
78
|
+
| API smoke: GET /api/{entity}/{id} | PASS (200) |
|
|
79
|
+
| API smoke: PUT /api/{entity}/{id} | PASS (200) |
|
|
80
|
+
| API smoke: DELETE /api/{entity}/{id} | PASS (204) |
|
|
81
|
+
|
|
82
|
+
Result: ALL CHECKS PASSED
|
|
83
|
+
```
|