---
name: smoke-generation
description: Validate CLI templates by checking that every imported component, type, and method signature documented in /templates/skills/ actually exists in SmartStack.app (IA-Workflow). Catches the "EntityLookup paradox" class of drift where docs reference things that don't exist in the platform.
argument-hint: "[--quick|--full] [--scope=frontend|backend|all] [--app-path=<path>] [--report-only]"
model: sonnet
allowed-tools: Read, Grep, Glob, Bash, Write
---

## Current state (auto-injected)

- CLI version: !`node -p "require('./package.json').version" 2>/dev/null || echo "unknown"`
- App branch: !`git -C "D:/01 - projets/SmartStack.app/features/IA-Workflow" rev-parse --abbrev-ref HEAD 2>/dev/null || echo "unknown"`
- App last commit: !`git -C "D:/01 - projets/SmartStack.app/features/IA-Workflow" log --oneline -1 2>/dev/null || echo "unknown"`
- Last smoke run: !`cat .claude/cache/smoke-generation.json 2>/dev/null | head -5 || echo "no previous run"`

<objective>
Detect "documentation lies": patterns/imports/types that the CLI documents as canonical (and may even enforce via post-checks) but that do NOT exist in SmartStack.app. The canonical example is `EntityLookup`: documented in 4 CLI files and enforced by check C7, but the component does not exist in `web/smartstack-web/src/components/ui/`. This skill would have caught that on day 1.

Two modes :
- **`--quick` (default)** — pure static analysis (~30s). Greps imports / types / method signatures in `templates/skills/**/*.md`, verifies each one resolves to a real file or symbol in `D:/01 - projets/SmartStack.app/features/IA-Workflow/`.
- **`--full`** — runs an actual scaffold + `dotnet build` + `npm run build` in a sandbox. Heavier (~5-10 min) but catches runtime errors not visible by static analysis.
</objective>

<quick_start>
```bash
/smoke-generation                        # Quick static analysis on all CLI templates
/smoke-generation --quick                # Same as above (explicit)
/smoke-generation --full                 # Full sandbox scaffold + build (slow, thorough)
/smoke-generation --scope=frontend       # Static analysis on frontend imports only
/smoke-generation --scope=backend        # Static analysis on backend types/signatures only
/smoke-generation --report-only          # Skip writing cache, print to stdout only
/smoke-generation --app-path=<path>      # Override default IA-Workflow path
```
</quick_start>

<paths>

```
APP_ROOT      = D:/01 - projets/SmartStack.app/features/IA-Workflow   # default
APP_FRONTEND  = $APP_ROOT/web/smartstack-web/src
APP_BACKEND   = $APP_ROOT/src/SmartStack.Domain   (+ Application + Infrastructure + Api)

CLI_TEMPLATES = D:/01 - projets/SmartStack.cli/02-Develop/templates/skills
CACHE_FILE    = D:/01 - projets/SmartStack.cli/02-Develop/.claude/cache/smoke-generation.json
```

If `--app-path=<path>` is provided, override `APP_ROOT`.

</paths>

<workflow>

## Step 0 — Preflight

```bash
APP_ROOT="${APP_PATH:-D:/01 - projets/SmartStack.app/features/IA-Workflow}"
[ -d "$APP_ROOT/src/SmartStack.Domain" ] || { echo "ERROR: APP_ROOT not found at $APP_ROOT"; exit 1; }
[ -d "$APP_ROOT/web/smartstack-web/src" ] || { echo "ERROR: app frontend not found"; exit 1; }
mkdir -p "D:/01 - projets/SmartStack.cli/02-Develop/.claude/cache"
```

## Step 1 — Frontend static checks (`--scope=frontend|all`)

### 1.1 Extract every documented frontend import

Grep all `import { X } from '@/components/...'` (and similar) across `templates/skills/**/*.md` :

```bash
TEMPLATES_ROOT="D:/01 - projets/SmartStack.cli/02-Develop/templates/skills"
APP_FRONTEND="$APP_ROOT/web/smartstack-web/src"

# Collect imports of the form: import { Foo, Bar } from '@/{path}'
grep -rPnho "import\s+\{[^}]+\}\s+from\s+['\"]@/[^'\"]+['\"]" "$TEMPLATES_ROOT" \
  --include='*.md' --include='*.tsx' --include='*.ts' \
  | sort -u > /tmp/smoke-imports.txt
```

### 1.2 Resolve each import against the real file system

For each line in `/tmp/smoke-imports.txt`:
- Extract the path part : `@/components/ui/EntityLookup` → `components/ui/EntityLookup`
- Extract the symbol(s) : `EntityLookup`, `EntityCard`, etc.
- Test : does `$APP_FRONTEND/components/ui/EntityLookup.tsx` exist ?
- If file exists, optional deeper check : grep the symbol export in the file (`export.*EntityLookup`)

