@atlashub/smartstack-cli 1.37.0 → 2.0.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (99) hide show
  1. package/config/mcp-defaults.json +62 -0
  2. package/dist/index.js +57 -4
  3. package/dist/index.js.map +1 -1
  4. package/dist/mcp-entry.mjs +16984 -0
  5. package/dist/mcp-entry.mjs.map +1 -0
  6. package/package.json +14 -5
  7. package/templates/agents/gitflow/start.md +5 -4
  8. package/templates/agents/mcp-healthcheck.md +15 -13
  9. package/templates/mcp-scaffolding/component.tsx.hbs +298 -0
  10. package/templates/mcp-scaffolding/controller.cs.hbs +184 -0
  11. package/templates/mcp-scaffolding/entity-extension.cs.hbs +231 -0
  12. package/templates/mcp-scaffolding/frontend/api-client.ts.hbs +116 -0
  13. package/templates/mcp-scaffolding/frontend/nav-routes.ts.hbs +133 -0
  14. package/templates/mcp-scaffolding/frontend/routes.tsx.hbs +134 -0
  15. package/templates/mcp-scaffolding/migrations/seed-roles.cs.hbs +261 -0
  16. package/templates/mcp-scaffolding/service-extension.cs.hbs +53 -0
  17. package/templates/mcp-scaffolding/tests/controller.test.cs.hbs +413 -0
  18. package/templates/mcp-scaffolding/tests/entity.test.cs.hbs +239 -0
  19. package/templates/mcp-scaffolding/tests/repository.test.cs.hbs +441 -0
  20. package/templates/mcp-scaffolding/tests/security.test.cs.hbs +442 -0
  21. package/templates/mcp-scaffolding/tests/service.test.cs.hbs +390 -0
  22. package/templates/mcp-scaffolding/tests/validator.test.cs.hbs +428 -0
  23. package/templates/ralph/README.md +3 -3
  24. package/templates/ralph/ralph.config.yaml +2 -2
  25. package/templates/skills/admin/SKILL.md +42 -0
  26. package/templates/skills/business-analyse/_shared.md +24 -1
  27. package/templates/skills/business-analyse/questionnaire/01-context.md +4 -4
  28. package/templates/skills/business-analyse/questionnaire/02-stakeholders.md +3 -3
  29. package/templates/skills/business-analyse/questionnaire/03-scope.md +4 -4
  30. package/templates/skills/business-analyse/questionnaire/04-data.md +7 -7
  31. package/templates/skills/business-analyse/questionnaire/05-integrations.md +1 -1
  32. package/templates/skills/business-analyse/questionnaire/06-security.md +3 -3
  33. package/templates/skills/business-analyse/questionnaire/07-ui.md +1 -1
  34. package/templates/skills/business-analyse/questionnaire/08-performance.md +3 -3
  35. package/templates/skills/business-analyse/questionnaire/09-constraints.md +4 -4
  36. package/templates/skills/business-analyse/questionnaire/10-documentation.md +2 -2
  37. package/templates/skills/business-analyse/questionnaire/11-data-lifecycle.md +2 -2
  38. package/templates/skills/business-analyse/questionnaire/12-migration.md +1 -1
  39. package/templates/skills/business-analyse/questionnaire/13-cross-module.md +2 -2
  40. package/templates/skills/business-analyse/steps/step-01-discover.md +50 -25
  41. package/templates/skills/business-analyse/steps/step-05-handoff.md +133 -34
  42. package/templates/skills/cc-agent/SKILL.md +129 -0
  43. package/templates/skills/cc-agent/references/agent-frontmatter.md +213 -0
  44. package/templates/skills/cc-agent/references/permission-modes.md +102 -0
  45. package/templates/skills/cc-agent/references/tools-reference.md +144 -0
  46. package/templates/skills/cc-agent/steps/step-00-init.md +134 -0
  47. package/templates/skills/cc-agent/steps/step-01-design.md +186 -0
  48. package/templates/skills/cc-agent/steps/step-02-generate.md +204 -0
  49. package/templates/skills/cc-agent/steps/step-03-validate.md +130 -0
  50. package/templates/skills/cc-agent/templates/agent-categorized.md +67 -0
  51. package/templates/skills/cc-agent/templates/agent-standalone.md +56 -0
  52. package/templates/skills/cc-agent/templates/agent-with-skills.md +94 -0
  53. package/templates/skills/cc-audit/SKILL.md +108 -0
  54. package/templates/skills/cc-audit/references/agent-checklist.md +91 -0
  55. package/templates/skills/cc-audit/references/hook-checklist.md +110 -0
  56. package/templates/skills/cc-audit/references/skill-checklist.md +70 -0
  57. package/templates/skills/cc-audit/steps/step-00-init.md +98 -0
  58. package/templates/skills/cc-audit/steps/step-01-scan.md +142 -0
  59. package/templates/skills/cc-audit/steps/step-02-analyze.md +158 -0
  60. package/templates/skills/cc-audit/steps/step-03-report.md +142 -0
  61. package/templates/skills/cc-skill/SKILL.md +134 -0
  62. package/templates/skills/cc-skill/references/best-practices.md +167 -0
  63. package/templates/skills/cc-skill/references/frontmatter-reference.md +182 -0
  64. package/templates/skills/cc-skill/references/skill-patterns.md +199 -0
  65. package/templates/skills/cc-skill/steps/step-00-init.md +119 -0
  66. package/templates/skills/cc-skill/steps/step-01-design.md +199 -0
  67. package/templates/skills/cc-skill/steps/step-02-generate.md +145 -0
  68. package/templates/skills/cc-skill/steps/step-03-steps.md +151 -0
  69. package/templates/skills/cc-skill/steps/step-04-validate.md +124 -0
  70. package/templates/skills/cc-skill/templates/skill-forked.md +85 -0
  71. package/templates/skills/cc-skill/templates/skill-progressive.md +102 -0
  72. package/templates/skills/cc-skill/templates/skill-simple.md +75 -0
  73. package/templates/skills/cc-skill/templates/step-template.md +82 -0
  74. package/templates/skills/check-version/SKILL.md +6 -0
  75. package/templates/skills/debug/SKILL.md +4 -0
  76. package/templates/skills/documentation/SKILL.md +1 -0
  77. package/templates/skills/efcore/SKILL.md +5 -0
  78. package/templates/skills/efcore/steps/db/step-deploy.md +26 -5
  79. package/templates/skills/efcore/steps/shared/step-00-init.md +21 -7
  80. package/templates/skills/explore/SKILL.md +28 -32
  81. package/templates/skills/feature-full/SKILL.md +1 -0
  82. package/templates/skills/gitflow/SKILL.md +8 -0
  83. package/templates/skills/gitflow/steps/step-start.md +45 -10
  84. package/templates/skills/mcp/SKILL.md +38 -18
  85. package/templates/skills/quick-search/SKILL.md +8 -1
  86. package/templates/skills/ralph-loop/SKILL.md +1 -1
  87. package/templates/skills/ralph-loop/steps/step-00-init.md +8 -68
  88. package/templates/skills/ralph-loop/steps/step-04-check.md +1 -1
  89. package/templates/skills/refactor/SKILL.md +1 -0
  90. package/templates/skills/review-code/SKILL.md +7 -1
  91. package/templates/skills/ui-components/SKILL.md +31 -438
  92. package/templates/skills/ui-components/accessibility.md +170 -0
  93. package/templates/skills/ui-components/patterns/data-table.md +39 -0
  94. package/templates/skills/ui-components/patterns/entity-card.md +77 -0
  95. package/templates/skills/ui-components/patterns/grid-layout.md +91 -0
  96. package/templates/skills/ui-components/patterns/kanban.md +43 -0
  97. package/templates/skills/ui-components/style-guide.md +86 -0
  98. package/templates/skills/utils/SKILL.md +1 -0
  99. package/templates/skills/validate/SKILL.md +1 -0
