# Challenge Questions — APEX

> **Referenced by:** step-00-init.md
> Question templates for context detection, hierarchy validation, and need challenging.
> Consolidates all challenge questions and hierarchy validation in a single file.

---

## 4-Level Navigation Hierarchy (MANDATORY)

SmartStack uses a **4-level navigation hierarchy:**
- **Level 1: Application** — e.g., "HumanResources", "ProjectManagement"
- **Level 2: Module** — e.g., "Employees", "Timesheet"
- **Level 3: Section** — e.g., "List", "Dashboard", "Approval"
- **Level 4: Resource** — e.g., "Export", "Settings" (optional)

Every module MUST have at least one section. A module without sections produces an incomplete navigation tree, broken seed data, and missing frontend routes.

---

## 4a. Application Validation

If `{app_name}` was NOT clearly inferred from the task description:

```yaml
questions:
  - header: "Application"
    question: "Which application does this module belong to?"
    options:
      - label: "<best guess from task> (Recommended)"
        description: "Inferred from your task description"
      - label: "New application"
        description: "Create a new application"
      - label: "Existing application"
        description: "Add to an existing application (specify in Other)"
    multiSelect: false
```

If "New application": collect `{app_name}`, `{app_code}`, `{app_icon}`, `{app_labels}` (4 langs).
If "Existing application": scan `**/Seeding/Data/**/NavigationApplicationSeedData.cs` and present discovered apps.

---

## 4b. Module Validation

If `{module_code}` was NOT clearly inferred from the task description:

```yaml
questions:
  - header: "Module"
    question: "What is the module code? (kebab-case, e.g., 'order-management', 'employees')"
    options:
      - label: "<inferred module code> (Recommended)"
        description: "Inferred from your task description"
      - label: "<alternative suggestion>"
        description: "Alternative based on keywords"
    multiSelect: false
```

---

## 4c. Section Selection

> This question MUST be asked. `{sections}` MUST contain at least one entry before proceeding.

Infer section suggestions from:
1. Task description (extract nouns/concepts that suggest functional sub-areas)
2. PRD/feature.json if available (module.sections)
3. Common patterns: "list" (default for simple CRUD), "dashboard", "settings", "reports"

```yaml
questions:
  - header: "Sections"
    question: "What sections should the module '{module_code}' contain? (Select at least one — use 'Other' to add custom sections)"
    options:
      - label: "<inferred section 1>"
        description: "Primary functional area based on module purpose"
      - label: "<inferred section 2>"
        description: "Secondary functional area"
      - label: "<inferred section 3>"
        description: "Additional area inferred from context"
    multiSelect: true
```

**Reserved codes (NOT valid sections):**
- `detail` — auto-generated as `/:id` route when "list" section exists
- `create` — auto-generated as `/create` route when "list" section exists
- `edit` — auto-generated as `/:id/edit` route when "list" section exists

These are **view modes**, not sections. A "list" section automatically generates 4 pages: ListPage (index), DetailPage (/:id), CreatePage (/create), EditPage (/:id/edit).

**Validation:**
```
RESERVED_SECTION_CODES = ["detail", "create", "edit"]

IF any section.code IN RESERVED_SECTION_CODES:
  DISPLAY: "'{section.code}' is a view mode, not a section.
    The 'list' section automatically includes detail (/:id), create (/create),
    and edit (/:id/edit) pages. Remove '{section.code}' from your sections."
  → Remove the offending section(s) from the list
  → Re-ask the sections question if {sections}.length == 0
  → DO NOT proceed

IF {sections}.length == 0:
  DISPLAY: "Every module must have at least one section. Please select or define at least one."
  → Re-ask the sections question
  → DO NOT proceed to next step
```

**Store for each section:**
```yaml
sections:
  - code: "section-kebab"
    labels: { fr: "...", en: "...", it: "...", de: "..." }
    icon: "LucideIconName"
    displayOrder: 10
```

---

## 5a. Entity Scope & Relationships

