# 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; 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.