@@ -0,0 +1,428 @@
1
+ {{!-- SmartStack Validator Test Template --}}
2
+ {{!-- Generates unit tests for FluentValidation validators following SmartStack conventions --}}
3
+
4
+ using FluentAssertions;
5
+ using FluentValidation.TestHelper;
6
+ using Xunit;
7
+ using {{namespace}}.Application.DTOs;
8
+ using {{namespace}}.Application.Validators;
9
+
10
+ namespace {{namespace}}.Tests.Unit.Validators;
11
+
12
+ /// <summary>
13
+ /// Unit tests for <see cref="{{name}}Validator"/>.
14
+ /// Follows SmartStack testing conventions: {Method}_When{Condition}_Should{Result}
15
+ /// </summary>
16
+ public class {{name}}ValidatorTests
17
+ {
18
+ private readonly Create{{name}}RequestValidator _createValidator;
19
+ private readonly Update{{name}}RequestValidator _updateValidator;
20
+
21
+ public {{name}}ValidatorTests()
22
+ {
23
+ _createValidator = new Create{{name}}RequestValidator();
24
+ _updateValidator = new Update{{name}}RequestValidator();
25
+ }
26
+
27
+ #region Create Request - Code Validation
28
+
29
+ [Fact]
30
+ public void CreateValidator_WhenCodeIsValid_ShouldNotHaveErrors()
31
+ {
32
+ // Arrange
33
+ var request = new Create{{name}}Request { Code = "VALID-001" };
34
+
35
+ // Act
36
+ var result = _createValidator.TestValidate(request);
37
+
38
+ // Assert
39
+ result.ShouldNotHaveValidationErrorFor(x => x.Code);
40
+ }
41
+
42
+ [Theory]
43
+ [InlineData(null)]
44
+ [InlineData("")]
45
+ [InlineData(" ")]
46
+ public void CreateValidator_WhenCodeIsNullOrEmpty_ShouldHaveError(string? invalidCode)
47
+ {
48
+ // Arrange
49
+ var request = new Create{{name}}Request { Code = invalidCode! };
50
+
51
+ // Act
52
+ var result = _createValidator.TestValidate(request);
53
+
54
+ // Assert
55
+ result.ShouldHaveValidationErrorFor(x => x.Code)
56
+ .WithErrorMessage("*required*");
57
+ }
58
+
59
+ [Fact]
60
+ public void CreateValidator_WhenCodeExceedsMaxLength_ShouldHaveError()
61
+ {
62
+ // Arrange
63
+ var request = new Create{{name}}Request
64
+ {
65
+ Code = new string('A', 101) // Exceeds 100 char limit
66
+ };
67
+
68
+ // Act
69
+ var result = _createValidator.TestValidate(request);
70
+
71
+ // Assert
72
+ result.ShouldHaveValidationErrorFor(x => x.Code)
73
+ .WithErrorMessage("*100 characters*");
74
+ }
75
+
76
+ [Theory]
77
+ [InlineData("valid-code")]
78
+ [InlineData("VALID_CODE_123")]
79
+ [InlineData("Code.With.Dots")]
80
+ public void CreateValidator_WhenCodeHasValidFormat_ShouldNotHaveErrors(string validCode)
81
+ {
82
+ // Arrange
83
+ var request = new Create{{name}}Request { Code = validCode };
84
+
85
+ // Act
86
+ var result = _createValidator.TestValidate(request);
87
+
88
+ // Assert
89
+ result.ShouldNotHaveValidationErrorFor(x => x.Code);
90
+ }
91
+
92
+ [Theory]
93
+ [InlineData("code with spaces")]
94
+ [InlineData("code<script>")]
95
+ [InlineData("code;drop")]
96
+ public void CreateValidator_WhenCodeHasInvalidCharacters_ShouldHaveError(string invalidCode)
97
+ {
98
+ // Arrange
99
+ var request = new Create{{name}}Request { Code = invalidCode };
100
+
101
+ // Act
102
+ var result = _createValidator.TestValidate(request);
103
+
104
+ // Assert
105
+ result.ShouldHaveValidationErrorFor(x => x.Code)
106
+ .WithErrorMessage("*invalid characters*");
107
+ }
108
+
109
+ #endregion
110
+
111
+ #region Create Request - Name Validation
112
+
113
+ [Fact]
114
+ public void CreateValidator_WhenNameIsValid_ShouldNotHaveErrors()
115
+ {
116
+ // Arrange
117
+ var request = new Create{{name}}Request
118
+ {
119
+ Code = "TEST",
120
+ Name = "Valid Name"
121
+ };
122
+
123
+ // Act
124
+ var result = _createValidator.TestValidate(request);
125
+
126
+ // Assert
127
+ result.ShouldNotHaveValidationErrorFor(x => x.Name);
128
+ }
129
+
130
+ [Fact]
131
+ public void CreateValidator_WhenNameExceedsMaxLength_ShouldHaveError()
132
+ {
133
+ // Arrange
134
+ var request = new Create{{name}}Request
135
+ {
136
+ Code = "TEST",
137
+ Name = new string('A', 256) // Exceeds 255 char limit
138
+ };
139
+
140
+ // Act
141
+ var result = _createValidator.TestValidate(request);
142
+
143
+ // Assert
144
+ result.ShouldHaveValidationErrorFor(x => x.Name)
145
+ .WithErrorMessage("*255 characters*");
146
+ }
147
+
148
+ #endregion
149
+
150
+ #region Update Request Validation
151
+
152
+ [Fact]
153
+ public void UpdateValidator_WhenValidData_ShouldNotHaveErrors()
154
+ {
155
+ // Arrange
156
+ var request = new Update{{name}}Request
157
+ {
158
+ Name = "Updated Name",
159
+ // Add other updatable properties
160
+ };
161
+
162
+ // Act
163
+ var result = _updateValidator.TestValidate(request);
164
+
165
+ // Assert
166
+ result.ShouldNotHaveAnyValidationErrors();
167
+ }
168
+
169
+ [Fact]
170
+ public void UpdateValidator_WhenOptionalFieldsAreNull_ShouldNotHaveErrors()
171
+ {
172
+ // Arrange
173
+ var request = new Update{{name}}Request
174
+ {
175
+ Name = null, // Optional field can be null
176
+ };
177
+
178
+ // Act
179
+ var result = _updateValidator.TestValidate(request);
180
+
181
+ // Assert
182
+ result.ShouldNotHaveAnyValidationErrors();
183
+ }
184
+
185
+ #endregion
186
+
187
+ #region Date Validation (if applicable)
188
+
189
+ [Fact]
190
+ public void CreateValidator_WhenStartDateIsInPast_ShouldHaveError()
191
+ {
192
+ // Arrange
193
+ var request = new Create{{name}}Request
194
+ {
195
+ Code = "TEST",
196
+ StartDate = DateTime.UtcNow.AddDays(-1)
197
+ };
198
+
199
+ // Act
200
+ var result = _createValidator.TestValidate(request);
201
+
202
+ // Assert
203
+ result.ShouldHaveValidationErrorFor(x => x.StartDate)
204
+ .WithErrorMessage("*future*");
205
+ }
206
+
207
+ [Fact]
208
+ public void CreateValidator_WhenEndDateBeforeStartDate_ShouldHaveError()
209
+ {
210
+ // Arrange
211
+ var request = new Create{{name}}Request
212
+ {
213
+ Code = "TEST",
214
+ StartDate = DateTime.UtcNow.AddDays(10),
215
+ EndDate = DateTime.UtcNow.AddDays(5)
216
+ };
217
+
218
+ // Act
219
+ var result = _createValidator.TestValidate(request);
220
+
221
+ // Assert
222
+ result.ShouldHaveValidationErrorFor(x => x.EndDate)
223
+ .WithErrorMessage("*after start date*");
224
+ }
225
+
226
+ #endregion
227
+
228
+ #region Numeric Validation (if applicable)
229
+
230
+ [Theory]
231
+ [InlineData(-1)]
232
+ [InlineData(-100)]
233
+ public void CreateValidator_WhenQuantityIsNegative_ShouldHaveError(int invalidQuantity)
234
+ {
235
+ // Arrange
236
+ var request = new Create{{name}}Request
237
+ {
238
+ Code = "TEST",
239
+ Quantity = invalidQuantity
240
+ };
241
+
242
+ // Act
243
+ var result = _createValidator.TestValidate(request);
244
+
245
+ // Assert
246
+ result.ShouldHaveValidationErrorFor(x => x.Quantity)
247
+ .WithErrorMessage("*greater than*0*");
248
+ }
249
+
250
+ [Theory]
251
+ [InlineData(0)]
252
+ [InlineData(1)]
253
+ [InlineData(1000)]
254
+ public void CreateValidator_WhenQuantityIsValid_ShouldNotHaveErrors(int validQuantity)
255
+ {
256
+ // Arrange
257
+ var request = new Create{{name}}Request
258
+ {
259
+ Code = "TEST",
260
+ Quantity = validQuantity
261
+ };
262
+
263
+ // Act
264
+ var result = _createValidator.TestValidate(request);
265
+
266
+ // Assert
267
+ result.ShouldNotHaveValidationErrorFor(x => x.Quantity);
268
+ }
269
+
270
+ #endregion
271
+
272
+ #region Email Validation (if applicable)
273
+
274
+ [Theory]
275
+ [InlineData("valid@example.com")]
276
+ [InlineData("user.name@domain.org")]
277
+ [InlineData("user+tag@example.co.uk")]
278
+ public void CreateValidator_WhenEmailIsValid_ShouldNotHaveErrors(string validEmail)
279
+ {
280
+ // Arrange
281
+ var request = new Create{{name}}Request
282
+ {
283
+ Code = "TEST",
284
+ Email = validEmail
285
+ };
286
+
287
+ // Act
288
+ var result = _createValidator.TestValidate(request);
289
+
290
+ // Assert
291
+ result.ShouldNotHaveValidationErrorFor(x => x.Email);
292
+ }
293
+
294
+ [Theory]
295
+ [InlineData("invalid")]
296
+ [InlineData("invalid@")]
297
+ [InlineData("@invalid.com")]
298
+ [InlineData("invalid@.com")]
299
+ public void CreateValidator_WhenEmailIsInvalid_ShouldHaveError(string invalidEmail)
300
+ {
301
+ // Arrange
302
+ var request = new Create{{name}}Request
303
+ {
304
+ Code = "TEST",
305
+ Email = invalidEmail
306
+ };
307
+
308
+ // Act
309
+ var result = _createValidator.TestValidate(request);
310
+
311
+ // Assert
312
+ result.ShouldHaveValidationErrorFor(x => x.Email)
313
+ .WithErrorMessage("*valid email*");
314
+ }
315
+
316
+ #endregion
317
+
318
+ #region Collection Validation (if applicable)
319
+
320
+ [Fact]
321
+ public void CreateValidator_WhenItemsCollectionIsEmpty_ShouldHaveError()
322
+ {
323
+ // Arrange
324
+ var request = new Create{{name}}Request
325
+ {
326
+ Code = "TEST",
327
+ Items = new List<string>()
328
+ };
329
+
330
+ // Act
331
+ var result = _createValidator.TestValidate(request);
332
+
333
+ // Assert
334
+ result.ShouldHaveValidationErrorFor(x => x.Items)
335
+ .WithErrorMessage("*at least one item*");
336
+ }
337
+
338
+ [Fact]
339
+ public void CreateValidator_WhenItemsExceedMaxCount_ShouldHaveError()
340
+ {
341
+ // Arrange
342
+ var request = new Create{{name}}Request
343
+ {
344
+ Code = "TEST",
345
+ Items = Enumerable.Range(1, 101).Select(i => $"Item-{i}").ToList()
346
+ };
347
+
348
+ // Act
349
+ var result = _createValidator.TestValidate(request);
350
+
351
+ // Assert
352
+ result.ShouldHaveValidationErrorFor(x => x.Items)
353
+ .WithErrorMessage("*maximum*100*");
354
+ }
355
+
356
+ #endregion
357
+
358
+ #region Cross-Field Validation
359
+
360
+ [Fact]
361
+ public void CreateValidator_WhenDependentFieldsMissing_ShouldHaveError()
362
+ {
363
+ // Arrange
364
+ var request = new Create{{name}}Request
365
+ {
366
+ Code = "TEST",
367
+ RequiresApproval = true,
368
+ ApproverEmail = null // Required when RequiresApproval is true
369
+ };
370
+
371
+ // Act
372
+ var result = _createValidator.TestValidate(request);
373
+
374
+ // Assert
375
+ result.ShouldHaveValidationErrorFor(x => x.ApproverEmail)
376
+ .WithErrorMessage("*required when*");
377
+ }
378
+
379
+ #endregion
380
+
381
+ #region Security Validation
382
+
383
+ [Theory]
384
+ [InlineData("<script>alert('xss')</script>")]
385
+ [InlineData("'; DROP TABLE Users; --")]
386
+ [InlineData("{{'{{'}}constructor{{'}}'}}")]
387
+ public void CreateValidator_WhenInputContainsMaliciousContent_ShouldHaveError(string maliciousInput)
388
+ {
389
+ // Arrange
390
+ var request = new Create{{name}}Request
391
+ {
392
+ Code = "TEST",
393
+ Description = maliciousInput
394
+ };
395
+
396
+ // Act
397
+ var result = _createValidator.TestValidate(request);
398
+
399
+ // Assert
400
+ result.ShouldHaveValidationErrorFor(x => x.Description)
401
+ .WithErrorMessage("*invalid characters*");
402
+ }
403
+
404
+ #endregion
405
+
406
+ #region Error Message Format
407
+
408
+ [Fact]
409
+ public void CreateValidator_WhenMultipleErrors_ShouldReturnAllErrors()
410
+ {
411
+ // Arrange
412
+ var request = new Create{{name}}Request
413
+ {
414
+ Code = "", // Invalid
415
+ Name = new string('A', 500), // Too long
416
+ };
417
+
418
+ // Act
419
+ var result = _createValidator.TestValidate(request);
420
+
421
+ // Assert
422
+ result.Errors.Should().HaveCountGreaterThan(1);
423
+ result.ShouldHaveValidationErrorFor(x => x.Code);
424
+ result.ShouldHaveValidationErrorFor(x => x.Name);
425
+ }
426
+
427
+ #endregion
428
+ }
@@ -27,15 +27,15 @@ Edit `ralph.config.yaml` to customize:
27
27
 
