# Behavioral Guidelines Store — Spec

## Guideline Entity

```typescript
interface GuidelineContent {
  condition: string;     // When...
  action: string | null; // Then...
  description: string | null;
}

interface Guideline {
  id: string;
  creationUtc: string;
  content: GuidelineContent;
  enabled: boolean;
  tags: string[];
  labels: string[];
  metadata: Record<string, unknown>;
  criticality: "low" | "medium" | "high";
  title: string | null;
  priority: number;
}
```

## GuidelineDocumentStore

File-based JSON store at `.boo/guidelines/`. Versioned with migration support.

Methods:
- `createGuideline(condition, action?, description?, ...) → Guideline`
- `listGuidelines(tags?, labels?) → Guideline[]`
- `readGuideline(id) → Guideline`
- `updateGuideline(id, params) → Guideline`
- `deleteGuideline(id) → void`
- `findGuideline(content: {condition, action?}) → Guideline`

Version migration chain (port from Parlant v0.1.0 → v0.11.0):
- v0.1.0 → v0.2.0: add enabled field
- v0.2.0 → v0.3.0: remove guideline_set (migration script only)
- v0.3.0 → v0.4.0: add optional action, description, metadata
- v0.4.0 → v0.5.0: description as optional
- v0.5.0 → v0.6.0: add criticality (default "medium")
- v0.6.0 → v0.7.0: add composition_mode (optional)
- v0.7.0 → v0.8.0: add track (default true)
- v0.8.0 → v0.9.0: add labels (default empty)
- v0.9.0 → v0.10.0: add priority (default 0)
- v0.10.0 → v0.11.0: add title (default null)

## Tag & Label Filtering

- `listGuidelines({tags: ["tag1"]})` → guidelines with ANY of the specified tags
- `listGuidelines({labels: ["label1"]})` → guidelines with ALL specified labels (subset match)
- Combined: both filters apply (intersection)

## Journey → Guideline Projection

Port of Parlant's `JourneyGuidelineProjection.project_journey_to_guidelines()`:

- DFS traversal of Journey nodes from root
- Each (edge, node) pair → one Guideline
- Edge condition becomes guideline condition
- Node action becomes guideline action
- Edge/node metadata merged into guideline metadata with journey_node key
- follow_ups list populated with downstream guideline IDs
- BFS queue avoids infinite loops via visited set

## Journey Backtrack Detection

```typescript
interface BacktrackCheck {
  journeyId: string;
  currentNodeId: string;
  previousNodeId: string;
  isBacktrack: boolean;
  recommendation: string | null;
}
```

Scans the edge list for source→target relationships. If the agent's current step has an edge back to a previously visited node (and that node is not in a forward path from current), it's flagged as a backtrack regression.
