@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.
Files changed (81) hide show
  1. package/dist/index.js +87 -41
  2. package/dist/index.js.map +1 -1
  3. package/package.json +1 -1
  4. package/templates/project/claude-md/root.CLAUDE.md.template +1 -1
  5. package/templates/skills/ai-prompt/SKILL.md +64 -0
  6. package/templates/skills/ai-prompt/references/ai-agent-modes.md +89 -0
  7. package/templates/skills/ai-prompt/references/eval-framework.md +129 -0
  8. package/templates/skills/apex/SKILL.md +2 -2
  9. package/templates/skills/apex/references/checks/frontend-checks.sh +123 -11
  10. package/templates/skills/apex/references/checks/seed-checks.sh +81 -7
  11. package/templates/skills/apex/references/core-seed-data.md +27 -22
  12. package/templates/skills/apex/references/domain-events-pattern.md +45 -0
  13. package/templates/skills/apex/references/entity-hooks-pattern.md +68 -0
  14. package/templates/skills/apex/references/licensing-enforcement.md +52 -0
  15. package/templates/skills/apex/references/post-checks.md +18 -1
  16. package/templates/skills/apex/references/smartstack-api.md +116 -5
  17. package/templates/skills/apex/references/smartstack-frontend.md +1 -1
  18. package/templates/skills/apex/references/smartstack-layers.md +6 -6
  19. package/templates/skills/apex/steps/step-00-init.md +1 -1
  20. package/templates/skills/apex/steps/step-03b-layer1-seed.md +26 -0
  21. package/templates/skills/apex/steps/step-03d-layer3-frontend.md +124 -2
  22. package/templates/skills/apex/steps/step-04-examine.md +163 -0
  23. package/templates/skills/apex-verify/SKILL.md +110 -0
  24. package/templates/skills/apex-verify/references/audit-rules.md +50 -0
  25. package/templates/skills/apex-verify/steps/step-00-init.md +119 -0
  26. package/templates/skills/apex-verify/steps/step-01-nav-audit.md +96 -0
  27. package/templates/skills/apex-verify/steps/step-02-crud-audit.md +127 -0
  28. package/templates/skills/apex-verify/steps/step-03-perm-audit.md +119 -0
  29. package/templates/skills/apex-verify/steps/step-04-route-audit.md +98 -0
  30. package/templates/skills/apex-verify/steps/step-05-report.md +110 -0
  31. package/templates/skills/application/references/contexts-cheatsheet.md +86 -0
  32. package/templates/skills/application/references/extensions-system.md +158 -0
  33. package/templates/skills/application/references/frontend-route-naming.md +7 -5
  34. package/templates/skills/application/references/frontend-verification.md +7 -5
  35. package/templates/skills/application/references/provider-template.md +4 -2
  36. package/templates/skills/application/references/smartstack-provider.md +118 -0
  37. package/templates/skills/application/references/themes-db-driven.md +484 -0
  38. package/templates/skills/application/templates-frontend.md +2 -2
  39. package/templates/skills/application/templates-seed.md +4 -2
  40. package/templates/skills/audit-route/references/routing-pattern.md +3 -1
  41. package/templates/skills/business-analyse/SKILL.md +3 -3
  42. package/templates/skills/business-analyse/_shared.md +37 -0
  43. package/templates/skills/business-analyse/react/components.md +30 -28
  44. package/templates/skills/business-analyse/references/03-json-schemas.md +11 -3
  45. package/templates/skills/business-analyse/references/03-post-check-validation.md +64 -0
  46. package/templates/skills/business-analyse/references/canonical-json-formats.md +7 -3
  47. package/templates/skills/business-analyse/references/robustness-checks.md +1 -1
  48. package/templates/skills/business-analyse/references/validation-checklist.md +5 -5
  49. package/templates/skills/business-analyse/schemas/sections/analysis-schema.json +15 -4
  50. package/templates/skills/business-analyse/steps/step-03-specify.md +162 -4
  51. package/templates/skills/business-analyse/steps/step-04-consolidate.md +211 -1
  52. package/templates/skills/business-analyse/templates-react.md +15 -15
  53. package/templates/skills/business-analyse-handoff/references/agent-handoff-transform-prompt.md +3 -0
  54. package/templates/skills/business-analyse-html/html/ba-interactive.html +198 -16
  55. package/templates/skills/business-analyse-html/html/src/scripts/01-data-init.js +64 -0
  56. package/templates/skills/business-analyse-html/html/src/scripts/05-render-specs.js +80 -11
  57. package/templates/skills/business-analyse-html/html/src/scripts/06-render-consolidation.js +2 -2
  58. package/templates/skills/business-analyse-html/html/src/scripts/06-render-mockups.js +6 -3
  59. package/templates/skills/business-analyse-html/html/src/scripts/12-render-diagrams.js +46 -0
  60. package/templates/skills/business-analyse-html/references/02-feature-data-building.md +4 -2
  61. package/templates/skills/business-analyse-html/references/data-build.md +2 -0
  62. package/templates/skills/business-analyse-html/references/data-mapping.md +88 -21
  63. package/templates/skills/business-analyse-html/steps/step-02-build-data.md +6 -0
  64. package/templates/skills/business-analyse-html/steps/step-04-verify.md +92 -3
  65. package/templates/skills/business-analyse-quick/SKILL.md +807 -0
  66. package/templates/skills/{sketch → business-analyse-quick}/references/domain-heuristics.md +59 -3
  67. package/templates/skills/business-analyse-quick/references/prd-schema.md +268 -0
  68. package/templates/skills/business-analyse-review/references/review-data-mapping.md +6 -0
  69. package/templates/skills/cli-app-sync/SKILL.md +105 -4
  70. package/templates/skills/cli-app-sync/references/comparison-map.md +13 -0
  71. package/templates/skills/cli-app-sync/references/diff-entities.md +162 -0
  72. package/templates/skills/dev-start/SKILL.md +7 -7
  73. package/templates/skills/documentation/templates.md +16 -16
  74. package/templates/skills/migrate/SKILL.md +312 -0
  75. package/templates/skills/migrate/references/v3.34-to-v3.46.md +289 -0
  76. package/templates/skills/sketch/SKILL.md +15 -153
  77. package/templates/skills/smoke-generation/SKILL.md +313 -0
  78. package/templates/skills/ui-components/SKILL.md +11 -1
  79. package/templates/skills/ui-components/patterns/data-table.md +1 -1
  80. package/templates/skills/ui-components/references/component-catalog.md +82 -0
  81. 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=$(grep -oP '"DefaultConnection":\s*"\K[^"]+' src/SmartStack.Api/appsettings.json 2>/dev/null)
