taski 0.2.0 → 0.2.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.
@@ -0,0 +1,202 @@
1
+ # frozen_string_literal: true
2
+
3
+ module Taski
4
+ # Enhanced logging functionality for Taski framework
5
+ # Provides structured logging with multiple levels and context information
6
+ class Logger
7
+ # Log levels in order of severity
8
+ LEVELS = {debug: 0, info: 1, warn: 2, error: 3}.freeze
9
+
10
+ # @param level [Symbol] Minimum log level to output (:debug, :info, :warn, :error)
11
+ # @param output [IO] Output destination (default: $stdout)
12
+ # @param format [Symbol] Log format (:simple, :structured, :json)
13
+ def initialize(level: :info, output: $stdout, format: :structured)
14
+ @level = level
15
+ @output = output
16
+ @format = format
17
+ @start_time = Time.now
18
+ end
19
+
20
+ # Log debug message with optional context
21
+ # @param message [String] Log message
22
+ # @param context [Hash] Additional context information
23
+ def debug(message, **context)
24
+ log(:debug, message, context)
25
+ end
26
+
27
+ # Log info message with optional context
28
+ # @param message [String] Log message
29
+ # @param context [Hash] Additional context information
30
+ def info(message, **context)
31
+ log(:info, message, context)
32
+ end
33
+
34
+ # Log warning message with optional context
35
+ # @param message [String] Log message
36
+ # @param context [Hash] Additional context information
37
+ def warn(message, **context)
38
+ log(:warn, message, context)
39
+ end
40
+
41
+ # Log error message with optional context
42
+ # @param message [String] Log message
43
+ # @param context [Hash] Additional context information
44
+ def error(message, **context)
45
+ log(:error, message, context)
46
+ end
47
+
48
+ # Log task build start event
49
+ # @param task_name [String] Name of the task being built
50
+ # @param dependencies [Array] List of task dependencies
51
+ def task_build_start(task_name, dependencies: [])
52
+ info("Task build started",
53
+ task: task_name,
54
+ dependencies: dependencies.size,
55
+ dependency_names: dependencies.map { |dep| dep.is_a?(Hash) ? dep[:klass].inspect : dep.inspect })
56
+ end
57
+
58
+ # Log task build completion event
59
+ # @param task_name [String] Name of the task that was built
60
+ # @param duration [Float] Build duration in seconds
61
+ def task_build_complete(task_name, duration: nil)
62
+ context = {task: task_name}
63
+ context[:duration_ms] = (duration * 1000).round(2) if duration
64
+ info("Task build completed", **context)
65
+ end
66
+
67
+ # Log task build failure event
68
+ # @param task_name [String] Name of the task that failed
69
+ # @param error [Exception] The error that occurred
70
+ # @param duration [Float] Duration before failure in seconds
71
+ def task_build_failed(task_name, error:, duration: nil)
72
+ context = {
73
+ task: task_name,
74
+ error_class: error.class.name,
75
+ error_message: error.message
76
+ }
77
+ context[:duration_ms] = (duration * 1000).round(2) if duration
78
+ context[:backtrace] = error.backtrace&.first(3) if error.backtrace
79
+ error("Task build failed", **context)
80
+ end
81
+
82
+ # Log dependency resolution event
83
+ # @param task_name [String] Name of the task resolving dependencies
84
+ # @param resolved_count [Integer] Number of dependencies resolved
85
+ def dependency_resolved(task_name, resolved_count:)
86
+ debug("Dependencies resolved",
87
+ task: task_name,
88
+ resolved_dependencies: resolved_count)
89
+ end
90
+
91
+ # Log circular dependency detection
92
+ # @param cycle_path [Array] The circular dependency path
93
+ def circular_dependency_detected(cycle_path)
94
+ error("Circular dependency detected",
95
+ cycle: cycle_path.map { |klass| klass.name || klass.inspect },
96
+ cycle_length: cycle_path.size)
97
+ end
98
+
99
+ private
100
+
101
+ # Core logging method
102
+ # @param level [Symbol] Log level
103
+ # @param message [String] Log message
104
+ # @param context [Hash] Additional context
105
+ def log(level, message, context)
106
+ return unless should_log?(level)
107
+
108
+ case @format
109
+ when :simple
110
+ log_simple(level, message, context)
111
+ when :structured
112
+ log_structured(level, message, context)
113
+ when :json
114
+ log_json(level, message, context)
115
+ end
116
+ end
117
+
118
+ # Check if message should be logged based on current level
119
+ # @param level [Symbol] Message level to check
120
+ # @return [Boolean] True if message should be logged
121
+ def should_log?(level)
122
+ LEVELS[@level] <= LEVELS[level]
123
+ end
124
+
125
+ # Simple log format: [LEVEL] message
126
+ def log_simple(level, message, context)
127
+ @output.puts "[#{level.upcase}] #{message}"
128
+ end
129
+
130
+ # Structured log format with timestamp and context
131
+ def log_structured(level, message, context)
132
+ timestamp = Time.now.strftime("%Y-%m-%d %H:%M:%S.%3N")
133
+ elapsed = ((Time.now - @start_time) * 1000).round(1)
134
+
135
+ line = "[#{timestamp}] [#{elapsed}ms] #{level.to_s.upcase.ljust(5)} Taski: #{message}"
136
+
137
+ unless context.empty?
138
+ context_parts = context.map do |key, value|
139
+ "#{key}=#{format_value(value)}"
140
+ end
141
+ line += " (#{context_parts.join(", ")})"
142
+ end
143
+
144
+ @output.puts line
145
+ end
146
+
147
+ # JSON log format for structured logging systems
148
+ def log_json(level, message, context)
149
+ require "json"
150
+
151
+ log_entry = {
152
+ timestamp: Time.now.iso8601(3),
153
+ level: level.to_s,
154
+ logger: "taski",
155
+ message: message,
156
+ elapsed_ms: ((Time.now - @start_time) * 1000).round(1)
157
+ }.merge(context)
158
+
159
+ @output.puts JSON.generate(log_entry)
160
+ end
161
+
162
+ # Format values for structured logging
163
+ def format_value(value)
164
+ case value
165
+ when String
166
+ (value.length > 50) ? "#{value[0..47]}..." : value
167
+ when Array
168
+ (value.size > 5) ? "[#{value[0..4].join(", ")}, ...]" : value.inspect
169
+ when Hash
170
+ (value.size > 3) ? "{#{value.keys[0..2].join(", ")}, ...}" : value.inspect
171
+ else
172
+ value.inspect
173
+ end
174
+ end
175
+ end
176
+
177
+ class << self
178
+ # Get the current logger instance
179
+ # @return [Logger] Current logger instance
180
+ def logger
181
+ @logger ||= Logger.new
182
+ end
183
+
184
+ # Configure the logger with new settings
185
+ # @param level [Symbol] Log level (:debug, :info, :warn, :error)
186
+ # @param output [IO] Output destination
187
+ # @param format [Symbol] Log format (:simple, :structured, :json)
188
+ def configure_logger(level: :info, output: $stdout, format: :structured)
189
+ @logger = Logger.new(level: level, output: output, format: format)
190
+ end
191
+
192
+ # Set logger to quiet mode (only errors)
193
+ def quiet!
194
+ @logger = Logger.new(level: :error, output: @logger&.instance_variable_get(:@output) || $stdout)
195
+ end
196
+
197
+ # Set logger to verbose mode (all messages)
198
+ def verbose!
199
+ @logger = Logger.new(level: :debug, output: @logger&.instance_variable_get(:@output) || $stdout)
200
+ end
201
+ end
202
+ end
@@ -1,10 +1,10 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative 'exceptions'
3
+ require_relative "exceptions"
4
4
 
