taski 0.8.3 → 0.9.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (51) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +52 -0
  3. data/README.md +108 -50
  4. data/docs/GUIDE.md +79 -55
  5. data/examples/README.md +10 -29
  6. data/examples/clean_demo.rb +25 -65
  7. data/examples/large_tree_demo.rb +356 -0
  8. data/examples/message_demo.rb +0 -1
  9. data/examples/progress_demo.rb +13 -24
  10. data/examples/reexecution_demo.rb +8 -44
  11. data/lib/taski/execution/execution_facade.rb +150 -0
  12. data/lib/taski/execution/executor.rb +167 -359
  13. data/lib/taski/execution/fiber_protocol.rb +27 -0
  14. data/lib/taski/execution/registry.rb +15 -19
  15. data/lib/taski/execution/scheduler.rb +161 -140
  16. data/lib/taski/execution/task_observer.rb +41 -0
  17. data/lib/taski/execution/task_output_router.rb +41 -58
  18. data/lib/taski/execution/task_wrapper.rb +123 -219
  19. data/lib/taski/execution/worker_pool.rb +279 -64
  20. data/lib/taski/logging.rb +105 -0
  21. data/lib/taski/progress/layout/base.rb +600 -0
  22. data/lib/taski/progress/layout/filters.rb +126 -0
  23. data/lib/taski/progress/layout/log.rb +27 -0
  24. data/lib/taski/progress/layout/simple.rb +166 -0
  25. data/lib/taski/progress/layout/tags.rb +76 -0
  26. data/lib/taski/progress/layout/theme_drop.rb +84 -0
  27. data/lib/taski/progress/layout/tree.rb +300 -0
  28. data/lib/taski/progress/theme/base.rb +224 -0
  29. data/lib/taski/progress/theme/compact.rb +58 -0
  30. data/lib/taski/progress/theme/default.rb +25 -0
  31. data/lib/taski/progress/theme/detail.rb +48 -0
  32. data/lib/taski/progress/theme/plain.rb +40 -0
  33. data/lib/taski/static_analysis/analyzer.rb +5 -17
  34. data/lib/taski/static_analysis/dependency_graph.rb +19 -1
  35. data/lib/taski/static_analysis/start_dep_analyzer.rb +400 -0
  36. data/lib/taski/static_analysis/visitor.rb +1 -39
  37. data/lib/taski/task.rb +49 -58
  38. data/lib/taski/task_proxy.rb +59 -0
  39. data/lib/taski/test_helper/errors.rb +1 -1
  40. data/lib/taski/test_helper.rb +22 -36
  41. data/lib/taski/version.rb +1 -1
  42. data/lib/taski.rb +62 -61
  43. data/sig/taski.rbs +194 -203
  44. metadata +34 -8
  45. data/examples/section_demo.rb +0 -195
  46. data/lib/taski/execution/base_progress_display.rb +0 -393
  47. data/lib/taski/execution/execution_context.rb +0 -390
  48. data/lib/taski/execution/plain_progress_display.rb +0 -76
  49. data/lib/taski/execution/simple_progress_display.rb +0 -247
  50. data/lib/taski/execution/tree_progress_display.rb +0 -643
  51. data/lib/taski/section.rb +0 -74
data/sig/taski.rbs CHANGED
@@ -1,23 +1,19 @@
1
1
  module Taski
2
2
  VERSION: String
3
3
 
4
- self.@global_registry: Execution::Registry?
5
- self.@progress_display: Execution::TreeProgressDisplay?
4
+ NOT_CONFIGURED: Object
5
+ self.@progress_display: Progress::Layout::Base | Object | nil
6
6
  self.@args: Args?
7
7
  self.@args_monitor: Monitor
8
8
 
9
9
  # Type alias for Task class (singleton type with class methods)
10
10
  # This represents a Class that inherits from Taski::Task
11
11
  type task_class = singleton(Task)
12
-
13
- # Module-level methods
14
- def self.global_registry: () -> Execution::Registry
15
- def self.reset_global_registry!: () -> void
16
- def self.progress_display: () -> Execution::TreeProgressDisplay?
17
- def self.progress_disabled?: () -> bool
12
+ def self.progress_display: () -> (Progress::Layout::Base | untyped)?
13
+ def self.progress_display=: (untyped display) -> void
18
14
  def self.reset_progress_display!: () -> void
19
15
  def self.args: () -> Args?
20
- def self.start_args: (options: Hash[Symbol, untyped], root_task: Class) -> void
16
+ def self.start_args: (options: Hash[Symbol, untyped]) -> void
21
17
  def self.reset_args!: () -> void
22
18
  def self.args_worker_count: () -> Integer?
23
19
 
@@ -37,11 +33,13 @@ module Taski
37
33
  class TaskFailure