```bash
while IFS= read -r LINE; do
  # Parse the path
  PATH_PART=$(echo "$LINE" | sed -E "s/.*from\s+['\"]@\/([^'\"]+)['\"].*/\1/")
  # Resolve to .ts / .tsx / .ts (index.ts)
  FOUND=""
  for EXT in ".tsx" ".ts" "/index.tsx" "/index.ts"; do
    if [ -f "$APP_FRONTEND/${PATH_PART}${EXT}" ]; then
      FOUND="$APP_FRONTEND/${PATH_PART}${EXT}"
      break
    fi
  done
  if [ -z "$FOUND" ]; then
    echo "[BROKEN] @/${PATH_PART}  ← documented in CLI, NOT in app"
  fi
done < /tmp/smoke-imports.txt
```

### 1.3 Hook signatures (useTheme, useAuth, etc.)

Grep documented hook usages and verify the destructured field exists in the source :

```bash
# Documented usages like : const { user, login, logout } = useAuth();
grep -rPnh "const\s+\{([^}]+)\}\s*=\s*use\w+\(\)" "$TEMPLATES_ROOT" \
  --include='*.md' \
  | sort -u > /tmp/smoke-hook-usages.txt
```

For each `useX()` call, locate the matching context in `$APP_FRONTEND/contexts/{X}Context.tsx` (e.g. `useAuth` → `AuthContext.tsx`), extract the context value type, and verify each destructured field is exported. Symbols missing from the context value → `[BROKEN]`.

### 1.4 Component props (DataTable, EntityCard, etc.)

For each documented component prop usage in templates (e.g. `<DataTable data={...} columns={...} searchable />`), open the component source file and verify the prop is declared in its `Props` interface. Mismatches → `[BROKEN]`.

## Step 2 — Backend static checks (`--scope=backend|all`)

### 2.1 Extract documented C# types and signatures

Grep all `using SmartStack.{X}` and explicit type names referenced in code blocks of `templates/skills/**/*.md` :

```bash
APP_BACKEND_ROOT="$APP_ROOT/src"
grep -rPnh "^\s*using\s+SmartStack\.[A-Za-z.]+;" "$TEMPLATES_ROOT" --include='*.md' \
  | sort -u > /tmp/smoke-usings.txt
```

For each `using SmartStack.X.Y.Z;`, verify a corresponding directory or file exists under `$APP_BACKEND_ROOT/SmartStack.{Layer}/...`.

### 2.2 Domain entity references

Grep documented C# class names (like `NavigationApplication`, `AiTool`, `WorkflowVersion`) in templates, then verify each one exists in `$APP_BACKEND_ROOT/SmartStack.Domain/`.

```bash
# Pattern : public class Foo : BaseEntity
grep -rPnho "(?:public\s+)?(?:class|record|interface)\s+([A-Z][A-Za-z0-9]+)\s*:?\s*(?:BaseEntity|IRequest|I[A-Z][A-Za-z]+Entity)" "$TEMPLATES_ROOT" \
  --include='*.md' \
  | sort -u > /tmp/smoke-types.txt
```

For each extracted type, run a Glob in `$APP_BACKEND_ROOT/**/*.cs` for `class TypeName` or `record TypeName`. No match → `[BROKEN]`.

### 2.3 Method signatures

For commonly cited methods (`NavigationApplication.Create(...)`, `Permission.CreateForModule(...)`, etc.), grep the signature in the documented template and the actual signature in the source file. Compare parameter list (count + names). Diff → `[DRIFT]`.

Critical method signatures to cross-check :
- `NavigationApplication.Create` (currently `code, label, description?, icon?, iconType, route?, displayOrder, isOpen=false, isPersonal=false`)
- `Permission.CreateForModule`, `Permission.CreateForSection`, `Permission.CreateForResource`
- `BaseEntity.GetExtensionValue<T>` / `SetExtensionValue<T>` / `RemoveExtensionValue` / etc.

## Step 3 — Cross-cut checks (always run)

### 3.1 i18n namespace consistency
Already covered by `frontend-checks.sh` C28 — call it directly :
```bash
bash "$TEMPLATES_ROOT/apex/references/checks/frontend-checks.sh" 2>&1 | grep -E "C28|i18n"
```

### 3.2 Theme tokens documented vs exposed
Compare the CSS variables documented in `application/references/themes-db-driven.md` against `$APP_FRONTEND/index.css`. Variables in doc but not in CSS → `[BROKEN]`.

### 3.3 Layouts count
Verify exactly 4 layout files in `$APP_FRONTEND/layouts/` (`AppLayout`, `AuthLayout`, `DocsLayout`, `PublicLayout`).

## Step 4 — Build the report