28
28
  Ralph **requires** these MCP servers to function:
29
29
 
30
- ### 1. Download MCP packages
30
+ ### 1. Install packages
31
31
  ```bash
32
- npm install -g @atlashub/smartstack-mcp
32
+ npm install -g @atlashub/smartstack-cli
33
33
  npm install -g @upstash/context7-mcp
34
34
  ```
35
35
 
36
36
  ### 2. Register in Claude Code
37
37
  ```bash
38
- claude mcp add smartstack -- npx @atlashub/smartstack-mcp
38
+ claude mcp add smartstack -- npx -p @atlashub/smartstack-cli smartstack-mcp
39
39
  claude mcp add context7 -- npx @upstash/context7-mcp
40
40
  ```
41
41
 
@@ -13,8 +13,8 @@ mcp:
13
13
  health_check: true
14
14
 
15
15
  - name: smartstack
16
- description: "SmartStack validation and scaffolding"
17
- install_command: "npm install -g @atlashub/smartstack-mcp && claude mcp add smartstack -- npx @atlashub/smartstack-mcp"
16
+ description: "SmartStack validation and scaffolding (bundled in CLI)"
17
+ install_command: "claude mcp add smartstack -- npx -p @atlashub/smartstack-cli smartstack-mcp"
18
18
  health_check: true