```yaml
questions:
  - header: "Entities"
    question: "What are the main entities this module manages? (e.g., 'Order, OrderLine, OrderStatus')"
    options:
      - label: "<inferred primary entity>"
        description: "Main entity inferred from module name"
      - label: "<inferred primary + secondary>"
        description: "Primary entity plus related entities from context"
      - label: "Only the primary entity"
        description: "Simple module — single entity '{module_code}' with standard CRUD"
    multiSelect: false
  - header: "Complexity"
    question: "What best describes this module's behavior?"
    options:
      - label: "Simple CRUD (Recommended)"
        description: "Standard list/create/edit/delete — no special business logic"
      - label: "CRUD + Business rules"
        description: "CRUD with validations, computed fields, status transitions, or constraints"
      - label: "CRUD + Workflow/Notifications"
        description: "CRUD with automated actions (emails, approvals, webhooks)"
      - label: "Complex module"
        description: "Multiple interrelated entities with specific business logic"
    multiSelect: false
```

---

## 5b. Dependency Auto-Detection (NO user question)

> **Principle:** The agent detects dependencies — the user should NEVER be asked about this.

### Algorithm

```
1. INTRA-MODULE FK detection (from {entities} collected in 5a):
   For each entity pair (A, B) in {entities}:
     IF entity A name appears as "{B}Id" pattern in typical HR/business domain:
       → Record: { entity: A, fkProperty: "{B}Id", targetEntity: B, isInterModule: false }
     Example: entities = [Employee, Absence] → Absence likely has EmployeeId FK

2. INTER-MODULE FK detection (scan existing codebase):
   existing_entities = Glob("**/Domain/Entities/**/*.cs") → extract class names (exclude enums, VOs)

   IF existing_entities.length > 0:
     For each entity in {entities}:
       For each existing in existing_entities:
         IF task description or entity context suggests relationship to existing:
           → Record: { entity, fkProperty: "{existing}Id", targetEntity: existing, isInterModule: true }

   IF existing_entities.length == 0 (fresh project):
     → {has_dependencies} = "none" or "intra-only"
     → Skip inter-module detection entirely

3. STORE results:
   {has_dependencies} = "none" | "intra-only" | "inter-module"
   {detected_fks} = [{ entity, fkProperty, targetEntity, isInterModule }]

4. DISPLAY summary (no question, just confirmation):
   "Dependencies detected: Absence → Employee (intra-module FK)"
   Or: "No inter-module dependencies detected (fresh project)"
```

### False Positive Guards

- Only match against classes extending `BaseEntity` / `AuditableEntity` (not enums, value objects)
- If entity name is a substring of another (e.g., "Employee" in "EmployeeStatus"), verify the target is a navigable entity
- Limit inter-module scan to entities whose names appear in the task description or {entities} list

---

## 5b-bis. Key Properties

```yaml
questions:
  - header: "Key fields"
    question: "Beyond standard fields (Id, TenantId, Audit), what are the key business properties of the main entity?"
    options:
      - label: "<inferred properties from context>"
        description: "Properties inferred from module purpose"
      - label: "Standard fields only"
        description: "I'll define properties later during implementation"
      - label: "I have specific requirements"
        description: "Describe your fields in 'Other'"
    multiSelect: false

---

## 5c. Code Generation Strategy

> **Purpose:** When `/apex` is used directly (without `/business-analyse`), the user is never asked about entity code generation strategy. This section fills that gap with a rapid, consolidated question.

### Skip Conditions

```
IF delegate_mode (-d flag):
  → SKIP (business-analyse-develop / PRD already defines code patterns)

IF feature.json exists AND ALL entities have codePattern defined:
  → SKIP (BA already collected code patterns)
  → Extract {code_patterns} from feature.json for each entity

IF foundation_mode (--foundation):
  → SKIP (foundation generates entities but code strategy comes from PRD)
```

### Code Pattern Heuristic — `suggestCodePattern(entityName)`

Suggests a recommended strategy + prefix based on entity name:

```
FUNCTION suggestCodePattern(entityName):
  prefix = KNOWN_PREFIXES[entityName] ?? entityName[0:3].toLowerCase()
  strategy = KNOWN_STRATEGIES[entityName] ?? "sequential"
  digits = 5  # default (covers 99,999 records per tenant)
  RETURN { strategy, prefix, digits, includeTenantSlug: true, separator: "-" }