5
5
  module Taski
6
6
  # Reference class for task references
7
- #
7
+ #
8
8
  # Used to create lazy references to task classes by name,
9
9
  # which is useful for dependency tracking and metaprogramming.
10
10
  class Reference
@@ -37,4 +37,4 @@ module Taski
37
37
  "&#{@klass}"
38
38
  end
39
39
  end
40
- end
40
+ end
@@ -1,13 +1,13 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require_relative '../exceptions'
3
+ require_relative "../exceptions"
4
4
 
5
5
  module Taski
6
6
  # Base Task class that provides the foundation for task framework
7
7
  # This module contains the core constants and basic structure
8
8
  class Task
9
9
  # Constants for thread-local keys and method tracking
10
- THREAD_KEY_SUFFIX = '_building'
10
+ THREAD_KEY_SUFFIX = "_building"
11
11
  TASKI_ANALYZING_DEFINE_KEY = :taski_analyzing_define
12
12
  ANALYZED_METHODS = [:build, :clean].freeze
13
13
 
@@ -57,4 +57,4 @@ module Taski
57
57
  # Default implementation does nothing
58
58
  end
59
59
  end
60
- end
60
+ end
@@ -1,7 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'set'
4
-
5
3
  module Taski
6
4
  class Task
7
5
  class << self