19
19
 
20
20
  # Behavior when MCP is unavailable
@@ -0,0 +1,42 @@
1
+ ---
2
+ name: admin
3
+ description: Admin account management - reset passwords, manage local admin accounts
4
+ argument-hint: "<subcommand> [options]"
5
+ disable-model-invocation: true
6
+ ---
7
+
8
+ <objective>
9
+ Manage SmartStack admin accounts. Wraps the `smartstack admin` CLI command with guided workflows.
10
+
11
+ **WARNING:** This skill modifies database records directly. Always confirm before executing.
12
+ </objective>
13
+
14
+ <quick_start>
15
+ ```bash
16
+ /admin reset # Reset local admin password (guided)
17
+ /admin reset --force # Reset without confirmation
18
+ ```
19
+ </quick_start>
20
+
21
+ <workflow>
22
+
23
+ ## Subcommands
24
+
25
+ | Command | Description |
26
+ |---------|-------------|
27
+ | `/admin reset` | Reset the localAdmin account password |
28
+
29
+ ## /admin reset
30
+
31
+ 1. **Detect SmartStack.app** - Look for `.smartstack/config.json` or `SmartStack.Api/` directory
32
+ 2. **Run CLI command:**
33
+ ```bash
34
+ smartstack admin reset
35
+ ```
36
+ 3. **If `--force` flag passed:**
37
+ ```bash
38
+ smartstack admin reset --force
39
+ ```
40
+ 4. **Report result** - Show new credentials or error message
41
+
42
+ </workflow>
@@ -214,6 +214,26 @@ generate_feature_id():
214
214
 
