@atlashub/smartstack-cli 4.75.0 → 4.79.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/index.js +87 -41
- package/dist/index.js.map +1 -1
- package/package.json +1 -1
- package/templates/project/claude-md/root.CLAUDE.md.template +1 -1
- package/templates/skills/ai-prompt/SKILL.md +64 -0
- package/templates/skills/ai-prompt/references/ai-agent-modes.md +89 -0
- package/templates/skills/ai-prompt/references/eval-framework.md +129 -0
- package/templates/skills/apex/SKILL.md +2 -2
- package/templates/skills/apex/references/checks/frontend-checks.sh +123 -11
- package/templates/skills/apex/references/checks/seed-checks.sh +81 -7
- package/templates/skills/apex/references/core-seed-data.md +27 -22
- package/templates/skills/apex/references/domain-events-pattern.md +45 -0
- package/templates/skills/apex/references/entity-hooks-pattern.md +68 -0
- package/templates/skills/apex/references/licensing-enforcement.md +52 -0
- package/templates/skills/apex/references/post-checks.md +18 -1
- package/templates/skills/apex/references/smartstack-api.md +116 -5
- package/templates/skills/apex/references/smartstack-frontend.md +1 -1
- package/templates/skills/apex/references/smartstack-layers.md +6 -6
- package/templates/skills/apex/steps/step-00-init.md +1 -1
- package/templates/skills/apex/steps/step-03b-layer1-seed.md +26 -0
- package/templates/skills/apex/steps/step-03d-layer3-frontend.md +124 -2
- package/templates/skills/apex/steps/step-04-examine.md +163 -0
- package/templates/skills/apex-verify/SKILL.md +110 -0
- package/templates/skills/apex-verify/references/audit-rules.md +50 -0
- package/templates/skills/apex-verify/steps/step-00-init.md +119 -0
- package/templates/skills/apex-verify/steps/step-01-nav-audit.md +96 -0
- package/templates/skills/apex-verify/steps/step-02-crud-audit.md +127 -0
- package/templates/skills/apex-verify/steps/step-03-perm-audit.md +119 -0
- package/templates/skills/apex-verify/steps/step-04-route-audit.md +98 -0
- package/templates/skills/apex-verify/steps/step-05-report.md +110 -0
- package/templates/skills/application/references/contexts-cheatsheet.md +86 -0
- package/templates/skills/application/references/extensions-system.md +158 -0
- package/templates/skills/application/references/frontend-route-naming.md +7 -5
- package/templates/skills/application/references/frontend-verification.md +7 -5
- package/templates/skills/application/references/provider-template.md +4 -2
- package/templates/skills/application/references/smartstack-provider.md +118 -0
- package/templates/skills/application/references/themes-db-driven.md +484 -0
- package/templates/skills/application/templates-frontend.md +2 -2
- package/templates/skills/application/templates-seed.md +4 -2
- package/templates/skills/audit-route/references/routing-pattern.md +3 -1
- package/templates/skills/business-analyse/SKILL.md +3 -3
- package/templates/skills/business-analyse/_shared.md +37 -0
- package/templates/skills/business-analyse/react/components.md +30 -28
- package/templates/skills/business-analyse/references/03-json-schemas.md +11 -3
- package/templates/skills/business-analyse/references/03-post-check-validation.md +64 -0
- package/templates/skills/business-analyse/references/canonical-json-formats.md +7 -3
- package/templates/skills/business-analyse/references/robustness-checks.md +1 -1
- package/templates/skills/business-analyse/references/validation-checklist.md +5 -5
- package/templates/skills/business-analyse/schemas/sections/analysis-schema.json +15 -4
- package/templates/skills/business-analyse/steps/step-03-specify.md +162 -4
- package/templates/skills/business-analyse/steps/step-04-consolidate.md +211 -1
- package/templates/skills/business-analyse/templates-react.md +15 -15
- package/templates/skills/business-analyse-handoff/references/agent-handoff-transform-prompt.md +3 -0
- package/templates/skills/business-analyse-html/html/ba-interactive.html +198 -16
- package/templates/skills/business-analyse-html/html/src/scripts/01-data-init.js +64 -0
- package/templates/skills/business-analyse-html/html/src/scripts/05-render-specs.js +80 -11
- package/templates/skills/business-analyse-html/html/src/scripts/06-render-consolidation.js +2 -2
- package/templates/skills/business-analyse-html/html/src/scripts/06-render-mockups.js +6 -3
- package/templates/skills/business-analyse-html/html/src/scripts/12-render-diagrams.js +46 -0
- package/templates/skills/business-analyse-html/references/02-feature-data-building.md +4 -2
- package/templates/skills/business-analyse-html/references/data-build.md +2 -0
- package/templates/skills/business-analyse-html/references/data-mapping.md +88 -21
- package/templates/skills/business-analyse-html/steps/step-02-build-data.md +6 -0
- package/templates/skills/business-analyse-html/steps/step-04-verify.md +92 -3
- package/templates/skills/business-analyse-quick/SKILL.md +807 -0
- package/templates/skills/{sketch → business-analyse-quick}/references/domain-heuristics.md +59 -3
- package/templates/skills/business-analyse-quick/references/prd-schema.md +268 -0
- package/templates/skills/business-analyse-review/references/review-data-mapping.md +6 -0
- package/templates/skills/cli-app-sync/SKILL.md +105 -4
- package/templates/skills/cli-app-sync/references/comparison-map.md +13 -0
- package/templates/skills/cli-app-sync/references/diff-entities.md +162 -0
- package/templates/skills/dev-start/SKILL.md +7 -7
- package/templates/skills/documentation/templates.md +16 -16
- package/templates/skills/migrate/SKILL.md +312 -0
- package/templates/skills/migrate/references/v3.34-to-v3.46.md +289 -0
- package/templates/skills/sketch/SKILL.md +15 -153
- package/templates/skills/smoke-generation/SKILL.md +313 -0
- package/templates/skills/ui-components/SKILL.md +11 -1
- package/templates/skills/ui-components/patterns/data-table.md +1 -1
- package/templates/skills/ui-components/references/component-catalog.md +82 -0
- package/templates/skills/workflow/SKILL.md +70 -1
|
@@ -0,0 +1,162 @@
|
|
|
1
|
+
# `/cli-app-sync diff-entities` — Reference
|
|
2
|
+
|
|
3
|
+
> Detailed algorithm and rules for the `diff-entities` sub-mode of `/cli-app-sync`.
|
|
4
|
+
|
|
5
|
+
## What it solves
|
|
6
|
+
|
|
7
|
+
The default `cli-app-sync` mode compares **known file pairs** (Program.cs ↔ Program.cs.template, vite.config.ts ↔ inline `init.ts`, etc.). It is good at catching **explicit drift** in those known surfaces.
|
|
8
|
+
|
|
9
|
+
It is blind to **trous** : when SmartStack.app introduces a brand-new entity (e.g. `AiTool` in v3.46) that no skill in `templates/skills/` mentions, nothing fires. The drift only surfaces during a manual audit (which is what just happened in the v3.46 alignment iteration 3 — 7 uncovered entities discovered by reading the `Domain/` directory by hand).
|
|
10
|
+
|
|
11
|
+
`diff-entities` automates that audit : it enumerates every Domain entity and reports those without coverage in the CLI skills.
|
|
12
|
+
|
|
13
|
+
## Inputs
|
|
14
|
+
|
|
15
|
+
| Variable | Default | Source |
|
|
16
|
+
|---|---|---|
|
|
17
|
+
| `APP_PATH` | `D:/01 - projets/SmartStack.app/features/IA-Workflow` | `--app-path=...` flag, otherwise the IA-Workflow branch (current source of truth) |
|
|
18
|
+
| `CLI_SKILLS` | `D:/01 - projets/SmartStack.cli/02-Develop/templates/skills` | hardcoded |
|
|
19
|
+
| `MIN_REFS` | `3` | a "well-covered" entity has at least 3 mentions across templates |
|
|
20
|
+
|
|
21
|
+
## Step-by-step algorithm
|
|
22
|
+
|
|
23
|
+
### 1. Enumerate Domain entities (the haystack)
|
|
24
|
+
|
|
25
|
+
Pattern (Bash + grep) :
|
|
26
|
+
```bash
|
|
27
|
+
APP_DOMAIN="$APP_PATH/src/SmartStack.Domain"
|
|
28
|
+
|
|
29
|
+
grep -rPnh \
|
|
30
|
+
"^\s*public\s+(?:partial\s+)?(?:abstract\s+)?(?:class|record)\s+([A-Z][A-Za-z0-9]+)\s*:?\s*(?:BaseEntity|I[A-Z][A-Za-z]+Entity|IDomainEvent|DomainEvent)\b" \
|
|
31
|
+
"$APP_DOMAIN" --include='*.cs' \
|
|
32
|
+
| sed -E "s/.*\b(?:class|record)\s+([A-Z][A-Za-z0-9]+).*/\1/" \
|
|
33
|
+
| sort -u > /tmp/app-entities.txt
|
|
34
|
+
```
|
|
35
|
+
|
|
36
|
+
This captures :
|
|
37
|
+
- Classes inheriting `BaseEntity` (most aggregate roots)
|
|
38
|
+
- Classes implementing `IXxxEntity` interfaces (`ITenantEntity`, `IOptionalTenantEntity`, …)
|
|
39
|
+
- Domain events (inheriting `DomainEvent` or implementing `IDomainEvent`)
|
|
40
|
+
|
|
41
|
+
It deliberately excludes :
|
|
42
|
+
- Pure value objects (no marker interface)
|
|
43
|
+
- Internal helper classes
|
|
44
|
+
- DTOs (those live in `Application/`)
|
|
45
|
+
|
|
46
|
+
If you suspect an entity is missed, broaden the regex or add a manual entry in the exclusion list.
|
|
47
|
+
|
|
48
|
+
### 2. Count references in CLI skills (the needles)
|
|
49
|
+
|
|
50
|
+
For each entity name `E`, count how many `templates/skills/**/*.md|*.sh` files mention it as a whole word :
|
|
51
|
+
|
|
52
|
+
```bash
|
|
53
|
+
CLI_SKILLS="D:/01 - projets/SmartStack.cli/02-Develop/templates/skills"
|
|
54
|
+
|
|
55
|
+
while IFS= read -r ENT; do
|
|
56
|
+
COUNT=$(grep -rl --include='*.md' --include='*.sh' -E "\\b${ENT}\\b" "$CLI_SKILLS" | wc -l)
|
|
57
|
+
echo -e "${ENT}\t${COUNT}"
|
|
58
|
+
done < /tmp/app-entities.txt > /tmp/entity-coverage.tsv
|
|
59
|
+
```
|
|
60
|
+
|
|
61
|
+
Counting **distinct files** (not occurrences) is intentional — 50 mentions in one file ≈ 1 file with deep coverage, not 50 files of shallow coverage.
|
|
62
|
+
|
|
63
|
+
### 3. Classify
|
|
64
|
+
|
|
65
|
+
| Bucket | Rule | Action |
|
|
66
|
+
|---|---|---|
|
|
67
|
+
| `[NEW UNCOVERED]` | `count == 0` | Propose a skill destination (table below) |
|
|
68
|
+
| `[THIN]` | `1 <= count < MIN_REFS` (default `MIN_REFS=3`) | Suggest extending an existing skill or adding a dedicated `references/` doc |
|
|
69
|
+
| `[COVERED]` | `count >= MIN_REFS` | Hide from report unless `--verbose` |
|
|
70
|
+
|
|
71
|
+
### 4. Suggest a skill destination
|
|
72
|
+
|
|
73
|
+
Map the entity's namespace to a target skill :
|
|
74
|
+
|
|
75
|
+
```python
|
|
76
|
+
def suggest_skill(namespace, entity_name):
|
|
77
|
+
rules = [
|
|
78
|
+
("Domain.AI.Evaluations", "ai-prompt/references/eval-framework.md"),
|
|
79
|
+
("Domain.AI.Tools", "ai-prompt"),
|
|
80
|
+
("Domain.AI.Agents", "ai-prompt"),
|
|
81
|
+
("Domain.AI.Skills", "ai-prompt"),
|
|
82
|
+
("Domain.AI", "ai-prompt"),
|
|
83
|
+
("Domain.Communications.Workflow", "workflow"),
|
|
84
|
+
("Domain.Communications.EmailTemplate", "notification"),
|
|
85
|
+
("Domain.Communications", "workflow"),
|
|
86
|
+
("Domain.Navigation", "application"),
|
|
87
|
+
("Domain.Platform.Administration.UiConfiguration", "application/references/themes-db-driven.md"),
|
|
88
|
+
("Domain.Platform.Administration", "application"),
|
|
89
|
+
("Domain.Licensing", "apex/references/smartstack-api.md (Licensing section)"),
|
|
90
|
+
("Domain.Common", "apex/references/smartstack-api.md"),
|
|
91
|
+
("Domain.Support", "notification"),
|
|
92
|
+
("Application.Common.Interfaces.Hooks", "apex/references/smartstack-api.md (Entity Lifecycle Hooks)"),
|
|
93
|
+
]
|
|
94
|
+
for prefix, skill in rules:
|
|
95
|
+
if namespace.startswith(prefix):
|
|
96
|
+
return skill
|
|
97
|
+
return f"NEW SKILL — propose name based on namespace: {namespace.split('.')[-1].lower()}"
|
|
98
|
+
```
|
|
99
|
+
|
|
100
|
+
When the namespace doesn't match any rule, propose a brand-new skill name derived from the leaf segment.
|
|
101
|
+
|
|
102
|
+
### 5. Render the report
|
|
103
|
+
|
|
104
|
+
See the example output in `SKILL.md` (`<diff_entities_workflow>` section).
|
|
105
|
+
|
|
106
|
+
Sort order : `[NEW UNCOVERED]` first, then `[THIN]`, then (only with `--verbose`) `[COVERED]`. Within each bucket, alphabetical.
|
|
107
|
+
|
|
108
|
+
## Exclusion list
|
|
109
|
+
|
|
110
|
+
Some entities are intentionally NOT documented by any skill — they are infrastructure plumbing the SDK abstracts away. Maintain this list manually :
|
|
111
|
+
|
|
112
|
+
```
|
|
113
|
+
EXCLUDED_ENTITIES = {
|
|
114
|
+
# Marker / framework types — not domain concepts
|
|
115
|
+
"DomainEvent", # abstract base, not a concrete event
|
|
116
|
+
"BaseEntity", # already documented in smartstack-api.md
|
|
117
|
+
"EntityScope", # enum, documented inline
|
|
118
|
+
|
|
119
|
+
# Internal helpers — not part of the public SDK
|
|
120
|
+
# (add as needed)
|
|
121
|
+
}
|
|
122
|
+
```
|
|
123
|
+
|
|
124
|
+
Implementation : after step 1, filter out names in this set before counting.
|
|
125
|
+
|
|
126
|
+
## Output flags
|
|
127
|
+
|
|
128
|
+
| Flag | Effect |
|
|
129
|
+
|---|---|
|
|
130
|
+
| `--verbose` | Show `[COVERED]` entities too (debugging) |
|
|
131
|
+
| `--report-only` | Don't write cache, print to stdout only |
|
|
132
|
+
| `--app-path=<path>` | Override the default APP_PATH (e.g. testing against `02-Develop` or another branch) |
|
|
133
|
+
| `--min-refs=<n>` | Custom threshold for `[THIN]` vs `[COVERED]` (default 3) |
|
|
134
|
+
| `--json` | Output machine-readable JSON instead of human report |
|
|
135
|
+
|
|
136
|
+
## Exit code
|
|
137
|
+
|
|
138
|
+
- 0 if zero entities classified `[NEW UNCOVERED]`
|
|
139
|
+
- 1 otherwise (so `diff-entities` can be a CI quality gate)
|
|
140
|
+
|
|
141
|
+
`[THIN]` entities do NOT fail the gate — they're warnings.
|
|
142
|
+
|
|
143
|
+
## Performance
|
|
144
|
+
|
|
145
|
+
- Step 1 (enumerate) : ~200-400 ms (grep over `Domain/` ≈ 100 files)
|
|
146
|
+
- Step 2 (count) : ~2-5 s (grep over `templates/skills/` ≈ 350 files × N entities)
|
|
147
|
+
- Total : < 10 s for a typical run — eligible for pre-commit hooks and CI
|
|
148
|
+
|
|
149
|
+
## Limitations
|
|
150
|
+
|
|
151
|
+
- **Heuristic regex for entity discovery** : may miss entities that don't follow the `class X : BaseEntity` pattern. Augment with explicit lookups for known patterns if false negatives appear.
|
|
152
|
+
- **Word-boundary count** : `AiTool` matches `AiTool` exactly but also matches a `AiTool` mention in a code comment. Acceptable noise — the goal is to spot zero-reference entities.
|
|
153
|
+
- **No DTO / Service coverage** : the skill only enumerates Domain entities. DTOs and Services live in `Application/` and are not in scope (they're typically auto-generated by MCP, so missing skill coverage is less impactful).
|
|
154
|
+
- **Doesn't catch DELETED entities** : if an entity is removed from app but still cited in skills, this skill won't flag it. Use the existing `cli-app-sync report` for that direction.
|
|
155
|
+
|
|
156
|
+
## Relation to other skills / checks
|
|
157
|
+
|
|
158
|
+
- **`cli-app-sync report`** : detects **content drift** in known file pairs. Complementary, not redundant.
|
|
159
|
+
- **`smoke-generation --quick`** : detects **broken imports** (the EntityLookup paradox). Catches references to things the CLI invented but the app doesn't have. `diff-entities` catches the inverse direction.
|
|
160
|
+
- **`apex-verify`** : runs after generation, catches generated code that doesn't follow conventions. Operates at a different layer.
|
|
161
|
+
|
|
162
|
+
Together, the trio `cli-app-sync report` + `cli-app-sync diff-entities` + `smoke-generation` covers the full bidirectional drift surface.
|
|
@@ -87,9 +87,9 @@ echo "=== MODE ==="
|
|
|
87
87
|
echo "=== ENV ==="
|
|
88
88
|
cat web/smartstack-web/.env.development 2>/dev/null || cat web/smartstack-web/.env.standalone 2>/dev/null || echo "NONE"
|
|
89
89
|
echo "=== SQL ==="
|
|
90
|
-
CS=$(
|
|
91
|
-
SN=$(echo "$CS" |
|
|
92
|
-
DB=$(echo "$CS" |
|
|
90
|
+
CS=$(sed -n 's/.*"DefaultConnection":\s*"\([^"]*\)".*/\1/p' src/SmartStack.Api/appsettings.json 2>/dev/null)
|
|
91
|
+
SN=$(echo "$CS" | sed -n 's/.*[Ss]erver=\([^;]*\).*/\1/p' | sed 's/(local)/./')
|
|
92
|
+
DB=$(echo "$CS" | sed -n 's/.*[Dd]atabase=\([^;]*\).*/\1/p')
|
|
93
93
|
sqlcmd -S "$SN" -Q "SET NOCOUNT ON;SELECT name FROM sys.databases WHERE name='$DB'" -t 5 -E -C -h -1 -W 2>/dev/null | grep -q "$DB" && echo "ok $SN $DB" || echo "warn $SN $DB"
|
|
94
94
|
```
|
|
95
95
|
|
|
@@ -177,8 +177,8 @@ for i in $(seq 1 20); do
|
|
|
177
177
|
sleep 2
|
|
178
178
|
done
|
|
179
179
|
RESULT=$(timeout 20 smartstack admin reset --connection '{connection_string}' --force --json 2>&1 | grep -E '^\{')
|
|
180
|
-
EMAIL=$(echo "$RESULT" |
|
|
181
|
-
PASS=$(echo "$RESULT" |
|
|
180
|
+
EMAIL=$(echo "$RESULT" | sed -n 's/.*"email":"\([^"]*\)".*/\1/p')
|
|
181
|
+
PASS=$(echo "$RESULT" | sed -n 's/.*"password":"\([^"]*\)".*/\1/p')
|
|
182
182
|
cat > .claude/dev-session.json << SESSEOF
|
|
183
183
|
{"admin_email":"$EMAIL","admin_password":"$PASS","last_reset":"$(date -Iseconds)","api_port":{api_port},"web_port":{web_port},"environment":"{mode}","status":"ready"}
|
|
184
184
|
SESSEOF
|
|
@@ -189,8 +189,8 @@ echo "CREDENTIALS: $EMAIL / $PASS"
|
|
|
189
189
|
Single Bash — reset only (no wait needed):
|
|
190
190
|
```bash
|
|
191
191
|
RESULT=$(timeout 20 smartstack admin reset --connection '{connection_string}' --force --json 2>&1 | grep -E '^\{')
|
|
192
|
-
EMAIL=$(echo "$RESULT" |
|
|
193
|
-
PASS=$(echo "$RESULT" |
|
|
192
|
+
EMAIL=$(echo "$RESULT" | sed -n 's/.*"email":"\([^"]*\)".*/\1/p')
|
|
193
|
+
PASS=$(echo "$RESULT" | sed -n 's/.*"password":"\([^"]*\)".*/\1/p')
|
|
194
194
|
cat > .claude/dev-session.json << SESSEOF
|
|
195
195
|
{"admin_email":"$EMAIL","admin_password":"$PASS","last_reset":"$(date -Iseconds)","api_port":{api_port},"web_port":{web_port},"environment":"{mode}","status":"ready"}
|
|
196
196
|
SESSEOF
|
|
@@ -116,7 +116,7 @@ import { Info } from 'lucide-react';
|
|
|
116
116
|
|
|
117
117
|
function Annotation({ text }: { text: string }) {
|
|
118
118
|
return (
|
|
119
|
-
<div className="flex items-start gap-2 p-2.5 rounded-lg bg-
|
|
119
|
+
<div className="flex items-start gap-2 p-2.5 rounded-lg bg-[var(--info-bg)] border border-[var(--info-border)] text-sm text-[var(--info-text)]">
|
|
120
120
|
<Info className="w-4 h-4 mt-0.5 flex-shrink-0" />
|
|
121
121
|
<span>{text}</span>
|
|
122
122
|
</div>
|
|
@@ -168,7 +168,7 @@ import {
|
|
|
168
168
|
// ═══════════════════════════════════════════════════
|
|
169
169
|
function Annotation({ text }: { text: string }) {
|
|
170
170
|
return (
|
|
171
|
-
<div className="flex items-start gap-2 p-2.5 rounded-lg bg-
|
|
171
|
+
<div className="flex items-start gap-2 p-2.5 rounded-lg bg-[var(--info-bg)] border border-[var(--info-border)] text-sm text-[var(--info-text)]">
|
|
172
172
|
<Info className="w-4 h-4 mt-0.5 flex-shrink-0" />
|
|
173
173
|
<span>{text}</span>
|
|
174
174
|
</div>
|
|
@@ -231,14 +231,14 @@ export default function {Module}DocPage() {
|
|
|
231
231
|
<div className="card p-6">
|
|
232
232
|
<div className="mb-6">
|
|
233
233
|
<h3 className="font-semibold mb-3 flex items-center gap-2">
|
|
234
|
-
<Target className="w-5 h-5 text-
|
|
234
|
+
<Target className="w-5 h-5 text-[var(--error-text)]" />
|
|
235
235
|
{t('sections.problem')}
|
|
236
236
|
</h3>
|
|
237
237
|
<p className="text-[var(--text-secondary)]">{t('problem')}</p>
|
|
238
238
|
</div>
|
|
239
239
|
|
|
240
|
-
<div className="p-4 rounded-lg bg-
|
|
241
|
-
<h3 className="font-semibold mb-2 flex items-center gap-2 text-
|
|
240
|
+
<div className="p-4 rounded-lg bg-[var(--success-bg)] border border-[var(--success-border)]">
|
|
241
|
+
<h3 className="font-semibold mb-2 flex items-center gap-2 text-[var(--success-text)]">
|
|
242
242
|
<Lightbulb className="w-5 h-5" />
|
|
243
243
|
{t('sections.solution')}
|
|
244
244
|
</h3>
|
|
@@ -371,8 +371,8 @@ export default function {Module}DocPage() {
|
|
|
371
371
|
{[1, 2, 3].map((i) => (
|
|
372
372
|
<div key={i} className="card p-6">
|
|
373
373
|
<div className="flex items-center gap-3 mb-4">
|
|
374
|
-
<div className="w-10 h-10 rounded-full bg-
|
|
375
|
-
<Users className="w-5 h-5 text-
|
|
374
|
+
<div className="w-10 h-10 rounded-full bg-[var(--accent-bg)] flex items-center justify-center">
|
|
375
|
+
<Users className="w-5 h-5 text-[var(--accent-text)]" />
|
|
376
376
|
</div>
|
|
377
377
|
<div>
|
|
378
378
|
<div className="font-semibold">{t(`useCases.${i}.persona`)}</div>
|
|
@@ -384,8 +384,8 @@ export default function {Module}DocPage() {
|
|
|
384
384
|
<span className="font-medium text-[var(--text-secondary)]">Situation:</span>
|
|
385
385
|
<p>{t(`useCases.${i}.situation`)}</p>
|
|
386
386
|
</div>
|
|
387
|
-
<div className="text-sm p-3 rounded-lg bg-
|
|
388
|
-
<span className="font-medium text-
|
|
387
|
+
<div className="text-sm p-3 rounded-lg bg-[var(--success-bg)] border border-[var(--success-border)]">
|
|
388
|
+
<span className="font-medium text-[var(--success-text)]">Avec la fonctionnalite:</span>
|
|
389
389
|
<p>{t(`useCases.${i}.withFeature`)}</p>
|
|
390
390
|
</div>
|
|
391
391
|
</div>
|
|
@@ -454,7 +454,7 @@ export default function {Module}DocPage() {
|
|
|
454
454
|
<section id="reference" className="scroll-mt-4">
|
|
455
455
|
<details className="card">
|
|
456
456
|
<summary className="p-4 cursor-pointer hover:bg-[var(--bg-secondary)] rounded-lg font-semibold flex items-center gap-2">
|
|
457
|
-
<span className="w-8 h-8 rounded-full bg-
|
|
457
|
+
<span className="w-8 h-8 rounded-full bg-[var(--bg-tertiary)] text-[var(--text-secondary)] flex items-center justify-center text-sm">9</span>
|
|
458
458
|
{t('sections.technicalRef')}
|
|
459
459
|
</summary>
|
|
460
460
|
<div className="p-6 pt-2 space-y-8">
|
|
@@ -499,12 +499,12 @@ export default function {Module}DocPage() {
|
|
|
499
499
|
{apiEndpoints.map((ep, i) => (
|
|
500
500
|
<tr key={i} className="border-b border-[var(--border-color)]">
|
|
501
501
|
<td className="py-2 px-3">
|
|
502
|
-
<span className={`px-2 py-0.5 rounded text-xs font-medium ${
|
|
503
|
-
ep.method === 'GET'
|
|
504
|
-
ep.method === 'POST'
|
|
505
|
-
ep.method === 'PUT'
|
|
506
|
-
ep.method === 'PATCH'
|
|
507
|
-
|
|
502
|
+
<span className={`px-2 py-0.5 rounded text-xs font-medium border ${
|
|
503
|
+
ep.method === 'GET' ? 'bg-[var(--info-bg)] text-[var(--info-text)] border-[var(--info-border)]' :
|
|
504
|
+
ep.method === 'POST' ? 'bg-[var(--success-bg)] text-[var(--success-text)] border-[var(--success-border)]' :
|
|
505
|
+
ep.method === 'PUT' ? 'bg-[var(--warning-bg)] text-[var(--warning-text)] border-[var(--warning-border)]' :
|
|
506
|
+
ep.method === 'PATCH' ? 'bg-[var(--accent-bg)] text-[var(--accent-text)] border-[var(--accent-border)]' :
|
|
507
|
+
'bg-[var(--error-bg)] text-[var(--error-text)] border-[var(--error-border)]'
|
|
508
508
|
}`}>{ep.method}</span>
|
|
509
509
|
</td>
|
|
510
510
|
<td className="py-2 px-3 font-mono text-xs">{ep.path}</td>
|
|
@@ -0,0 +1,312 @@
|
|
|
1
|
+
---
|
|
2
|
+
name: migrate
|
|
3
|
+
description: Migrate an existing SmartStack client project from one platform version to another (currently v3.34 → v3.46). Detects the current version, applies declarative rules (renames, signature updates, layout consolidation, theme tokens), then runs validation checks. Designed for clients on older CLI versions who want to upgrade without redoing /apex from scratch.
|
|
4
|
+
argument-hint: "[--from=<version>] [--to=<version>] [--scope=backend|frontend|all] [--dry-run] [--apply]"
|
|
5
|
+
model: sonnet
|
|
6
|
+
allowed-tools: Read, Grep, Glob, Bash, Edit, Write
|
|
7
|
+
---
|
|
8
|
+
|
|
9
|
+
## Current state (auto-injected)
|
|
10
|
+
|
|
11
|
+
- Project root: !`pwd 2>/dev/null`
|
|
12
|
+
- Detected SmartStack package version: !`grep -oP '"@atlashub/smartstack":\s*"\K[^"]+' web/smartstack-web/package.json 2>/dev/null || cat src/SmartStack.Api/*.csproj 2>/dev/null | grep -oP 'SmartStack[A-Za-z.]*"\s*Version="\K[^"]+' | head -1 || echo "unknown"`
|
|
13
|
+
- Detected legacy patterns: !`grep -rl "ApplicationZone\|<\(AdminLayout\|BusinessLayout\|UserLayout\)" src/ web/ 2>/dev/null | head -5 || echo "none"`
|
|
14
|
+
- Last migration run: !`cat .claude/cache/migrate.json 2>/dev/null | head -3 || echo "no previous run"`
|
|
15
|
+
|
|
16
|
+
<objective>
|
|
17
|
+
Patch an existing client project (one already generated by an older CLI version) so that it conforms to the latest SmartStack platform version. Current rule set covers `v3.34 → v3.46` (the breaking changes shipped in iteration 1 of the v3.46 alignment work : `ApplicationZone` removal, layout consolidation 7→4, NavigationApplication.Create signature change, Tailwind tokenization).
|
|
18
|
+
|
|
19
|
+
This skill exists because :
|
|
20
|
+
- A client app generated on CLI v3.34 has `Zone = ApplicationZone.Business` hardcoded everywhere — **cannot compile** against v3.46 NuGet packages.
|
|
21
|
+
- Re-running `/apex` from scratch would lose the client's business logic.
|
|
22
|
+
- Manually patching is error-prone (40+ files to touch on a real project).
|
|
23
|
+
|
|
24
|
+
The rules are **declarative** (in `references/v3.34-to-v3.46.md`), so adding a new migration target later is just a new reference doc + a register entry.
|
|
25
|
+
</objective>
|
|
26
|
+
|
|
27
|
+
<quick_start>
|
|
28
|
+
```bash
|
|
29
|
+
/migrate # Detect version + dry-run report
|
|
30
|
+
/migrate --from=3.34 --to=3.46 # Explicit version pair
|
|
31
|
+
/migrate --dry-run # Print proposed changes without writing
|
|
32
|
+
/migrate --apply # Apply all rules (asks confirmation per category)
|
|
33
|
+
/migrate --scope=frontend --apply # Only frontend rules
|
|
34
|
+
/migrate --scope=backend --apply # Only backend rules
|
|
35
|
+
```
|
|
36
|
+
</quick_start>
|
|
37
|
+
|
|
38
|
+
<subcommands>
|
|
39
|
+
|
|
40
|
+
| Command | Effect |
|
|
41
|
+
|---|---|
|
|
42
|
+
| `/migrate` (no args) | Auto-detect from→to, run dry-run, print report |
|
|
43
|
+
| `/migrate --from=X --to=Y` | Force version pair (for testing) |
|
|
44
|
+
| `/migrate --dry-run` | Default — report only, no file edits |
|
|
45
|
+
| `/migrate --apply` | Apply rules. Asks confirmation per category (backend / frontend / seed / config) |
|
|
46
|
+
| `/migrate --scope=<s>` | Restrict to one layer |
|
|
47
|
+
| `/migrate --rules` | List all available migration paths and their rule files |
|
|
48
|
+
|
|
49
|
+
</subcommands>
|
|
50
|
+
|
|
51
|
+
<workflow>
|
|
52
|
+
|
|
53
|
+
## Step 0 — Detect from-version (if not provided)
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
# Look at @atlashub/smartstack version
|
|
57
|
+
PKG_VER=$(grep -oP '"@atlashub/smartstack":\s*"\K[^"]+' web/smartstack-web/package.json 2>/dev/null | sed 's/[\^~]//g' | cut -d. -f1-2)
|
|
58
|
+
|
|
59
|
+
# Look at SmartStack NuGet versions
|
|
60
|
+
NUGET_VER=$(grep -hPoR 'PackageReference\s+Include="SmartStack[^"]*"\s+Version="\K[^"]+' src/ 2>/dev/null | sort -u | head -1 | cut -d. -f1-2)
|
|
61
|
+
|
|
62
|
+
# Look at legacy patterns to confirm
|
|
63
|
+
HAS_ZONE=$(grep -rl "ApplicationZone\." src/ 2>/dev/null | wc -l)
|
|
64
|
+
HAS_LEGACY_LAYOUT=$(grep -rlE "<(AdminLayout|BusinessLayout|UserLayout|HRLayout|SalesLayout)\b" web/ src/ 2>/dev/null | wc -l)
|
|
65
|
+
|
|
66
|
+
# Decide source version
|
|
67
|
+
if [ "$HAS_ZONE" -gt 0 ] || [ "$HAS_LEGACY_LAYOUT" -gt 0 ]; then
|
|
68
|
+
FROM_VERSION="3.34" # Pre-v3.46 platform
|
|
69
|
+
else
|
|
70
|
+
FROM_VERSION="${PKG_VER:-unknown}"
|
|
71
|
+
fi
|
|
72
|
+
```
|
|
73
|
+
|
|
74
|
+
## Step 1 — Pick the rule file
|
|
75
|
+
|
|
76
|
+
Map `(from, to)` to a rule file under `references/` :
|
|
77
|
+
|
|
78
|
+
| from → to | Rule file |
|
|
79
|
+
|---|---|
|
|
80
|
+
| `3.34 → 3.46` | [references/v3.34-to-v3.46.md](references/v3.34-to-v3.46.md) |
|
|
81
|
+
| (future) `3.46 → 3.47` | references/v3.46-to-v3.47.md |
|
|
82
|
+
| any unsupported pair | abort with explicit error + suggested manual path |
|
|
83
|
+
|
|
84
|
+
Load the rule file and parse the rule list (each rule has `id`, `category`, `description`, `detect_pattern`, `replace_pattern`, `glob`, `severity`, `requires_confirmation`).
|
|
85
|
+
|
|
86
|
+
## Step 2 — Detect applicable rules (dry-run)
|
|
87
|
+
|
|
88
|
+
For each rule in the file :
|
|
89
|
+
|
|
90
|
+
1. Run the `detect_pattern` (grep) over `glob` paths to find candidate files
|
|
91
|
+
2. Compute the matched count
|
|
92
|
+
3. If 0 matches : skip (already migrated)
|
|
93
|
+
4. If ≥ 1 match : add to "applicable rules" list
|
|
94
|
+
|
|
95
|
+
Build the dry-run report :
|
|
96
|
+
|
|
97
|
+
```
|
|
98
|
+
================================================================================
|
|
99
|
+
MIGRATION DRY-RUN — {from} → {to}
|
|
100
|
+
================================================================================
|
|
101
|
+
Project root: {pwd}
|
|
102
|
+
Source version detected: {FROM_VERSION} (via {package.json | NuGet | legacy patterns})
|
|
103
|
+
Rule file: references/v{from}-to-v{to}.md ({total_rules} rules)
|
|
104
|
+
|
|
105
|
+
[BACKEND] ({applicable_be_count} of {total_be_count} rules applicable)
|
|
106
|
+
|
|
107
|
+
R-BE-001 ApplicationZone enum removal
|
|
108
|
+
severity: BLOCKING files: 6
|
|
109
|
+
sample: src/SmartStack.Infrastructure/Persistence/Seeding/Data/NavigationApplicationSeedData.cs:23
|
|
110
|
+
Zone = ApplicationZone.Business
|
|
111
|
+
|
|
112
|
+
R-BE-002 NavigationApplication.Create signature
|
|
113
|
+
severity: BLOCKING files: 2
|
|
114
|
+
sample: src/SmartStack.Infrastructure/.../SeedDataProvider.cs:46
|
|
115
|
+
NavigationApplication.Create(ApplicationZone.Business, code, label, ...)
|
|
116
|
+
|
|
117
|
+
R-BE-003 AddDbContext alias rename (if applicable)
|
|
118
|
+
severity: WARNING files: 0 (no occurrence — skipped)
|
|
119
|
+
|
|
120
|
+
[FRONTEND] ({applicable_fe_count} of {total_fe_count} rules applicable)
|
|
121
|
+
|
|
122
|
+
R-FE-001 Legacy domain-specific layouts (AdminLayout, BusinessLayout, UserLayout, …)
|
|
123
|
+
severity: BLOCKING files: 4
|
|
124
|
+
sample: web/smartstack-web/src/App.tsx:127
|
|
125
|
+
<Route path="/sales" element={<SalesLayout />}>
|
|
126
|
+
|
|
127
|
+
R-FE-002 Hardcoded Tailwind colors → CSS vars
|
|
128
|
+
severity: WARNING files: 12
|
|
129
|
+
|
|
130
|
+
R-FE-003 mergeRoutes() → PageRegistry.register()
|
|
131
|
+
severity: BLOCKING files: 1
|
|
132
|
+
|
|
133
|
+
[SEED] ({applicable_seed_count} of {total_seed_count} rules applicable)
|
|
134
|
+
…
|
|
135
|
+
|
|
136
|
+
[CONFIG] ({applicable_cfg_count} of {total_cfg_count} rules applicable)
|
|
137
|
+
…
|
|
138
|
+
|
|
139
|
+
--------------------------------------------------------------------------------
|
|
140
|
+
SUMMARY : {total_applicable} rules applicable across {total_files} files
|
|
141
|
+
{blocking} BLOCKING — must be fixed before the project compiles against v{to}
|
|
142
|
+
{warning} WARNING — should be fixed soon
|
|
143
|
+
================================================================================
|
|
144
|
+
```
|
|
145
|
+
|
|
146
|
+
If `--dry-run` (default) → stop here, exit 0.
|
|
147
|
+
|
|
148
|
+
## Step 3 — Apply mode (`--apply`)
|
|
149
|
+
|
|
150
|
+
Group applicable rules by **category** (BACKEND / FRONTEND / SEED / CONFIG). For each category :
|
|
151
|
+
|
|
152
|
+
```yaml
|
|
153
|
+
AskUserQuestion:
|
|
154
|
+
header: "Apply BACKEND rules?"
|
|
155
|
+
question: "{N} BACKEND rules will modify {M} files (e.g. R-BE-001, R-BE-002). Apply?"
|
|
156
|
+
options:
|
|
157
|
+
- label: "Yes, apply all BACKEND rules"
|
|
158
|
+
description: "Run all BLOCKING + WARNING rules in this category"
|
|
159
|
+
- label: "Yes, BLOCKING only"
|
|
160
|
+
description: "Apply only BLOCKING (safer for review)"
|
|
161
|
+
- label: "Skip this category"
|
|
162
|
+
description: "Don't touch BACKEND files"
|
|
163
|
+
- label: "Review one by one"
|
|
164
|
+
description: "Confirm before each rule"
|
|
165
|
+
```
|
|
166
|
+
|
|
167
|
+
For each rule the user accepts :
|
|
168
|
+
1. Read each candidate file
|
|
169
|
+
2. Apply the `replace_pattern` (often a regex substitution, sometimes a whole-block rewrite — see rule definition)
|
|
170
|
+
3. Save the file
|
|
171
|
+
4. Track the change in a per-rule changelog
|
|
172
|
+
|
|
173
|
+
After every rule in the batch is applied, build the post-apply report and run **post-validation** (Step 4).
|
|
174
|
+
|
|
175
|
+
## Step 4 — Post-validation
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
# Backend compilation (smoke test)
|
|
179
|
+
if [ "$SCOPE" != "frontend" ]; then
|
|
180
|
+
cd src/SmartStack.Api 2>/dev/null && dotnet build --nologo 2>&1 | tail -20 | tee /tmp/migrate-build-be.log
|
|
181
|
+
fi
|
|
182
|
+
|
|
183
|
+
# Frontend compilation
|
|
184
|
+
if [ "$SCOPE" != "backend" ]; then
|
|
185
|
+
cd web/smartstack-web 2>/dev/null && npx tsc -b --noEmit 2>&1 | tail -20 | tee /tmp/migrate-build-fe.log
|
|
186
|
+
fi
|
|
187
|
+
|
|
188
|
+
# Run apex post-checks if available
|
|
189
|
+
if [ -f templates/skills/apex/references/checks/seed-checks.sh ]; then
|
|
190
|
+
bash templates/skills/apex/references/checks/seed-checks.sh 2>&1 | tail -30
|
|
191
|
+
fi
|
|
192
|
+
```
|
|
193
|
+
|
|
194
|
+
Print the validation report. If errors remain : explicit list of "manual fixes still needed" + suggested next action (`/debug` skill).
|
|
195
|
+
|
|
196
|
+
## Step 5 — Cache and summary
|
|
197
|
+
|
|
198
|
+
```bash
|
|
199
|
+
mkdir -p .claude/cache
|
|
200
|
+
cat > .claude/cache/migrate.json << EOF
|
|
201
|
+
{
|
|
202
|
+
"lastRun": "$(date -Iseconds)",
|
|
203
|
+
"from": "{from}",
|
|
204
|
+
"to": "{to}",
|
|
205
|
+
"scope": "{scope}",
|
|
206
|
+
"rulesApplied": {N},
|
|
207
|
+
"filesChanged": {M},
|
|
208
|
+
"buildPassed": {true|false},
|
|
209
|
+
"remainingIssues": {K}
|
|
210
|
+
}
|
|
211
|
+
EOF
|
|
212
|
+
```
|
|
213
|
+
|
|
214
|
+
Print a final summary :
|
|
215
|
+
|
|
216
|
+
```
|
|
217
|
+
================================================================================
|
|
218
|
+
MIGRATION COMPLETE — {from} → {to}
|
|
219
|
+
================================================================================
|
|
220
|
+
Rules applied : {N} ({blocking} BLOCKING, {warning} WARNING)
|
|
221
|
+
Files changed : {M}
|
|
222
|
+
Build status : {OK | FAILED}
|
|
223
|
+
Manual fixes : {K} remaining (see /tmp/migrate-build-*.log)
|
|
224
|
+
|
|
225
|
+
Next steps :
|
|
226
|
+
1. Review changes: git diff
|
|
227
|
+
2. Run tests: dotnet test + npm test
|
|
228
|
+
3. Commit migration: /gitflow commit
|
|
229
|
+
4. If issues remain: /debug
|
|
230
|
+
================================================================================
|
|
231
|
+
```
|
|
232
|
+
|
|
233
|
+
## Step 6 — Exit code
|
|
234
|
+
|
|
235
|
+
- 0 if all rules applied and build passes
|
|
236
|
+
- 1 if any rule failed to apply (likely needs manual intervention)
|
|
237
|
+
- 2 if build doesn't pass after migration
|
|
238
|
+
|
|
239
|
+
</workflow>
|
|
240
|
+
|
|
241
|
+
<safety>
|
|
242
|
+
|
|
243
|
+
- **Always run dry-run first** : the default mode. Forces the user to see the diff before any file is touched.
|
|
244
|
+
- **Per-category confirmation** in `--apply` mode. No "yes to all" shortcut.
|
|
245
|
+
- **Backup is the user's responsibility** — recommend `git stash` or `git commit` before running `--apply`. The skill will print this as a banner.
|
|
246
|
+
- **Some rules cannot be safely automated** : signature changes that depend on context. Those rules have `requires_confirmation: true` in the rule file, and the skill walks through them one by one.
|
|
247
|
+
- **Never modify files outside the project root** (cwd). Defensive `pwd`-based path resolution.
|
|
248
|
+
|
|
249
|
+
</safety>
|
|
250
|
+
|
|
251
|
+
<rule_file_format>
|
|
252
|
+
|
|
253
|
+
Each `references/v{from}-to-v{to}.md` file contains a YAML-fenced rule list :
|
|
254
|
+
|
|
255
|
+
````markdown
|
|
256
|
+
# Migration rules: v{from} → v{to}
|
|
257
|
+
|
|
258
|
+
```yaml
|
|
259
|
+
rules:
|
|
260
|
+
- id: R-BE-001
|
|
261
|
+
category: backend
|
|
262
|
+
description: ApplicationZone enum removed in v3.46
|
|
263
|
+
detect_pattern: "ApplicationZone\\.\\w+"
|
|
264
|
+
replace_pattern: |
|
|
265
|
+
# Custom multi-line replacement (see "implementations" below)
|
|
266
|
+
glob: "src/**/Seeding/Data/**/*.cs"
|
|
267
|
+
severity: BLOCKING
|
|
268
|
+
requires_confirmation: false
|
|
269
|
+
references:
|
|
270
|
+
- templates/skills/apex/references/core-seed-data.md
|
|
271
|
+
- templates/skills/application/references/provider-template.md
|
|
272
|
+
|
|
273
|
+
- id: R-BE-002
|
|
274
|
+
category: backend
|
|
275
|
+
…
|
|
276
|
+
```
|
|
277
|
+
|
|
278
|
+
## Implementations
|
|
279
|
+
|
|
280
|
+
Some rules are too complex for a single regex. The "implementation" section
|
|
281
|
+
provides a step-by-step Bash/sed/Edit recipe per rule.
|
|
282
|
+
|
|
283
|
+
### R-BE-001 — ApplicationZone removal
|
|
284
|
+
|
|
285
|
+
For each file matching the glob :
|
|
286
|
+
1. Remove the line `Zone = ApplicationZone.Business,`
|
|
287
|
+
2. Insert two lines : `IsPersonal = false,` and `IsOpen = false,`
|
|
288
|
+
3. … (full recipe)
|
|
289
|
+
````
|
|
290
|
+
|
|
291
|
+
The skill parses the YAML block, then for each rule with `requires_confirmation: true` it falls back to the implementation recipe (read + execute step by step).
|
|
292
|
+
|
|
293
|
+
</rule_file_format>
|
|
294
|
+
|
|
295
|
+
<known_limitations>
|
|
296
|
+
|
|
297
|
+
- **Single migration path supported today** : `v3.34 → v3.46`. Adding `v3.46 → v3.47` is a new rule file, not a code change.
|
|
298
|
+
- **No multi-hop chaining yet** : if a project is on `v3.20`, you can't go straight to `v3.46`. Manual intervention required.
|
|
299
|
+
- **Doesn't migrate database schema** — rules are code-only. Schema migration is `/efcore migration` territory.
|
|
300
|
+
- **Heuristic version detection** : if `package.json` lacks `@atlashub/smartstack`, the skill falls back to grepping legacy patterns. Always confirm the detected version before `--apply`.
|
|
301
|
+
|
|
302
|
+
</known_limitations>
|
|
303
|
+
|
|
304
|
+
<success_criteria>
|
|
305
|
+
- Detects current SmartStack version from project artifacts
|
|
306
|
+
- Picks the correct rule file based on (from, to)
|
|
307
|
+
- Dry-run report lists every applicable rule with file/line evidence
|
|
308
|
+
- Apply mode confirms per category before touching files
|
|
309
|
+
- Post-validation runs `dotnet build` and `tsc --noEmit` to catch new compile errors
|
|
310
|
+
- Cache record allows subsequent `/migrate` runs to skip already-applied rules
|
|
311
|
+
- Exit code reflects success/failure for CI scripting
|
|
312
|
+
</success_criteria>
|