@@ -18,6 +16,9 @@ module Taski
18
16
  @dependencies ||= []
19
17
  @definitions ||= {}
20
18
 
19
+ # Ensure ref method is defined first time define is called
20
+ create_ref_method_if_needed
21
+
21
22
  # Create method that tracks dependencies on first call
22
23
  create_tracking_method(name)
23
24
 
@@ -25,16 +26,25 @@ module Taski
25
26
  dependencies = analyze_define_dependencies(block)
26
27
 
27
28
  @dependencies += dependencies
28
- @definitions[name] = { block:, options:, classes: dependencies }
29
+ @definitions[name] = {block:, options:, classes: dependencies}
29
30
  end
30
31
 
31
32
  private
32
33
 
33
34
  # === Define API Implementation ===
34
35
 
36
+ # Create ref method if needed to avoid redefinition warnings
37
+ def create_ref_method_if_needed
38
+ return if method_defined_for_define?(:ref)
39
+
40
+ define_singleton_method(:ref) { |klass| Object.const_get(klass) }
41
+ mark_method_as_defined(:ref)
42
+ end
43
+
35
44
  # Create method that tracks dependencies for define API
36
45
  # @param name [Symbol] Method name to create
37
46
  def create_tracking_method(name)
47
+ # Only create tracking method during dependency analysis
38
48
  class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
39
49
  def self.#{name}
40
50
  __resolve__[__callee__] ||= false
@@ -65,7 +75,7 @@ module Taski
65
75
 
66
76
  break if klass.nil?
67
77
 
68
- classes << { klass:, task: }
78
+ classes << {klass:, task:}
69
79
  end
70
80
 
71
81
  # Reset resolution state
@@ -90,6 +100,9 @@ module Taski
90
100
  # @param name [Symbol] Method name
91
101
  # @param definition [Hash] Method definition information
92
102
  def create_defined_method(name, definition)
103
+ # Remove tracking method first to avoid redefinition warnings
104
+ singleton_class.undef_method(name) if singleton_class.method_defined?(name)
105
+
93
106
  # Class method with lazy evaluation
94
107
  define_singleton_method(name) do
95
108
  @__defined_values ||= {}
@@ -101,7 +114,7 @@ module Taski
101
114
  @__defined_values ||= {}
102
115
  @__defined_values[name] ||= self.class.send(name)
103
116
  end
104
-
117
+
105
118
  # Mark as defined for this resolution
106
119
  mark_method_as_defined(name)
107
120
  end
@@ -122,4 +135,4 @@ module Taski
122
135
  end
123
136
  end
124
137
  end
125
- end
138
+ end
@@ -1,7 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'set'
4
- require_relative '../dependency_analyzer'
3
+ require_relative "../dependency_analyzer"
5
4
 
6
5
  module Taski
7
6
  class Task
@@ -23,12 +22,6 @@ module Taski
23
22
  queue << task_class
24
23
  end
25
24
 
26
- # Override ref method after resolution for define API compatibility
27
- # Note: This may cause "method redefined" warnings, which is expected behavior
28
- if (@definitions && !@definitions.empty?) && !method_defined_for_define?(:ref)
29
- define_singleton_method(:ref) { |klass| Object.const_get(klass) }
30
- end
31
-
32
25
  # Create getter methods for defined values
33
26
  create_defined_methods
34
27
 
@@ -42,6 +35,7 @@ module Taski
42
35
  resolved = []
43
36
  visited = Set.new
44
37
  resolving = Set.new # Track currently resolving tasks
38
+ path_map = {self => []} # Track paths to each task
45
39
 
46
40
  while queue.any?
47
41
  task_class = queue.shift
@@ -49,12 +43,26 @@ module Taski
49
43
 
50
44
  # Check for circular dependency
51
45
  if resolving.include?(task_class)