215
215
  ### AskUserQuestion Format
216
216
 
217
+ > **⚠️ FORMATTING CRITICAL: `AskUserQuestion` does NOT support markdown or line breaks.**
218
+ > Le champ `question` est rendu en texte brut (plain text). Il n'y a pas de retour à la ligne,
219
+ > pas de gras, pas de puces. Une question simple reste lisible meme longue. Mais du contenu
220
+ > structuré (listes, résumés multi-points, tableaux) devient un mur de texte illisible.
221
+
222
+ | Field | Rule |
223
+ |-------|------|
224
+ | `question` | **1 question ou 1 phrase.** Jamais de liste, résumé multi-points ou contenu structuré. |
225
+ | `header` | 1-2 mots (max 12 chars) |
226
+ | `label` (option) | Court et clair (~20 chars) |
227
+ | `description` (option) | 1 phrase explicative (~60 chars) |
228
+
229
+ > **Pour afficher du contenu structuré** (résumés, listes, tableaux, synthèses) :
230
+ > **TOUJOURS** utiliser du **texte direct** (output text) AVANT l'appel `AskUserQuestion`.
231
+ > Le texte direct supporte le markdown et sera correctement formaté avec titres, puces, gras, etc.
232
+ >
233
+ > **Exemple — Validation de synthèse :**
234
+ > 1. Afficher le résumé structuré en markdown (texte direct)
235
+ > 2. Puis poser une question courte : "Cette synthèse est-elle correcte ?"
236
+
217
237
  ```
218
238
  AskUserQuestion({
219
239
  questions: [
@@ -469,7 +489,7 @@ Le champ `language` dans `.business-analyse/config.json` définit la langue :
469
489
  | Relances et follow-ups (Elicitation Guide) | **OUI** — traduire les probes à la volée |
470
490
  | Documents générés (discovery, BRD, FRD, handoff) | **OUI** — rédigés dans `{language}` |
471
491
  | Référence technique interne (patterns, architecture) | NON — reste en langue du fichier |
472
- | Noms de code (entités, permissions, paths) | NON — toujours en anglais (convention SmartStack) |
492
+ | Noms de code (entités, permissions, paths) | NON — toujours en anglais (convention plateforme) |
473
493
 
474
494
  ### Règle
475
495
 
@@ -480,6 +500,9 @@ Le champ `language` dans `.business-analyse/config.json` définit la langue :
480
500
  → Si {language} ≠ "fr", les traduire à la volée
481
501
  4. Les documents générés sont rédigés dans {language}
482
502
  5. Le code, les noms d'entités et les paths restent TOUJOURS en anglais
503
+ 6. Ne JAMAIS utiliser "SmartStack" dans les communications utilisateur
504
+ → Utiliser "la plateforme", "l'application" ou "le système" à la place
505
+ → SmartStack est le nom interne du framework, le projet client a son propre nom
483
506
  ```
484
507
 
485
508
  ---
@@ -20,8 +20,8 @@
20
20
  |---|----------|-------------|
21
21
  | Q1.5 | What ROI do you expect? (time, money, efficiency) | Quantitative |
22
22
  | Q1.6 | What savings or gains will this module bring? | Estimation |
23
- | Q1.7 | What happens if this module is NOT developed? | Impact |
24
- | Q1.8 | What is the priority compared to other needs? | High/Medium/Low |
23
+ | Q1.7 | What triggered this need? (urgency, regulation, roadmap) | Trigger type |
24
+ | Q1.8 | What is the expected delivery timeline? | Timeline |
25
25
 
26
26
  ---
27
27
 
@@ -36,7 +36,7 @@
36
36
  | Q1.3 (TO-BE) | Vague ("ça ira mieux") | "Concrètement, quel geste ou tâche sera différent ? Combien de clics/minutes en moins ?" |
37
37
  | Q1.4 (KPIs) | No measurable metric | "Comment saurez-vous dans 3 mois que cette fonctionnalité a réussi ? Quel chiffre regarderez-vous ?" |
38
38
  | Q1.5 (ROI) | "I don't know" | "Combien de temps passez-vous sur ce processus aujourd'hui par semaine ? À combien de personnes ?" |
39
- | Q1.7 (if NOT built) | Minimized impact | "Si on ne fait rien pendant 6 mois, qu'est-ce qui empire ? Quel est le coût de l'inaction ?" |
39
+ | Q1.7 (trigger) | Vague ("c'est utile") | "Quel événement ou quelle situation a déclenché ce besoin maintenant ? Obligation, inefficacité, opportunité ?" |
40
40
 
41
41
  ### Anti-patterns to Detect
42
42
 
@@ -45,4 +45,4 @@
45
45
  | "Il faudrait un bouton/écran/champ..." | **Solution disguised as need** | Apply Solution → Problem Reframing |
46
46
  | "C'est évident", "tout le monde sait" | **Implicit assumption** | "Pouvez-vous le formuler explicitement pour que je puisse le documenter ?" |
47
47
  | KPIs are feelings ("ça sera mieux") | **Non-measurable success** | "Quel chiffre regarderez-vous pour savoir si c'est réussi ?" |
48
- | Q1.7 = "rien de grave" | **Faible justification business** | Challenge: si ce n'est pas grave, pourquoi le développer ? |
48
+ | Q1.7 = "Opportunité" sans urgence | **Déclencheur à clarifier** | "Quel gain concret attendez-vous ? Comment mesurerez-vous l'amélioration ?" |
@@ -27,10 +27,10 @@
27
27
 
28
28
  ## Role -> Permission Mapping
29
29
 
30
- > **⚠️ RBAC RULE: Roles are SmartStack permissions, NOT entity attributes.**
30
+ > **⚠️ RBAC RULE: Roles are platform permissions, NOT entity attributes.**
31
31
  >
32
32
  > When stakeholders mention "roles" (admin, manager, user...), these MUST be mapped
33
- > to SmartStack's RBAC permission system (`business.{app}.{module}.{action}`).
33
+ > to the platform's RBAC permission system (`business.{app}.{module}.{action}`).
34
34
  >
35
35
  > **NEVER** model a role as:
36
36
  > - A property/column on a User entity (e.g. `User.Role`, `User.RoleType`)
@@ -39,7 +39,7 @@
39
39
  >
40
40
  > **ALWAYS** map roles to permission sets in the matrix below:
41
41
 
42
- | Discovered Role | SmartStack Permission |
42
+ | Discovered Role | Platform Permission |
43
43
  |-----------------|----------------------|
44
44
  | Admin | `*.admin` |
45
45
  | Manager | `*.read,create,update` |
@@ -12,7 +12,7 @@
12
12
  | Q3.1 | List ESSENTIAL features (Must-Have) | List |
13
13
  | Q3.2 | List DESIRED features (Should-Have) | List |
14
14
  | Q3.3 | List OPTIONAL features (Could-Have) | List |
15
- | Q3.4 | What is EXPLICITLY excluded? | List of exclusions |
15
+ | Q3.4 | Any known constraints limiting v1 scope? | List of constraints |
16
16
 
17
17
  ## 3.2 Business Process
18
18
 
@@ -32,7 +32,7 @@
32
32
  | Must | Without this feature, the module has no value |
33
33
  | Should | Brings significant value but can wait for v2 |
34
34
  | Could | Nice-to-have, can be implemented if time available |
35
- | Won't | Explicitly excluded from scope |
35
+ | Won't | Deferred will be considered for future versions |
36
36
 
37
37
  ## Elicitation Guide
38
38
 
@@ -43,7 +43,7 @@
43
43
  | Q3.1 (Must-Have) | > 10 items listed | "Si vous ne pouviez en garder que 3 pour la v1, lesquels ? Les autres sont peut-être Should-Have." |
44
44
  | Q3.1 (Must-Have) | Mélange CRUD + complexe | "Le CRUD de base (liste, création, modification, suppression) est-il un Must, ou certaines actions sont Could ?" |
45
45
  | Q3.2 (Should-Have) | Vide | "Y a-t-il des fonctionnalités utiles mais qui peuvent attendre une v2 ? Export, filtres avancés, notifications ?" |
46
- | Q3.4 (exclusions) | Vide | "Que ne voulez-vous surtout PAS dans ce module ? Intégrations, reporting, mobile, historique ?" |
46
+ | Q3.4 (limites) | Vide | "Y a-t-il des contraintes connues qui pourraient limiter le périmètre ? (budget, délai, dépendance)" |
47
47
  | Q3.5 (main flow) | < 3 étapes | "Détaillez : l'utilisateur arrive sur l'écran → que voit-il ? → que clique-t-il ? → que se passe-t-il ?" |
48
48
  | Q3.7 (alt flows) | "Il n'y en a pas" | "Que se passe-t-il si l'utilisateur annule ? S'il n'a pas la permission ? Si les données sont invalides ?" |
