Tasks
Tasks represent units of work to be tracked and completed within Stoneforge. They support rich metadata, scheduling, assignment, and lifecycle management.
Task Interface
interface Task extends Element {
readonly type : 'task' ;
// Content
title : string ;
descriptionRef ?: DocumentId ;
acceptanceCriteria ?: string ;
// Workflow
status : TaskStatus ;
priority : Priority ; // 1-5, 1 is highest
complexity : Complexity ; // 1-5, 1 is simplest
taskType : TaskTypeValue ;
closeReason ?: string ;
// Assignment
assignee ?: EntityId ;
owner ?: EntityId ;
// Scheduling
deadline ?: Timestamp ;
scheduledFor ?: Timestamp ;
closedAt ?: Timestamp ;
// Soft Delete
deletedAt ?: Timestamp ;
deletedBy ?: EntityId ;
deleteReason ?: string ;
// External Integration
externalRef ?: string ;
}
Task title, 1-500 characters
Reference to description Document for detailed information
Definition of done criteria (max 10,000 characters)
Current lifecycle state (open, in_progress, blocked, etc.)
Priority scale 1-5, where 1 is highest (default: 3)
Complexity scale 1-5, where 1 is simplest (default: 3)
Classification: bug, feature, task, or chore (default: task)
Task Status
Task status represents the current lifecycle state:
const TaskStatus = {
OPEN: 'open' , // Available for work
IN_PROGRESS: 'in_progress' , // Currently being worked on
BLOCKED: 'blocked' , // Waiting on dependency
DEFERRED: 'deferred' , // Deliberately postponed
BACKLOG: 'backlog' , // Not ready, needs triage
REVIEW: 'review' , // Awaiting merge/review
CLOSED: 'closed' , // Completed and merged
TOMBSTONE: 'tombstone' , // Soft-deleted
} as const ;
Ready Statuses
Status Transitions
Open and In Progress are considered “ready for work”:const READY_STATUSES = [ 'open' , 'in_progress' ];
// Check if task is ready
isReadyForWork ( task : Task ): boolean
Valid transitions are enforced: // From OPEN, can transition to:
[ 'in_progress' , 'blocked' , 'deferred' , 'backlog' , 'closed' ]
// From IN_PROGRESS, can transition to:
[ 'open' , 'blocked' , 'deferred' , 'review' , 'closed' ]
// Validate transition
validateStatusTransition ( from : TaskStatus , to : TaskStatus ): void
BLOCKED status is computed - Never set status: 'blocked' directly. It’s derived from blocking dependencies.
Status Utilities
// Status checks
isReadyForWork ( task : Task ): boolean
isBlocked ( task : Task ): boolean
isClosed ( task : Task ): boolean
isDeleted ( task : Task ): boolean
isBacklog ( task : Task ): boolean
// Display names
getStatusDisplayName ( status : TaskStatus ): string
// Returns: "Open", "In Progress", "Blocked", etc.
Priority
Priority scale from 1-5, where 1 is highest:
const Priority = {
CRITICAL: 1 , // Production issues, security vulnerabilities
HIGH: 2 , // Important features, significant bugs
MEDIUM: 3 , // Standard work items (default)
LOW: 4 , // Nice-to-have improvements
MINIMAL: 5 , // Can be done when time permits
} as const ;
type Priority = 1 | 2 | 3 | 4 | 5 ;
Default priority for new tasks
Priority Validation
// Validate priority value
validatePriority ( value : unknown ): Priority
// Type guard
isValidPriority ( value : unknown ): value is Priority
// Display name
getPriorityDisplayName ( priority : Priority ): string
// Returns: "Critical", "High", "Medium", "Low", "Minimal"
Complexity
Complexity scale from 1-5, where 1 is simplest:
const Complexity = {
TRIVIAL: 1 , // Single-line changes, typo fixes
SIMPLE: 2 , // Small, well-defined changes
MEDIUM: 3 , // Moderate changes, some research needed
COMPLEX: 4 , // Significant changes, multiple components
VERY_COMPLEX: 5 , // Large scope, architectural changes
} as const ;
type Complexity = 1 | 2 | 3 | 4 | 5 ;
Default complexity for new tasks
Complexity Utilities
// Validate complexity value
validateComplexity ( value : unknown ): Complexity
// Type guard
isValidComplexity ( value : unknown ): value is Complexity
// Display name
getComplexityDisplayName ( complexity : Complexity ): string
// Returns: "Trivial", "Simple", "Medium", "Complex", "Very Complex"
Task Type
Task type classification:
const TaskTypeValue = {
BUG: 'bug' , // Defect requiring fix
FEATURE: 'feature' , // New functionality
TASK: 'task' , // General work item
CHORE: 'chore' , // Maintenance, cleanup, technical debt
} as const ;
type TaskTypeValue = 'bug' | 'feature' | 'task' | 'chore' ;
DEFAULT_TASK_TYPE
TaskTypeValue
default: "task"
Default task type for new tasks
Task Type Utilities
// Validate task type
validateTaskType ( value : unknown ): TaskTypeValue
// Type guard
isValidTaskType ( value : unknown ): value is TaskTypeValue
// Display name
getTaskTypeDisplayName ( taskType : TaskTypeValue ): string
// Returns: "Bug", "Feature", "Task", "Chore"
Creating Tasks
interface CreateTaskInput {
title : string ;
createdBy : EntityId ;
// Optional fields
id ?: ElementId ; // Pre-generated ID for hierarchical tasks
descriptionRef ?: DocumentId ;
acceptanceCriteria ?: string ;
status ?: TaskStatus ; // default: 'open'
priority ?: Priority ; // default: 3
complexity ?: Complexity ; // default: 3
taskType ?: TaskTypeValue ; // default: 'task'
assignee ?: EntityId ;
owner ?: EntityId ;
deadline ?: Timestamp ;
scheduledFor ?: Timestamp ;
externalRef ?: string ;
tags ?: string [];
metadata ?: Record < string , unknown >;
}
// Create a new task
await createTask ( input : CreateTaskInput , config ?: IdGeneratorConfig ): Promise < Task >
Show Example: Create Task
import { createTask , asEntityId } from '@stoneforge/core' ;
const task = await createTask ({
title: 'Implement task filtering' ,
createdBy: asEntityId ( 'el-abc123' ),
priority: 2 , // HIGH
complexity: 3 , // MEDIUM
taskType: 'feature' ,
acceptanceCriteria: 'Users can filter tasks by status, priority, and assignee' ,
tags: [ 'frontend' , 'ui' ],
metadata: { component: 'TaskList' },
});
Updating Tasks
Update Status
interface UpdateTaskStatusInput {
status : TaskStatus ;
closeReason ?: string ; // Required when closing
}
// Update task status with transition validation
updateTaskStatus ( task : Task , input : UpdateTaskStatusInput ): Task
import { updateTaskStatus } from '@stoneforge/core' ;
const updatedTask = updateTaskStatus ( task , {
status: 'closed' ,
closeReason: 'Implemented and merged to main' ,
});
Soft Delete
interface DeleteTaskInput {
deletedBy : EntityId ;
deleteReason ?: string ;
}
// Soft-delete a task (transitions to tombstone status)
softDeleteTask ( task : Task , input : DeleteTaskInput ): Task
Soft-deleted tasks (tombstone status) are terminal and cannot be reopened. Use deferred or backlog for postponed work.
Scheduling Utilities
// Check if task is scheduled for the future
isScheduledForFuture ( task : Task ): boolean
// Check if task is past its deadline
isPastDeadline ( task : Task ): boolean
Assignment Utilities
// Check if task has an assignee
isAssigned ( task : Task ): boolean
// Check if task has an owner
hasOwner ( task : Task ): boolean
Filtering and Sorting
Filter Functions
// Filter by status
filterByStatus < T extends Task >( tasks : T [], status : TaskStatus ) : T []
// Filter by priority
filterByPriority < T extends Task >( tasks : T [], priority : Priority ) : T []
// Filter by assignee
filterByAssignee < T extends Task >( tasks : T [], assignee : EntityId | undefined ) : T []
// Filter ready tasks
filterReadyTasks < T extends Task >( tasks : T []) : T []
Sort Functions
// Sort by priority (highest first)
sortByPriority < T extends Task >( tasks : T []) : T []
// Sort by deadline (earliest first, null deadlines last)
sortByDeadline < T extends Task >( tasks : T []) : T []
Show Example: Get High-Priority Ready Tasks
import { filterReadyTasks , filterByPriority , sortByDeadline } from '@stoneforge/core' ;
const readyTasks = filterReadyTasks ( allTasks );
const highPriority = filterByPriority ( readyTasks , 2 );
const sorted = sortByDeadline ( highPriority );
Validation Constants
MAX_ACCEPTANCE_CRITERIA_LENGTH
Maximum acceptance criteria length
Maximum close reason length
Maximum delete reason length
Type Guards
// Check if value is a valid Task
isTask ( value : unknown ): value is Task
// Comprehensive validation with detailed errors
validateTask ( value : unknown ): Task
Best Practices
Never Set Blocked Directly blocked status is computed from dependencies. Use the dependency system instead.
Use Status Transitions Always validate status transitions with validateStatusTransition()
Link to Documents Use descriptionRef to link detailed descriptions instead of storing large text
Track Reasons Always provide closeReason when closing and deleteReason when soft-deleting