38
34
  @task_class: Class
39
35
  @error: Exception
36
+ @output_lines: Array[String]
40
37
 
41
38
  attr_reader task_class: Class
42
39
  attr_reader error: Exception
40
+ attr_reader output_lines: Array[String]
43
41
 
44
- def initialize: (task_class: Class, error: Exception) -> void
42
+ def initialize: (task_class: Class, error: Exception, ?output_lines: Array[String]) -> void
45
43
  end
46
44
 
47
45
  # Mixin for exception classes to enable transparent rescue matching with AggregateError
@@ -80,15 +78,8 @@ module Taski
80
78
  # Args class for execution arguments management
81
79
  class Args
82
80
  @options: Hash[Symbol | String, untyped]
83
- @root_task: Class
84
- @started_at: Time
85
- @working_directory: String
86
-
87
- attr_reader started_at: Time
88
- attr_reader working_directory: String
89
- attr_reader root_task: Class
90
81
 
91
- def initialize: (options: Hash[Symbol | String, untyped], root_task: Class) -> void
82
+ def initialize: (options: Hash[Symbol | String, untyped]) -> void
92
83
  def []: (Symbol | String key) -> untyped
93
84
  def fetch: (Symbol | String key, ?untyped default) ?{ () -> untyped } -> untyped
94
85
  def key?: (Symbol | String key) -> bool
@@ -109,7 +100,7 @@ module Taski
109
100
  def self.clear_dependency_cache: () -> void
110
101
  def self.run: (?args: Hash[Symbol, untyped], ?workers: Integer?) -> untyped
111
102
  def self.clean: (?args: Hash[Symbol, untyped], ?workers: Integer?) -> void
112
- def self.run_and_clean: (?args: Hash[Symbol, untyped], ?workers: Integer?) -> untyped
103
+ def self.run_and_clean: (?args: Hash[Symbol, untyped], ?workers: Integer?, ?clean_on_failure: bool) ?{ () -> void } -> untyped
113
104
  def self.registry: () -> Execution::Registry
114
105
  def self.reset!: () -> void
115
106
  def self.tree: () -> String
@@ -117,6 +108,7 @@ module Taski
117
108
  # Instance methods
118
109
  def run: () -> void
119
110
  def clean: () -> void
111
+ def group: (String name) { () -> untyped } -> untyped
120
112
  def system: (*untyped args, **untyped opts) -> bool?
121
113
  def reset!: () -> void
122
114
 
@@ -130,36 +122,18 @@ module Taski
130
122
  def self.validate_workers!: (untyped workers) -> void
131
123
  end
132
124
 
133
- # Section class for abstraction layers (inherits from Task)
134
- class Section < Task
135
- def self.interfaces: (*Symbol interface_methods) -> void
136
-
137
- def run: () -> void
138
- def impl: () -> task_class
139
-
140
- private
141
-
142
- def apply_interface_to_implementation: (task_class implementation_class) -> void
143
- end
144
-
145
125
  # Execution module
146
126
  module Execution
147
- # TaskTiming struct (Data.define)
148
- class TaskTiming
149
- attr_reader start_time: Time
150
- attr_reader end_time: Time?
151
-
152
- # Data.define provides both positional and keyword argument constructors
153
- def initialize: (Time start_time, Time? end_time) -> void
154
- | (start_time: Time, end_time: Time?) -> void
155
-
156
- def self.new: (Time start_time, Time? end_time) -> TaskTiming
157
- | (start_time: Time, end_time: Time?) -> TaskTiming
158
-
159
- def self.start_now: () -> TaskTiming
160
- def duration_ms: () -> (Integer | Float)?
161
- def with_end_now: () -> TaskTiming
162
- def with: (?start_time: Time, ?end_time: Time?) -> TaskTiming
127
+ # Base class for observers of the execution lifecycle
128
+ class TaskObserver
129
+ attr_accessor context: ExecutionFacade?
130
+
131
+ def on_ready: () -> void
132
+ def on_start: () -> void
133
+ def on_stop: () -> void
134
+ def on_task_updated: (Class task_class, previous_state: Symbol?, current_state: Symbol, phase: Symbol, timestamp: Time) -> void
135
+ def on_group_started: (Class task_class, String group_name, phase: Symbol, timestamp: Time) -> void
136
+ def on_group_completed: (Class task_class, String group_name, phase: Symbol, timestamp: Time) -> void
163
137
  end
164
138
 
165
139
  # Registry class for task instance management
@@ -171,57 +145,55 @@ module Taski
171
145
 
172
146
  def initialize: () -> void
173
147
  def get_or_create: (Class task_class) { () -> TaskWrapper } -> TaskWrapper