91
- SN=$(echo "$CS" | grep -oiP '(?:Server|Data Source)=\K[^;]+' | sed 's/(local)/./')
92
- DB=$(echo "$CS" | grep -oiP '(?:Database|Initial Catalog)=\K[^;]+')
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" | grep -oP '"email":"\K[^"]+')
181
- PASS=$(echo "$RESULT" | grep -oP '"password":"\K[^"]+')
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" | grep -oP '"email":"\K[^"]+')
193
- PASS=$(echo "$RESULT" | grep -oP '"password":"\K[^"]+')
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-blue-500/5 border border-blue-500/15 text-sm text-blue-700 dark:text-blue-400">
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-blue-500/5 border border-blue-500/15 text-sm text-blue-700 dark:text-blue-400">
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-red-500" />
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-green-500/10 border border-green-500/20">
241
- <h3 className="font-semibold mb-2 flex items-center gap-2 text-green-700">
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-blue-500/10 flex items-center justify-center">
375
- <Users className="w-5 h-5 text-blue-600" />
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-green-500/5 border border-green-500/15">
388
- <span className="font-medium text-green-600">Avec la fonctionnalite:</span>
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-gray-500/10 text-gray-600 flex items-center justify-center text-sm">9</span>
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' ? 'bg-blue-500/10 text-blue-600' :
504
- ep.method === 'POST' ? 'bg-green-500/10 text-green-600' :
505
- ep.method === 'PUT' ? 'bg-orange-500/10 text-orange-600' :
506
- ep.method === 'PATCH' ? 'bg-purple-500/10 text-purple-600' :
507
- 'bg-red-500/10 text-red-600'
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>