52
- raise CircularDependencyError, "Circular dependency detected involving #{task_class.name}"
46
+ # Build error message with path information
47
+ cycle_path = build_cycle_path(task_class, path_map)
48
+ raise CircularDependencyError, build_circular_dependency_message(cycle_path)
53
49
  end
54
50
 
55
51
  resolving << task_class
56
52
  visited << task_class
53
+
54
+ # Store current path for dependencies
55
+ current_path = path_map[task_class] || []
56
+
57
+ # Let task resolve its dependencies
57
58
  task_class.resolve(queue, resolved)
59
+
60
+ # Track paths for each dependency
61
+ task_class.instance_variable_get(:@dependencies)&.each do |dep|
62
+ dep_class = extract_class(dep)
63
+ path_map[dep_class] = current_path + [task_class] unless path_map.key?(dep_class)
64
+ end
65
+
58
66
  resolving.delete(task_class)
59
67
  resolved << task_class unless resolved.include?(task_class)
60
68
  end
@@ -62,6 +70,31 @@ module Taski
62
70
  resolved
63
71
  end
64
72
 
73
+ private
74
+
75
+ # Build the cycle path from path tracking information
76
+ def build_cycle_path(task_class, path_map)
77
+ path = path_map[task_class] || []
78
+ path + [task_class]
79
+ end
80
+
81
+ # Build detailed error message for circular dependencies
82
+ def build_circular_dependency_message(cycle_path)
83
+ path_names = cycle_path.map { |klass| klass.name || klass.to_s }
84
+
85
+ message = "Circular dependency detected!\n"
86
+ message += "Cycle: #{path_names.join(" → ")}\n\n"
87
+ message += "Detailed dependency chain:\n"
88
+
89
+ cycle_path.each_cons(2).with_index do |(from, to), index|
90
+ message += " #{index + 1}. #{from.name} depends on → #{to.name}\n"
91
+ end
92
+
93
+ message
94
+ end
95
+
96
+ public
97
+
65
98
  # === Static Analysis ===
66
99
 
67
100
  # Analyze dependencies when methods are defined
@@ -91,7 +124,7 @@ module Taski
91
124
  # @param dep_class [Class] Dependency class to add
92
125
  def add_dependency(dep_class)
93
126
  @dependencies ||= []
94
- @dependencies << { klass: dep_class }
127
+ @dependencies << {klass: dep_class}
95
128
  end
96
129
 
97
130
  # Check if dependency already exists
@@ -102,4 +135,4 @@ module Taski
102
135
  end
103
136
  end
104
137
  end
105
- end
138
+ end
@@ -28,4 +28,4 @@ module Taski
28
28
  end
29
29
  end
30
30
  end
31
- end
31
+ end
@@ -1,6 +1,6 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'monitor'
3
+ require "monitor"
4
4
 
5
5
  module Taski
6
6
  class Task
@@ -9,7 +9,7 @@ module Taski
9
9
 
10
10
  # Build this task and all its dependencies
11
11
  def build
12
- resolve_dependencies.reverse.each do |task_class|
12
+ resolve_dependencies.reverse_each do |task_class|
13
13
  task_class.ensure_instance_built
14
14
  end
15
15
  end
@@ -56,7 +56,9 @@ module Taski
56
56
  # Prevent infinite recursion using thread-local storage
57
57
  thread_key = build_thread_key
58
58
  if Thread.current[thread_key]
59
- raise CircularDependencyError, "Circular dependency detected: #{self.name} is already being built"
59
+ # Build dependency path for better error message
60
+ cycle_path = build_current_dependency_path
61
+ raise CircularDependencyError, build_runtime_circular_dependency_message(cycle_path)
60
62
  end
61
63
 
62
64
  Thread.current[thread_key] = true
@@ -84,21 +86,25 @@ module Taski
84
86
  # Generate thread key for recursion detection
85
87
  # @return [String] Thread key for this task
86
88
  def build_thread_key
87
- "#{self.name}#{THREAD_KEY_SUFFIX}"
89
+ "#{name}#{THREAD_KEY_SUFFIX}"
88
90
  end
89
91
 
90
92
  # Build and configure task instance
91
93
  # @return [Task] Built task instance
92
94
  def build_instance
93
- instance = self.new
95
+ instance = new
96
+ build_start_time = Time.now
94
97
  begin
98
+ Taski.logger.task_build_start(name.to_s, dependencies: @dependencies || [])
95
99
  instance.build