174
- def get_task: (Class task_class) -> TaskWrapper?
148
+ def create_wrapper: (Class task_class, execution_facade: ExecutionFacade) -> TaskWrapper
175
149
  def register: (Class task_class, TaskWrapper wrapper) -> void
176
150
  def register_thread: (Thread thread) -> void
177
151
  def wait_all: () -> void
178
152
  def reset!: () -> void
179
153
  def request_abort!: () -> void
180
154
  def abort_requested?: () -> bool
181
- def run: (Class task_class, Array[Symbol] exported_methods) -> untyped
155
+ def registered?: (Class task_class) -> bool
182
156
  def failed_wrappers: () -> Array[TaskWrapper]
183
157
  def failed_clean_wrappers: () -> Array[TaskWrapper]
184
158
  end
185
159
 
186
- # ExecutionContext manages execution state and notifies observers about execution events
187
- class ExecutionContext
160
+ # ExecutionFacade is the central hub for execution events with both Push and Pull APIs
161
+ class ExecutionFacade
188
162
  THREAD_LOCAL_KEY: Symbol
189
163
 
164
+ attr_reader root_task_class: Class?
165
+ attr_reader dependency_graph: StaticAnalysis::DependencyGraph?
166
+
167
+ @root_task_class: Class?
168
+ @dependency_graph: StaticAnalysis::DependencyGraph?
190
169
  @monitor: Monitor
191
170
  @observers: Array[untyped]
192
- @execution_trigger: (^(Class, Registry) -> void)?
193
- @clean_trigger: (^(Class, Registry) -> void)?
194
171
  @output_capture: TaskOutputRouter?
195
172
  @original_stdout: IO?
196
- @runtime_dependencies: Hash[Class, Set[Class]]
173
+ @original_stderr: IO?
197
174
 
198
- def self.current: () -> ExecutionContext?
199
- def self.current=: (ExecutionContext? context) -> void
175
+ def self.build_default: (root_task_class: Class) -> ExecutionFacade
176
+ def self.current: () -> ExecutionFacade?
177
+ def self.current=: (ExecutionFacade? context) -> void
200
178
 
201
- def initialize: () -> void
179
+ def initialize: (root_task_class: Class) -> void
202
180
  def output_capture_active?: () -> bool
181
+ def original_stdout: () -> IO?
182
+ def original_stderr: () -> IO?
203
183
  def setup_output_capture: (IO output_io) -> void
204
184
  def teardown_output_capture: () -> void
205
185
  def output_capture: () -> TaskOutputRouter?
206
- def execution_trigger=: ((^(Class, Registry) -> void)? trigger) -> void
207
- def clean_trigger=: ((^(Class, Registry) -> void)? trigger) -> void
208
186
  def trigger_execution: (Class task_class, registry: Registry) -> void
209
- def trigger_clean: (Class task_class, registry: Registry) -> untyped
210
- def register_runtime_dependency: (Class from_class, Class to_class) -> void
211
- def runtime_dependencies: () -> Hash[Class, Set[Class]]
187
+ def trigger_clean: (Class task_class, registry: Registry) -> void
212
188
  def add_observer: (untyped observer) -> void
213
189
  def remove_observer: (untyped observer) -> void
214
190
  def observers: () -> Array[untyped]
215
- def notify_task_registered: (Class task_class) -> void
216
- def notify_task_started: (Class task_class) -> void
217
- def notify_task_completed: (Class task_class, ?duration: Float?, ?error: Exception?) -> void
218
- def notify_section_impl_selected: (Class section_class, Class impl_class) -> void
219
- def notify_set_root_task: (Class task_class) -> void
220
- def notify_set_output_capture: (TaskOutputRouter output_capture) -> void
191
+ def notify_ready: () -> void
221
192
  def notify_start: () -> void
222
193
  def notify_stop: () -> void
223
- def notify_clean_started: (Class task_class) -> void
224
- def notify_clean_completed: (Class task_class, ?duration: Float?, ?error: Exception?) -> void
194
+ def notify_task_updated: (Class task_class, previous_state: Symbol?, current_state: Symbol, phase: Symbol, timestamp: Time) -> void
195
+ def notify_group_started: (Class task_class, String group_name, phase: Symbol, timestamp: Time) -> void
196
+ def notify_group_completed: (Class task_class, String group_name, phase: Symbol, timestamp: Time) -> void
225
197
 
226
198
  private
227
199
 
@@ -230,41 +202,49 @@ module Taski
230
202
 
231
203
  # TaskOutputRouter for routing task output
232
204
  class TaskOutputRouter
233
- def initialize: (IO original_io) -> void
205
+ def initialize: (IO original_io, ?ExecutionFacade? execution_facade) -> void
234
206
  def current_write_io: () -> IO?
235
207
  def start_capture: (Class task_class) -> void