```
================================================================================
              SMOKE GENERATION REPORT — {date}
================================================================================
APP : IA-Workflow @ {commit}
CLI : v{version} @ {branch}
SCOPE : {scope}   MODE : {quick|full}

[FRONTEND]
  imports scanned    : {N}
  imports broken     : {B}
  hooks scanned      : {N}
  hooks broken       : {B}
  component props    : {N}    drift : {D}

[BACKEND]
  usings scanned     : {N}    broken : {B}
  types scanned      : {N}    missing : {M}
  signatures scanned : {N}    drift : {D}

[CROSS-CUT]
  i18n consistency   : {OK|FAIL}
  theme tokens       : {OK|FAIL — {n} missing}
  layouts count      : {OK|FAIL — found {n}, expected 4}

--------------------------------------------------------------------------------
DETAILED ISSUES
--------------------------------------------------------------------------------

[BROKEN] @/components/ui/EntityLookup
  → Referenced in :
    - templates/skills/ui-components/SKILL.md:64
    - templates/skills/apex/references/smartstack-frontend.md:6 (multiple)
    - templates/skills/apex/references/checks/frontend-checks.sh:147 (C7 enforcement)
  → Action : either scaffold the component in app, OR remove from CLI doc.

[DRIFT] NavigationApplication.Create signature
  → CLI docs : Create(code, label, ..., isOpen=false, isPersonal=false)
  → App impl : Create(code, label, ..., isOpen=false, isPersonal=false, isHidden=false)
  → Action : update templates to include `isHidden` parameter.

...

--------------------------------------------------------------------------------
SUMMARY : {totalIssues} issues  ({broken} BROKEN, {drift} DRIFT, {missing} MISSING)
================================================================================
```

## Step 5 — Persist cache (unless `--report-only`)

```bash
cat > "$CACHE_FILE" << EOF
{
  "lastRun": "$(date -Iseconds)",
  "appCommit": "$(git -C "$APP_ROOT" rev-parse --short HEAD)",
  "appBranch": "$(git -C "$APP_ROOT" rev-parse --abbrev-ref HEAD)",
  "scope": "{scope}",
  "mode": "{quick|full}",
  "totalIssues": {N},
  "broken": {B},
  "drift": {D},
  "missing": {M}
}
EOF
```

## Step 6 — Exit code

- 0 issues → exit 0
- ≥ 1 issues → exit 1 (so the skill can be called as a CI quality gate, e.g. inside a pre-commit hook).

</workflow>

<full_mode>

## `--full` mode (sandbox + real build)

This mode is documented for completeness but is OPTIONAL — `--quick` covers ~80 % of drifts at a tiny fraction of the cost.

### Steps (full mode only)

1. Create a sandbox under `~/.smartstack-smoke/run-{timestamp}/`
2. Run `ss init smoke-test --provider=azure-devops --no-prompt` in the sandbox
3. Generate a representative module via MCP : 1 entity (`Product`), 1 FK (`CategoryId`), one CRUD page set (List, Detail, Create, Edit)
4. Run :
   - `cd src/SmartStack.Api && dotnet restore && dotnet build`
   - `cd web/smartstack-web && npm install && npm run build`
5. Capture stderr/stdout, parse for errors, fail if any compile error or missing import
6. Cleanup the sandbox unless `--keep-sandbox` flag is passed

### When to prefer `--full` over `--quick`

- Before publishing a new CLI version (release gate)
- After a non-trivial refactor of MCP scaffolding
- When `--quick` reports 0 issues but you suspect a runtime-only problem

### Cost
- Network : ~50-150 MB (npm install)
- Disk : ~500 MB (sandbox + node_modules)
- Time : 5-10 min (mostly npm install + dotnet restore)

</full_mode>

<integration>

### Pre-commit hook
Add to `.git/hooks/pre-commit` (or via husky) :

```bash
#!/bin/bash
# Block commits that introduce documentation drift
bash -c '/smoke-generation --quick --report-only' && exit 0 || {
  echo "[smoke-generation] BROKEN imports / DRIFT detected — fix before commit."
  exit 1
}
```

### Manual workflow
- After enriching any `templates/skills/**/*.md` with new imports/types : run `/smoke-generation --quick`
- Before opening a PR that touches multiple skills : run `/smoke-generation --quick` and paste the report into the PR description
- After bumping the SmartStack.app target branch : run `/smoke-generation --quick` to surface drifts triggered by the new version

</integration>

<known_limitations>

- **Quick mode misses runtime-only errors** : a bad TS generic, a wrong async return shape, a missing CSS class — `--full` mode is needed for these.
- **Heuristic regex** : may produce false positives on unusual import syntaxes (rare in practice). Verify each `[BROKEN]` manually if in doubt.
- **Single source of truth** : assumes the IA-Workflow branch IS the source of truth for v3.46+. Override via `--app-path` if testing against a different branch (e.g. for forward-compat testing on a feature branch).
- **Does not check MCP scaffolders** : the C# code emitted by MCP tools (`scaffold_extension`, `scaffold_routes`, …) is not validated by this skill. Use `--full` for that path.

</known_limitations>

<success_criteria>
- Quick mode runs in < 60 seconds on a clean install
- Detects the "EntityLookup class of drift" reliably (documented import not present in app)
- Detects method signature drift (parameters added/removed in app but doc not updated)
- Detects missing CSS theme variables (doc claims a token, app doesn't expose it)
- Reports are deterministic, scannable, and actionable
- Exit code reflects the number of issues — usable as a quality gate
</success_criteria>
