Class: Ace::Task::Molecules::SubtaskCreator

Inherits:
Object
  • Object
show all
Defined in:
lib/ace/task/molecules/subtask_creator.rb

Overview

Creates subtasks within a parent task’s folder. Allocates subtask characters sequentially: 0-9 then a-z (max 36 subtasks).

Constant Summary collapse

MAX_SUBTASKS =

Maximum number of subtasks per parent (0-9 = 10, a-z = 26)

36
SUBTASK_CHARS =

Ordered sequence of subtask characters

(0..35).map { |i| i.to_s(36) }.freeze

Instance Method Summary collapse

Constructor Details

#initialize(config: {}) ⇒ SubtaskCreator

Returns a new instance of SubtaskCreator.

Parameters:

  • config (Hash) (defaults to: {})

    Configuration hash



21
22
23
# File 'lib/ace/task/molecules/subtask_creator.rb', line 21

def initialize(config: {})
  @config = config
end

Instance Method Details

#create(parent_task, title, status: nil, priority: nil, tags: [], time: Time.now.utc, estimate: nil, github_issue: nil) ⇒ Models::Task

Create a subtask within a parent task’s folder.

Parameters:

  • parent_task (Models::Task)

    Parent task

  • title (String)

    Subtask title

  • status (String, nil) (defaults to: nil)

    Initial status

  • priority (String, nil) (defaults to: nil)

    Priority level

  • tags (Array<String>) (defaults to: [])

    Tags

  • time (Time) (defaults to: Time.now.utc)

    Creation time (default: now)

Returns:

Raises:

  • (RangeError)

    If parent already has 36 subtasks



35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
# File 'lib/ace/task/molecules/subtask_creator.rb', line 35

def create(
  parent_task,
  title,
  status: nil,
  priority: nil,
  tags: [],
  time: Time.now.utc,
  estimate: nil,
  github_issue: nil
)
  raise ArgumentError, "Title is required" if title.nil? || title.strip.empty?

  # Find next available subtask character
  existing_chars = scan_existing_subtask_chars(parent_task.path, parent_task.id)
  next_char = allocate_next_char(existing_chars)

  # Build subtask ID: parent_id + ".{char}"
  subtask_id = "#{parent_task.id}.#{next_char}"

  # Generate slugs (folder: 5 words, file: 7 words)
  folder_slug = generate_folder_slug(title)
  file_slug = generate_file_slug(title)

  # Build folder and file names
  folder_name = "#{next_char}-#{folder_slug}"
  subtask_dir = File.join(parent_task.path, folder_name)
  FileUtils.mkdir_p(subtask_dir)

  # Build frontmatter
  effective_status = status || @config.dig("task", "default_status") || "pending"
  frontmatter = Atoms::TaskFrontmatterDefaults.build(
    id: subtask_id,
    status: effective_status,
    priority: priority,
    tags: tags,
    created_at: time,
    parent: parent_task.id,
    estimate: estimate,
    github_issue: github_issue
  )

  # Write spec file
  spec_filename = "#{subtask_id}-#{file_slug}.s.md"
  spec_file = File.join(subtask_dir, spec_filename)
  content = build_spec_content(frontmatter: frontmatter, title: title)
  File.write(spec_file, content)

  # Load and return
  loader = TaskLoader.new
  loader.load(subtask_dir, id: subtask_id, load_subtasks: false)
end