49
49
  | Q3.8 (errors) | Liste vide | "Que se passe-t-il si le réseau coupe ? Si un champ obligatoire manque ? Si un doublon existe ?" |
@@ -53,6 +53,6 @@
53
53
  | Signal | Anti-pattern | Action |
54
54
  |--------|-------------|--------|
55
55
  | Tout est Must-Have | **Scope non priorisé** | Appliquer le test : "Sans cette fonctionnalité, le module a-t-il ZÉRO valeur ?" |
56
- | Q3.4 vide (rien d'exclu) | **Scope illimité** | "Si tout est inclus, le risque est de ne jamais livrer. Qu'est-ce qui est hors périmètre v1 ?" |
56
+ | Q3.4 pas de limite identifiée | **Scope à valider** | Le scope sera naturellement borné par les Must-Have/Should-Have. Vérifier que les Must-Have sont réalistes. |
57
57
  | Flow linéaire sans alternative | **Happy path uniquement** | "Que se passe-t-il au step X si la condition Y n'est pas remplie ?" |
58
58
  | Mélange fonctionnel/technique | **Solution dans le scope** | Séparer : "gérer les commandes" (fonctionnel) vs "utiliser Redis" (technique) |
@@ -25,9 +25,9 @@
25
25
 
26
26
  ---
27
27
 
28
- ## SmartStack Mapping
28
+ ## Technical Mapping
29
29
 
30
- | Business Concept | SmartStack |
30
+ | Business Concept | Platform |
31
31
  |-----------------|------------|
32
32
  | Main entity | Domain Entity |
33
33
  | Required attribute | `[Required]` |
@@ -35,7 +35,7 @@
35
35
  | 1:N relationship | Navigation property |
36
36
  | Sensitive data | Encryption + audit |
37
37
 
38
- > **⚠️ RBAC EXCLUSION: The following concepts are handled by SmartStack's RBAC system
38
+ > **⚠️ RBAC EXCLUSION: The following concepts are handled by the platform's RBAC system
39
39
  > and MUST NOT be modeled as entity attributes or separate entities:**
40
40
  >
41
41
  > | Concept | ❌ Wrong (entity attribute) | ✅ Correct (RBAC) |
@@ -54,7 +54,7 @@
54
54
  | Question | If answer is vague/insufficient | Probe |
55
55
  |----------|-------------------------------|-------|
56
56
  | Q4.1 (entities) | Single entity listed | "Cette entité a-t-elle des sous-éléments ? (lignes de commande, pièces jointes, historique)" |
57
- | Q4.1 (entities) | Mentions "User" as entity | "L'utilisateur est géré par SmartStack (Identity). Décrivez plutôt l'entité MÉTIER (Client, Employee, Contact...)" |
57
+ | Q4.1 (entities) | Mentions "User" as entity | "L'utilisateur est géré par la plateforme (Identity). Décrivez plutôt l'entité MÉTIER (Client, Employee, Contact...)" |
58
58
  | Q4.2 (attributes) | Liste de champs techniques (ID, CreatedDate) | "Les champs techniques (Id, TenantId, audit) sont auto-gérés. Quels sont les attributs MÉTIER ?" |
59
59
  | Q4.3 (relationships) | "1:N" without detail | "Un {Parent} peut avoir combien de {Children} max ? Un {Child} peut-il exister sans {Parent} ?" |
60
60
  | Q4.4 (volume) | "Beaucoup" | "Ordre de grandeur : dizaines, centaines, milliers, millions ? Croissance par mois ?" |
@@ -65,14 +65,14 @@
65
65
 
66
66
  | Signal | Anti-pattern | Action |
67
67
  |--------|-------------|--------|
68
- | Entity "User" avec attributs métier | **Confusion User/Identity** | SmartStack gère les Users via Identity. L'entité métier = Client, Employee, Contact |
68
+ | Entity "User" avec attributs métier | **Confusion User/Identity** | La plateforme gère les Users via Identity. L'entité métier = Client, Employee, Contact |
69
69
  | Attributs Id, TenantId, CreatedBy listés | **Champs techniques comme métier** | Ces champs sont auto-générés par `AuditableEntity`. Ne pas les lister. |
70
70
  | Pas de soft delete mentionné | **Suppression non clarifiée** | "Les données supprimées sont-elles effacées définitivement ou archivées ?" → `SoftDeletableEntity` |
71
71
  | Aucune contrainte d'unicité | **Unicité non vérifiée** | "Deux entités peuvent-elles avoir le même nom/code/email ?" |
72
72
 
73
- ### SmartStack Entity Patterns
73
+ ### Entity Patterns
74
74
 
75
- | Besoin métier | Base class SmartStack | Inclut automatiquement |
75
+ | Besoin métier | Base class plateforme | Inclut automatiquement |
76
76
  |---------------|----------------------|----------------------|
77
77
  | Entité simple | `Entity` | Id, TenantId |
78
78
  | Avec audit | `AuditableEntity` | + CreatedBy, CreatedDate, ModifiedBy, ModifiedDate |