lex-factory 0.1.0 → 0.1.2
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.
- checksums.yaml +4 -4
- data/CHANGELOG.md +12 -0
- data/lib/legion/extensions/factory/pipeline_runner.rb +74 -11
- data/lib/legion/extensions/factory/version.rb +1 -1
- data/lib/legion/extensions/factory.rb +4 -0
- metadata +30 -2
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 3acf180b15bcba7e4c947f454d552620b04c2251eb62aed7a8214bfa88ecc2be
|
|
4
|
+
data.tar.gz: 8d04ca9595404aaefd7fc54f07cef8e8a70099b4a18f2553d05a0774a3922dec
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 9f20b6cf1089657e6a3946bd4dbdde46239beb55c528b7e10ff4a40c91a4c17392bd9dcc0254050e2100ebc80564041c6aef33cafb9af17a873c790d48ca756f
|
|
7
|
+
data.tar.gz: 99362119a0d5bc9d649b358b145df44119dd57f5578a4f08fa1b1cc36dcebd5e821f32b38c45059f91c907399c51d12c5c32539fd4940ea64ba71aea220d343b
|
data/CHANGELOG.md
CHANGED
|
@@ -1,5 +1,17 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## [0.1.2] - 2026-03-28
|
|
4
|
+
|
|
5
|
+
### Changed
|
|
6
|
+
- Implement develop stage via real LLM code generation, delegating to `lex-codegen` `FromGap.generate`
|
|
7
|
+
- Graceful fallback to stub strategy when lex-codegen is not loaded
|
|
8
|
+
- Exclude `pipeline_runner.rb` from `Metrics/ClassLength` and `Metrics/AbcSize` in rubocop config
|
|
9
|
+
|
|
10
|
+
## [0.1.1] - 2026-03-26
|
|
11
|
+
|
|
12
|
+
### Changed
|
|
13
|
+
- fix remote_invocable? to use class method for local dispatch
|
|
14
|
+
|
|
3
15
|
## [0.1.0] - 2026-03-24
|
|
4
16
|
|
|
5
17
|
### Added
|
|
@@ -1,12 +1,15 @@
|
|
|
1
1
|
# frozen_string_literal: true
|
|
2
2
|
|
|
3
|
-
require 'json'
|
|
3
|
+
require 'legion/json'
|
|
4
4
|
require 'fileutils'
|
|
5
5
|
|
|
6
6
|
module Legion
|
|
7
7
|
module Extensions
|
|
8
8
|
module Factory
|
|
9
9
|
class PipelineRunner
|
|
10
|
+
include Legion::JSON::Helper
|
|
11
|
+
include Legion::Logging::Helper
|
|
12
|
+
|
|
10
13
|
attr_reader :spec_path, :output_dir
|
|
11
14
|
|
|
12
15
|
def initialize(spec_path:, output_dir: nil, threshold: nil, max_retries: nil)
|
|
@@ -39,6 +42,7 @@ module Legion
|
|
|
39
42
|
output_dir: @output_dir
|
|
40
43
|
}
|
|
41
44
|
rescue StandardError => e
|
|
45
|
+
log.error "PipelineRunner#run failed at stage #{@context[:current_stage]}: #{e.message}"
|
|
42
46
|
save_state
|
|
43
47
|
{ success: false, error: e.message, last_stage: @context[:current_stage] }
|
|
44
48
|
end
|
|
@@ -78,11 +82,14 @@ module Legion
|
|
|
78
82
|
|
|
79
83
|
def stage_develop(ctx)
|
|
80
84
|
tasks = ctx.dig(:define, :tasks) || []
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
85
|
+
|
|
86
|
+
if codegen_available?
|
|
87
|
+
develop_with_codegen(ctx, tasks)
|
|
88
|
+
else
|
|
89
|
+
tasks.each { |t| t[:status] = :completed }
|
|
90
|
+
ctx[:develop] = { tasks_completed: tasks.size, tasks_failed: 0, strategy: :stub }
|
|
91
|
+
end
|
|
92
|
+
|
|
86
93
|
ctx
|
|
87
94
|
end
|
|
88
95
|
|
|
@@ -106,6 +113,59 @@ module Legion
|
|
|
106
113
|
ctx
|
|
107
114
|
end
|
|
108
115
|
|
|
116
|
+
def codegen_available?
|
|
117
|
+
defined?(Legion::Extensions::Codegen::Runners::FromGap) &&
|
|
118
|
+
Legion::Extensions::Codegen::Runners::FromGap.respond_to?(:generate)
|
|
119
|
+
end
|
|
120
|
+
|
|
121
|
+
def develop_with_codegen(ctx, tasks)
|
|
122
|
+
counters = { completed: 0, failed: 0 }
|
|
123
|
+
artifacts = []
|
|
124
|
+
|
|
125
|
+
tasks.each { |task| run_codegen_task(task, counters, artifacts) }
|
|
126
|
+
|
|
127
|
+
ctx[:develop] = build_develop_context(ctx, counters, artifacts)
|
|
128
|
+
end
|
|
129
|
+
|
|
130
|
+
def run_codegen_task(task, counters, artifacts)
|
|
131
|
+
result = Legion::Extensions::Codegen::Runners::FromGap.generate(
|
|
132
|
+
gap: { id: task[:id], type: :runner_method, intent: task[:requirement] }
|
|
133
|
+
)
|
|
134
|
+
apply_task_result(task, result, counters, artifacts)
|
|
135
|
+
rescue StandardError => e
|
|
136
|
+
log.error "PipelineRunner#run_codegen_task failed for task #{task[:id]}: #{e.message}"
|
|
137
|
+
task[:status] = :failed
|
|
138
|
+
task[:reason] = e.message
|
|
139
|
+
counters[:failed] += 1
|
|
140
|
+
end
|
|
141
|
+
|
|
142
|
+
def apply_task_result(task, result, counters, artifacts)
|
|
143
|
+
if result[:success]
|
|
144
|
+
task[:status] = :completed
|
|
145
|
+
task[:generation_id] = result[:generation_id]
|
|
146
|
+
task[:file_path] = result[:file_path]
|
|
147
|
+
artifacts << result
|
|
148
|
+
counters[:completed] += 1
|
|
149
|
+
else
|
|
150
|
+
task[:status] = :failed
|
|
151
|
+
task[:reason] = result[:reason]
|
|
152
|
+
counters[:failed] += 1
|
|
153
|
+
end
|
|
154
|
+
end
|
|
155
|
+
|
|
156
|
+
def build_develop_context(ctx, counters, artifacts)
|
|
157
|
+
{
|
|
158
|
+
tasks_completed: counters[:completed],
|
|
159
|
+
tasks_failed: counters[:failed],
|
|
160
|
+
strategy: :codegen,
|
|
161
|
+
spec_title: ctx.dig(:discover, :title) || 'unknown',
|
|
162
|
+
spec_length: (ctx[:raw_spec] || '').length,
|
|
163
|
+
artifacts: artifacts.map do |a|
|
|
164
|
+
{ generation_id: a[:generation_id], tier: a[:tier], file_path: a[:file_path] }
|
|
165
|
+
end
|
|
166
|
+
}
|
|
167
|
+
end
|
|
168
|
+
|
|
109
169
|
def extract_requirements(parsed)
|
|
110
170
|
return [] unless parsed[:success]
|
|
111
171
|
|
|
@@ -120,19 +180,21 @@ module Legion
|
|
|
120
180
|
|
|
121
181
|
def save_state
|
|
122
182
|
::FileUtils.mkdir_p(@output_dir)
|
|
123
|
-
File.write(state_file_path,
|
|
124
|
-
rescue StandardError
|
|
183
|
+
File.write(state_file_path, json_dump(serialize_context(@context)))
|
|
184
|
+
rescue StandardError => e
|
|
185
|
+
log.warn "PipelineRunner#save_state failed: #{e.message}"
|
|
125
186
|
nil
|
|
126
187
|
end
|
|
127
188
|
|
|
128
189
|
def load_state
|
|
129
190
|
return default_context unless File.exist?(state_file_path)
|
|
130
191
|
|
|
131
|
-
data =
|
|
192
|
+
data = json_load(File.read(state_file_path))
|
|
132
193
|
data[:completed_stages] = (data[:completed_stages] || []).map(&:to_sym)
|
|
133
194
|
data[:current_stage] = data[:current_stage]&.to_sym
|
|
134
195
|
data
|
|
135
|
-
rescue StandardError
|
|
196
|
+
rescue StandardError => e
|
|
197
|
+
log.warn "PipelineRunner#load_state failed: #{e.message}"
|
|
136
198
|
default_context
|
|
137
199
|
end
|
|
138
200
|
|
|
@@ -161,7 +223,8 @@ module Legion
|
|
|
161
223
|
return {} unless defined?(Legion::Settings) && !Legion::Settings[:factory].nil?
|
|
162
224
|
|
|
163
225
|
Legion::Settings[:factory] || {}
|
|
164
|
-
rescue StandardError
|
|
226
|
+
rescue StandardError => e
|
|
227
|
+
log.debug "PipelineRunner#factory_settings failed: #{e.message}"
|
|
165
228
|
{}
|
|
166
229
|
end
|
|
167
230
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,42 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: lex-factory
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 0.1.
|
|
4
|
+
version: 0.1.2
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Esity
|
|
8
8
|
bindir: bin
|
|
9
9
|
cert_chain: []
|
|
10
10
|
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
-
dependencies:
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: legion-json
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '1.2'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '1.2'
|
|
26
|
+
- !ruby/object:Gem::Dependency
|
|
27
|
+
name: legion-logging
|
|
28
|
+
requirement: !ruby/object:Gem::Requirement
|
|
29
|
+
requirements:
|
|
30
|
+
- - ">="
|
|
31
|
+
- !ruby/object:Gem::Version
|
|
32
|
+
version: '0.3'
|
|
33
|
+
type: :runtime
|
|
34
|
+
prerelease: false
|
|
35
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
36
|
+
requirements:
|
|
37
|
+
- - ">="
|
|
38
|
+
- !ruby/object:Gem::Version
|
|
39
|
+
version: '0.3'
|
|
12
40
|
description: Double Diamond pipeline that takes a specification and produces working
|
|
13
41
|
code with tests
|
|
14
42
|
email:
|