Skip to content

Task Resolution

After project detection builds a ProjectProfile, xtarterize resolves which tasks are relevant and what their current status is.

ProjectProfile → resolveTasks() → applicable tasks → resolveTaskStatuses() → status map

Filters the full task registry to only those where task.applicable(profile) returns true. This is a pure synchronous filter — no I/O, no side effects.

import { resolveTasks } from '@xtarterize/core'
const applicable = resolveTasks(profile, getAllTasks())
// → only tasks whose conditions are met

Runs task.check() for each applicable task in parallel and returns a Map<taskId, TaskStatus>. Each task determines its own status by inspecting the filesystem.

import { resolveTaskStatuses } from '@xtarterize/core'
const statuses = await resolveTaskStatuses(applicable, cwd, profile)
// → Map<string, 'new' | 'patch' | 'skip' | 'conflict'>

The four statuses drive which tasks appear as actionable:

StatusMeaningActionable for initActionable for sync
newConfig doesn’t exist yetYesNo
patchConfig exists, can be updatedYesYes
skipAlready conformantNoNo
conflictIncompatible changes neededOnly if explicitly selectedOnly if explicitly selected

Each task’s applicable() method checks ProjectProfile properties:

// TypeScript tasks: only if project uses TS
applicable: (profile) => profile.typescript
// Vite plugin tasks: only if bundler is Vite
applicable: (profile) => profile.bundler === 'vite'
// CI tasks: only if GitHub detected
applicable: (profile) => profile.hasGitHub
// Turbo task: only if monorepo uses Turborepo
applicable: (profile) => profile.monorepoTool === 'turbo'

Task statuses are evaluated in parallel via Promise.all, making resolution efficient even with many tasks.