Skip to content

refactor(orchestrator): split TaskManager into Task (L2) and SubTask (L3) managers by domain layer #26

Description

@mushrafmim

Current Limitation

taskflow/orchestrator/TaskManager is a single struct that flattens two domain layers from the package doc into one type:

  • Layer 2 (Task / micro-journey): StartTask, HandleTaskCompletion, plus the presentation/read methods GetTaskRenderInfo, GetAllTasks.
  • Layer 3 (SubTask / interaction steps): StartSubTask, CompleteTaskStep.

Because everything lives on one struct, every consumer must construct the full TaskManager with all ~7 dependencies (db, registry, pluginsRegistry, taskWorkflowManager, onTaskCompleted, renderer, extensionsRegistry), even when it only operates at one layer. Each method actually uses only a subset:

Method db registry pluginsRegistry taskWorkflowManager onTaskCompleted renderer extensionsRegistry
StartTask
HandleTaskCompletion
GetTaskRenderInfo
GetAllTasks
StartSubTask
CompleteTaskStep

This makes the API harder to integrate against and couples unrelated concerns (e.g. a parent-workflow consumer drags in the plugin/extension registries it never touches).

Suggested Improvement

Split TaskManager into two managers grouped by domain layer (sharing the store.TaskStore spine — no duplicated state, pure move-the-methods refactor with no behavior change):

TaskManager (Layer 2 — Task + presentation)

  • Methods: StartTask, HandleTaskCompletion, GetTaskRenderInfo, GetAllTasks
  • Deps: db, registry, taskWorkflowManager, onTaskCompleted, renderer

SubTaskManager (Layer 3 — SubTask / interaction steps)

  • Methods: StartSubTask, CompleteTaskStep
  • Deps: db, registry, pluginsRegistry, taskWorkflowManager, extensionsRegistry

Why this axis:

  • Mirrors the documented Workflow → Task → SubTask hierarchy, so the code structure is self-explanatory.
  • Keeps StartSubTask + CompleteTaskStep together — both mutate the active-subtask coordinates on the record (SubTaskNodeID, ActiveOutputNamespace, ActiveExtensions), a shared invariant that should not be split across structs.
  • Isolates pluginsRegistry and extensionsRegistry cleanly to Layer 3.
  • Shrinks per-consumer wiring from ~7 deps to ~5: a Layer 2 consumer drops pluginsRegistry/extensionsRegistry; a Layer 3 consumer drops onTaskCompleted/renderer.

Acceptance criteria

  • SubTaskManager introduced with StartSubTask + CompleteTaskStep and only its required deps
  • TaskManager retains StartTask, HandleTaskCompletion, GetTaskRenderInfo, GetAllTasks
  • Shared helpers (setNestedKey, payloadKeys, deepcopy/runExtensions usage) placed so both managers can use them without duplication
  • Composition root updated to construct both (shared deps passed to each)
  • No behavior change; existing orchestrator tests pass (split/retarget as needed)

Version

main @ cca024f

Additional Context

  • Naming: ExecuteTask in discussion == the existing CompleteTaskStep method (no rename planned in this issue).
  • Scope note: This is a structural refactor only. Two follow-ups are explicitly out of scope: (1) optionally exposing narrow interfaces (e.g. a StepCompleter) so call-sites depend on 1–2 methods rather than the concrete struct — a further wiring win; (2) if GetTaskRenderInfo later gains the plugin-driven render-metadata fetching its doc comment aspirationally describes, the read side would re-acquire a pluginsRegistry dependency.
  • Alternative axis considered: a read/write (CQRS-ish) split would give rendering a {db, renderer}-only home (minimal wiring for API consumers) but would separate the active-subtask invariant and not mirror the domain doc. The layer axis was chosen for conceptual clarity.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    Type/ImprovementEnhancement to existing functionality

    Type

    No type

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions