@atlashub/smartstack-cli 1.35.0 → 1.36.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 CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "@atlashub/smartstack-cli",
3
- "version": "1.35.0",
3
+ "version": "1.36.0",
4
4
  "description": "SmartStack Claude Code automation toolkit - GitFlow, APEX, EF Core migrations, prompts and more",
5
5
  "author": {
6
6
  "name": "SmartStack",
@@ -15,13 +15,13 @@ Domain → Application → Infrastructure → API → Web
15
15
  ```
16
16
 
17
17
  ### Layers
18
- | Layer | Responsibility | Namespace |
19
- |-------|-----------------|-----------|
20
- | Domain | Entities, ValueObjects | `SmartStack.Domain.{Context}` |
21
- | Application | Services, DTOs, Interfaces | `SmartStack.Application.{Context}` |
22
- | Infrastructure | Implementations, EF Core | `SmartStack.Infrastructure.{Context}` |
23
- | API | Controllers, Middleware | `SmartStack.Api.Controllers.{Area}` |
24
- | Web | React components, pages | `src/pages/{context}/{app}/{module}` |
18
+ | Layer | Responsibility | Namespace | Folder Hierarchy |
19
+ |-------|-----------------|-----------|------------------|
20
+ | Domain | Entities, ValueObjects | `SmartStack.Domain.{Context}.{App}.{Module}` | `Domain/{Context}/{App}/{Module}/` |
21
+ | Application | Interfaces (Common), DTOs | `SmartStack.Application.Common.Interfaces` / `.{Context}.{App}.{Module}.DTOs` | `Application/Common/Interfaces/` + `Application/{Context}/{App}/{Module}/DTOs/` |
22
+ | Infrastructure | Service Impl, EF Core | `SmartStack.Infrastructure.Services.{Module}` | `Infrastructure/Services/{Module}/` + `Persistence/Configurations/{Module}/` |
23
+ | API | Controllers, Middleware | `SmartStack.Api.Controllers.{Context}` | `Api/Controllers/{Context}/` |
24
+ | Web | React components, pages | N/A | `pages/{context}/{app}/{module}/` + `components/{context}/{module}/` |
25
25
 
26
26
  ## Permissions (2 mandatory files)
27
27
 
@@ -80,15 +80,15 @@ Args:
80
80
 
81
81
  ### 4. Parse MCP Response
82
82
 
83
- The tool generates:
84
- - `Domain/{EntityName}.cs` - Entity with BaseEntity
85
- - `Infrastructure/Persistence/Configurations/{EntityName}Configuration.cs` - EF Config
86
- - `Application/Services/I{EntityName}Service.cs` - Interface
87
- - `Application/Services/{EntityName}Service.cs` - Implementation
88
- - `Api/Controllers/{EntityName}Controller.cs` - REST Controller
89
- - `Application/DTOs/{EntityName}Dto.cs` - Response DTO
90
- - `Application/DTOs/Create{EntityName}Dto.cs` - Create request
91
- - `Application/DTOs/Update{EntityName}Dto.cs` - Update request
83
+ The tool generates (paths organized by navRoute hierarchy `{context}.{application}.{module}`):
84
+ - `Domain/{Context}/{Application}/{Module}/{EntityName}.cs` - Entity with BaseEntity
85
+ - `Infrastructure/Persistence/Configurations/{Module}/{EntityName}Configuration.cs` - EF Config
86
+ - `Application/Common/Interfaces/I{EntityName}Service.cs` - Service Interface
87
+ - `Infrastructure/Services/{Module}/{EntityName}Service.cs` - Service Implementation
88
+ - `Api/Controllers/{Context}/{EntityName}Controller.cs` - REST Controller
89
+ - `Application/{Context}/{Application}/{Module}/DTOs/{EntityName}ResponseDto.cs` - Response DTO
90
+ - `Application/{Context}/{Application}/{Module}/DTOs/Create{EntityName}Dto.cs` - Create request
91
+ - `Application/{Context}/{Application}/{Module}/DTOs/Update{EntityName}Dto.cs` - Update request
92
92
 
93
93
  ### 5. Present Output to User
94
94
 
@@ -96,20 +96,20 @@ The tool generates:
96
96
  ## Backend Code Generated
97
97
 
98
98
  ### Domain Layer
99
- - `Domain/{EntityName}.cs`
99
+ - `Domain/{Context}/{Application}/{Module}/{EntityName}.cs`
100
100
 
101
101
  ### Infrastructure Layer
102
- - `Persistence/Configurations/{EntityName}Configuration.cs`
102
+ - `Persistence/Configurations/{Module}/{EntityName}Configuration.cs`
103
+ - `Services/{Module}/{EntityName}Service.cs`
103
104
 
104
105
  ### Application Layer
105
- - `Services/I{EntityName}Service.cs`
106
- - `Services/{EntityName}Service.cs`
107
- - `DTOs/{EntityName}Dto.cs`
108
- - `DTOs/Create{EntityName}Dto.cs`
109
- - `DTOs/Update{EntityName}Dto.cs`
106
+ - `Common/Interfaces/I{EntityName}Service.cs`
107
+ - `{Context}/{Application}/{Module}/DTOs/{EntityName}ResponseDto.cs`
108
+ - `{Context}/{Application}/{Module}/DTOs/Create{EntityName}Dto.cs`
109
+ - `{Context}/{Application}/{Module}/DTOs/Update{EntityName}Dto.cs`
110
110
 
111
111
  ### API Layer
112
- - `Controllers/{EntityName}Controller.cs`
112
+ - `Controllers/{Context}/{EntityName}Controller.cs`
113
113
  - NavRoute: `{full_path}`
114
114
  - Endpoints:
115
115
  - GET /api/{code} - List all
@@ -129,9 +129,12 @@ Repeat for en, it, de with appropriate translations.
129
129
  ```markdown
130
130
  ## Frontend Code Generated
131
131
 
132
- ### Components
132
+ ### Pages
133
133
  - `pages/{context}/{application}/{module}/{EntityName}Page.tsx`
134
134
  - `pages/{context}/{application}/{module}/{EntityName}ListView.tsx`
135
+
136
+ ### Components
137
+ - `components/{context}/{module}/{EntityName}.tsx`
135
138
  - `hooks/use{EntityName}.ts`
136
139
 
137
140
  ### API Client
@@ -49,7 +49,7 @@ public static class Erp
49
49
  ```csharp
50
50
  // src/SmartStack.Application/Common/Interfaces/I{Module}Service.cs
51
51
 
52
- using SmartStack.Application.$MODULE_PASCAL.Models;
52
+ using SmartStack.Application.$CONTEXT_PASCAL.$APPLICATION_PASCAL.$MODULE_PASCAL.DTOs;
53
53
 
54
54
  namespace SmartStack.Application.Common.Interfaces;
55
55
 
@@ -88,8 +88,8 @@ public interface I$MODULE_PASCALService
88
88
  using Microsoft.EntityFrameworkCore;
89
89
  using Microsoft.Extensions.Logging;
90
90
  using SmartStack.Application.Common.Interfaces;
91
- using SmartStack.Application.$MODULE_PASCAL.Models;
92
- using SmartStack.Domain.$MODULE_PASCAL;
91
+ using SmartStack.Application.$CONTEXT_PASCAL.$APPLICATION_PASCAL.$MODULE_PASCAL.DTOs;
92
+ using SmartStack.Domain.$CONTEXT_PASCAL.$APPLICATION_PASCAL.$MODULE_PASCAL;
93
93
 
94
94
  namespace SmartStack.Infrastructure.Services.$MODULE_PASCAL;
95
95
 
@@ -269,9 +269,9 @@ public class $MODULE_PASCALService : I$MODULE_PASCALService
269
269
  ## TEMPLATE: DTOs
270
270
 
271
271
  ```csharp
272
- // src/SmartStack.Application/$MODULE_PASCAL/Models/$ENTITY_PASCALDto.cs
272
+ // src/SmartStack.Application/$CONTEXT_PASCAL/$APPLICATION_PASCAL/$MODULE_PASCAL/DTOs/$ENTITY_PASCALDto.cs
273
273
 
274
- namespace SmartStack.Application.$MODULE_PASCAL.Models;
274
+ namespace SmartStack.Application.$CONTEXT_PASCAL.$APPLICATION_PASCAL.$MODULE_PASCAL.DTOs;
275
275
 
276
276
  public record $ENTITY_PASCALDto
277
277
  {
@@ -310,11 +310,11 @@ public record $ENTITY_PASCALQueryParameters
310
310
  ## TEMPLATE: DOMAIN ENTITY
311
311
 
312
312
  ```csharp
313
- // src/SmartStack.Domain/$MODULE_PASCAL/$ENTITY_PASCAL.cs
313
+ // src/SmartStack.Domain/$CONTEXT_PASCAL/$APPLICATION_PASCAL/$MODULE_PASCAL/$ENTITY_PASCAL.cs
314
314
 
315
315
  using SmartStack.Domain.Common;
316
316
 
317
- namespace SmartStack.Domain.$MODULE_PASCAL;
317
+ namespace SmartStack.Domain.$CONTEXT_PASCAL.$APPLICATION_PASCAL.$MODULE_PASCAL;
318
318
 
319
319
  public class $ENTITY_PASCAL : BaseEntity
320
320
  {
@@ -363,7 +363,7 @@ public class $ENTITY_PASCAL : BaseEntity
363
363
 
364
364
  using Microsoft.EntityFrameworkCore;
365
365
  using Microsoft.EntityFrameworkCore.Metadata.Builders;
366
- using SmartStack.Domain.$MODULE_PASCAL;
366
+ using SmartStack.Domain.$CONTEXT_PASCAL.$APPLICATION_PASCAL.$MODULE_PASCAL;
367
367
 
368
368
  namespace SmartStack.Infrastructure.Persistence.Configurations.$MODULE_PASCAL;
369
369
 
@@ -8,11 +8,11 @@
8
8
 
9
9
  ```
10
10
  web/smartstack-web/src/
11
- ├── pages/$CONTEXT/$MODULE/
11
+ ├── pages/$CONTEXT/$APPLICATION/$MODULE/
12
12
  │ ├── $MODULE_PASCALPage.tsx # Main page (list)
13
13
  │ ├── $MODULE_PASCALDetailPage.tsx # Detail page
14
14
  │ └── Create$MODULE_PASCALPage.tsx # Create page
15
- ├── components/$MODULE/
15
+ ├── components/$CONTEXT/$MODULE/
16
16
  │ ├── $MODULE_PASCALListView.tsx # Reusable list component
17
17
  │ ├── $MODULE_PASCALForm.tsx # CRUD form
18
18
  │ └── $MODULE_PASCALFilters.tsx # Filters
@@ -35,10 +35,10 @@ web/smartstack-web/src/
35
35
  ## TEMPLATE: MAIN PAGE
36
36
 
37
37
  ```tsx
38
- // pages/$CONTEXT/$MODULE/$MODULE_PASCALPage.tsx
38
+ // pages/$CONTEXT/$APPLICATION/$MODULE/$MODULE_PASCALPage.tsx
39
39
 
40
40
  import { useTranslation } from 'react-i18next';
41
- import { $MODULE_PASCALListView } from '@/components/$MODULE/$MODULE_PASCALListView';
41
+ import { $MODULE_PASCALListView } from '@/components/$CONTEXT/$MODULE/$MODULE_PASCALListView';
42
42
 
43
43
  export function $MODULE_PASCALPage() {
44
44
  const { t } = useTranslation(['$module', 'common']);
@@ -59,7 +59,7 @@ export function $MODULE_PASCALPage() {
59
59
  ## TEMPLATE: LIST VIEW (Reusable component)
60
60
 
61
61
  ```tsx
62
- // components/$MODULE/$MODULE_PASCALListView.tsx
62
+ // components/$CONTEXT/$MODULE/$MODULE_PASCALListView.tsx
63
63
 
64
64
  import { useState, useEffect } from 'react';
65
65
  import { useNavigate } from 'react-router-dom';
@@ -491,9 +491,9 @@ React Router v7 **requires** nested routes for multi-module applications.
491
491
  ```tsx
492
492
  // Add to App.tsx
493
493
 
494
- import { $MODULE_PASCALPage } from '@/pages/$CONTEXT/$MODULE/$MODULE_PASCALPage';
495
- import { $MODULE_PASCALDetailPage } from '@/pages/$CONTEXT/$MODULE/$MODULE_PASCALDetailPage';
496
- import { Create$MODULE_PASCALPage } from '@/pages/$CONTEXT/$MODULE/Create$MODULE_PASCALPage';
494
+ import { $MODULE_PASCALPage } from '@/pages/$CONTEXT/$APPLICATION/$MODULE/$MODULE_PASCALPage';
495
+ import { $MODULE_PASCALDetailPage } from '@/pages/$CONTEXT/$APPLICATION/$MODULE/$MODULE_PASCALDetailPage';
496
+ import { Create$MODULE_PASCALPage } from '@/pages/$CONTEXT/$APPLICATION/$MODULE/Create$MODULE_PASCALPage';
497
497
 
498
498
  // In routes - NESTED STRUCTURE
499
499
  <Route path="$APPLICATION">
@@ -45,12 +45,113 @@ normalize_branch_name() {
45
45
 
46
46
  ---
47
47
 
48
+ ## RESOLVE_CONFIG_PATH
49
+
50
+ Resolves the config.json path regardless of current working directory.
51
+ Searches in: pwd, develop worktree, then git root.
52
+
53
+ ```bash
54
+ resolve_gitflow_config_path() {
55
+ # 1. Try current directory
56
+ [ -f ".claude/gitflow/config.json" ] && { echo ".claude/gitflow/config.json"; return 0; }
57
+
58
+ # 2. Try to find develop worktree from git worktree list
59
+ local DEVELOP_PATH
60
+ DEVELOP_PATH=$(git worktree list --porcelain 2>/dev/null | grep -A1 "branch refs/heads/develop" | grep "^worktree " | sed 's/^worktree //')
61
+ [ -n "$DEVELOP_PATH" ] && [ -f "$DEVELOP_PATH/.claude/gitflow/config.json" ] && {
62
+ echo "$DEVELOP_PATH/.claude/gitflow/config.json"
63
+ return 0
64
+ }
65
+
66
+ # 3. Try git toplevel
67
+ local GIT_ROOT
68
+ GIT_ROOT=$(git rev-parse --show-toplevel 2>/dev/null)
69
+ [ -n "$GIT_ROOT" ] && [ -f "$GIT_ROOT/.claude/gitflow/config.json" ] && {
70
+ echo "$GIT_ROOT/.claude/gitflow/config.json"
71
+ return 0
72
+ }
73
+
74
+ return 1
75
+ }
76
+ ```
77
+
78
+ ---
79
+
80
+ ## READ_GITFLOW_CONFIG
81
+
82
+ Reads GitFlow configuration from config.json. Exposes all variables needed by steps and phases.
83
+
84
+ ```bash
85
+ read_gitflow_config() {
86
+ local CONFIG_FILE
87
+ CONFIG_FILE=$(resolve_gitflow_config_path) || {
88
+ echo "❌ GitFlow config not found. Run /gitflow init first."
89
+ return 1
90
+ }
91
+
92
+ # Repository
93
+ GF_PROJECT_NAME=$(grep -oP '"name":\s*"\K[^"]+' "$CONFIG_FILE" | head -1)
94
+ GF_ROOT_FOLDER=$(grep -oP '"rootFolder":\s*"\K[^"]+' "$CONFIG_FILE" | head -1)
95
+ GF_REMOTE_URL=$(grep -oP '"remoteUrl":\s*"\K[^"]+' "$CONFIG_FILE" | head -1)
96
+
97
+ # Git provider and branches
98
+ GF_PROVIDER=$(grep -oP '"provider":\s*"\K[^"]+' "$CONFIG_FILE" | head -1)
99
+ GF_MAIN_BRANCH=$(grep -oP '"main":\s*"\K[^"]+' "$CONFIG_FILE" | head -1)
100
+ GF_DEVELOP_BRANCH=$(grep -oP '"develop":\s*"\K[^"]+' "$CONFIG_FILE" | head -1)
101
+
102
+ # Prefixes
103
+ GF_FEATURE_PREFIX=$(grep -oP '"feature":\s*"\K[^"]+' "$CONFIG_FILE" | head -1)
104
+ GF_RELEASE_PREFIX=$(grep -oP '"release":\s*"\K[^"]+' "$CONFIG_FILE" | head -1)
105
+ GF_HOTFIX_PREFIX=$(grep -oP '"hotfix":\s*"\K[^"]+' "$CONFIG_FILE" | head -1)
106
+
107
+ # Worktrees
108
+ GF_WORKTREE_MODE=$(grep -oP '"mode":\s*"\K[^"]+' "$CONFIG_FILE" | head -1)
109
+ GF_MAIN_PATH=$(grep -A1 '"structure"' "$CONFIG_FILE" | grep -oP '"main":\s*"\K[^"]+' | head -1)
110
+ GF_DEVELOP_PATH=$(grep -A2 '"structure"' "$CONFIG_FILE" | grep -oP '"develop":\s*"\K[^"]+' | head -1)
111
+ GF_FEATURES_PATH=$(grep -oP '"features":\s*"\K[^"]+' "$CONFIG_FILE" | head -1)
112
+ GF_RELEASES_PATH=$(grep -oP '"releases":\s*"\K[^"]+' "$CONFIG_FILE" | head -1)
113
+ GF_HOTFIXES_PATH=$(grep -oP '"hotfixes":\s*"\K[^"]+' "$CONFIG_FILE" | head -1)
114
+
115
+ # Language
116
+ GF_LANG=$(grep -oP '"code":\s*"\K[^"]+' "$CONFIG_FILE" | head -1)
117
+
118
+ # Versioning
119
+ GF_VERSION=$(grep -oP '"current":\s*"\K[^"]+' "$CONFIG_FILE" | head -1)
120
+ GF_TAG_PREFIX=$(grep -oP '"tagPrefix":\s*"\K[^"]+' "$CONFIG_FILE" | head -1)
121
+
122
+ # Defaults for missing values
123
+ GF_LANG=${GF_LANG:-en}
124
+ GF_WORKTREE_MODE=${GF_WORKTREE_MODE:-organized}
125
+ GF_MAIN_BRANCH=${GF_MAIN_BRANCH:-main}
126
+ GF_DEVELOP_BRANCH=${GF_DEVELOP_BRANCH:-develop}
127
+ GF_FEATURE_PREFIX=${GF_FEATURE_PREFIX:-feature/}
128
+ GF_RELEASE_PREFIX=${GF_RELEASE_PREFIX:-release/}
129
+ GF_HOTFIX_PREFIX=${GF_HOTFIX_PREFIX:-hotfix/}
130
+ GF_TAG_PREFIX=${GF_TAG_PREFIX:-v}
131
+ GF_VERSION=${GF_VERSION:-0.1.0}
132
+
133
+ # Export config file path for steps that need to update it
134
+ GF_CONFIG_FILE="$CONFIG_FILE"
135
+ }
136
+ ```
137
+
138
+ ---
139
+
48
140
  ## DETECT_WORKTREE_MODE
49
141
 
50
- Detects worktree mode (organized, adjacent, none).
142
+ Detects worktree mode. Reads config first, falls back to filesystem detection.
51
143
 
52
144
  ```bash
53
145
  detect_worktree_mode() {
146
+ # 1. Try config first (authoritative)
147
+ local CONFIG_FILE
148
+ CONFIG_FILE=$(resolve_gitflow_config_path 2>/dev/null)
149
+ if [ -n "$CONFIG_FILE" ] && [ -f "$CONFIG_FILE" ]; then
150
+ WORKTREE_MODE=$(grep -oP '"mode":\s*"\K[^"]+' "$CONFIG_FILE" | head -1)
151
+ [ -n "$WORKTREE_MODE" ] && return 0
152
+ fi
153
+
154
+ # 2. Fallback: filesystem detection
54
155
  if [ -d "../features" ] && [ -d "../releases" ] && [ -d "../hotfixes" ]; then
55
156
  WORKTREE_MODE="organized"
56
157
  elif [ -d "../01-Main" ] && [ -d "../02-Develop" ]; then
@@ -58,9 +159,7 @@ detect_worktree_mode() {
58
159
  elif [ -d "../worktrees" ]; then
59
160
  WORKTREE_MODE="adjacent"
60
161
  else
61
- CONFIG_FILE=".claude/gitflow/config.json"
62
- [ -f "$CONFIG_FILE" ] && WORKTREE_MODE=$(grep -oP '"mode":\s*"\K[^"]+' "$CONFIG_FILE" | head -1)
63
- WORKTREE_MODE=${WORKTREE_MODE:-adjacent}
162
+ WORKTREE_MODE="organized"
64
163
  fi
65
164
  }
66
165
  ```
@@ -69,26 +168,30 @@ detect_worktree_mode() {
69
168
 
70
169
  ## CLEANUP_WORKTREE
71
170
 
72
- Cleans up a worktree for a given branch.
171
+ Cleans up a worktree for a given branch. Uses config paths when available.
73
172
 
74
173
  ```bash
75
174
  cleanup_worktree_for_branch() {
76
- local BRANCH=$1 WORKTREE_BASE="../worktrees" WORKTREE_PATH=""
77
-
78
- case "$BRANCH" in
79
- feature/*) WORKTREE_PATH="$WORKTREE_BASE/features/${BRANCH#feature/}" ;;
80
- release/*) WORKTREE_PATH="$WORKTREE_BASE/releases/${BRANCH#release/}" ;;
81
- hotfix/*) WORKTREE_PATH="$WORKTREE_BASE/hotfixes/${BRANCH#hotfix/}" ;;
82
- esac
83
-
84
- # Organized mode
85
- [ -d "../features" ] && case "$BRANCH" in
86
- feature/*) WORKTREE_PATH="../features/${BRANCH#feature/}" ;;
87
- release/*) WORKTREE_PATH="../releases/${BRANCH#release/}" ;;
88
- hotfix/*) WORKTREE_PATH="../hotfixes/${BRANCH#hotfix/}" ;;
89
- esac
90
-
91
- [ -d "$WORKTREE_PATH" ] && {
175
+ local BRANCH=$1 WORKTREE_PATH=""
176
+
177
+ # Try config-based paths first (absolute, reliable)
178
+ read_gitflow_config 2>/dev/null
179
+ if [ -n "$GF_FEATURES_PATH" ]; then
180
+ case "$BRANCH" in
181
+ feature/*) WORKTREE_PATH="$GF_FEATURES_PATH/${BRANCH#feature/}" ;;
182
+ release/*) WORKTREE_PATH="$GF_RELEASES_PATH/${BRANCH#release/}" ;;
183
+ hotfix/*) WORKTREE_PATH="$GF_HOTFIXES_PATH/${BRANCH#hotfix/}" ;;
184
+ esac
185
+ else
186
+ # Fallback: relative paths
187
+ case "$BRANCH" in
188
+ feature/*) WORKTREE_PATH="../features/${BRANCH#feature/}" ;;
189
+ release/*) WORKTREE_PATH="../releases/${BRANCH#release/}" ;;
190
+ hotfix/*) WORKTREE_PATH="../hotfixes/${BRANCH#hotfix/}" ;;
191
+ esac
192
+ fi
193
+
194
+ [ -n "$WORKTREE_PATH" ] && [ -d "$WORKTREE_PATH" ] && {
92
195
  git worktree remove "$WORKTREE_PATH" --force 2>/dev/null || rm -rf "$WORKTREE_PATH"
93
196
  git worktree prune
94
197
  echo "✓ Worktree cleaned: $WORKTREE_PATH"
@@ -116,47 +219,79 @@ sync_with_remote() {
116
219
 
117
220
  ---
118
221
 
119
- ## READ_GITFLOW_CONFIG
120
-
121
- Reads GitFlow configuration.
122
-
123
- ```bash
124
- read_gitflow_config() {
125
- local CONFIG_FILE=".claude/gitflow/config.json"
126
- [ ! -f "$CONFIG_FILE" ] && return 1
127
-
128
- # Exported variables
129
- GF_LANG=$(grep -oP '"code":\s*"\K[^"]+' "$CONFIG_FILE" | head -1)
130
- GF_WORKTREE_MODE=$(grep -oP '"mode":\s*"\K[^"]+' "$CONFIG_FILE" | head -1)
131
- GF_MAIN_BRANCH=$(grep -oP '"main":\s*"\K[^"]+' "$CONFIG_FILE" | head -1)
132
- GF_DEVELOP_BRANCH=$(grep -oP '"develop":\s*"\K[^"]+' "$CONFIG_FILE" | head -1)
133
-
134
- GF_LANG=${GF_LANG:-en}
135
- GF_WORKTREE_MODE=${GF_WORKTREE_MODE:-adjacent}
136
- GF_MAIN_BRANCH=${GF_MAIN_BRANCH:-main}
137
- GF_DEVELOP_BRANCH=${GF_DEVELOP_BRANCH:-develop}
138
- }
139
- ```
140
-
141
- ---
142
-
143
222
  ## CONFIG_TEMPLATE
144
223
 
145
- GitFlow configuration JSON template (minimal version).
224
+ GitFlow configuration JSON template v2.0.0 (aligned with `templates/config.json`).
146
225
 
147
226
  ```json
148
227
  {
149
- "version": "1.3.0",
150
- "branches": { "main": "main", "develop": "develop" },
151
- "prefixes": { "feature": "feature/", "release": "release/", "hotfix": "hotfix/" },
152
- "worktrees": { "mode": "organized" },
153
- "language": { "code": "en" }
228
+ "version": "2.0.0",
229
+ "repository": {
230
+ "name": "",
231
+ "rootFolder": "",
232
+ "nameVariants": {
233
+ "pascalCaseDot": "",
234
+ "pascalCase": "",
235
+ "kebabCase": "",
236
+ "snakeCase": "",
237
+ "displayName": ""
238
+ },
239
+ "defaultBranch": "main",
240
+ "remoteUrl": ""
241
+ },
242
+ "git": {
243
+ "provider": "",
244
+ "branches": {
245
+ "main": "main",
246
+ "develop": "develop"
247
+ },
248
+ "prefixes": {
249
+ "feature": "feature/",
250
+ "release": "release/",
251
+ "hotfix": "hotfix/"
252
+ }
253
+ },
254
+ "worktrees": {
255
+ "enabled": true,
256
+ "mode": "organized",
257
+ "structure": {
258
+ "main": "",
259
+ "develop": "",
260
+ "features": "",
261
+ "releases": "",
262
+ "hotfixes": ""
263
+ }
264
+ },
265
+ "versioning": {
266
+ "strategy": "semver",
267
+ "current": "0.1.0",
268
+ "tagPrefix": "v",
269
+ "sources": ["csproj", "package.json", "VERSION"]
270
+ },
271
+ "efcore": {
272
+ "enabled": true,
273
+ "validateOnCommit": true,
274
+ "blockDestructive": true,
275
+ "migrationNaming": "{context}_v{version}_{sequence}_{Description}"
276
+ },
277
+ "workflow": {
278
+ "push": {
279
+ "afterCommit": "worktree"
280
+ },
281
+ "pr": {
282
+ "autoLabels": true,
283
+ "requireReview": true
284
+ }
285
+ },
286
+ "language": {
287
+ "code": "en"
288
+ }
154
289
  }
155
290
  ```
156
291
 
157
292
  **worktrees.mode options:**
158
- - `organized`: `../features/`, `../releases/`, `../hotfixes/`
159
- - `adjacent`: `../worktrees/{type}/`
293
+ - `organized`: Uses absolute paths from config (`structure.features`, etc.)
294
+ - `adjacent`: `{rootFolder}/worktrees/{type}/`
160
295
  - `disabled`: No worktrees
161
296
 
162
297
  ---
@@ -11,6 +11,13 @@ Provide rollback and recovery options for GitFlow operations.
11
11
 
12
12
  ---
13
13
 
14
+ ## PRE-CHECK:
15
+
16
+ ```bash
17
+ # Load GitFlow config (sets GF_* variables)
18
+ read_gitflow_config || { echo "❌ Run /gitflow init first."; exit 1; }
19
+ ```
20
+
14
21
  ## OPTIONS:
15
22
 
16
23
  ```yaml
@@ -23,7 +30,7 @@ AskUserQuestion:
23
30
  - label: "Abandon current branch"
24
31
  description: "Delete branch and worktree, return to develop"
25
32
  - label: "Restore from checkpoint"
26
- description: "Restore to a saved checkpoint"
33
+ description: "Restore to a saved checkpoint (not yet implemented)"
27
34
  - label: "Reset branch to remote"
28
35
  description: "Discard local changes, match remote"
29
36
  ```
@@ -69,7 +76,7 @@ git tag "$BACKUP_TAG" HEAD
69
76
  echo "✓ Backup created: $BACKUP_TAG"
70
77
 
71
78
  # Switch to develop
72
- git checkout develop
79
+ git checkout $GF_DEVELOP_BRANCH
73
80
 
74
81
  # Remove worktree
75
82
  [ -n "$WORKTREE" ] && {
@@ -87,30 +94,35 @@ echo " Backup: $BACKUP_TAG (use 'git checkout $BACKUP_TAG' to recover)"
87
94
 
88
95
  ### Option 3: Restore from Checkpoint
89
96
 
97
+ > **Note:** Checkpoint creation is not yet implemented. This option uses backup tags
98
+ > created by abort operations as a recovery mechanism. Full checkpoint support
99
+ > (automatic state snapshots during plan execution) is planned for a future release.
100
+
90
101
  ```bash
91
- # List available checkpoints
92
- CHECKPOINTS=$(ls -t .claude/gitflow/logs/checkpoint_*.json 2>/dev/null)
102
+ # List available backup tags (created by abandon operations)
103
+ BACKUPS=$(git tag -l "backup/*" --sort=-creatordate 2>/dev/null)
93
104
 
94
- if [ -z "$CHECKPOINTS" ]; then
95
- echo "No checkpoints found"
105
+ if [ -z "$BACKUPS" ]; then
106
+ echo "No backup tags found"
107
+ echo " Backup tags are created automatically when abandoning branches."
108
+ echo " Use 'Reset branch to remote' instead."
96
109
  exit 1
97
110
  fi
98
111
 
99
- echo "Available checkpoints:"
100
- for cp in $CHECKPOINTS; do
101
- TIMESTAMP=$(grep -oP '"timestamp":\s*"\K[^"]+' "$cp")
102
- BRANCH=$(grep -oP '"branch":\s*"\K[^"]+' "$cp")
103
- COMMIT=$(grep -oP '"commit":\s*"\K[^"]+' "$cp")
104
- echo " - $TIMESTAMP: $BRANCH @ $COMMIT"
112
+ echo "Available backups:"
113
+ for tag in $BACKUPS; do
114
+ COMMIT=$(git rev-parse --short "$tag")
115
+ DATE=$(git log -1 --format=%ci "$tag" 2>/dev/null)
116
+ echo " - $tag $COMMIT ($DATE)"
105
117
  done
106
118
 
107
- # Select checkpoint
119
+ # Select backup
108
120
  # ... user selection ...
109
121
 
110
122
  # Restore
111
- COMMIT=$(grep -oP '"commit":\s*"\K[^"]+' "$SELECTED_CHECKPOINT")
112
- git reset --hard "$COMMIT"
113
- echo "✓ Restored to $COMMIT"
123
+ git checkout "$SELECTED_TAG"
124
+ git checkout -b "recovered-$(date +%Y%m%d-%H%M%S)"
125
+ echo "✓ Restored from $SELECTED_TAG to new branch"
114
126
  ```
115
127
 
116
128
  ### Option 4: Reset to Remote
@@ -16,12 +16,15 @@ Audit worktrees and branches, remove orphaned/stale items.
16
16
  ## PRE-CHECK:
17
17
 
18
18
  ```bash
19
+ # Load GitFlow config (sets GF_* variables)
20
+ read_gitflow_config || { echo "❌ Run /gitflow init first."; exit 1; }
21
+
19
22
  CURRENT=$(git rev-parse --abbrev-ref HEAD)
20
23
 
21
- [[ "$CURRENT" != "main" ]] && [[ "$CURRENT" != "develop" ]] && {
22
- echo "❌ Cleanup must be run from main or develop"
24
+ [[ "$CURRENT" != "$GF_MAIN_BRANCH" ]] && [[ "$CURRENT" != "$GF_DEVELOP_BRANCH" ]] && {
25
+ echo "❌ Cleanup must be run from $GF_MAIN_BRANCH or $GF_DEVELOP_BRANCH"
23
26
  echo " Current branch: $CURRENT"
24
- echo "→ Run: git checkout develop"
27
+ echo "→ Run: git checkout $GF_DEVELOP_BRANCH"
25
28
  STOP
26
29
  }
27
30
  ```
@@ -35,7 +38,8 @@ CURRENT=$(git rev-parse --abbrev-ref HEAD)
35
38
  ```bash
36
39
  echo "Scanning worktrees..."
37
40
 
38
- git worktree list > /tmp/worktrees.txt
41
+ mkdir -p .claude/gitflow/cache
42
+ git worktree list > .claude/gitflow/cache/worktrees.txt
39
43
 
40
44
  ORPHANED=()
41
45
  STALE=()
@@ -54,13 +58,13 @@ while read -r line; do
54
58
 
55
59
  # Check if branch still exists on remote
56
60
  REMOTE_EXISTS=$(git branch -r --list "origin/$WT_BRANCH" | wc -l)
57
- if [ "$REMOTE_EXISTS" -eq 0 ] && [[ "$WT_BRANCH" != "main" ]] && [[ "$WT_BRANCH" != "develop" ]]; then
61
+ if [ "$REMOTE_EXISTS" -eq 0 ] && [[ "$WT_BRANCH" != "$GF_MAIN_BRANCH" ]] && [[ "$WT_BRANCH" != "$GF_DEVELOP_BRANCH" ]]; then
58
62
  STALE+=("$WT_PATH:$WT_BRANCH")
59
63
  continue
60
64
  fi
61
65
 
62
66
  VALID+=("$WT_PATH:$WT_BRANCH")
63
- done < /tmp/worktrees.txt
67
+ done < .claude/gitflow/cache/worktrees.txt
64
68
  ```
65
69
 
66
70
  ### 2. Audit Local Branches
@@ -72,17 +76,17 @@ MERGED_BRANCHES=()
72
76
  UNMERGED_BRANCHES=()
73
77
 
74
78
  # Find merged branches
75
- for branch in $(git branch --merged develop | grep -v "^\*" | grep -v "main" | grep -v "develop"); do
79
+ for branch in $(git branch --merged $GF_DEVELOP_BRANCH | grep -v "^\*" | grep -v "$GF_MAIN_BRANCH" | grep -v "$GF_DEVELOP_BRANCH"); do
76
80
  # Check if remote exists
77
81
  REMOTE_EXISTS=$(git branch -r --list "origin/$branch" | wc -l)
78
82
  [ "$REMOTE_EXISTS" -eq 0 ] && MERGED_BRANCHES+=("$branch")
79
83
  done
80
84
 
81
85
  # Find branches without remote
82
- for branch in $(git branch | grep -v "^\*" | grep -v "main" | grep -v "develop"); do
86
+ for branch in $(git branch | grep -v "^\*" | grep -v "$GF_MAIN_BRANCH" | grep -v "$GF_DEVELOP_BRANCH"); do
83
87
  REMOTE_EXISTS=$(git branch -r --list "origin/$branch" | wc -l)
84
88
  [ "$REMOTE_EXISTS" -eq 0 ] && {
85
- MERGED=$(git branch --merged develop | grep -c "$branch")
89
+ MERGED=$(git branch --merged $GF_DEVELOP_BRANCH | grep -c "$branch")
86
90
  [ "$MERGED" -eq 0 ] && UNMERGED_BRANCHES+=("$branch")
87
91
  }
88
92
  done