The Dependency type provides relationship management between elements, supporting blocking relationships for task orchestration, associative links for knowledge graphs, and attribution tracking.
interface Dependency { readonly blockedId: ElementId; // Element that is waiting/blocked readonly blockerId: ElementId; // Element doing the blocking readonly type: DependencyType; // Category of relationship readonly createdAt: Timestamp; // When dependency was created readonly createdBy: EntityId; // Who created the dependency metadata: Record<string, unknown>; // Type-specific data}
The composite key is (blockedId, blockerId, type), allowing multiple dependency types between the same elements.
Blocking direction: In blocks dependencies, blockedId is the task that is BLOCKED BY blockerId. The blocker must complete first.
Affect work readiness - tasks cannot proceed until blockers resolve:
const BlockingDependencyType = { BLOCKS: 'blocks', // Blocked element waits for blocker to close PARENT_CHILD: 'parent-child', // Hierarchical containment with transitive blocking AWAITS: 'awaits', // External gate dependency} as const;
blocks
parent-child
awaits
Task A is blocked by Task B:
// Task A waits for Task B to close{ blockedId: taskA.id, blockerId: taskB.id, type: 'blocks' }
Direction reminder: sf dependency add --type=blocks A B means A is blocked BY B
Hierarchical containment with transitive blocking:
// Check if value is valid DependencyisDependency(value: unknown): value is Dependency// Check dependency type categoryisBlockingDependencyType(value: unknown): value is BlockingDependencyTypeisAssociativeDependencyType(value: unknown): value is AssociativeDependencyTypeisAttributionDependencyType(value: unknown): value is AttributionDependencyTypeisThreadingDependencyType(value: unknown): value is ThreadingDependencyType// Check specific dependencyisBlockingDependency(dependency: Dependency): booleanisAssociativeDependency(dependency: Dependency): booleanisMentionsDependency(dependency: Dependency): boolean
// Get awaits metadata from dependencygetAwaitsMetadata(dependency: Dependency): AwaitsMetadata | null// Get validates metadata from dependencygetValidatesMetadata(dependency: Dependency): ValidatesMetadata | null
// Normalize relates-to IDs (smaller ID always as blockedId)normalizeRelatesToDependency( blockedId: ElementId, blockerId: ElementId): { blockedId: ElementId; blockerId: ElementId }// Check if two elements are related (in either direction)areRelated( dependencies: Dependency[], elementA: ElementId, elementB: ElementId): boolean
Only blocking dependencies participate in cycle detection:
// Check if type participates in cycle detectionparticipatesInCycleDetection(type: DependencyType): boolean// Note: relates-to is excluded (bidirectional by design)
The createDependency() function does NOT check for cycles. Use DependencyService.detectCycle() from @stoneforge/quarry for cycle detection.