236
208
  def stop_capture: () -> void
209
+ def read: (Class task_class, ?limit: Integer?) -> Array[String]
237
210
  end
238
211
 
239
212
  # Scheduler manages task dependency state and determines execution order
240
213
  class Scheduler
241
214
  STATE_PENDING: Symbol
242
- STATE_ENQUEUED: Symbol
215
+ STATE_RUNNING: Symbol
243
216
  STATE_COMPLETED: Symbol
244
- CLEAN_STATE_PENDING: Symbol
245
- CLEAN_STATE_ENQUEUED: Symbol
246
- CLEAN_STATE_COMPLETED: Symbol
217
+ STATE_FAILED: Symbol
218
+ STATE_SKIPPED: Symbol
247
219
 
248
- @dependencies: Hash[Class, Set[Class]]
220
+ @dependencies: Hash[Class, Array[Class]]
249
221
  @task_states: Hash[Class, Symbol]
250
- @completed_tasks: Set[Class]
222
+ @finished_tasks: Set[Class]
223
+ @run_reverse_deps: Hash[Class, Set[Class]]
251
224
  @reverse_dependencies: Hash[Class, Set[Class]]
252
225
  @clean_task_states: Hash[Class, Symbol]
253
- @clean_completed_tasks: Set[Class]
226
+ @clean_finished_tasks: Set[Class]
254
227
 
255
228
  def initialize: () -> void
256
- def build_dependency_graph: (Class root_task_class) -> void
229
+ def load_graph: (StaticAnalysis::DependencyGraph dependency_graph, Class root_task_class) -> void
257
230
  def next_ready_tasks: () -> Array[Class]
258
- def mark_enqueued: (Class task_class) -> void
231
+ def mark_running: (Class task_class) -> void
259
232
  def mark_completed: (Class task_class) -> void
260
- def completed?: (Class task_class) -> bool
233
+ def mark_failed: (Class task_class) -> void
234
+ def pending?: (Class task_class) -> bool
235
+ def finished?: (Class task_class) -> bool
261
236
  def running_tasks?: () -> bool
262
- def merge_runtime_dependencies: (Hash[Class, Set[Class]] runtime_deps) -> void
263
- def build_reverse_dependency_graph: (Class root_task_class) -> void
237
+ def task_count: () -> Integer
238
+ def never_started_task_classes: () -> Array[Class]
239
+ def mark_skipped: (Class task_class) -> bool
240
+ def skipped_count: () -> Integer
241
+ def pending_dependents_of: (Class task_class) -> Array[Class]
242
+ def build_reverse_dependency_graph: () -> void
264
243
  def next_ready_clean_tasks: () -> Array[Class]
265
- def mark_clean_enqueued: (Class task_class) -> void
244
+ def mark_clean_running: (Class task_class) -> void
266
245
  def mark_clean_completed: (Class task_class) -> void
267
- def clean_completed?: (Class task_class) -> bool
246
+ def mark_clean_failed: (Class task_class) -> void
247
+ def clean_finished?: (Class task_class) -> bool
268
248
  def running_clean_tasks?: () -> bool
269
249
 
270
250
  private
@@ -273,72 +253,94 @@ module Taski
273
253
  def ready_to_clean?: (Class task_class) -> bool
274
254
  end
275
255
 
276
- # WorkerPool manages a pool of worker threads that execute tasks
256
+ def self.default_worker_count: () -> Integer
257
+
258
+ # WorkerPool manages N threads, each with its own command Queue
259
+ # Tasks are executed within Fibers on worker threads
277
260
  class WorkerPool
278
- attr_reader execution_queue: Thread::Queue
261
+ attr_reader worker_count: Integer
279
262
 
280
- @worker_count: Integer
281
263
  @registry: Registry
282
- @on_execute: ^(Class, TaskWrapper) -> void
283
- @execution_queue: Thread::Queue
284
- @workers: Array[Thread]
264
+ @execution_facade: ExecutionFacade
265
+ @worker_count: Integer
266
+ @completion_queue: Thread::Queue
267
+ @threads: Array[Thread]
268
+ @thread_queues: Array[Thread::Queue]
269
+ @next_thread_index: Integer
270
+ @fiber_contexts_mutex: Mutex
271
+ @fiber_contexts: Hash[Integer, Array[untyped]]
272
+ @task_start_times: Hash[Class, Time]
285
273
 
286
- def initialize: (registry: Registry, ?worker_count: Integer?) { (Class, TaskWrapper) -> void } -> void
274
+ def initialize: (registry: Registry, execution_facade: ExecutionFacade, completion_queue: Thread::Queue, ?worker_count: Integer?) -> void
287
275
  def start: () -> void
288
276
  def enqueue: (Class task_class, TaskWrapper wrapper) -> void
