# OpenSpec Change: enterprise-gaming-behavior-tree - **Change ID**: enterprise-gaming-behavior-tree - **Package**: `@suaveplan/behavior-tree` - **Category**: gaming/ai - **Target path**: `gaming/ai/behavior-tree` - **Status**: PROPOSED - **Date**: 2026-04-24 - **Reference spec**: `/mnt/s/web/suaveplan/enterprise/behavior-tree.md` --- ## Summary Deliver `@suaveplan/behavior-tree` on the genesis branch from scratch at enterprise quality. The package provides a behavior tree engine with composite nodes (Sequence, Selector, Parallel), decorator nodes (Inverter, Repeater, Cooldown, Timeout), leaf nodes (Action, Condition, Wait), a typed Blackboard for shared agent state, and a fluent builder API. `BehaviorTreeRunner` advances the tree one tick at a time returning `SUCCESS | FAILURE | RUNNING`. Genesis adds Zod blackboard key schemas, structured errors, OTel tick-duration histogram, injectable clock, and property tests for tree traversal invariants. --- ## Current-state audit (genesis) Package does not exist on genesis yet — fresh build. --- ## Available workspace deps on genesis | Package | Role | |---|---| | `@suaveplan/error` (`workspace:^`) | `BehaviorTreeError`; `BT.*` codes | | `@suaveplan/types` (`workspace:^`) | `Clock` | | `zod` (`catalog:forms`) | Blackboard key schemas | | `@opentelemetry/api` (`catalog:observability`) | Tick duration histogram | --- ## Public API surface ```ts type NodeStatus = 'SUCCESS' | 'FAILURE' | 'RUNNING' interface TreeNode { readonly name: string tick(blackboard: Blackboard, dt: number): NodeStatus reset(): void } // Composites function sequence(name: string, children: TreeNode[]): TreeNode function selector(name: string, children: TreeNode[]): TreeNode function parallel(name: string, children: TreeNode[], successPolicy?: 'all' | 'any', failurePolicy?: 'all' | 'any'): TreeNode // Decorators function inverter(name: string, child: TreeNode): TreeNode function repeater(name: string, child: TreeNode, times?: number): TreeNode // undefined = forever function cooldown(name: string, child: TreeNode, cooldownSeconds: number, clock?: Clock): TreeNode function timeout(name: string, child: TreeNode, timeoutSeconds: number, clock?: Clock): TreeNode // Leaves function action(name: string, fn: (bb: Blackboard, dt: number) => NodeStatus): TreeNode function condition(name: string, fn: (bb: Blackboard) => boolean): TreeNode function wait(name: string, durationSeconds: number, clock?: Clock): TreeNode // Blackboard function createBlackboard>(initial?: Partial): Blackboard interface Blackboard = Record> { get(key: K): T[K] | undefined set(key: K, value: T[K]): void has(key: keyof T): boolean delete(key: keyof T): void clear(): void clone(): Blackboard } // Runner function createBehaviorTreeRunner(root: TreeNode, blackboard: Blackboard, clock?: Clock): BehaviorTreeRunner interface BehaviorTreeRunner { tick(dt: number): NodeStatus reset(): void readonly lastStatus: NodeStatus | null readonly tickCount: number } // Fluent builder function bt(name: string): BehaviorTreeBuilder ``` ### Error codes ```ts type BtErrorCode = | 'BT_EMPTY_COMPOSITE' | 'BT_BLACKBOARD_KEY_NOT_FOUND' | 'BT_NODE_TICK_FAILED' | 'BT_INVALID_POLICY' ``` --- ## New additions for genesis 1. **Parallel policies** — configurable success/failure policies for parallel composite. 2. **Cooldown decorator** — injectable clock; skips subtree when cooldown active, returns `FAILURE`. 3. **Timeout decorator** — returns `FAILURE` if child runs longer than timeout. 4. **Blackboard clone** — `clone()` for subtree isolation in parallel branches. 5. **OTel** — `bt.tick_duration_ms` histogram; `bt.node_status_total` counter by status. --- ## File layout ```text gaming/ai/behavior-tree/ package.json tsconfig.json vitest.config.ts src/ index.ts error-codes.ts constants/index.ts types/common.ts types/common.md core/ blackboard/ blackboard.ts blackboard.md blackboard.types.ts blackboard.test.ts index.ts nodes/ composites.ts composites.md composites.test.ts decorators.ts decorators.md decorators.test.ts leaves.ts leaves.md leaves.test.ts runner/ runner.ts runner.md runner.types.ts runner.test.ts index.ts builder/ builder.ts builder.md builder.test.ts index.ts tests/ property.test.ts ``` --- ## Impact **Downstream**: `@suaveplan/npc` builds per-NPC behavior trees; `@suaveplan/r3f-npc` renders debug tree overlays. Prerequisites: `@suaveplan/error`, `@suaveplan/types`.