100
+ duration = Time.now - build_start_time
101
+ Taski.logger.task_build_complete(name.to_s, duration: duration)
96
102
  instance
97
103
  rescue => e
98
- # Log the error but don't let it crash the entire system
99
- warn "Taski: Failed to build #{self.name}: #{e.message}"
100
- warn "Taski: #{e.backtrace.first}" if e.backtrace
101
- raise TaskBuildError, "Failed to build task #{self.name}: #{e.message}"
104
+ duration = Time.now - build_start_time
105
+ # Log the error with full context
106
+ Taski.logger.task_build_failed(name.to_s, error: e, duration: duration)
107
+ raise TaskBuildError, "Failed to build task #{name}: #{e.message}"
102
108
  end
103
109
  end
104
110
 
@@ -123,6 +129,41 @@ module Taski
123
129
  end
124
130
  end
125
131
 
132
+ # Build current dependency path from thread-local storage
133
+ # @return [Array<Class>] Array of classes in the current build path
134
+ def build_current_dependency_path
135
+ path = []
136
+ Thread.current.keys.each do |key|
137
+ if key.to_s.end_with?(THREAD_KEY_SUFFIX) && Thread.current[key]
138
+ class_name = key.to_s.sub(THREAD_KEY_SUFFIX, "")
139
+ begin
140
+ path << Object.const_get(class_name)
141
+ rescue NameError
142
+ # Skip if class not found
143
+ end
144
+ end
145
+ end
146
+ path << self
147
+ end
148
+
149
+ # Build runtime circular dependency error message
150
+ # @param cycle_path [Array<Class>] The circular dependency path
151
+ # @return [String] Formatted error message
152
+ def build_runtime_circular_dependency_message(cycle_path)
153
+ path_names = cycle_path.map { |klass| klass.name || klass.to_s }
154
+
155
+ message = "Circular dependency detected!\n"
156
+ message += "Cycle: #{path_names.join(" → ")}\n\n"
157
+ message += "The dependency chain is:\n"
158
+
159
+ cycle_path.each_cons(2).with_index do |(from, to), index|
160
+ message += " #{index + 1}. #{from.name} is trying to build → #{to.name}\n"
161
+ end
162
+
163
+ message += "\nThis creates an infinite loop that cannot be resolved."
164
+ message
165
+ end
166
+
126
167
  # Extract class from dependency hash
127
168
  # @param dep [Hash] Dependency information
128
169
  # @return [Class] The dependency class
@@ -132,4 +173,4 @@ module Taski
132
173
  end
133
174
  end
134
175
  end
135
- end
176
+ end
data/lib/taski/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Taski
4
- VERSION = "0.2.0"
4
+ VERSION = "0.2.1"
5
5
  end
data/lib/taski.rb CHANGED
@@ -1,11 +1,11 @@
1
1
  # frozen_string_literal: true
2
2
 
3
- require 'set'
4
- require 'monitor'
3
+ require "monitor"
5
4
 
6
5
  # Load core components
7
6
  require_relative "taski/version"
8
7
  require_relative "taski/exceptions"
8
+ require_relative "taski/logger"
9
9
  require_relative "taski/reference"
10
10
  require_relative "taski/dependency_analyzer"
11
11
 
@@ -18,7 +18,7 @@ require_relative "taski/task/dependency_resolver"
18
18
 
19
19
  module Taski
20
20
  # Main module for the Taski task framework
21
- #
21
+ #
22
22
  # Taski provides a framework for defining and managing task dependencies
23
23
  # with two complementary APIs:
24
24
  # 1. Exports API - Export instance variables as class methods (static dependencies)
@@ -26,7 +26,7 @@ module Taski
26
26
  #
27
27
  # Use Define API when:
28
28
  # - Dependencies change based on runtime conditions
29
- # - Environment-specific configurations
29
+ # - Environment-specific configurations
30
30
  # - Feature flags determine which classes to use
31
31
  # - Complex conditional logic determines dependencies
32
32
  #
@@ -37,4 +37,4 @@ module Taski
37
37
  # - Thread-safe task building
38
38
  # - Circular dependency detection
39
39
  # - Memory leak prevention
40
- end
40
+ end
data/sig/taski.rbs CHANGED
@@ -33,15 +33,19 @@ module Taski
33
33
 
34
34
  # Public API methods
35
35
  def self.exports: (*Symbol names) -> void