277
+ def enqueue_clean: (Class task_class, TaskWrapper wrapper) -> void
289
278
  def shutdown: () -> void
290
- def enqueue_shutdown_signals: () -> void
291
279
 
292
280
  private
293
281
 
294
- def default_worker_count: () -> Integer
295
- def worker_loop: () -> void
296
- def debug_log: (String message) -> void
282
+ def worker_loop: (Thread::Queue queue) -> void
283
+ def drive_fiber: (Class task_class, TaskWrapper wrapper, Thread::Queue queue) -> void
284
+ def drive_fiber_loop: (Fiber fiber, Class task_class, TaskWrapper wrapper, Thread::Queue queue, ?untyped resume_value) -> void
285
+ def handle_dependency: (Class dep_class, Symbol method, Fiber fiber, Class task_class, TaskWrapper wrapper, Thread::Queue queue) -> void
286
+ def resume_fiber: (Fiber fiber, untyped value, Thread::Queue queue) -> void
287
+ def resume_fiber_with_error: (Fiber fiber, Exception error, Thread::Queue queue) -> void
288
+ def start_dependency: (Class dep_class, TaskWrapper dep_wrapper, Thread::Queue queue) -> void
289
+ def complete_task: (Class task_class, TaskWrapper wrapper, untyped result) -> void
290
+ def fail_task: (Class task_class, TaskWrapper wrapper, Exception error) -> void
291
+ def execute_clean_task: (Class task_class, TaskWrapper wrapper) -> void
292
+ def setup_clean_thread_locals: () -> void
293
+ def setup_run_thread_locals: () -> void
294
+ def teardown_thread_locals: () -> void
295
+ def start_output_capture: (Class task_class) -> void
296
+ def stop_output_capture: () -> void
297
+ def store_fiber_context: (Fiber fiber, Class task_class, TaskWrapper wrapper) -> void
298
+ def get_fiber_context: (Fiber fiber) -> Array[untyped]?
299
+ def task_duration_ms: (Class task_class) -> Float?
297
300
  end
298
301
 
299
- # Executor class for parallel task execution (Producer-Consumer pattern)
302
+ # Executor orchestrates both run and clean phases of task execution
303
+ # Both run and clean phases use WorkerPool
300
304
  class Executor
301
305
  @registry: Registry
302
306
  @completion_queue: Thread::Queue
303
- @execution_context: ExecutionContext
307
+ @execution_facade: ExecutionFacade
304
308
  @scheduler: Scheduler
305
309
  @effective_worker_count: Integer?
306
- @worker_pool: WorkerPool
307
- @clean_worker_pool: WorkerPool?
310
+ @worker_pool: WorkerPool?
311
+ @saved_output_capture: TaskOutputRouter?
308
312
 
309
- def self.execute: (Class root_task_class, registry: Registry, ?execution_context: ExecutionContext?) -> void
310
- def self.execute_clean: (Class root_task_class, registry: Registry, ?execution_context: ExecutionContext?) -> void
311
- def initialize: (registry: Registry, ?worker_count: Integer?, ?execution_context: ExecutionContext?) -> void
313
+ def self.execute: (Class root_task_class, registry: Registry, execution_facade: ExecutionFacade) -> void
314
+ def self.execute_clean: (Class root_task_class, registry: Registry, execution_facade: ExecutionFacade) -> void
315
+ def initialize: (registry: Registry, execution_facade: ExecutionFacade, ?worker_count: Integer?) -> void
312
316
  def execute: (Class root_task_class) -> void
313
317
  def execute_clean: (Class root_task_class) -> void
314
318
 
315
319
  private
316
320
 
317
- def enqueue_ready_tasks: () -> void
318
- def enqueue_task: (Class task_class) -> void
319
- def get_or_create_wrapper: (Class task_class) -> TaskWrapper
320
- def execute_task: (Class task_class, TaskWrapper wrapper) -> void
321
+ def pre_start_leaf_tasks: () -> void
322
+ def enqueue_root_if_needed: (Class root_task_class) -> void
321
323
  def run_main_loop: (Class root_task_class) -> void
322
324
  def handle_completion: (Hash[Symbol, untyped] event) -> void
325
+ def enqueue_for_execution: (Class task_class) -> void
326
+ def skip_pending_dependents: (Class failed_task_class) -> void
327
+ def notify_skipped_tasks: () -> void
323
328
  def enqueue_ready_clean_tasks: () -> void
324
329
  def enqueue_clean_task: (Class task_class) -> void
325
- def execute_clean_task: (Class task_class, TaskWrapper wrapper) -> void
326
- def run_clean_main_loop: (Class root_task_class) -> void
330
+ def run_clean_main_loop: () -> void
327
331
  def handle_clean_completion: (Hash[Symbol, untyped] event) -> void
