@atlashub/smartstack-cli 4.6.0 → 4.7.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/dist/mcp-entry.mjs +24 -0
- package/dist/mcp-entry.mjs.map +1 -1
- package/package.json +1 -1
- package/templates/skills/apex/references/frontend-route-wiring-app-tsx.md +139 -0
- package/templates/skills/cli-app-sync/SKILL.md +272 -0
- package/templates/skills/cli-app-sync/references/comparison-map.md +228 -0
- package/templates/skills/gitflow/SKILL.md +5 -0
- package/templates/skills/gitflow/steps/step-init.md +19 -0
package/package.json
CHANGED
|
@@ -0,0 +1,139 @@
|
|
|
1
|
+
# Frontend: Route Wiring in App.tsx
|
|
2
|
+
|
|
3
|
+
> Referenced from `steps/step-03-execute.md` — Detailed route wiring patterns and verification.
|
|
4
|
+
|
|
5
|
+
---
|
|
6
|
+
|
|
7
|
+
## Step 4: Wire Routes to App.tsx (BLOCKING)
|
|
8
|
+
|
|
9
|
+
**CRITICAL:** This step is MANDATORY. Without it, routes exist as files but are invisible to the React Router. The page will be BLANK.
|
|
10
|
+
|
|
11
|
+
After `scaffold_routes` generates the route files, you MUST manually insert the routes into `App.tsx`.
|
|
12
|
+
|
|
13
|
+
---
|
|
14
|
+
|
|
15
|
+
## Step 4a: Import Page Components
|
|
16
|
+
|
|
17
|
+
At the top of App.tsx:
|
|
18
|
+
|
|
19
|
+
```tsx
|
|
20
|
+
import { {EntityName}Page } from '@/pages/{Application}/{Module}/{EntityName}Page';
|
|
21
|
+
// Or lazy-loaded:
|
|
22
|
+
const {EntityName}Page = lazy(() => import('@/pages/{Application}/{Module}/{EntityName}Page'));
|
|
23
|
+
```
|
|
24
|
+
|
|
25
|
+
---
|
|
26
|
+
|
|
27
|
+
## Step 4b: Detect App.tsx Routing Pattern
|
|
28
|
+
|
|
29
|
+
Read App.tsx and detect which pattern is used:
|
|
30
|
+
|
|
31
|
+
### Pattern A: applicationRoutes Object
|
|
32
|
+
|
|
33
|
+
**If App.tsx contains:** `applicationRoutes: ApplicationRouteExtensions`
|
|
34
|
+
|
|
35
|
+
→ Add routes to `applicationRoutes.{application}[]` with **RELATIVE** paths (no leading `/`)
|
|
36
|
+
|
|
37
|
+
```tsx
|
|
38
|
+
const applicationRoutes: ApplicationRouteExtensions = {
|
|
39
|
+
'human-resources': [
|
|
40
|
+
// existing routes...
|
|
41
|
+
{ path: '{module_kebab}/{section_kebab}', element: <{EntityName}ListPage /> },
|
|
42
|
+
{ path: '{module_kebab}/{section_kebab}/new', element: <Create{EntityName}Page /> },
|
|
43
|
+
{ path: '{module_kebab}/{section_kebab}/:id', element: <{EntityName}DetailPage /> },
|
|
44
|
+
{ path: '{module_kebab}/{section_kebab}/:id/edit', element: <Create{EntityName}Page /> },
|
|
45
|
+
|
|
46
|
+
// Parent redirect routes (MANDATORY — prevents /login redirect on parent navigation)
|
|
47
|
+
{ path: '{module_kebab}', element: <Navigate to="{module_kebab}/{first_section_kebab}" replace /> },
|
|
48
|
+
{ path: '', element: <Navigate to="{first_module_kebab}/{first_section_kebab}" replace /> },
|
|
49
|
+
],
|
|
50
|
+
};
|
|
51
|
+
```
|
|
52
|
+
|
|
53
|
+
Routes are automatically injected into BOTH standard (`/{application}/...`) and tenant-prefixed (`/t/:slug/{application}/...`) route trees by `mergeRoutes()`. No manual duplication needed.
|
|
54
|
+
|
|
55
|
+
### Pattern B: JSX Routes
|
|
56
|
+
|
|
57
|
+
**If App.tsx contains:** `<Route path="/{application}" element={<{Layout} />}>`
|
|
58
|
+
|
|
59
|
+
→ Insert `<Route>` children inside the Layout wrapper:
|
|
60
|
+
|
|
61
|
+
```tsx
|
|
62
|
+
<Route path="/human-resources" element={<AppLayout />}>
|
|
63
|
+
{/* ... existing routes ... */}
|
|
64
|
+
<Route path="{module_kebab}" element={<{EntityName}Page />} />
|
|
65
|
+
</Route>
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
**ALSO add the same routes inside the tenant-prefixed block:**
|
|
69
|
+
|
|
70
|
+
Find `<Route path="/t/:slug">` and add the **same route entries** there.
|
|
71
|
+
|
|
72
|
+
---
|
|
73
|
+
|
|
74
|
+
## Step 4c: Application-to-Layout Mapping
|
|
75
|
+
|
|
76
|
+
| Application prefix | Layout Component | Route path |
|
|
77
|
+
|---------|------------------|------------|
|
|
78
|
+
| `administration.*` | `AppLayout` | `/administration` |
|
|
79
|
+
| `*` (business apps) | `AppLayout` | `/{application}` |
|
|
80
|
+
| `myspace.*` | `AppLayout` | `/myspace` |
|
|
81
|
+
|
|
82
|
+
---
|
|
83
|
+
|
|
84
|
+
## Step 4d: Verify Wiring
|
|
85
|
+
|
|
86
|
+
```
|
|
87
|
+
Tool: mcp__smartstack__validate_frontend_routes
|
|
88
|
+
Args:
|
|
89
|
+
scope: "routes"
|
|
90
|
+
```
|
|
91
|
+
|
|
92
|
+
If `appWiring.issues` is not empty, fix the wiring before proceeding.
|
|
93
|
+
|
|
94
|
+
---
|
|
95
|
+
|
|
96
|
+
## Step 4e: Parent Redirect Routes (MANDATORY)
|
|
97
|
+
|
|
98
|
+
**CRITICAL:** Without parent redirects, navigating to an application or module URL (e.g., `/human-resources` or `/human-resources/employees`) will cause a redirect to `/login` because no route matches.
|
|
99
|
+
|
|
100
|
+
For each application, you MUST add:
|
|
101
|
+
|
|
102
|
+
1. **Application root redirect** — redirects `/{application}` to the first module/section:
|
|
103
|
+
```tsx
|
|
104
|
+
{ path: '', element: <Navigate to="{first_module}/{first_section}" replace /> }
|
|
105
|
+
```
|
|
106
|
+
|
|
107
|
+
2. **Module redirect** (if modules have sections) — redirects `/{application}/{module}` to first section:
|
|
108
|
+
```tsx
|
|
109
|
+
{ path: '{module}', element: <Navigate to="{module}/{first_section}" replace /> }
|
|
110
|
+
```
|
|
111
|
+
|
|
112
|
+
**Example:** For NavRoutes `human-resources.employees.management` and `human-resources.employees.departments`:
|
|
113
|
+
```tsx
|
|
114
|
+
{ path: 'employees', element: <Navigate to="employees/management" replace /> },
|
|
115
|
+
{ path: '', element: <Navigate to="employees/management" replace /> },
|
|
116
|
+
```
|
|
117
|
+
|
|
118
|
+
The `to` prop is resolved relative to the **parent route** (`/{application}`), so always use the full path from the application root.
|
|
119
|
+
|
|
120
|
+
> Note: `scaffold_routes` with `outputFormat: "clientRoutes"` generates these redirects automatically.
|
|
121
|
+
|
|
122
|
+
---
|
|
123
|
+
|
|
124
|
+
## Forbidden Patterns (BOTH patterns)
|
|
125
|
+
|
|
126
|
+
- Adding application routes to `clientRoutes[]` with absolute paths — `clientRoutes` is ONLY for routes outside SmartStack applications (e.g., `/about`, `/pricing`)
|
|
127
|
+
- Adding routes OUTSIDE the Layout wrapper (shell will not render)
|
|
128
|
+
- Using `createBrowserRouter` (SmartStack uses `useRoutes()` + `mergeRoutes()`)
|
|
129
|
+
|
|
130
|
+
---
|
|
131
|
+
|
|
132
|
+
## Verification Checklist
|
|
133
|
+
|
|
134
|
+
- [ ] Routes are inside the AppLayout wrapper
|
|
135
|
+
- [ ] Routes use NESTED structure (not flat)
|
|
136
|
+
- [ ] Application kebab-case matches navigation seed data
|
|
137
|
+
- [ ] Both standard and tenant-prefixed blocks have routes (if using Pattern B)
|
|
138
|
+
- [ ] Page components are imported at top of App.tsx
|
|
139
|
+
- [ ] `mcp__smartstack__validate_frontend_routes` returns no issues
|
|
@@ -0,0 +1,272 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: cli-app-sync
|
|
3
|
+
description: Detect and fix template drift between SmartStack.app (source of truth) and CLI templates
|
|
4
|
+
argument-hint: "[report|fix|check <file>]"
|
|
5
|
+
model: sonnet
|
|
6
|
+
allowed-tools: Read, Grep, Glob, Bash, Edit, Write
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Current state (auto-injected)
|
|
10
|
+
- CLI version: !`node -p "require('./package.json').version" 2>/dev/null || echo "unknown"`
|
|
11
|
+
- CLI branch: !`git rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown"`
|
|
12
|
+
- App branch: !`git -C "D:/01 - projets/SmartStack.app/02-Develop" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown"`
|
|
13
|
+
- App last commit: !`git -C "D:/01 - projets/SmartStack.app/02-Develop" log --oneline -1 2>/dev/null || echo "unknown"`
|
|
14
|
+
|
|
15
|
+
<objective>
|
|
16
|
+
Detect drift between SmartStack.app (the platform / source of truth) and the CLI project templates used by `ss init`.
|
|
17
|
+
|
|
18
|
+
SmartStack.app defines the reference architecture. The CLI templates generate **client projects** that consume the platform via NuGet/npm. Some differences are **intentional by design** (see exclusions below). This skill identifies **unintentional drift** that should be corrected.
|
|
19
|
+
|
|
20
|
+
See [references/comparison-map.md](references/comparison-map.md) for the full file mapping and exclusion rules.
|
|
21
|
+
</objective>
|
|
22
|
+
|
|
23
|
+
<quick_start>
|
|
24
|
+
```bash
|
|
25
|
+
/cli-app-sync # Full drift report (read-only)
|
|
26
|
+
/cli-app-sync report # Same as above
|
|
27
|
+
/cli-app-sync fix # Detect drift + apply fixes interactively
|
|
28
|
+
/cli-app-sync check Program # Check a single file mapping
|
|
29
|
+
```
|
|
30
|
+
</quick_start>
|
|
31
|
+
|
|
32
|
+
<subcommands>
|
|
33
|
+
|
|
34
|
+
| Command | Description |
|
|
35
|
+
|---------|-------------|
|
|
36
|
+
| `/cli-app-sync` | Full drift report across all comparison points |
|
|
37
|
+
| `/cli-app-sync report` | Same as above (explicit) |
|
|
38
|
+
| `/cli-app-sync fix` | Detect drift and propose fixes interactively |
|
|
39
|
+
| `/cli-app-sync check <name>` | Check a single comparison point by name |
|
|
40
|
+
|
|
41
|
+
</subcommands>
|
|
42
|
+
|
|
43
|
+
<paths>
|
|
44
|
+
|
|
45
|
+
**Source of truth (SmartStack.app):**
|
|
46
|
+
```
|
|
47
|
+
APP_ROOT = D:/01 - projets/SmartStack.app/02-Develop
|
|
48
|
+
APP_API = $APP_ROOT/src/SmartStack.Api
|
|
49
|
+
APP_WEB = $APP_ROOT/web/smartstack-web
|
|
50
|
+
```
|
|
51
|
+
|
|
52
|
+
**CLI templates (to validate):**
|
|
53
|
+
```
|
|
54
|
+
CLI_ROOT = D:/01 - projets/SmartStack.cli/02-Develop
|
|
55
|
+
CLI_TEMPLATES = $CLI_ROOT/templates/project
|
|
56
|
+
CLI_INIT = $CLI_ROOT/src/commands/init.ts
|
|
57
|
+
```
|
|
58
|
+
|
|
59
|
+
</paths>
|
|
60
|
+
|
|
61
|
+
<workflow>
|
|
62
|
+
|
|
63
|
+
## Step 1: Resolve paths and verify access
|
|
64
|
+
|
|
65
|
+
```bash
|
|
66
|
+
APP_ROOT="D:/01 - projets/SmartStack.app/02-Develop"
|
|
67
|
+
CLI_ROOT="D:/01 - projets/SmartStack.cli/02-Develop"
|
|
68
|
+
|
|
69
|
+
# Verify both projects are accessible
|
|
70
|
+
[ -d "$APP_ROOT/src/SmartStack.Api" ] || { echo "ERROR: SmartStack.app not found at $APP_ROOT"; exit 1; }
|
|
71
|
+
[ -d "$CLI_ROOT/templates/project" ] || { echo "ERROR: CLI templates not found at $CLI_ROOT"; exit 1; }
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Step 2: Run comparison for each mapping
|
|
75
|
+
|
|
76
|
+
For each entry in the [comparison map](references/comparison-map.md):
|
|
77
|
+
|
|
78
|
+
1. **Read the reference file** from SmartStack.app
|
|
79
|
+
2. **Read the template file** from CLI (either `.template` file or inline content in `init.ts`)
|
|
80
|
+
3. **Compare** the relevant patterns/sections (not byte-for-byte — templates have `{{ProjectName}}` placeholders)
|
|
81
|
+
4. **Classify** the result: `OK`, `DRIFT`, or `INTENTIONAL`
|
|
82
|
+
|
|
83
|
+
### Comparison strategy by type
|
|
84
|
+
|
|
85
|
+
**Template files** (`templates/project/*.template`):
|
|
86
|
+
- Read both files
|
|
87
|
+
- Replace `{{ProjectName}}` with `SmartStack` in the template for comparison
|
|
88
|
+
- Compare structure, imports, method calls, middleware order
|
|
89
|
+
|
|
90
|
+
**Inline templates in `init.ts`**:
|
|
91
|
+
- Extract the template string from `init.ts` (look for the variable assignment)
|
|
92
|
+
- Compare key properties/patterns against the reference file
|
|
93
|
+
- Focus on: dependency versions, compiler options, proxy config, CSS directives
|
|
94
|
+
|
|
95
|
+
## Step 3: Generate report
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
================================================================================
|
|
99
|
+
CLI ↔ APP TEMPLATE SYNC REPORT
|
|
100
|
+
================================================================================
|
|
101
|
+
|
|
102
|
+
SmartStack.app: {branch} @ {commit}
|
|
103
|
+
SmartStack.cli: v{version} @ {branch}
|
|
104
|
+
Date: {date}
|
|
105
|
+
|
|
106
|
+
COMPARISON POINTS: {total}
|
|
107
|
+
--------------------------------------------------------------------------------
|
|
108
|
+
|
|
109
|
+
[OK] Program.cs — Serilog, Kestrel, Swagger, AppInsights present
|
|
110
|
+
[DRIFT] package.json — @types/node ^24.0.0 vs ^26.0.0 in app
|
|
111
|
+
[DRIFT] vite.config.ts — bypass() present but missing ws reconnect
|
|
112
|
+
[OK] tsconfig.json — ES2022, verbatimModuleSyntax, erasableSyntaxOnly
|
|
113
|
+
[OK] index.css — @custom-variant dark present
|
|
114
|
+
[OK] DependencyInjection.Application — MediatR warning present
|
|
115
|
+
[OK] DependencyInjection.Infrastructure — SQL Server pattern matches
|
|
116
|
+
[SKIP] App.tsx — Intentionally different (mergeRoutes pattern)
|
|
117
|
+
[SKIP] ExtensionsDbContext — Intentionally simplified
|
|
118
|
+
|
|
119
|
+
--------------------------------------------------------------------------------
|
|
120
|
+
SUMMARY: {ok} OK | {drift} DRIFT | {skip} SKIPPED
|
|
121
|
+
================================================================================
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
## Step 4: Handle drifts (fix mode)
|
|
125
|
+
|
|
126
|
+
If running `/cli-app-sync fix` and drifts are detected:
|
|
127
|
+
|
|
128
|
+
```yaml
|
|
129
|
+
AskUserQuestion:
|
|
130
|
+
header: "Fix drifts"
|
|
131
|
+
question: "Drifts detected. How do you want to proceed?"
|
|
132
|
+
options:
|
|
133
|
+
- label: "Fix all (Recommended)"
|
|
134
|
+
description: "Apply all fixes automatically"
|
|
135
|
+
- label: "Fix interactively"
|
|
136
|
+
description: "Review and approve each fix individually"
|
|
137
|
+
- label: "Report only"
|
|
138
|
+
description: "Show details without fixing"
|
|
139
|
+
multiSelect: false
|
|
140
|
+
```
|
|
141
|
+
|
|
142
|
+
For each drift in fix mode:
|
|
143
|
+
1. Show the diff (what changed in app vs what the template has)
|
|
144
|
+
2. Propose the fix
|
|
145
|
+
3. Apply using Edit tool (for `.template` files) or inline edit (for `init.ts`)
|
|
146
|
+
|
|
147
|
+
## Step 5: Post-fix verification
|
|
148
|
+
|
|
149
|
+
After applying fixes:
|
|
150
|
+
```bash
|
|
151
|
+
cd "$CLI_ROOT" && npm run build 2>&1
|
|
152
|
+
```
|
|
153
|
+
|
|
154
|
+
If build succeeds, display summary of changes.
|
|
155
|
+
|
|
156
|
+
</workflow>
|
|
157
|
+
|
|
158
|
+
<intentional_differences>
|
|
159
|
+
|
|
160
|
+
These differences are **by design** and should always be marked `[SKIP]`:
|
|
161
|
+
|
|
162
|
+
| File/Pattern | Reason |
|
|
163
|
+
|---|---|
|
|
164
|
+
| `App.tsx` — `mergeRoutes` + `SmartStackProvider` | Client projects use extension routing pattern, not platform routing |
|
|
165
|
+
| `ExtensionsDbContext` | Intentionally simplified vs `CoreDbContext` — different architectural role |
|
|
166
|
+
| `api.ts` | Re-exports SmartStack client — wrapper pattern is correct |
|
|
167
|
+
| `DependencyInjection.Infrastructure.cs` | SQL Server connection pattern identical by design |
|
|
168
|
+
| Skills/Agents/Hooks | Installed globally via `ss install`, not by `ss init` |
|
|
169
|
+
| SmartStack.app-only skills | `bugfix-issue`, `feature-test`, `sonar`, `version-bump` are platform-specific |
|
|
170
|
+
| `appsettings.json` | Client projects have a simplified config (no core service settings) |
|
|
171
|
+
|
|
172
|
+
</intentional_differences>
|
|
173
|
+
|
|
174
|
+
<comparison_categories>
|
|
175
|
+
|
|
176
|
+
### Backend comparisons
|
|
177
|
+
|
|
178
|
+
| ID | App reference | CLI template | Key patterns to check |
|
|
179
|
+
|---|---|---|---|
|
|
180
|
+
| `program-cs` | `src/SmartStack.Api/Program.cs` | `templates/project/Program.cs.template` | Serilog bootstrap, Kestrel HTTP/1.1, appsettings.Local.json, UseSmartStackSerilog, AppInsights, UseSmartStackSwagger, try/catch/finally |
|
|
181
|
+
| `di-app` | *(no direct equivalent)* | `templates/project/DependencyInjection.Application.cs.template` | MediatR warning comment, no double-registration |
|
|
182
|
+
| `di-infra` | `src/SmartStack.Infrastructure/DependencyInjection.cs` | `templates/project/DependencyInjection.Infrastructure.cs.template` | SQL Server connection pattern, AddDbContext |
|
|
183
|
+
| `appsettings` | `src/SmartStack.Api/appsettings.json` | `templates/project/appsettings.json.template` | Serilog config section, ConnectionStrings pattern, Logging sinks |
|
|
184
|
+
|
|
185
|
+
### Frontend comparisons
|
|
186
|
+
|
|
187
|
+
| ID | App reference | CLI template (in `init.ts`) | Key patterns to check |
|
|
188
|
+
|---|---|---|---|
|
|
189
|
+
| `package-json` | `web/smartstack-web/package.json` | `init.ts` → `packageJson` variable | Dependency versions (`@types/node`, `typescript`, `eslint-plugin-react-refresh`), testing stack (`vitest`, `@testing-library/*`), scripts (`test`, `test:watch`, `test:coverage`) |
|
|
190
|
+
| `vite-config` | `web/smartstack-web/vite.config.ts` | `init.ts` → `viteConfig` variable | Proxy bypass() function, plugin list, resolve aliases |
|
|
191
|
+
| `tsconfig` | `web/smartstack-web/tsconfig.json` or `tsconfig.app.json` | `init.ts` → `tsConfig` variable | `target`, `lib`, `verbatimModuleSyntax`, `erasableSyntaxOnly`, no `isolatedModules` |
|
|
192
|
+
| `index-css` | `web/smartstack-web/src/index.css` | `init.ts` → `indexCss` variable | `@import "tailwindcss"`, `@source` directive, `@custom-variant dark` |
|
|
193
|
+
|
|
194
|
+
</comparison_categories>
|
|
195
|
+
|
|
196
|
+
<extraction_patterns>
|
|
197
|
+
|
|
198
|
+
### Extracting inline templates from `init.ts`
|
|
199
|
+
|
|
200
|
+
Templates in `init.ts` are assigned as template literals or objects. Use these patterns to locate them:
|
|
201
|
+
|
|
202
|
+
```
|
|
203
|
+
package.json → search for: "const packageJson = {"
|
|
204
|
+
vite.config → search for: "const viteConfig = \`"
|
|
205
|
+
tsconfig → search for: "const tsConfig = {"
|
|
206
|
+
index.css → search for: "const indexCss = \`"
|
|
207
|
+
```
|
|
208
|
+
|
|
209
|
+
### Comparing versions
|
|
210
|
+
|
|
211
|
+
For `package.json` dependencies, compare:
|
|
212
|
+
- Major version range: `^22.0.0` vs `^24.0.0` → DRIFT if major differs by > 1
|
|
213
|
+
- Tilde vs caret: `~5.9.0` vs `^5.7.0` → DRIFT if strategy differs
|
|
214
|
+
- Missing packages: present in app but absent in template → DRIFT
|
|
215
|
+
- Extra packages in template are OK (client-specific needs)
|
|
216
|
+
|
|
217
|
+
### Comparing TypeScript config
|
|
218
|
+
|
|
219
|
+
Compare key compiler options:
|
|
220
|
+
- `target` and `lib` → must match
|
|
221
|
+
- `verbatimModuleSyntax` → must be present (replaces deprecated `isolatedModules`)
|
|
222
|
+
- `erasableSyntaxOnly` → must be present
|
|
223
|
+
- Other options → informational only
|
|
224
|
+
|
|
225
|
+
</extraction_patterns>
|
|
226
|
+
|
|
227
|
+
<output_format>
|
|
228
|
+
|
|
229
|
+
### Per-comparison detail (verbose)
|
|
230
|
+
|
|
231
|
+
```
|
|
232
|
+
--- program-cs ---
|
|
233
|
+
Reference: SmartStack.app/src/SmartStack.Api/Program.cs
|
|
234
|
+
Template: templates/project/Program.cs.template
|
|
235
|
+
|
|
236
|
+
Checks:
|
|
237
|
+
[OK] Serilog bootstrap logger (Log.Logger = new LoggerConfiguration...)
|
|
238
|
+
[OK] try/catch/finally pattern
|
|
239
|
+
[OK] ConfigureKestrel HTTP/1.1
|
|
240
|
+
[OK] appsettings.Local.json loading
|
|
241
|
+
[OK] UseSmartStackSerilog()
|
|
242
|
+
[OK] Application Insights conditional
|
|
243
|
+
[OK] UseSmartStackSwagger()
|
|
244
|
+
[OK] Log.Information start/success messages
|
|
245
|
+
|
|
246
|
+
Status: OK
|
|
247
|
+
```
|
|
248
|
+
|
|
249
|
+
### Drift detail
|
|
250
|
+
|
|
251
|
+
```
|
|
252
|
+
--- package-json ---
|
|
253
|
+
Reference: SmartStack.app/web/smartstack-web/package.json
|
|
254
|
+
Template: init.ts → packageJson
|
|
255
|
+
|
|
256
|
+
Drifts:
|
|
257
|
+
[DRIFT] @types/node: template=^24.0.0, app=^26.0.0
|
|
258
|
+
[DRIFT] Missing devDependency: @testing-library/dom
|
|
259
|
+
|
|
260
|
+
Status: DRIFT (2 issues)
|
|
261
|
+
```
|
|
262
|
+
|
|
263
|
+
</output_format>
|
|
264
|
+
|
|
265
|
+
<success_criteria>
|
|
266
|
+
- All comparison points from the map are checked
|
|
267
|
+
- Intentional differences are correctly identified as SKIP
|
|
268
|
+
- Drift detection catches: missing patterns, outdated versions, removed options
|
|
269
|
+
- Fix mode correctly updates template files and init.ts inline templates
|
|
270
|
+
- Build passes after fixes are applied
|
|
271
|
+
- Report is clear, actionable, and easy to scan
|
|
272
|
+
</success_criteria>
|
|
@@ -0,0 +1,228 @@
|
|
|
1
|
+
# Comparison Map: SmartStack.app ↔ CLI Templates
|
|
2
|
+
|
|
3
|
+
> This file defines the **exact mapping** between SmartStack.app (source of truth)
|
|
4
|
+
> and CLI templates. Used by `/cli-app-sync` to detect drift.
|
|
5
|
+
|
|
6
|
+
## Paths
|
|
7
|
+
|
|
8
|
+
| Alias | Path |
|
|
9
|
+
|---|---|
|
|
10
|
+
| `APP_API` | `D:/01 - projets/SmartStack.app/02-Develop/src/SmartStack.Api` |
|
|
11
|
+
| `APP_WEB` | `D:/01 - projets/SmartStack.app/02-Develop/web/smartstack-web` |
|
|
12
|
+
| `CLI_TPL` | `D:/01 - projets/SmartStack.cli/02-Develop/templates/project` |
|
|
13
|
+
| `CLI_INIT` | `D:/01 - projets/SmartStack.cli/02-Develop/src/commands/init.ts` |
|
|
14
|
+
|
|
15
|
+
---
|
|
16
|
+
|
|
17
|
+
## Backend Comparisons
|
|
18
|
+
|
|
19
|
+
### `program-cs` — Program.cs startup pipeline
|
|
20
|
+
|
|
21
|
+
| | Path |
|
|
22
|
+
|---|---|
|
|
23
|
+
| **Reference** | `APP_API/Program.cs` |
|
|
24
|
+
| **Template** | `CLI_TPL/Program.cs.template` |
|
|
25
|
+
|
|
26
|
+
**Patterns to verify (ordered by startup sequence):**
|
|
27
|
+
|
|
28
|
+
| # | Pattern | Grep/search | Critical |
|
|
29
|
+
|---|---|---|---|
|
|
30
|
+
| 1 | Serilog usings | `using Serilog;` + `using Serilog.Events;` | YES |
|
|
31
|
+
| 2 | Bootstrap logger | `Log.Logger = new LoggerConfiguration()` | YES |
|
|
32
|
+
| 3 | try/catch/finally | `try {` ... `catch (Exception` ... `finally` | YES |
|
|
33
|
+
| 4 | Kestrel HTTP/1.1 | `ConfigureKestrel` + `HttpProtocols.Http1` | YES |
|
|
34
|
+
| 5 | appsettings.Local.json | `AddJsonFile("appsettings.Local.json"` | YES |
|
|
35
|
+
| 6 | Serilog from config | `UseSmartStackSerilog()` | YES |
|
|
36
|
+
| 7 | Application Insights | `AddApplicationInsightsTelemetry` | YES |
|
|
37
|
+
| 8 | AddSmartStack | `AddSmartStack(builder.Configuration` | YES |
|
|
38
|
+
| 9 | InitializeSmartStackAsync | `InitializeSmartStackAsync()` | YES |
|
|
39
|
+
| 10 | Swagger | `UseSmartStackSwagger()` | YES |
|
|
40
|
+
| 11 | Middleware pipeline | `UseSmartStack()` then `MapSmartStack()` | YES |
|
|
41
|
+
| 12 | Success log | `Log.Information(` ... `started successfully` | NO |
|
|
42
|
+
| 13 | Fatal log | `Log.Fatal(ex,` | YES |
|
|
43
|
+
| 14 | CloseAndFlush | `Log.CloseAndFlush()` | YES |
|
|
44
|
+
|
|
45
|
+
**Template-specific additions (not in app):**
|
|
46
|
+
- `using Microsoft.EntityFrameworkCore;` (for ExtensionsDbContext migration)
|
|
47
|
+
- `Add{{ProjectName}}Infrastructure` / `Add{{ProjectName}}Application` (client DI)
|
|
48
|
+
- ExtensionsDbContext migration block (after InitializeSmartStackAsync)
|
|
49
|
+
|
|
50
|
+
---
|
|
51
|
+
|
|
52
|
+
### `di-app` — DependencyInjection.Application.cs
|
|
53
|
+
|
|
54
|
+
| | Path |
|
|
55
|
+
|---|---|
|
|
56
|
+
| **Reference** | *(no app equivalent — client-only pattern)* |
|
|
57
|
+
| **Template** | `CLI_TPL/DependencyInjection.Application.cs.template` |
|
|
58
|
+
|
|
59
|
+
**Patterns to verify:**
|
|
60
|
+
|
|
61
|
+
| # | Pattern | Search | Critical |
|
|
62
|
+
|---|---|---|---|
|
|
63
|
+
| 1 | MediatR warning | `MediatR is already registered` or `do NOT register it again` | YES |
|
|
64
|
+
| 2 | No AddMediatR example | must NOT contain `services.AddMediatR(cfg =>` | YES |
|
|
65
|
+
|
|
66
|
+
---
|
|
67
|
+
|
|
68
|
+
### `di-infra` — DependencyInjection.Infrastructure.cs
|
|
69
|
+
|
|
70
|
+
| | Path |
|
|
71
|
+
|---|---|
|
|
72
|
+
| **Reference** | `APP_API/../SmartStack.Infrastructure/DependencyInjection.cs` |
|
|
73
|
+
| **Template** | `CLI_TPL/DependencyInjection.Infrastructure.cs.template` |
|
|
74
|
+
|
|
75
|
+
**Patterns to verify:**
|
|
76
|
+
|
|
77
|
+
| # | Pattern | Search | Critical |
|
|
78
|
+
|---|---|---|---|
|
|
79
|
+
| 1 | AddDbContext pattern | `AddDbContext<ExtensionsDbContext>` | YES |
|
|
80
|
+
| 2 | SQL Server | `UseSqlServer` | YES |
|
|
81
|
+
| 3 | Connection string | `GetConnectionString` | YES |
|
|
82
|
+
|
|
83
|
+
---
|
|
84
|
+
|
|
85
|
+
### `appsettings` — appsettings.json
|
|
86
|
+
|
|
87
|
+
| | Path |
|
|
88
|
+
|---|---|
|
|
89
|
+
| **Reference** | `APP_API/appsettings.json` |
|
|
90
|
+
| **Template** | `CLI_TPL/appsettings.json.template` |
|
|
91
|
+
|
|
92
|
+
**Patterns to verify:**
|
|
93
|
+
|
|
94
|
+
| # | Pattern | Search | Critical |
|
|
95
|
+
|---|---|---|---|
|
|
96
|
+
| 1 | Serilog config section | `"Serilog"` | YES |
|
|
97
|
+
| 2 | ConnectionStrings | `"ConnectionStrings"` | YES |
|
|
98
|
+
| 3 | Logging sinks | `"Logging"` section | NO |
|
|
99
|
+
|
|
100
|
+
---
|
|
101
|
+
|
|
102
|
+
## Frontend Comparisons
|
|
103
|
+
|
|
104
|
+
### `package-json` — package.json dependencies and scripts
|
|
105
|
+
|
|
106
|
+
| | Path |
|
|
107
|
+
|---|---|
|
|
108
|
+
| **Reference** | `APP_WEB/package.json` |
|
|
109
|
+
| **Template** | `CLI_INIT` → variable `packageJson` (search: `const packageJson = {`) |
|
|
110
|
+
|
|
111
|
+
**Dependency version checks:**
|
|
112
|
+
|
|
113
|
+
| Package | Category | Compare rule |
|
|
114
|
+
|---|---|---|
|
|
115
|
+
| `@types/node` | devDependencies | Major range must match app (e.g., `^24` vs `^26`) |
|
|
116
|
+
| `typescript` | devDependencies | Range strategy and major must match (`~5.9` vs `~5.9`) |
|
|
117
|
+
| `eslint-plugin-react-refresh` | devDependencies | Major range must match |
|
|
118
|
+
| `react` | dependencies | Major range must match |
|
|
119
|
+
| `react-dom` | dependencies | Major range must match |
|
|
120
|
+
| `vite` | devDependencies | Major range must match |
|
|
121
|
+
| `tailwindcss` | dependencies | Major range must match |
|
|
122
|
+
|
|
123
|
+
**Testing stack (must be present in template):**
|
|
124
|
+
|
|
125
|
+
| Package | Required |
|
|
126
|
+
|---|---|
|
|
127
|
+
| `vitest` | YES |
|
|
128
|
+
| `@vitest/coverage-v8` | YES |
|
|
129
|
+
| `@testing-library/react` | YES |
|
|
130
|
+
| `@testing-library/jest-dom` | YES |
|
|
131
|
+
| `@testing-library/user-event` | YES |
|
|
132
|
+
| `jsdom` | YES |
|
|
133
|
+
|
|
134
|
+
**Scripts (must be present in template):**
|
|
135
|
+
|
|
136
|
+
| Script | Command |
|
|
137
|
+
|---|---|
|
|
138
|
+
| `test` | `vitest run` |
|
|
139
|
+
| `test:watch` | `vitest` |
|
|
140
|
+
| `test:coverage` | `vitest run --coverage` |
|
|
141
|
+
|
|
142
|
+
---
|
|
143
|
+
|
|
144
|
+
### `vite-config` — vite.config.ts proxy and plugins
|
|
145
|
+
|
|
146
|
+
| | Path |
|
|
147
|
+
|---|---|
|
|
148
|
+
| **Reference** | `APP_WEB/vite.config.ts` |
|
|
149
|
+
| **Template** | `CLI_INIT` → variable `viteConfig` (search: `` const viteConfig = ` ``) |
|
|
150
|
+
|
|
151
|
+
**Patterns to verify:**
|
|
152
|
+
|
|
153
|
+
| # | Pattern | Search | Critical |
|
|
154
|
+
|---|---|---|---|
|
|
155
|
+
| 1 | React plugin | `react()` | YES |
|
|
156
|
+
| 2 | Tailwind plugin | `tailwindcss()` | YES |
|
|
157
|
+
| 3 | API proxy | `'/api':` | YES |
|
|
158
|
+
| 4 | Proxy bypass | `bypass(req` or `bypass:` | YES |
|
|
159
|
+
| 5 | HTML accept check | `accept?.includes('text/html')` | YES |
|
|
160
|
+
| 6 | SignalR proxy | `'/hubs':` | YES |
|
|
161
|
+
| 7 | WebSocket flag | `ws: true` | YES |
|
|
162
|
+
| 8 | Path alias | `'@': '/src'` or `'@/': './src'` | YES |
|
|
163
|
+
|
|
164
|
+
---
|
|
165
|
+
|
|
166
|
+
### `tsconfig` — tsconfig.json compiler options
|
|
167
|
+
|
|
168
|
+
| | Path |
|
|
169
|
+
|---|---|
|
|
170
|
+
| **Reference** | `APP_WEB/tsconfig.json` or `APP_WEB/tsconfig.app.json` |
|
|
171
|
+
| **Template** | `CLI_INIT` → variable `tsConfig` (search: `const tsConfig = {`) |
|
|
172
|
+
|
|
173
|
+
**Options to verify:**
|
|
174
|
+
|
|
175
|
+
| Option | Expected value | Critical |
|
|
176
|
+
|---|---|---|
|
|
177
|
+
| `target` | `ES2022` | YES |
|
|
178
|
+
| `lib` | includes `ES2022` | YES |
|
|
179
|
+
| `verbatimModuleSyntax` | `true` | YES |
|
|
180
|
+
| `erasableSyntaxOnly` | `true` | YES |
|
|
181
|
+
| `isolatedModules` | must NOT be present (deprecated) | YES |
|
|
182
|
+
| `moduleResolution` | `bundler` | YES |
|
|
183
|
+
| `jsx` | `react-jsx` | YES |
|
|
184
|
+
| `strict` | `true` | YES |
|
|
185
|
+
|
|
186
|
+
---
|
|
187
|
+
|
|
188
|
+
### `index-css` — index.css Tailwind directives
|
|
189
|
+
|
|
190
|
+
| | Path |
|
|
191
|
+
|---|---|
|
|
192
|
+
| **Reference** | `APP_WEB/src/index.css` |
|
|
193
|
+
| **Template** | `CLI_INIT` → variable `indexCss` (search: `` const indexCss = ` ``) |
|
|
194
|
+
|
|
195
|
+
**Patterns to verify:**
|
|
196
|
+
|
|
197
|
+
| # | Pattern | Search | Critical |
|
|
198
|
+
|---|---|---|---|
|
|
199
|
+
| 1 | Tailwind import | `@import "tailwindcss"` | YES |
|
|
200
|
+
| 2 | Source directive | `@source "../node_modules/@atlashub/smartstack` | YES |
|
|
201
|
+
| 3 | Dark mode variant | `@custom-variant dark` | YES |
|
|
202
|
+
|
|
203
|
+
---
|
|
204
|
+
|
|
205
|
+
## Intentional Exclusions (SKIP)
|
|
206
|
+
|
|
207
|
+
These comparisons should **always** return `[SKIP]` — differences are by design.
|
|
208
|
+
|
|
209
|
+
| Item | Reason |
|
|
210
|
+
|---|---|
|
|
211
|
+
| `App.tsx` | Client uses `mergeRoutes` + `SmartStackProvider`; app uses direct routing |
|
|
212
|
+
| `api.ts` | Client re-exports SmartStack client — wrapper pattern is correct |
|
|
213
|
+
| `ExtensionsDbContext` | Intentionally simplified vs `CoreDbContext` |
|
|
214
|
+
| `GlobalUsings.cs` | App has platform-wide usings; client has minimal set |
|
|
215
|
+
| Skills/Agents/Hooks | Installed globally via `ss install`, not by `ss init` |
|
|
216
|
+
| Platform-specific skills | `bugfix-issue`, `feature-test`, `sonar`, `version-bump` |
|
|
217
|
+
| CI/CD files | `azure-pipelines.yml` is platform-specific |
|
|
218
|
+
| `CLAUDE.md` | Each project has its own instructions |
|
|
219
|
+
|
|
220
|
+
---
|
|
221
|
+
|
|
222
|
+
## Maintenance
|
|
223
|
+
|
|
224
|
+
When adding a new comparison point:
|
|
225
|
+
1. Add an entry to the appropriate section above
|
|
226
|
+
2. Define the reference path and template location
|
|
227
|
+
3. List the key patterns to check with criticality
|
|
228
|
+
4. Update the SKILL.md `<comparison_categories>` table
|
|
@@ -59,6 +59,7 @@ Execute GitFlow workflows with automatic versioning, worktree management, and EF
|
|
|
59
59
|
| `-s` | `--status` | Status mode: show state only, no actions |
|
|
60
60
|
| `-v` | `--verbose` | Verbose output |
|
|
61
61
|
| `--dry-run` | | Preview actions without executing |
|
|
62
|
+
| `--smartstack` | | Init + SmartStack project scaffolding (backend, frontend, config) |
|
|
62
63
|
|
|
63
64
|
**⚠️ CRITICAL: Without `-a`, each command executes ONLY its own step then STOPS.**
|
|
64
65
|
|
|
@@ -125,6 +126,9 @@ Execute GitFlow workflows with automatic versioning, worktree management, and EF
|
|
|
125
126
|
# UTILITY COMMANDS
|
|
126
127
|
# ══════════════════════════════════════════════════════════════
|
|
127
128
|
|
|
129
|
+
/gitflow init # Git structure only (bare + worktrees)
|
|
130
|
+
/gitflow init --smartstack # Git structure + SmartStack project init
|
|
131
|
+
|
|
128
132
|
/gitflow status # Show current state
|
|
129
133
|
/gitflow -s # Shorthand for status
|
|
130
134
|
/gitflow abort # Rollback current operation
|
|
@@ -186,6 +190,7 @@ start ──► commit* ──► sync ──► pr ──► merge ──► fi
|
|
|
186
190
|
| Input Pattern | Step File | Task Agent (`subagent_type`) |
|
|
187
191
|
|---------------|-----------|----------------------------|
|
|
188
192
|
| `init` | `steps/step-init.md` | **ALWAYS INLINE** (see below) |
|
|
193
|
+
| `init --smartstack` | `steps/step-init.md` | **ALWAYS INLINE** (Git + SmartStack init) |
|
|
189
194
|
| `start`, `-f`, `-r`, `-h` | `steps/step-start.md` | `gitflow-start` |
|
|
190
195
|
| `commit [msg]` | `steps/step-commit.md` | `gitflow-commit` |
|
|
191
196
|
| `sync` | `steps/step-sync.md` | — |
|