36
- def self.define: (Symbol name, Proc block, **untyped options) -> void
36
+ def self.define: (Symbol name) { () -> untyped } -> void
37
37
  def self.build: () -> void
38
38
  def self.clean: () -> void
39
39
  def self.reset!: () -> self
40
40
  def self.refresh: () -> self
41
41
  def self.resolve: (Array[untyped] queue, Array[untyped] resolved) -> self
42
- def self.ref: (String klass) -> Reference
42
+ def self.ref: (String | Class klass) -> (Reference | Class)
43
43
  def self.ensure_instance_built: () -> Task
44
44
 
45
+ # Define API methods
46
+ def self.__resolve__: () -> Hash[Symbol, untyped]
47
+ def self.resolve_dependencies: () -> void
48
+
45
49
  # Instance methods
46
50
  def build: () -> void
47
51
  def clean: () -> void
@@ -53,10 +57,43 @@ module Taski
53
57
  # Allow dynamic class method definitions
54
58
  def self.method_missing: (Symbol name, *untyped args) ?{ (*untyped) -> untyped } -> untyped
55
59
  def self.respond_to_missing?: (Symbol name, bool include_private) -> bool
60
+
61
+ private
62
+
63
+ # Private class methods for dependency resolution
64
+ def self.resolve_queue: (Array[Class] queue, Array[Class] resolved) -> Array[Class]
65
+ def self.detect_circular_dependencies: (Array[Class] queue, Array[Class] resolved) -> void
66
+ def self.build_instance: (Class task_class) -> void
67
+
68
+ # Private class methods for Define API
69
+ def self.create_defined_method: (Symbol name) { () -> untyped } -> void
70
+ def self.create_ref_method_if_needed: () -> void
71
+ def self.method_defined_for_define?: (Symbol method_name) -> bool
72
+ def self.mark_method_as_defined: (Symbol method_name) -> void
56
73
  end
57
74
 
58
75
  # Dependency analyzer module
59
76
  module DependencyAnalyzer
60
77
  def self.analyze_method: (Class klass, Symbol method_name) -> Array[Class]
78
+
79
+ # Task dependency visitor for AST analysis
80
+ class TaskDependencyVisitor < Prism::Visitor
81
+ @dependencies: Array[Class]
82
+
83
+ def initialize: () -> void
84
+ def dependencies: () -> Array[Class]
85
+ def visit_call_node: (Prism::CallNode node) -> void
86
+
87
+ private
88
+
89
+ def extract_class_from_constant: (String constant_name) -> Class?
90
+ def safe_constantize: (String name) -> Class?
91
+ def extract_class_from_ref_call: (Prism::CallNode node) -> Class?
92
+ end
93
+
94
+ private
95
+
96
+ def self.parse_method_code: (Class klass, Symbol method_name) -> Prism::ParseResult?
97
+ def self.extract_dependencies_from_ast: (Prism::Node ast) -> Array[Class]
61
98
  end
62
99
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: taski
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - ahogappa
8
8
  bindir: exe
9
9
  cert_chain: []
10
- date: 2025-06-15 00:00:00.000000000 Z
10
+ date: 2025-06-21 00:00:00.000000000 Z
11
11
  dependencies:
12
12
  - !ruby/object:Gem::Dependency
13
13
  name: prism
@@ -35,15 +35,16 @@ executables: []
35
35
  extensions: []
36
36
  extra_rdoc_files: []
37
37
  files:
38
+ - ".standard.yml"
38
39
  - LICENSE
39
40
  - README.md
40
41
  - Rakefile
41
- - Steepfile
42
42
  - examples/complex_example.rb
43
43
  - examples/readme_example.rb
44
44
  - lib/taski.rb
45
45
  - lib/taski/dependency_analyzer.rb
46
46
  - lib/taski/exceptions.rb
47
+ - lib/taski/logger.rb
47
48
  - lib/taski/reference.rb
48
49
  - lib/taski/task/base.rb
49
50
  - lib/taski/task/define_api.rb
@@ -65,7 +66,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
65
66
  requirements:
66
67
  - - ">="
67
68
  - !ruby/object:Gem::Version
68
- version: 3.1.0
69
+ version: 3.2.0
69
70
  required_rubygems_version: !ruby/object:Gem::Requirement
70
71
  requirements:
71
72
  - - ">="