328
332
  def all_tasks_cleaned?: () -> bool
329
- def setup_progress_display: (Class root_task_class) -> void
333
+ def with_display_lifecycle: (Class root_task_class) { () -> void } -> void
330
334
  def setup_output_capture_if_needed: () -> bool
331
- def teardown_output_capture: () -> void
332
- def start_progress_display: () -> void
333
- def stop_progress_display: () -> void
334
- def create_default_execution_context: () -> ExecutionContext
335
- def debug_log: (String message) -> void
336
335
  def raise_if_any_failures: () -> void
337
- def flatten_failures: (Array[TaskWrapper] failed_wrappers) -> Array[TaskFailure]
338
- def wrap_with_task_error: (Class task_class, Exception error) -> TaskError
339
336
  def raise_if_any_clean_failures: () -> void
340
- def flatten_clean_failures: (Array[TaskWrapper] failed_wrappers) -> Array[TaskFailure]
337
+ def raise_if_any_failures_from: (Array[TaskWrapper] failed_wrappers, error_accessor: ^(TaskWrapper) -> StandardError?) -> void
338
+ def flatten_failures_from: (Array[TaskWrapper] failed_wrappers, error_accessor: ^(TaskWrapper) -> StandardError?) -> Array[TaskFailure]
339
+ def wrap_with_task_error: (Class task_class, Exception error) -> TaskError
341
340
  def error_identity: (Exception error) -> Integer
341
+ def log_execution_started: (Class root_task_class) -> void
342
+ def log_execution_completed: (Class root_task_class, Time start_time) -> void
343
+ def log_error_detail: (Class task_class, Exception error) -> void
342
344
  end
343
345
 
344
346
  # TaskWrapper class for task execution
@@ -347,11 +349,11 @@ module Taski
347
349
  attr_reader result: untyped
348
350
  attr_reader error: StandardError?
349
351
  attr_reader clean_error: StandardError?
350
- attr_reader timing: TaskTiming?
351
352
 
352
353
  @task: Task
353
354
  @registry: Registry
354
- @execution_context: ExecutionContext?
355
+ @execution_facade: ExecutionFacade?
356
+ @args: Hash[Symbol, untyped]?
355
357
  @result: untyped
356
358
  @clean_result: untyped
357
359
  @error: StandardError?
@@ -361,26 +363,30 @@ module Taski
361
363
  @clean_condition: MonitorMixin::ConditionVariable
362
364
  @state: Symbol
363
365
  @clean_state: Symbol
364
- @timing: TaskTiming?
366
+ @waiters: Array[Array[untyped]]
365
367
 
366
368
  STATE_PENDING: Symbol
367
369
  STATE_RUNNING: Symbol
368
370
  STATE_COMPLETED: Symbol
369
371
  STATE_FAILED: Symbol
372
+ STATE_SKIPPED: Symbol
370
373
 
371
- def initialize: (Task task, registry: Registry, ?execution_context: ExecutionContext?) -> void
374
+ def initialize: (Task task, registry: Registry, ?execution_facade: ExecutionFacade?, ?args: Hash[Symbol, untyped]?) -> void
372
375
  def state: () -> Symbol
373
376
  def pending?: () -> bool
374
377
  def completed?: () -> bool
375
378
  def failed?: () -> bool
376
- def clean_failed?: () -> bool
379
+ def skipped?: () -> bool
377
380
  def run: () -> untyped
378
381
  def clean: () -> untyped
379
- def run_and_clean: () -> untyped
382
+ def reset!: () -> void
383
+ def run_and_clean: (?clean_on_failure: bool) ?{ () -> void } -> untyped
380
384
  def get_exported_value: (Symbol method_name) -> untyped
385
+ def request_value: (Symbol method, Thread::Queue thread_queue, Fiber fiber) -> Array[untyped]
381
386
  def mark_running: () -> bool
382
387
  def mark_completed: (untyped result) -> void
383
388
  def mark_failed: (StandardError error) -> void
389
+ def mark_skipped: () -> bool
384
390
  def mark_clean_running: () -> bool
385
391
  def mark_clean_completed: (untyped result) -> void
386
392
  def mark_clean_failed: (StandardError error) -> void
@@ -391,89 +397,44 @@ module Taski
391
397
 
392
398
  private
393
399
 
400
+ def with_args_lifecycle: [T] () { () -> T } -> T
394
401
  def trigger_execution_and_wait: () -> void
395
402
  def trigger_clean_and_wait: () -> void
396
- def execute_clean: () -> void
397
- def wait_for_clean_dependencies: () -> void
403
+ def trigger_and_wait: (state_accessor: ^() -> Symbol, condition: MonitorMixin::ConditionVariable, trigger: ^(ExecutionFacade) -> void) -> void
398
404
  def check_abort!: () -> void
