@atlashub/smartstack-cli 3.21.0 → 3.23.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 (36) hide show
  1. package/dist/index.js +17 -5
  2. package/dist/index.js.map +1 -1
  3. package/dist/mcp-entry.mjs +155 -162
  4. package/dist/mcp-entry.mjs.map +1 -1
  5. package/package.json +1 -1
  6. package/templates/skills/apex/SKILL.md +21 -0
  7. package/templates/skills/apex/references/smartstack-api.md +481 -0
  8. package/templates/skills/apex/references/smartstack-layers.md +85 -15
  9. package/templates/skills/apex/steps/step-00-init.md +27 -14
  10. package/templates/skills/apex/steps/step-01-analyze.md +18 -0
  11. package/templates/skills/apex/steps/step-03-execute.md +8 -6
  12. package/templates/skills/apex/steps/step-04-validate.md +92 -0
  13. package/templates/skills/apex/steps/step-07-tests.md +29 -5
  14. package/templates/skills/application/references/application-roles-template.md +2 -2
  15. package/templates/skills/application/steps/step-05-frontend.md +40 -35
  16. package/templates/skills/application/templates-frontend.md +64 -36
  17. package/templates/skills/business-analyse/html/ba-interactive.html +80 -6
  18. package/templates/skills/business-analyse/html/src/scripts/05-render-specs.js +38 -6
  19. package/templates/skills/business-analyse/html/src/styles/06-wireframes.css +42 -0
  20. package/templates/skills/business-analyse/references/acceptance-criteria.md +169 -0
  21. package/templates/skills/business-analyse/references/deploy-data-build.md +5 -3
  22. package/templates/skills/business-analyse/references/handoff-file-templates.md +2 -1
  23. package/templates/skills/business-analyse/references/naming-conventions.md +245 -0
  24. package/templates/skills/business-analyse/references/validate-incremental-html.md +26 -4
  25. package/templates/skills/business-analyse/references/validation-checklist.md +31 -11
  26. package/templates/skills/business-analyse/references/wireframe-svg-style-guide.md +335 -0
  27. package/templates/skills/business-analyse/steps/step-03b-ui.md +59 -0
  28. package/templates/skills/business-analyse/steps/step-03c-compile.md +114 -0
  29. package/templates/skills/business-analyse/steps/step-03d-validate.md +144 -22
  30. package/templates/skills/business-analyse/steps/step-05a-handoff.md +114 -2
  31. package/templates/skills/business-analyse/steps/step-05b-deploy.md +28 -0
  32. package/templates/skills/ralph-loop/references/category-rules.md +5 -2
  33. package/templates/skills/ralph-loop/references/compact-loop.md +52 -1
  34. package/templates/skills/ralph-loop/references/core-seed-data.md +232 -21
  35. package/templates/skills/ralph-loop/steps/step-01-task.md +36 -4
  36. package/templates/skills/ralph-loop/steps/step-02-execute.md +81 -0
@@ -0,0 +1,245 @@
1
+ # Naming Conventions - SmartStack
2
+
3
+ > **Loaded by:** business-analyse steps when generating codes and routes
4
+ > **Purpose:** Define transformation rules between code identifiers (PascalCase) and URL routes (kebab-case)
5
+
6
+ ---
7
+
8
+ ## Module & Application Codes
9
+
10
+ ### In feature.json
11
+
12
+ - `modules[].code` = **PascalCase** (e.g., `"HumanResources"`, `"TimeManagement"`)
13
+ - `metadata.application` = **PascalCase** (e.g., `"HumanResources"`)
14
+ - Used for: C# namespaces, file paths, class names, folder structure
15
+
16
+ ### In URL Routes
17
+
18
+ - **kebab-case lowercase** (e.g., `"/business/human-resources/employees"`)
19
+ - Transform: `PascalCase` → `kebab-case` via helper function
20
+ - Used for: Web URLs, navigation routes, API paths
21
+
22
+ ---
23
+
24
+ ## Transformation Rules
25
+
26
+ | Source | Format | Example | Usage |
27
+ |--------|--------|---------|-------|
28
+ | Module code | `PascalCase` | `HumanResources` | C# files, classes, namespaces |
29
+ | Application code | `PascalCase` | `HumanResources` | Namespaces, folders |
30
+ | Context code | `lowercase` | `business` | URLs, routes, contexts |
31
+ | Route path | `kebab-case` | `/business/human-resources` | Web URLs, navigation |
32
+ | Section code | `kebab-case` | `time-tracking`, `approve` | URLs, API paths, sections |
33
+ | Resource code | `kebab-case` | `repair-grid`, `employee-form` | Component IDs, resources |
34
+
35
+ ---
36
+
37
+ ## Why These Conventions?
38
+
39
+ ### PascalCase for Code
40
+ - **C# Standard**: Namespaces, classes, properties follow PascalCase
41
+ - **File Structure**: Matches .NET project conventions
42
+ - **Compile-time**: Enforced by compiler and naming analyzers
43
+
44
+ ### kebab-case for URLs
45
+ - **Web Standard**: Readable, SEO-friendly, case-insensitive
46
+ - **REST API Convention**: Lowercase routes with hyphens
47
+ - **Frontend Compatibility**: React Router, Vue Router expect lowercase
48
+ - **Database Storage**: Navigation routes stored lowercase prevent case mismatch errors
49
+
50
+ ### Separation of Concerns
51
+ - **Code Identity** ≠ **URL Identity**
52
+ - Backend uses PascalCase internally
53
+ - URLs transform to kebab-case at persistence layer (seed data)
54
+ - Frontend consumes kebab-case routes from database
55
+
56
+ ---
57
+
58
+ ## Helper Functions
59
+
60
+ ### C# (Backend Seed Data)
61
+
62
+ **Location:** `NavigationSeedData.cs` templates in core-seed-data.md
63
+
64
+ **Usage:**
65
+ ```csharp
66
+ Route = ToKebabCase($"/{contextCode}/{appCode}/{moduleCode}")
67
+ ```
68
+
69
+ **Transformation Examples:**
70
+ - `HumanResources` → `human-resources`
71
+ - `TimeManagement` → `time-management`
72
+ - `Projects` → `projects` (single word, no change)
73
+ - `AI` → `ai` (acronym lowercase)
74
+
75
+ **Implementation:** See `templates/skills/ralph-loop/references/core-seed-data.md` line 162
76
+
77
+ ### JavaScript (BA Handoff Generation)
78
+
79
+ **Location:** Used in step-05a-handoff.md when building seedDataCore
80
+
81
+ **Usage:**
82
+ ```javascript
83
+ const route = `/${contextCode}/${toKebabCase(appCode)}/${toKebabCase(moduleCode)}`;
84
+ ```
85
+
86
+ **Implementation:**
87
+ ```javascript
88
+ function toKebabCase(code) {
89
+ return code
90
+ .replace(/([a-z])([A-Z])/g, '$1-$2')
91
+ .toLowerCase();
92
+ }
93
+ ```
94
+
95
+ ### TypeScript (Frontend MCP)
96
+
97
+ **Location:** Used in scaffold_routes and validate_frontend_routes
98
+
99
+ **Usage:**
100
+ ```typescript
101
+ const webPath = `/${navRoute.split('.').map(toKebabCase).join('/')}`;
102
+ ```
103
+
104
+ **Implementation:**
105
+ ```typescript
106
+ function toKebabCase(str: string): string {
107
+ return str
108
+ .replace(/([a-z])([A-Z])/g, '$1-$2')
109
+ .toLowerCase();
110
+ }
111
+ ```
112
+
113
+ ---
114
+
115
+ ## Validation
116
+
117
+ ### During Generation (ralph-loop)
118
+
119
+ POST-CHECK after NavigationSeedData generation:
120
+
121
+ ```bash
122
+ # Detect routes with uppercase
123
+ grep -E 'Route = "?/[^"]*[A-Z]' Infrastructure/Persistence/Seeding/Data/*/NavigationSeedData.cs
124
+ ```
125
+
126
+ If match found → ERROR, routes not transformed to kebab-case.
127
+
128
+ ### Via MCP
129
+
130
+ ```bash
131
+ validate_frontend_routes
132
+ ```
133
+
134
+ **Detects:**
135
+ - Routes with uppercase in URLs
136
+ - Seed data routes not matching frontend expectations
137
+ - PascalCase URLs without kebab-case conversion
138
+
139
+ **Output Example:**
140
+ ```
141
+ ❌ Case mismatch detected (1 routes with uppercase):
142
+ Route "business.humanresources" uses PascalCase in URL.
143
+ Found: business/HumanResources → Expected: business/human-resources
144
+ Fix: Use ToKebabCase() in NavigationSeedData route generation
145
+ ```
146
+
147
+ ---
148
+
149
+ ## Common Pitfalls
150
+
151
+ ### ❌ Generating Routes Without Transformation
152
+
153
+ **Wrong (causes 404 on menu click):**
154
+ ```csharp
155
+ Route = $"/{contextCode}/{appCode}/{moduleCode}"
156
+ // Result: /business/HumanResources/Projects
157
+ ```
158
+
159
+ **Correct:**
160
+ ```csharp
161
+ Route = ToKebabCase($"/{contextCode}/{appCode}/{moduleCode}")
162
+ // Result: /business/human-resources/projects
163
+ ```
164
+
165
+ ### ❌ Hardcoding Routes in lowercase
166
+
167
+ **Wrong (loses traceability to code):**
168
+ ```csharp
169
+ Route = "/business/humanresources" // Flattens multi-word into single word
170
+ ```
171
+
172
+ **Correct:**
173
+ ```csharp
174
+ Route = ToKebabCase($"/{contextCode}/{appCode}")
175
+ // If appCode = "HumanResources" → /business/human-resources
176
+ ```
177
+
178
+ ### ❌ Inconsistent Section/Resource Codes
179
+
180
+ **Wrong (mixing conventions):**
181
+ ```json
182
+ {
183
+ "code": "TimeTracking", // PascalCase
184
+ "route": "/time-tracking" // kebab-case route doesn't match
185
+ }
186
+ ```
187
+
188
+ **Correct:**
189
+ ```json
190
+ {
191
+ "code": "time-tracking", // kebab-case from start
192
+ "route": "/business/human-resources/time-tracking"
193
+ }
194
+ ```
195
+
196
+ Sections and resources ALWAYS use kebab-case (no transformation needed).
197
+
198
+ ---
199
+
200
+ ## Examples
201
+
202
+ ### Full Hierarchy Example
203
+
204
+ **BA Input (feature.json):**
205
+ ```json
206
+ {
207
+ "metadata": {
208
+ "context": "business",
209
+ "application": "HumanResources"
210
+ },
211
+ "modules": [
212
+ { "code": "TimeManagement" },
213
+ { "code": "Projects" }
214
+ ]
215
+ }
216
+ ```
217
+
218
+ **Generated Routes (seed data):**
219
+ ```
220
+ Application: /business/human-resources
221
+ Module 1: /business/human-resources/time-management
222
+ Module 2: /business/human-resources/projects
223
+ ```
224
+
225
+ **C# Code Structure:**
226
+ ```
227
+ src/Domain/Entities/Business/HumanResources/TimeManagement/TimeEntry.cs
228
+ src/Application/Services/Business/HumanResources/TimeManagement/TimeEntryService.cs
229
+ src/API/Controllers/Business/HumanResources/TimeManagementController.cs
230
+ ```
231
+
232
+ **Frontend Routes (React Router):**
233
+ ```tsx
234
+ <Route path="/business/human-resources/time-management" element={<TimeManagementPage />} />
235
+ <Route path="/business/human-resources/projects" element={<ProjectsPage />} />
236
+ ```
237
+
238
+ ---
239
+
240
+ ## References
241
+
242
+ - **Template:** `templates/skills/ralph-loop/references/core-seed-data.md`
243
+ - **Validation:** `src/mcp/tools/validate-frontend-routes.ts`
244
+ - **POST-CHECK:** `templates/skills/ralph-loop/steps/step-02-execute.md` (section 5)
245
+ - **Handoff:** `templates/skills/business-analyse/steps/step-05a-handoff.md` (section 4.6)
@@ -46,10 +46,11 @@ const EMBEDDED_ARTIFACTS = {
46
46
  // FOR EACH completed module: extract wireframes with RENAMED fields
47
47
  // SAFETY NET: check BOTH key names (agent may use either)
48
48
  [moduleCode]: (moduleFeature.specification.uiWireframes || moduleFeature.specification.wireframes || []).map(wf => ({
49
- screen: wf.screen,
50
- section: wf.section,
49
+ screen: wf.screen || wf.name || wf.title || wf.id || "", // SAFETY NET: fallback name/title/id → screen
50
+ section: wf.section || "",
51
51
  format: wf.mockupFormat || "ascii", // RENAME: mockupFormat → format
52
- content: wf.mockup, // RENAME: mockup → content
52
+ content: wf.mockup || wf.ascii || wf.content || "", // SAFETY NET: mockup/ascii/content → content
53
+ svgContent: null, // Populated by Step 3-bis SVG generation
53
54
  description: wf.description || "",
54
55
  elements: wf.elements || [],
55
56
  actions: wf.actions || [],
@@ -74,6 +75,27 @@ const EMBEDDED_ARTIFACTS = {
74
75
  > The HTML renderer reads `format` and `content`. You MUST rename these fields.
75
76
  > Failure to rename = empty mockup display in the browser.
76
77
 
78
+ ### Step 3-bis: Generate SVG Wireframes (Parallel Task Agents)
79
+
80
+ > **Purpose:** Enrich each ASCII wireframe with a professional SVG version for dual-view rendering.
81
+ > **Cost:** ~$0.01 per wireframe (Sonnet model). Negligible for 2-6 wireframes per module.
82
+ > **Fallback:** If ANY SVG generation fails, proceed with ASCII only (svgContent stays null).
83
+
84
+ See [references/wireframe-svg-style-guide.md](wireframe-svg-style-guide.md) for the complete SVG style specification, prompt template, and orchestration process.
85
+
86
+ **Process summary:**
87
+
88
+ 1. **Read** `references/wireframe-svg-style-guide.md` to get the prompt template
89
+ 2. **Collect** all wireframes in `EMBEDDED_ARTIFACTS.wireframes` where `content` exists and `svgContent` is null
90
+ 3. **Spawn parallel Task(sonnet) agents** — ONE per wireframe, ALL in a single message
91
+ 4. **Collect and validate** results: strip markdown fences if present, verify SVG starts with `<svg` and contains `</svg>`
92
+ 5. **Inject** valid SVGs into `EMBEDDED_ARTIFACTS.wireframes[moduleCode][index].svgContent`
93
+ 6. **Display** summary: `SVG wireframes: {generated}/{total} generated successfully`
94
+
95
+ > **CRITICAL:** This step is NEVER blocking. If all SVG generations fail, deployment
96
+ > continues with ASCII-only wireframes. The HTML renderer checks for `svgContent` before
97
+ > showing the SVG view. SVG is an enhancement, not a requirement.
98
+
77
99
  ### Step 4: Replace Placeholders in Template
78
100
 
79
101
  - Serialize the FEATURE_DATA object as JSON (2-space indentation)
@@ -93,7 +115,7 @@ const EMBEDDED_ARTIFACTS = {
93
115
  Modules included: {completedModules.length}/{totalModules} specified
94
116
  - {completedModule1}: {uc_count} UCs, {br_count} BRs, {wireframe_count} wireframes
95
117
  - {completedModule2}: ...
96
- Visual artifacts: {total_wireframes} wireframes embedded
118
+ Visual artifacts: {total_wireframes} wireframes embedded ({svg_count} with SVG, {ascii_only_count} ASCII only)
97
119
  Remaining: {pendingModules.join(', ')} (will be added after specification)
98
120
  → Client can open in browser to review completed modules now.
99
121
  ```
@@ -139,16 +139,16 @@ const checklist = {
139
139
 
140
140
  wireframes: {
141
141
  minimum: specification.sections.length, // 1 wireframe PER section
142
- actual: specification.uiWireframes.length,
142
+ actual: (specification.uiWireframes || specification.wireframes || []).length, // Check BOTH key names
143
143
  status: actual >= minimum ? "PASS" : "FAIL",
144
144
  blocking: true,
145
- details: "EVERY section MUST have a wireframe (ASCII/SVG)"
145
+ details: "EVERY section MUST have a wireframe (ASCII/SVG). Check both uiWireframes and wireframes keys."
146
146
  },
147
147
 
148
148
  wireframeSchemaCompliance: {
149
149
  check: "All wireframes have required fields: screen, section, mockupFormat, elements[], componentMapping[], layout (object), permissionsRequired[]",
150
- status: specification.uiWireframes.every(wf =>
151
- wf.screen && wf.section && wf.mockupFormat &&
150
+ status: (specification.uiWireframes || specification.wireframes || []).every(wf =>
151
+ (wf.screen || wf.title) && wf.section && (wf.mockupFormat || wf.mockup || wf.ascii) &&
152
152
  Array.isArray(wf.elements) && wf.elements.length > 0 &&
153
153
  Array.isArray(wf.componentMapping) && wf.componentMapping.length > 0 &&
154
154
  typeof wf.layout === 'object' && wf.layout !== null &&
@@ -156,8 +156,9 @@ const checklist = {
156
156
  ) ? "PASS" : "FAIL",
157
157
  blocking: true,
158
158
  details: "Wireframes missing metadata render as empty frames in HTML documentation. " +
159
- "Check: screen (not name/id), section, mockupFormat, elements[] non-empty, " +
160
- "componentMapping[] as array of {wireframeElement, reactComponent}, layout as object (not string)"
159
+ "Check: screen (not name/id/title), section, mockupFormat, elements[] non-empty, " +
160
+ "componentMapping[] as array of {wireframeElement, reactComponent}, layout as object (not string). " +
161
+ "Also see references/acceptance-criteria.md for bash-verifiable checks."
161
162
  },
162
163
 
163
164
  navigation: {
@@ -240,12 +241,31 @@ const checklist = {
240
241
  details: "Modules need field validation rules"
241
242
  },
242
243
 
243
- // SECTION 10: GHERKIN SCENARIOS (WARNING)
244
- gherkinScenarios: {
244
+ // SECTION 10: GHERKIN SCENARIOS (BLOCKING for format, WARNING for count)
245
+ gherkinFormat: {
246
+ check: "gherkinScenarios is ARRAY (not single object)",
247
+ status: Array.isArray(specification.gherkinScenarios) ? "PASS" : "FAIL",
248
+ blocking: true,
249
+ details: "gherkinScenarios MUST be an array [{feature, scenarios}], not a single object. " +
250
+ "Auto-fix: wrap in array [gherkinScenarios]. See step-03c ABSOLUTE FORMAT CHECKS."
251
+ },
252
+
253
+ gherkinContent: {
254
+ check: "Each gherkin entry has feature (string) + scenarios (array)",
255
+ status: (Array.isArray(specification.gherkinScenarios) &&
256
+ specification.gherkinScenarios.every(g => g.feature && Array.isArray(g.scenarios))
257
+ ) ? "PASS" : "FAIL",
258
+ blocking: true,
259
+ details: "Each gherkin entry must have {feature: string, scenarios: [{name, tags, given[], when[], then[]}]}"
260
+ },
261
+
262
+ gherkinScenarioCount: {
245
263
  minimum: 2,
246
- actual: specification.gherkinScenarios.scenarios.length,
264
+ actual: (Array.isArray(specification.gherkinScenarios)
265
+ ? specification.gherkinScenarios.reduce((sum, g) => sum + (g.scenarios || []).length, 0)
266
+ : 0),
247
267
  status: actual >= minimum ? "PASS" : "FAIL",
248
- blocking: false, // WARNING only
268
+ blocking: false, // WARNING only — count is advisory
249
269
  details: "Gherkin scenarios enable automated testing"
250
270
  }
251
271
  };
@@ -297,7 +317,7 @@ ELSE:
297
317
  | Seed Data | 2 | {n} | {n} | {n} |
298
318
  | API Endpoints | 2 | {n} | {n} | {n} |
299
319
  | Validations | 1 | {n} | {n} | {n} |
300
- | Gherkin | 1 | {n} | {n} | {n} |
320
+ | Gherkin | 3 | {n} | {n} | {n} |
301
321
 
302
322
  TOTAL: {total_checks} checks | {passed} ✓ | {failed} ✗ | {warnings} ⚠
303
323