# TutorialDetectorService

**Kind:** Service

**Source:** [`atloria-monorepo/apps/api/src/documentation/services/tutorial-detector.service.ts`](https://github.com/sherkety/atloria/blob/main/atloria-monorepo/apps/api/src/documentation/services/tutorial-detector.service.ts#L108)

Tutorial Detector Service

Detects single-step tutorials from state transitions.
Each state transition becomes a quick-start tutorial (2-5 minutes).

Strategy:
1. Find all state machines
2. For each transition, create a tutorial
3. Link tutorials via prerequisites/next steps
4. Group into learning paths by category

Example:
- State machine: JobStageEnum
- Transition: Offer → Order (convertToOrder)
- Tutorial: "How to Convert an Offer to an Order"
- Difficulty: Beginner
- Time: 2-3 minutes
- Prerequisites: "How to Create a Job Offer"
- Next steps: "How to Deliver an Order"

`TutorialDetectorService` scans application state machines and derives micro-tutorials from their state transitions. Each transition becomes a single-step quick-start tutorial (typically 2–5 minutes), enriched with difficulty, estimated time, and navigation links (prerequisites/next steps). It helps automatically generate structured learning paths by grouping tutorials by domain/category.

## Methods

| Method | Signature | Returns | Description |
|---|---|---|---|
| `detectTutorials` | `detectTutorials(entities: any[], appMap: any, features: any[])` | `Promise<{
    tutorials: DetectedTutorial[];
    learningPaths: LearningPath[];
  }>` | Detect tutorials from parsed entities |

## Where it refuses work

- `TutorialDetectorService` stops the work with an early return when `lowerMethod.includes('convert')`.
- `TutorialDetectorService` stops the work with an early return when `lowerMethod.includes('approve')`.
- `TutorialDetectorService` stops the work with an early return when `lowerMethod.includes('reject')`.
- `TutorialDetectorService` stops the work with an early return when `lowerMethod.includes('deliver')`.
- `TutorialDetectorService` stops the work with an early return when `lowerMethod.includes('cancel')`.
- `TutorialDetectorService` stops the work with an early return when `lowerMethod.includes('submit')`.

## When something fails

- `TutorialDetectorService` handles failure in 1 place: it turns it into a return value in all 1.

## Diagram

```mermaid
sequenceDiagram
  autonumber
  participant Caller as API/CLI/Job
  participant TDS as TutorialDetectorService
  participant SM as StateMachineRegistry
  participant GEN as TutorialGenerator
  participant LINK as TutorialLinker
  participant PATH as LearningPathGrouper
  participant OUT as Docs/DB Output

  Caller->>TDS: detectTutorials()
  TDS->>SM: listStateMachines()
  SM-->>TDS: stateMachines[]
  loop for each stateMachine
    TDS->>SM: getTransitions(stateMachine)
    SM-->>TDS: transitions[]
    loop for each transition
      TDS->>GEN: createTutorialFromTransition(transition)
      GEN-->>TDS: tutorial
    end
  end
  TDS->>LINK: linkPrerequisitesAndNextSteps(tutorials)
  LINK-->>TDS: linkedTutorials
  TDS->>PATH: groupByCategory(linkedTutorials)
  PATH-->>TDS: learningPaths
  TDS->>OUT: persistOrRender(learningPaths)
  OUT-->>Caller: result
```

## Usage

```ts
import { Injectable } from '@nestjs/common';
import { TutorialDetectorService } from './documentation/services/tutorial-detector.service';

@Injectable()
export class DocsGenerationJob {
  constructor(private readonly tutorialDetector: TutorialDetectorService) {}

  async run() {
    // Detect tutorials derived from all known state machine transitions.
    const result = await this.tutorialDetector.detectTutorials();

    // Example: iterate and print a few generated tutorial titles.
    for (const path of result.learningPaths ?? []) {
      console.log(`Learning Path: ${path.title}`);
      for (const tutorial of path.tutorials.slice(0, 3)) {
        console.log(` - ${tutorial.title} (${tutorial.difficulty}, ${tutorial.estimatedTime})`);
        console.log(`   prereq: ${tutorial.prerequisites?.join(', ') ?? 'none'}`);
        console.log(`   next:   ${tutorial.nextSteps?.join(', ') ?? 'none'}`);
      }
    }

    return result;
  }
}
```

## AI Coding Instructions

- Treat each state transition as the single source of truth for tutorial generation; avoid hand-curated tutorial definitions that drift from the state machine.
- Keep tutorial titles/action verbs deterministic (e.g., derived from transition name like `convertToOrder`) so linking and deduplication remain stable across runs.
- When adding or renaming states/transitions, ensure the detector can still resolve prerequisites/next steps (ordering or adjacency rules are a common failure point).
- Integrate category/grouping from domain metadata (state machine ownership/module) rather than parsing strings from enum names whenever possible.
- Prefer idempotent outputs (stable IDs/keys for tutorials and learning paths) so re-running generation doesn’t create duplicates in persisted docs/DB.

## Referenced By

- `DocumentationModule` (MODULE_PROVIDES)
- `DocumentationModule` (MODULE_EXPORTS)