399
- def update_progress: (Symbol state, ?duration: Numeric?, ?error: Exception?) -> void
400
- def debug_log: (String message) -> void
405
+ def ensure_execution_facade: () -> ExecutionFacade
406
+ def create_shared_context: () -> ExecutionFacade
407
+ def notify_skipped: () -> void
408
+ def update_progress: (Symbol state, ?error: Exception?) -> void
409
+ def update_clean_progress: (Symbol state, ?error: Exception?) -> void
410
+ def notify_state_change: (previous_state: Symbol?, current_state: Symbol, phase: Symbol) -> void
411
+ def notify_fiber_waiters_completed: (Array[Array[untyped]] waiters) -> void
412
+ def notify_fiber_waiters_failed: (Array[Array[untyped]] waiters, Exception error) -> void
401
413
  end
414
+ end
402
415
 
403
- # TreeProgressDisplay class for tree-based progress visualization
404
- class TreeProgressDisplay
405
- SPINNER_FRAMES: Array[String]
406
- COLORS: Hash[Symbol, String]
407
- ICONS: Hash[Symbol, String]
408
-
409
- @output: IO
410
- @tasks: Hash[Class, TaskProgress]
411
- @monitor: Monitor
412
- @spinner_index: Integer
413
- @renderer_thread: Thread?
414
- @running: bool
415
- @nest_level: Integer
416
- @root_task_class: Class?
417
- @tree_structure: Hash[Symbol, untyped]?
418
- @section_impl_map: Hash[Class, Class]
419
- @last_line_count: Integer
420
-
421
- # Shared class methods
422
- def self.section_class?: (Class klass) -> bool
423
- def self.nested_class?: (Class child_class, Class parent_class) -> bool
424
- def self.render_static_tree: (Class root_task_class) -> String
425
-
426
- # Static tree renderer (internal class)
427
- class StaticTreeRenderer
428
- @task_index_map: Hash[Class, Integer]
429
-
430
- def render: (Class root_task_class) -> String
431
-
432
- private
433
-
434
- def build_tree: (Class task_class, String prefix, bool is_impl, Set[Class] ancestors) -> String
435
- def render_dependency_branch: (Class dep, String prefix, bool is_last, bool is_impl, Set[Class] ancestors) -> String
436
- def get_task_number: (Class task_class) -> String
437
- def colored_type_label: (Class klass) -> String
416
+ # Progress module
417
+ module Progress
418
+ module Layout
419
+ # Base class for progress display layouts
420
+ class Base < Execution::TaskObserver
438
421
  end
439
422
 
440
- class TaskProgress
441
- attr_accessor state: Symbol
442
- attr_accessor start_time: Time?
443
- attr_accessor end_time: Time?
444
- attr_accessor error: Exception?
445
- attr_accessor duration: Numeric?
446
- attr_accessor is_impl_candidate: bool
447
-
448
- def initialize: () -> void
423
+ # Tree layout for hierarchical task display
424
+ class Tree < Base
425
+ def initialize: (?output: IO, ?theme: Theme::Base?) -> void
426
+ def render_tree: () -> String
449
427
  end
450
428
 
451
- def initialize: (?output: IO) -> void
452
- def set_root_task: (Class root_task_class) -> void
453
- def register_section_impl: (Class section_class, Class impl_class) -> void
454
- def register_task: (Class task_class) -> void
455
- def task_registered?: (Class task_class) -> bool
456
- def update_task: (Class task_class, state: Symbol, ?duration: Numeric?, ?error: Exception?) -> void
457
- def task_state: (Class task_class) -> Symbol?
458
- def start: () -> void
459
- def stop: () -> void
460
-
461
- private
429
+ # Simple layout for single-line progress display
430
+ class Simple < Base
431
+ def initialize: (?output: IO, ?theme: Theme::Base?) -> void
432
+ end
462
433
 
463
- def build_tree_structure: () -> void
464
- def build_tree_node: (Class task_class, Set[Class] ancestors) -> Hash[Symbol, untyped]?
465
- def register_tasks_from_tree: (Hash[Symbol, untyped] node) -> void
466
- def render_live: () -> void
467
- def render_final: () -> void
468
- def build_tree_display: () -> Array[String]
469
- def build_root_tree_lines: (Hash[Symbol, untyped] node, String prefix, Array[String] lines) -> void
470
- def render_children: (Hash[Symbol, untyped] node, String prefix, Array[String] lines, Class parent_task_class, bool ancestor_selected) -> void
471
- def format_tree_line: (Class task_class, TaskProgress? progress, bool is_impl, bool is_selected) -> String
472
- def format_unknown_task: (Class task_class, ?bool is_selected) -> String
473
- def spinner_char: () -> String
474
- def type_label_for: (Class task_class, ?bool is_selected) -> String
475
- def section_class?: (Class klass) -> bool
476
- def nested_class?: (Class child_class, Class parent_class) -> bool
434
+ # Log layout for non-TTY environments
435
+ class Log < Base
436
+ def initialize: (?output: IO, ?theme: Theme::Base?) -> void
437
+ end
477
438
  end