KNOWN_PREFIXES:
  Employee → "emp", Invoice → "inv", Contract → "ctr",
  Order → "ord", Ticket → "tkt", Project → "prj",
  Customer → "cus", Product → "prd", Expense → "exp",
  Leave → "lev", Department → "dep", Document → "doc"

KNOWN_STRATEGIES:
  Invoice, Order, Receipt, PurchaseOrder → "timestamp-daily"
  Ticket, Incident, SupportRequest → "timestamp-minute"
  Contract, Policy, Agreement → "year-sequential"
  Category, Status, Type (reference data) → "uuid-short"
  DEFAULT → "sequential"
```

### Question — Single Entity (1 entity)

When `{entities}.length == 1`:

```yaml
# Compute suggestion first
suggestion = suggestCodePattern({entities}[0])
example = "{suggestion.prefix}-{tenantSlug}-00001"  # or appropriate format per strategy

questions:
  - header: "Code"
    question: "How should the code for '{entities[0]}' be generated?"
    options:
      - label: "Auto-generate: {suggestion.strategy} with prefix '{suggestion.prefix}' (Recommended)"
        description: "Example: {example} — auto-generated, excluded from CreateDto"
      - label: "Auto-generate with custom settings"
        description: "Choose strategy, prefix, and separator yourself"
      - label: "Manual (user-provided)"
        description: "Code field included in CreateDto — user enters the code manually"
    multiSelect: false
```

**Follow-up if "custom settings":**
```yaml
questions:
  - header: "Strategy"
    question: "Which code generation strategy for '{entities[0]}'?"
    options:
      - label: "sequential"
        description: "Simple incrementing counter: {prefix}-{tenant}-00001, 00002, ..."
      - label: "timestamp-daily"
        description: "Date-based: {prefix}-{tenant}-20260222-001"
      - label: "year-sequential"
        description: "Year prefix: {prefix}-{tenant}-2026-00001"
      - label: "uuid-short"
        description: "Short unique ID: {prefix}-{tenant}-a1b2c3"
    multiSelect: false
  - header: "Prefix"
    question: "What prefix for the code? (2-6 lowercase letters)"
    options:
      - label: "{suggestion.prefix} (Recommended)"
        description: "Auto-suggested from entity name"
      - label: "Custom"
        description: "Enter your own prefix in 'Other'"
    multiSelect: false
```

### Question — Multiple Entities (2+ entities)

When `{entities}.length >= 2`:

```
Compute suggestions for ALL entities:
  recommendations = {entities}.map(e => { entity: e, ...suggestCodePattern(e) })

Display table:
  | Entity | Strategy | Prefix | Example |
  |--------|----------|--------|---------|
  | Employee | sequential | emp | emp-{tenant}-00001 |
  | Contract | year-sequential | ctr | ctr-{tenant}-2026-00001 |
```

```yaml
questions:
  - header: "Code"
    question: "How should entity codes be generated? (see recommendations above)"
    options:
      - label: "Accept all recommendations (Recommended)"
        description: "Use the suggested strategy and prefix for each entity"
      - label: "All manual (user-provided)"
        description: "No auto-generation — Code field in CreateDto for all entities"
      - label: "Customize per entity"
        description: "Choose strategy individually for each entity"
    multiSelect: false
```

**If "Customize per entity":**
→ Loop through each entity and ask the single-entity question (section above).

### Storage Format

```yaml
{code_patterns}:
  - entity: "Employee"
    strategy: "sequential"
    prefix: "emp"
    digits: 5
    includeTenantSlug: true
    separator: "-"
  - entity: "Contract"
    strategy: "year-sequential"
    prefix: "ctr"
    digits: 5
    includeTenantSlug: true
    separator: "-"
  # strategy: "manual" → no auto-generation for this entity
```

---

## Delegate Mode Skip (if -d flag)

When `/business-analyse-develop` invokes `/apex -d {prd_path}`, ALL hierarchy is extracted from the PRD file:
- Skip sections 4a-5b (no interactive questions)
- Jump directly to MCP verify section
```
