@atlashub/smartstack-cli 4.76.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/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/references/checks/frontend-checks.sh +97 -11
- package/templates/skills/apex/references/checks/seed-checks.sh +34 -0
- package/templates/skills/apex/references/core-seed-data.md +7 -4
- 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/smartstack-api.md +112 -1
- package/templates/skills/apex-verify/steps/step-01-nav-audit.md +4 -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-seed.md +4 -2
- package/templates/skills/audit-route/references/routing-pattern.md +3 -1
- package/templates/skills/business-analyse/react/components.md +30 -28
- package/templates/skills/business-analyse/templates-react.md +15 -15
- 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/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/smoke-generation/SKILL.md +313 -0
- package/templates/skills/ui-components/SKILL.md +10 -0
- package/templates/skills/ui-components/references/component-catalog.md +82 -0
- package/templates/skills/workflow/SKILL.md +70 -1
|
@@ -120,15 +120,15 @@ const docData: DocData = {
|
|
|
120
120
|
]
|
|
121
121
|
};
|
|
122
122
|
|
|
123
|
-
// Priority Badge Component
|
|
123
|
+
// Priority Badge Component (theme-aware via SmartStack status tokens)
|
|
124
124
|
function PriorityBadge({ priority }: { priority: string }) {
|
|
125
125
|
const colors = {
|
|
126
|
-
Must:
|
|
127
|
-
Should: 'bg-
|
|
128
|
-
Could:
|
|
126
|
+
Must: 'bg-[var(--error-bg)] text-[var(--error-text)] border border-[var(--error-border)]',
|
|
127
|
+
Should: 'bg-[var(--warning-bg)] text-[var(--warning-text)] border border-[var(--warning-border)]',
|
|
128
|
+
Could: 'bg-[var(--info-bg)] text-[var(--info-text)] border border-[var(--info-border)]'
|
|
129
129
|
};
|
|
130
130
|
return (
|
|
131
|
-
<span className={`px-2 py-0.5 rounded text-xs font-medium ${colors[priority as keyof typeof colors] || 'bg-
|
|
131
|
+
<span className={`px-2 py-0.5 rounded text-xs font-medium ${colors[priority as keyof typeof colors] || 'bg-[var(--bg-tertiary)] text-[var(--text-secondary)]'}`}>
|
|
132
132
|
{priority}
|
|
133
133
|
</span>
|
|
134
134
|
);
|
|
@@ -186,7 +186,7 @@ export function {ModuleName}DocPage() {
|
|
|
186
186
|
<span className="px-2 py-0.5 rounded bg-[var(--color-primary-600)]/10 text-[var(--color-primary-600)] text-xs font-medium">
|
|
187
187
|
{docData.featureId}
|
|
188
188
|
</span>
|
|
189
|
-
<span className="px-2 py-0.5 rounded bg-
|
|
189
|
+
<span className="px-2 py-0.5 rounded bg-[var(--success-bg)] text-[var(--success-text)] border border-[var(--success-border)] text-xs font-medium">
|
|
190
190
|
v{docData.version}
|
|
191
191
|
</span>
|
|
192
192
|
</div>
|
|
@@ -264,7 +264,7 @@ export function {ModuleName}DocPage() {
|
|
|
264
264
|
</div>
|
|
265
265
|
<p className="text-sm text-[var(--text-secondary)] mb-2">{uc.description}</p>
|
|
266
266
|
<div className="flex items-center gap-2 text-xs">
|
|
267
|
-
<Shield className="w-3 h-3 text-
|
|
267
|
+
<Shield className="w-3 h-3 text-[var(--warning-text)]" />
|
|
268
268
|
<code className="bg-[var(--bg-secondary)] px-2 py-0.5 rounded">{uc.permission}</code>
|
|
269
269
|
</div>
|
|
270
270
|
</div>
|
|
@@ -318,11 +318,11 @@ export function {ModuleName}DocPage() {
|
|
|
318
318
|
))}
|
|
319
319
|
</div>
|
|
320
320
|
|
|
321
|
-
{/* Permission Warning */}
|
|
322
|
-
<div className="mt-4 p-4 rounded-lg bg-
|
|
323
|
-
<AlertTriangle className="w-5 h-5 text-
|
|
321
|
+
{/* Permission Warning (theme-aware) */}
|
|
322
|
+
<div className="mt-4 p-4 rounded-lg bg-[var(--warning-bg)] border border-[var(--warning-border)] flex items-start gap-3">
|
|
323
|
+
<AlertTriangle className="w-5 h-5 text-[var(--warning-text)] flex-shrink-0 mt-0.5" />
|
|
324
324
|
<div>
|
|
325
|
-
<div className="font-medium text-
|
|
325
|
+
<div className="font-medium text-[var(--warning-text)]">{t('warnings.permissionCheck')}</div>
|
|
326
326
|
<p className="text-sm text-[var(--text-secondary)]">
|
|
327
327
|
{t('warnings.permissionCheckDescription')}
|
|
328
328
|
</p>
|
|
@@ -367,22 +367,22 @@ export function {ModuleName}DocPage() {
|
|
|
367
367
|
</thead>
|
|
368
368
|
<tbody>
|
|
369
369
|
<tr>
|
|
370
|
-
<td className="py-2 px-3"><span className="px-2 py-0.5 rounded bg-
|
|
370
|
+
<td className="py-2 px-3"><span className="px-2 py-0.5 rounded bg-[var(--success-bg)] text-[var(--success-text)] border border-[var(--success-border)]">GET</span></td>
|
|
371
371
|
<td className="py-2 px-3">/api/{'{module}'}</td>
|
|
372
372
|
<td className="py-2 px-3 text-[var(--text-secondary)]">.read</td>
|
|
373
373
|
</tr>
|
|
374
374
|
<tr className="bg-[var(--bg-secondary)]/50">
|
|
375
|
-
<td className="py-2 px-3"><span className="px-2 py-0.5 rounded bg-
|
|
375
|
+
<td className="py-2 px-3"><span className="px-2 py-0.5 rounded bg-[var(--info-bg)] text-[var(--info-text)] border border-[var(--info-border)]">POST</span></td>
|
|
376
376
|
<td className="py-2 px-3">/api/{'{module}'}</td>
|
|
377
377
|
<td className="py-2 px-3 text-[var(--text-secondary)]">.create</td>
|
|
378
378
|
</tr>
|
|
379
379
|
<tr>
|
|
380
|
-
<td className="py-2 px-3"><span className="px-2 py-0.5 rounded bg-
|
|
380
|
+
<td className="py-2 px-3"><span className="px-2 py-0.5 rounded bg-[var(--warning-bg)] text-[var(--warning-text)] border border-[var(--warning-border)]">PUT</span></td>
|
|
381
381
|
<td className="py-2 px-3">/api/{'{module}'}/{'{id}'}</td>
|
|
382
382
|
<td className="py-2 px-3 text-[var(--text-secondary)]">.update</td>
|
|
383
383
|
</tr>
|
|
384
384
|
<tr className="bg-[var(--bg-secondary)]/50">
|
|
385
|
-
<td className="py-2 px-3"><span className="px-2 py-0.5 rounded bg-
|
|
385
|
+
<td className="py-2 px-3"><span className="px-2 py-0.5 rounded bg-[var(--error-bg)] text-[var(--error-text)] border border-[var(--error-border)]">DELETE</span></td>
|
|
386
386
|
<td className="py-2 px-3">/api/{'{module}'}/{'{id}'}</td>
|
|
387
387
|
<td className="py-2 px-3 text-[var(--text-secondary)]">.delete</td>
|
|
388
388
|
</tr>
|
|
@@ -22,10 +22,11 @@ See [references/comparison-map.md](references/comparison-map.md) for the full fi
|
|
|
22
22
|
|
|
23
23
|
<quick_start>
|
|
24
24
|
```bash
|
|
25
|
-
/cli-app-sync
|
|
26
|
-
/cli-app-sync report
|
|
27
|
-
/cli-app-sync fix
|
|
28
|
-
/cli-app-sync check Program
|
|
25
|
+
/cli-app-sync # Full drift report (read-only)
|
|
26
|
+
/cli-app-sync report # Same as above
|
|
27
|
+
/cli-app-sync fix # Detect drift + apply fixes interactively
|
|
28
|
+
/cli-app-sync check Program # Check a single file mapping
|
|
29
|
+
/cli-app-sync diff-entities # List Domain entities NOT referenced by any skill
|
|
29
30
|
```
|
|
30
31
|
</quick_start>
|
|
31
32
|
|
|
@@ -37,6 +38,7 @@ See [references/comparison-map.md](references/comparison-map.md) for the full fi
|
|
|
37
38
|
| `/cli-app-sync report` | Same as above (explicit) |
|
|
38
39
|
| `/cli-app-sync fix` | Detect drift and propose fixes interactively |
|
|
39
40
|
| `/cli-app-sync check <name>` | Check a single comparison point by name |
|
|
41
|
+
| `/cli-app-sync diff-entities` | List Domain entities present in app but NOT covered by any CLI skill (uncovered drift detector) |
|
|
40
42
|
|
|
41
43
|
</subcommands>
|
|
42
44
|
|
|
@@ -262,6 +264,103 @@ Status: DRIFT (2 issues)
|
|
|
262
264
|
|
|
263
265
|
</output_format>
|
|
264
266
|
|
|
267
|
+
<diff_entities_workflow>
|
|
268
|
+
|
|
269
|
+
## `/cli-app-sync diff-entities` — uncovered Domain entities
|
|
270
|
+
|
|
271
|
+
**Why this exists.** `cli-app-sync` (default mode) compares known files in `templates/project/` and `init.ts` against their counterparts in `SmartStack.app`. It detects **explicit drift** but is blind to **trous** : a brand-new entity in the platform (e.g. `AiTool`, `WorkflowVersion`, `AiEvalDataset` added in v3.46) that no CLI skill mentions yet. Without `diff-entities`, those gaps are only caught by manual audit.
|
|
272
|
+
|
|
273
|
+
See [references/diff-entities.md](references/diff-entities.md) for the full algorithm (rules, exclusions, output format).
|
|
274
|
+
|
|
275
|
+
### Quick algorithm
|
|
276
|
+
|
|
277
|
+
1. **Enumerate Domain entities** :
|
|
278
|
+
```bash
|
|
279
|
+
APP_DOMAIN="${APP_PATH:-D:/01 - projets/SmartStack.app/features/IA-Workflow}/src/SmartStack.Domain"
|
|
280
|
+
# Classes/records that look like aggregate roots (inherit BaseEntity or are records under Domain/)
|
|
281
|
+
grep -rPnh "^\s*public\s+(?:partial\s+)?(?:class|record)\s+([A-Z][A-Za-z0-9]+)\s*:?\s*(?:BaseEntity|I[A-Z][A-Za-z]+Entity|IDomainEvent)" "$APP_DOMAIN" \
|
|
282
|
+
--include='*.cs' \
|
|
283
|
+
| sed -E "s/.*\b(class|record)\s+([A-Z][A-Za-z0-9]+).*/\2/" \
|
|
284
|
+
| sort -u > /tmp/app-entities.txt
|
|
285
|
+
```
|
|
286
|
+
|
|
287
|
+
2. **Enumerate entities referenced in CLI skills** :
|
|
288
|
+
```bash
|
|
289
|
+
CLI_SKILLS="D:/01 - projets/SmartStack.cli/02-Develop/templates/skills"
|
|
290
|
+
# Any PascalCase token in code blocks that matches an entity name
|
|
291
|
+
while IFS= read -r ENT; do
|
|
292
|
+
COUNT=$(grep -r --include='*.md' --include='*.sh' -lE "\b${ENT}\b" "$CLI_SKILLS" | wc -l)
|
|
293
|
+
echo "${ENT}|${COUNT}"
|
|
294
|
+
done < /tmp/app-entities.txt > /tmp/entity-coverage.tsv
|
|
295
|
+
```
|
|
296
|
+
|
|
297
|
+
3. **Classify** each entity :
|
|
298
|
+
- `count = 0` → `[NEW UNCOVERED]` — propose a skill to cover it
|
|
299
|
+
- `count = 1-2` → `[THIN]` — covered but might benefit from a dedicated reference
|
|
300
|
+
- `count ≥ 3` → `[COVERED]` — well documented (skip in report unless `--verbose`)
|
|
301
|
+
|
|
302
|
+
4. **Suggest a skill destination** based on the entity's namespace :
|
|
303
|
+
|
|
304
|
+
| Namespace prefix | Suggested skill |
|
|
305
|
+
|---|---|
|
|
306
|
+
| `Domain.AI.Agents.*` / `Domain.AI.Skills.*` | `ai-prompt` |
|
|
307
|
+
| `Domain.AI.Evaluations.*` | `ai-prompt` (`references/eval-framework.md`) |
|
|
308
|
+
| `Domain.AI.Tools.*` | `ai-prompt` |
|
|
309
|
+
| `Domain.Communications.Workflow*` | `workflow` |
|
|
310
|
+
| `Domain.Communications.EmailTemplate*` | `notification` (or `workflow`) |
|
|
311
|
+
| `Domain.Navigation.*` | `application` |
|
|
312
|
+
| `Domain.Platform.Administration.UiConfiguration.*` | `application/references/themes-db-driven.md` |
|
|
313
|
+
| `Domain.Licensing.*` | `apex/references/smartstack-api.md` (Licensing section) |
|
|
314
|
+
| `Domain.Common.*` (interfaces, enums) | `apex/references/smartstack-api.md` |
|
|
315
|
+
| `Domain.Support.*` | `notification` (or new skill) |
|
|
316
|
+
| other | propose a new skill name based on the namespace |
|
|
317
|
+
|
|
318
|
+
### Output (typical)
|
|
319
|
+
|
|
320
|
+
```
|
|
321
|
+
================================================================================
|
|
322
|
+
UNCOVERED DOMAIN ENTITIES — {date}
|
|
323
|
+
================================================================================
|
|
324
|
+
APP : IA-Workflow @ {commit}
|
|
325
|
+
Total Domain entities scanned: 87
|
|
326
|
+
|
|
327
|
+
[NEW UNCOVERED] (0 references in templates/skills/)
|
|
328
|
+
AiTool → Domain/AI/Tools/ → ai-prompt skill
|
|
329
|
+
AiSkillTool → Domain/AI/Tools/ → ai-prompt skill
|
|
330
|
+
AiEvalDataset → Domain/AI/Evaluations/ → ai-prompt/references/eval-framework.md
|
|
331
|
+
AiEvalDatasetItem → Domain/AI/Evaluations/ → idem
|
|
332
|
+
AiEvaluation → Domain/AI/Evaluations/ → idem
|
|
333
|
+
AiEvalResult → Domain/AI/Evaluations/ → idem
|
|
334
|
+
AiAgentExecution → Domain/AI/Agents/ → ai-prompt skill
|
|
335
|
+
AiAgentStepExecution → Domain/AI/Agents/ → ai-prompt skill
|
|
336
|
+
WorkflowVersion → Domain/Communications/ → workflow skill
|
|
337
|
+
IBeforeCreate → Application/Hooks/ → smartstack-api.md (Hooks section)
|
|
338
|
+
IDomainEvent → Domain/Support/Events/ → smartstack-api.md (Domain Events)
|
|
339
|
+
|
|
340
|
+
[THIN] (1-2 references — consider dedicated docs)
|
|
341
|
+
License (2 refs) → smartstack-api.md (Licensing section)
|
|
342
|
+
BrandingAsset (1 ref) → themes-db-driven.md
|
|
343
|
+
UiThemeTenantPublication (1 ref) → themes-db-driven.md
|
|
344
|
+
|
|
345
|
+
[COVERED] (≥3 references — well documented, hidden unless --verbose)
|
|
346
|
+
87 entities — 76 covered, 11 thin/uncovered
|
|
347
|
+
|
|
348
|
+
--------------------------------------------------------------------------------
|
|
349
|
+
SUMMARY : 11 entities need attention (8 NEW UNCOVERED, 3 THIN)
|
|
350
|
+
================================================================================
|
|
351
|
+
```
|
|
352
|
+
|
|
353
|
+
### Integration with the rest of `cli-app-sync`
|
|
354
|
+
|
|
355
|
+
`diff-entities` is independent from the comparison map (no overlap with `report` / `fix`). It only adds new findings ; it never modifies templates. To act on findings, the user runs the suggested skill author flow manually (or invokes `/apex` if a brand-new domain warrants a full skill).
|
|
356
|
+
|
|
357
|
+
Recommended cadence :
|
|
358
|
+
- Run after every bump of the `APP_PATH` branch (e.g. moving from `02-Develop` to `features/IA-Workflow`)
|
|
359
|
+
- Run before each release of the CLI (catch entities the platform shipped that the CLI hasn't documented yet)
|
|
360
|
+
- Run weekly as a background `/loop /cli-app-sync diff-entities --report-only`
|
|
361
|
+
|
|
362
|
+
</diff_entities_workflow>
|
|
363
|
+
|
|
265
364
|
<success_criteria>
|
|
266
365
|
- All comparison points from the map are checked
|
|
267
366
|
- Intentional differences are correctly identified as SKIP
|
|
@@ -269,4 +368,6 @@ Status: DRIFT (2 issues)
|
|
|
269
368
|
- Fix mode correctly updates template files and init.ts inline templates
|
|
270
369
|
- Build passes after fixes are applied
|
|
271
370
|
- Report is clear, actionable, and easy to scan
|
|
371
|
+
- `diff-entities` lists every Domain entity NOT covered by any CLI skill, with a suggested destination skill
|
|
372
|
+
- `diff-entities` matches the manual audit pattern that surfaced AiTool / AiEvalDataset / WorkflowVersion / Hooks gaps in the v3.46 alignment work
|
|
272
373
|
</success_criteria>
|
|
@@ -219,6 +219,19 @@ These comparisons should **always** return `[SKIP]` — differences are by desig
|
|
|
219
219
|
|
|
220
220
|
---
|
|
221
221
|
|
|
222
|
+
## v3.46+ Comparison Points
|
|
223
|
+
|
|
224
|
+
Added with the v3.46 alignment of CLI templates. These verify client projects honor the new architecture.
|
|
225
|
+
|
|
226
|
+
| ID | Comparison | Reference path | Patterns to check | Criticality |
|
|
227
|
+
|---|---|---|---|---|
|
|
228
|
+
| `nav-application-flags` | Seeds use `IsPersonal`/`IsOpen`, NOT `Zone = ApplicationZone.X` | `*/Seeding/Data/*NavigationApplicationSeedData.cs` and `*/Seeding/Data/*NavigationSeedData.cs` | Must match `IsPersonal\s*=` AND `IsOpen\s*=`. Must NOT match `ApplicationZone\.\w+`. | BLOCKING (with C66 grace period — currently WARNING) |
|
|
229
|
+
| `frontend-layouts-count` | Exactly 4 layouts present | `web/.../src/layouts/*.tsx` | Must contain `AppLayout.tsx`, `AuthLayout.tsx`, `DocsLayout.tsx`, `PublicLayout.tsx`. Must NOT contain `AdminLayout`, `BusinessLayout`, `UserLayout`, `HRLayout`, `SalesLayout`. | BLOCKING (C67 grace period — WARNING) |
|
|
230
|
+
| `provider-pattern` | Client root uses `<SmartStackProvider>` | `web/.../src/main.tsx` or `web/.../src/App.tsx` | Must contain `<SmartStackProvider config={` AND `<DynamicRouter />`. Must NOT contain manual `<AuthProvider>`/`<ThemeProvider>` re-wrap. | WARNING |
|
|
231
|
+
| `ai-agent-modes` | If AI activated, enums `AiAgentMode` / `AiAgentStepRole` are present | `src/.../Domain/AI/Agents/*.cs` | If `AiAgent.cs` exists, must reference `AiAgentMode` enum (Sequential/ReAct/PlanAndExecute/SelfCorrection). | WARNING |
|
|
232
|
+
|
|
233
|
+
---
|
|
234
|
+
|
|
222
235
|
## Maintenance
|
|
223
236
|
|
|
224
237
|
When adding a new comparison point:
|
|
@@ -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.
|
|
@@ -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>
|