478
439
  end
479
440
 
@@ -485,7 +446,6 @@ module Taski
485
446
 
486
447
  private
487
448
 
488
- def self.target_method_for: (Class task_class) -> Symbol
489
449
  def self.extract_method_location: (Class task_class, Symbol method_name) -> [String, Integer]?
490
450
  end
491
451
 
@@ -499,7 +459,7 @@ module Taski
499
459
 
500
460
  attr_reader dependencies: Set[task_class]
501
461
 
502
- def initialize: (Class task_class, Symbol target_method) -> void
462
+ def initialize: (Class task_class, ?Symbol target_method, ?Array[Symbol]? methods_to_analyze) -> void
503
463
  def visit_class_node: (Prism::ClassNode node) -> untyped
504
464
  def visit_module_node: (Prism::ModuleNode node) -> untyped
505
465
  def visit_def_node: (Prism::DefNode node) -> untyped
@@ -507,19 +467,20 @@ module Taski
507
467
 
508
468
  private
509
469
 
470
+ def follow_method_calls: () -> void
471
+ def collect_method_definitions: (Prism::ClassNode class_node) -> void
510
472
  def within_namespace: (String? name) { () -> void } -> void
511
473
  def in_target_class?: () -> bool
512
- def in_impl_method?: () -> bool
513
474
  def extract_constant_name: (untyped node) -> String?
475
+ def should_analyze_method?: (Symbol method_name) -> bool
476
+ def detect_method_call_to_follow: (Prism::CallNode node) -> void
477
+ def self_receiver?: (untyped receiver) -> bool
514
478
  def detect_task_dependency: (Prism::CallNode node) -> void
515
- def detect_impl_candidate: (untyped node) -> void
516
479
  def extract_receiver_constant: (untyped receiver) -> String?
517
480
  def resolve_and_add_dependency: (String constant_name) -> void
518
481
  def resolve_constant: (String name) -> task_class?
519
482
  def resolve_with_namespace_prefix: (String name) -> task_class?
520
483
  def valid_dependency?: (task_class klass) -> bool
521
- def is_parallel_task?: (task_class klass) -> boolish
522
- def is_parallel_section?: (task_class klass) -> boolish
523
484
  end
524
485
 
525
486
  # DependencyGraph class for topological sorting and cycle detection
@@ -530,6 +491,7 @@ module Taski
530
491
 
531
492
  def initialize: () -> void
532
493
  def build_from: (Class root_task_class) -> self
494
+ def build_from_cached: (Class root_task_class) -> self
533
495
  def sorted: () -> Array[Class]
534
496
  def cyclic?: () -> bool
535
497
  def strongly_connected_components: () -> Array[Array[Class]]
@@ -544,6 +506,35 @@ module Taski
544
506
  private
545
507
 
546
508
  def collect_dependencies: (Class task_class) -> void
509
+ def collect_cached_dependencies: (Class task_class) -> void
547
510
  end
548
511
  end
512
+
513
+ # Logging module
514
+ module Logging
515
+ module Events
516
+ EXECUTION_STARTED: String
517
+ EXECUTION_COMPLETED: String
518
+ TASK_STARTED: String
519
+ TASK_COMPLETED: String
520
+ TASK_FAILED: String
521
+ TASK_CLEAN_STARTED: String
522
+ TASK_CLEAN_COMPLETED: String
523
+ TASK_CLEAN_FAILED: String
524
+ TASK_SKIPPED: String
525
+ DEPENDENCY_RESOLVED: String
526
+ TASK_ERROR_DETAIL: String
527
+ TASK_OUTPUT: String
528
+ WORKER_POOL_ENQUEUED: String
529
+ EXECUTOR_TASK_COMPLETED: String
530
+ EXECUTOR_CLEAN_COMPLETED: String
531
+ OUTPUT_ROUTER_START_CAPTURE: String
532
+ OUTPUT_ROUTER_STOP_CAPTURE: String
533
+ OUTPUT_ROUTER_STOP_CAPTURE_UNREGISTERED: String
534
+ OUTPUT_ROUTER_DRAIN_PIPE: String
535
+ OUTPUT_ROUTER_STORE_LINES: String
536
+ OBSERVER_ERROR: String
537
+ end
538
+
539
+ end
549
540
  end