lex-rfp 0.1.0
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 +7 -0
- data/.github/workflows/ci.yml +16 -0
- data/.gitignore +12 -0
- data/.rspec +3 -0
- data/.rubocop.yml +66 -0
- data/CHANGELOG.md +15 -0
- data/CLAUDE.md +80 -0
- data/Dockerfile +6 -0
- data/Gemfile +12 -0
- data/LICENSE +21 -0
- data/README.md +119 -0
- data/lex-rfp.gemspec +32 -0
- data/lib/legion/extensions/rfp/analytics/client.rb +31 -0
- data/lib/legion/extensions/rfp/analytics/helpers/client.rb +24 -0
- data/lib/legion/extensions/rfp/analytics/runners/metrics.rb +87 -0
- data/lib/legion/extensions/rfp/analytics/runners/quality.rb +121 -0
- data/lib/legion/extensions/rfp/analytics/runners/win_rates.rb +88 -0
- data/lib/legion/extensions/rfp/analytics.rb +16 -0
- data/lib/legion/extensions/rfp/generate/client.rb +31 -0
- data/lib/legion/extensions/rfp/generate/helpers/client.rb +24 -0
- data/lib/legion/extensions/rfp/generate/runners/drafts.rb +98 -0
- data/lib/legion/extensions/rfp/generate/runners/sections.rb +97 -0
- data/lib/legion/extensions/rfp/generate/runners/templates.rb +61 -0
- data/lib/legion/extensions/rfp/generate.rb +16 -0
- data/lib/legion/extensions/rfp/ingest/client.rb +31 -0
- data/lib/legion/extensions/rfp/ingest/helpers/client.rb +24 -0
- data/lib/legion/extensions/rfp/ingest/runners/corpus.rb +66 -0
- data/lib/legion/extensions/rfp/ingest/runners/documents.rb +86 -0
- data/lib/legion/extensions/rfp/ingest/runners/parser.rb +84 -0
- data/lib/legion/extensions/rfp/ingest.rb +16 -0
- data/lib/legion/extensions/rfp/review/client.rb +31 -0
- data/lib/legion/extensions/rfp/review/helpers/client.rb +24 -0
- data/lib/legion/extensions/rfp/review/runners/approvals.rb +70 -0
- data/lib/legion/extensions/rfp/review/runners/comments.rb +76 -0
- data/lib/legion/extensions/rfp/review/runners/workflows.rb +86 -0
- data/lib/legion/extensions/rfp/review.rb +16 -0
- data/lib/legion/extensions/rfp/version.rb +9 -0
- data/lib/legion/extensions/rfp.rb +15 -0
- metadata +99 -0
|
@@ -0,0 +1,84 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Rfp
|
|
6
|
+
module Ingest
|
|
7
|
+
module Runners
|
|
8
|
+
module Parser
|
|
9
|
+
extend Legion::Extensions::Rfp::Ingest::Helpers::Client
|
|
10
|
+
|
|
11
|
+
def parse_rfp_questions(text:, **)
|
|
12
|
+
questions = []
|
|
13
|
+
current_section = nil
|
|
14
|
+
|
|
15
|
+
text.each_line do |line|
|
|
16
|
+
stripped = line.strip
|
|
17
|
+
next if stripped.empty?
|
|
18
|
+
|
|
19
|
+
if stripped.match?(/\A(?:section|part|category)\s+/i) || stripped.match?(/\A[A-Z][A-Z\s]{2,}[A-Z]\z/)
|
|
20
|
+
current_section = stripped
|
|
21
|
+
elsif stripped.match?(/\A\d+[.)]\s/) || stripped.match?(/\A[a-z][.)]\s/i)
|
|
22
|
+
questions << {
|
|
23
|
+
section: current_section,
|
|
24
|
+
question: stripped.sub(/\A[\da-z][.)]\s*/i, ''),
|
|
25
|
+
raw: stripped
|
|
26
|
+
}
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
{ result: questions, count: questions.length }
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def extract_requirements(text:, **)
|
|
34
|
+
requirements = []
|
|
35
|
+
|
|
36
|
+
text.each_line do |line|
|
|
37
|
+
stripped = line.strip
|
|
38
|
+
next if stripped.empty?
|
|
39
|
+
|
|
40
|
+
if stripped.match?(/\b(?:must|shall|required|mandatory)\b/i)
|
|
41
|
+
requirements << { text: stripped, type: :mandatory }
|
|
42
|
+
elsif stripped.match?(/\b(?:should|preferred|desired|optional)\b/i)
|
|
43
|
+
requirements << { text: stripped, type: :preferred }
|
|
44
|
+
end
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
{ result: requirements, mandatory: requirements.count { |r| r[:type] == :mandatory },
|
|
48
|
+
preferred: requirements.count { |r| r[:type] == :preferred } }
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
def extract_sections(text:, **)
|
|
52
|
+
sections = []
|
|
53
|
+
current_title = nil
|
|
54
|
+
current_content = []
|
|
55
|
+
|
|
56
|
+
text.each_line do |line|
|
|
57
|
+
stripped = line.strip
|
|
58
|
+
if stripped.match?(/\A(?:#{section_heading_pattern})/)
|
|
59
|
+
sections << { title: current_title, content: current_content.join("\n").strip } if current_title
|
|
60
|
+
current_title = stripped
|
|
61
|
+
current_content = []
|
|
62
|
+
else
|
|
63
|
+
current_content << line
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
sections << { title: current_title, content: current_content.join("\n").strip } if current_title
|
|
68
|
+
{ result: sections, count: sections.length }
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
|
|
73
|
+
def section_heading_pattern
|
|
74
|
+
'(?:section|part|category|chapter)\s+\d|[A-Z][A-Z\s]{2,}[A-Z]|\d+\.\s+[A-Z]'
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
78
|
+
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
79
|
+
end
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/rfp/ingest/helpers/client'
|
|
4
|
+
require 'legion/extensions/rfp/ingest/runners/documents'
|
|
5
|
+
require 'legion/extensions/rfp/ingest/runners/corpus'
|
|
6
|
+
require 'legion/extensions/rfp/ingest/runners/parser'
|
|
7
|
+
require 'legion/extensions/rfp/ingest/client'
|
|
8
|
+
|
|
9
|
+
module Legion
|
|
10
|
+
module Extensions
|
|
11
|
+
module Rfp
|
|
12
|
+
module Ingest
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,31 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require_relative 'helpers/client'
|
|
4
|
+
require_relative 'runners/workflows'
|
|
5
|
+
require_relative 'runners/comments'
|
|
6
|
+
require_relative 'runners/approvals'
|
|
7
|
+
|
|
8
|
+
module Legion
|
|
9
|
+
module Extensions
|
|
10
|
+
module Rfp
|
|
11
|
+
module Review
|
|
12
|
+
class Client
|
|
13
|
+
include Helpers::Client
|
|
14
|
+
include Runners::Workflows
|
|
15
|
+
include Runners::Comments
|
|
16
|
+
include Runners::Approvals
|
|
17
|
+
|
|
18
|
+
attr_reader :opts
|
|
19
|
+
|
|
20
|
+
def initialize(base_url: nil, token: nil, **)
|
|
21
|
+
@opts = { base_url: base_url, token: token }.compact
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def client(**override)
|
|
25
|
+
super(**@opts, **override)
|
|
26
|
+
end
|
|
27
|
+
end
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
31
|
+
end
|
|
@@ -0,0 +1,24 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'faraday'
|
|
4
|
+
|
|
5
|
+
module Legion
|
|
6
|
+
module Extensions
|
|
7
|
+
module Rfp
|
|
8
|
+
module Review
|
|
9
|
+
module Helpers
|
|
10
|
+
module Client
|
|
11
|
+
def client(base_url: 'http://localhost:4567', token: nil, **)
|
|
12
|
+
Faraday.new(url: base_url) do |conn|
|
|
13
|
+
conn.request :json
|
|
14
|
+
conn.response :json, content_type: /\bjson$/
|
|
15
|
+
conn.headers['Content-Type'] = 'application/json'
|
|
16
|
+
conn.headers['Authorization'] = "Bearer #{token}" if token
|
|
17
|
+
end
|
|
18
|
+
end
|
|
19
|
+
end
|
|
20
|
+
end
|
|
21
|
+
end
|
|
22
|
+
end
|
|
23
|
+
end
|
|
24
|
+
end
|
|
@@ -0,0 +1,70 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Rfp
|
|
6
|
+
module Review
|
|
7
|
+
module Runners
|
|
8
|
+
module Approvals
|
|
9
|
+
extend Legion::Extensions::Rfp::Review::Helpers::Client
|
|
10
|
+
|
|
11
|
+
def approve_section(workflow_id:, section_name:, approved_by:, notes: nil, **)
|
|
12
|
+
{
|
|
13
|
+
result: {
|
|
14
|
+
workflow_id: workflow_id,
|
|
15
|
+
section: section_name,
|
|
16
|
+
status: :approved,
|
|
17
|
+
approved_by: approved_by,
|
|
18
|
+
notes: notes,
|
|
19
|
+
approved_at: Time.now.iso8601
|
|
20
|
+
}
|
|
21
|
+
}
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def reject_section(workflow_id:, section_name:, rejected_by:, reason:, **)
|
|
25
|
+
{
|
|
26
|
+
result: {
|
|
27
|
+
workflow_id: workflow_id,
|
|
28
|
+
section: section_name,
|
|
29
|
+
status: :rejected,
|
|
30
|
+
rejected_by: rejected_by,
|
|
31
|
+
reason: reason,
|
|
32
|
+
rejected_at: Time.now.iso8601
|
|
33
|
+
}
|
|
34
|
+
}
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def approve_proposal(workflow_id:, approved_by:, notes: nil, **)
|
|
38
|
+
{
|
|
39
|
+
result: {
|
|
40
|
+
workflow_id: workflow_id,
|
|
41
|
+
status: :approved,
|
|
42
|
+
approved_by: approved_by,
|
|
43
|
+
notes: notes,
|
|
44
|
+
approved_at: Time.now.iso8601
|
|
45
|
+
}
|
|
46
|
+
}
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def check_readiness(sections:, **)
|
|
50
|
+
all_approved = sections.all? { |s| s[:status] == :approved }
|
|
51
|
+
pending = sections.reject { |s| s[:status] == :approved }
|
|
52
|
+
|
|
53
|
+
{
|
|
54
|
+
result: {
|
|
55
|
+
ready: all_approved,
|
|
56
|
+
total_sections: sections.length,
|
|
57
|
+
approved: sections.count { |s| s[:status] == :approved },
|
|
58
|
+
pending_sections: pending.map { |s| s[:name] }
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
64
|
+
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
65
|
+
end
|
|
66
|
+
end
|
|
67
|
+
end
|
|
68
|
+
end
|
|
69
|
+
end
|
|
70
|
+
end
|
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Rfp
|
|
6
|
+
module Review
|
|
7
|
+
module Runners
|
|
8
|
+
module Comments
|
|
9
|
+
extend Legion::Extensions::Rfp::Review::Helpers::Client
|
|
10
|
+
|
|
11
|
+
def add_comment(workflow_id:, section_name:, author:, body:, type: :general, **)
|
|
12
|
+
comment = {
|
|
13
|
+
id: generate_comment_id,
|
|
14
|
+
workflow_id: workflow_id,
|
|
15
|
+
section: section_name,
|
|
16
|
+
author: author,
|
|
17
|
+
body: body,
|
|
18
|
+
type: type.to_sym,
|
|
19
|
+
created_at: Time.now.iso8601
|
|
20
|
+
}
|
|
21
|
+
{ result: comment }
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def list_comments(workflow_id:, section_name: nil, **)
|
|
25
|
+
{
|
|
26
|
+
result: [],
|
|
27
|
+
workflow_id: workflow_id,
|
|
28
|
+
section: section_name,
|
|
29
|
+
error: 'Persistence requires legion-data'
|
|
30
|
+
}
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def resolve_comment(comment_id:, resolved_by:, **)
|
|
34
|
+
{
|
|
35
|
+
result: {
|
|
36
|
+
id: comment_id,
|
|
37
|
+
resolved: true,
|
|
38
|
+
resolved_by: resolved_by,
|
|
39
|
+
resolved_at: Time.now.iso8601
|
|
40
|
+
}
|
|
41
|
+
}
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def request_revision(workflow_id:, section_name:, author:, reason:, **)
|
|
45
|
+
comment = add_comment(
|
|
46
|
+
workflow_id: workflow_id,
|
|
47
|
+
section_name: section_name,
|
|
48
|
+
author: author,
|
|
49
|
+
body: reason,
|
|
50
|
+
type: :revision_request
|
|
51
|
+
)
|
|
52
|
+
|
|
53
|
+
{
|
|
54
|
+
result: {
|
|
55
|
+
comment: comment[:result],
|
|
56
|
+
section: section_name,
|
|
57
|
+
new_status: :revision_requested,
|
|
58
|
+
workflow_id: workflow_id
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
private
|
|
64
|
+
|
|
65
|
+
def generate_comment_id
|
|
66
|
+
"rfp-cmt-#{Time.now.to_i}-#{rand(10_000)}"
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
70
|
+
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
71
|
+
end
|
|
72
|
+
end
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,86 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module Legion
|
|
4
|
+
module Extensions
|
|
5
|
+
module Rfp
|
|
6
|
+
module Review
|
|
7
|
+
module Runners
|
|
8
|
+
module Workflows
|
|
9
|
+
extend Legion::Extensions::Rfp::Review::Helpers::Client
|
|
10
|
+
|
|
11
|
+
STATUSES = %i[draft in_review revision_requested approved rejected finalized].freeze
|
|
12
|
+
|
|
13
|
+
def create_workflow(proposal_id:, sections: [], reviewers: [], **)
|
|
14
|
+
workflow = {
|
|
15
|
+
id: generate_workflow_id,
|
|
16
|
+
proposal_id: proposal_id,
|
|
17
|
+
status: :draft,
|
|
18
|
+
sections: sections.map { |s| { name: s, status: :draft, reviewer: nil, comments: [] } },
|
|
19
|
+
reviewers: reviewers,
|
|
20
|
+
created_at: Time.now.iso8601,
|
|
21
|
+
updated_at: Time.now.iso8601
|
|
22
|
+
}
|
|
23
|
+
{ result: workflow }
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def get_workflow(workflow_id:, **)
|
|
27
|
+
{ result: { id: workflow_id, status: :draft }, error: 'Persistence requires legion-data' }
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def update_status(workflow_id:, status:, **)
|
|
31
|
+
status_sym = status.to_sym
|
|
32
|
+
return { result: nil, error: "Invalid status: #{status}. Valid: #{STATUSES.join(', ')}" } unless STATUSES.include?(status_sym)
|
|
33
|
+
|
|
34
|
+
{ result: { id: workflow_id, status: status_sym, updated_at: Time.now.iso8601 } }
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def update_section_status(workflow_id:, section_name:, status:, reviewer: nil, **)
|
|
38
|
+
status_sym = status.to_sym
|
|
39
|
+
return { result: nil, error: "Invalid status: #{status}" } unless STATUSES.include?(status_sym)
|
|
40
|
+
|
|
41
|
+
{
|
|
42
|
+
result: {
|
|
43
|
+
workflow_id: workflow_id,
|
|
44
|
+
section: section_name,
|
|
45
|
+
status: status_sym,
|
|
46
|
+
reviewer: reviewer,
|
|
47
|
+
updated_at: Time.now.iso8601
|
|
48
|
+
}
|
|
49
|
+
}
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def submit_for_review(workflow_id:, reviewers:, **)
|
|
53
|
+
{
|
|
54
|
+
result: {
|
|
55
|
+
workflow_id: workflow_id,
|
|
56
|
+
status: :in_review,
|
|
57
|
+
reviewers: reviewers,
|
|
58
|
+
submitted_at: Time.now.iso8601
|
|
59
|
+
}
|
|
60
|
+
}
|
|
61
|
+
end
|
|
62
|
+
|
|
63
|
+
def finalize(workflow_id:, **)
|
|
64
|
+
{
|
|
65
|
+
result: {
|
|
66
|
+
workflow_id: workflow_id,
|
|
67
|
+
status: :finalized,
|
|
68
|
+
finalized_at: Time.now.iso8601
|
|
69
|
+
}
|
|
70
|
+
}
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
private
|
|
74
|
+
|
|
75
|
+
def generate_workflow_id
|
|
76
|
+
"rfp-wf-#{Time.now.to_i}-#{rand(10_000)}"
|
|
77
|
+
end
|
|
78
|
+
|
|
79
|
+
include Legion::Extensions::Helpers::Lex if Legion::Extensions.const_defined?(:Helpers) &&
|
|
80
|
+
Legion::Extensions::Helpers.const_defined?(:Lex)
|
|
81
|
+
end
|
|
82
|
+
end
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
86
|
+
end
|
|
@@ -0,0 +1,16 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/rfp/review/helpers/client'
|
|
4
|
+
require 'legion/extensions/rfp/review/runners/workflows'
|
|
5
|
+
require 'legion/extensions/rfp/review/runners/comments'
|
|
6
|
+
require 'legion/extensions/rfp/review/runners/approvals'
|
|
7
|
+
require 'legion/extensions/rfp/review/client'
|
|
8
|
+
|
|
9
|
+
module Legion
|
|
10
|
+
module Extensions
|
|
11
|
+
module Rfp
|
|
12
|
+
module Review
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
|
16
|
+
end
|
|
@@ -0,0 +1,15 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'legion/extensions/rfp/version'
|
|
4
|
+
require_relative 'rfp/ingest'
|
|
5
|
+
require_relative 'rfp/generate'
|
|
6
|
+
require_relative 'rfp/review'
|
|
7
|
+
require_relative 'rfp/analytics'
|
|
8
|
+
|
|
9
|
+
module Legion
|
|
10
|
+
module Extensions
|
|
11
|
+
module Rfp
|
|
12
|
+
extend Legion::Extensions::Core if Legion::Extensions.const_defined? :Core
|
|
13
|
+
end
|
|
14
|
+
end
|
|
15
|
+
end
|
metadata
ADDED
|
@@ -0,0 +1,99 @@
|
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
|
2
|
+
name: lex-rfp
|
|
3
|
+
version: !ruby/object:Gem::Version
|
|
4
|
+
version: 0.1.0
|
|
5
|
+
platform: ruby
|
|
6
|
+
authors:
|
|
7
|
+
- Esity
|
|
8
|
+
bindir: bin
|
|
9
|
+
cert_chain: []
|
|
10
|
+
date: 1980-01-02 00:00:00.000000000 Z
|
|
11
|
+
dependencies:
|
|
12
|
+
- !ruby/object:Gem::Dependency
|
|
13
|
+
name: faraday
|
|
14
|
+
requirement: !ruby/object:Gem::Requirement
|
|
15
|
+
requirements:
|
|
16
|
+
- - ">="
|
|
17
|
+
- !ruby/object:Gem::Version
|
|
18
|
+
version: '2.0'
|
|
19
|
+
type: :runtime
|
|
20
|
+
prerelease: false
|
|
21
|
+
version_requirements: !ruby/object:Gem::Requirement
|
|
22
|
+
requirements:
|
|
23
|
+
- - ">="
|
|
24
|
+
- !ruby/object:Gem::Version
|
|
25
|
+
version: '2.0'
|
|
26
|
+
description: Generative AI-powered RFP and proposal automation for LegionIO. Ingests
|
|
27
|
+
past proposals into Apollo, generates draft responses via LLM pipeline with RAG,
|
|
28
|
+
and provides human-in-the-loop review workflows with analytics.
|
|
29
|
+
email:
|
|
30
|
+
- matthewdiverson@gmail.com
|
|
31
|
+
executables: []
|
|
32
|
+
extensions: []
|
|
33
|
+
extra_rdoc_files: []
|
|
34
|
+
files:
|
|
35
|
+
- ".github/workflows/ci.yml"
|
|
36
|
+
- ".gitignore"
|
|
37
|
+
- ".rspec"
|
|
38
|
+
- ".rubocop.yml"
|
|
39
|
+
- CHANGELOG.md
|
|
40
|
+
- CLAUDE.md
|
|
41
|
+
- Dockerfile
|
|
42
|
+
- Gemfile
|
|
43
|
+
- LICENSE
|
|
44
|
+
- README.md
|
|
45
|
+
- lex-rfp.gemspec
|
|
46
|
+
- lib/legion/extensions/rfp.rb
|
|
47
|
+
- lib/legion/extensions/rfp/analytics.rb
|
|
48
|
+
- lib/legion/extensions/rfp/analytics/client.rb
|
|
49
|
+
- lib/legion/extensions/rfp/analytics/helpers/client.rb
|
|
50
|
+
- lib/legion/extensions/rfp/analytics/runners/metrics.rb
|
|
51
|
+
- lib/legion/extensions/rfp/analytics/runners/quality.rb
|
|
52
|
+
- lib/legion/extensions/rfp/analytics/runners/win_rates.rb
|
|
53
|
+
- lib/legion/extensions/rfp/generate.rb
|
|
54
|
+
- lib/legion/extensions/rfp/generate/client.rb
|
|
55
|
+
- lib/legion/extensions/rfp/generate/helpers/client.rb
|
|
56
|
+
- lib/legion/extensions/rfp/generate/runners/drafts.rb
|
|
57
|
+
- lib/legion/extensions/rfp/generate/runners/sections.rb
|
|
58
|
+
- lib/legion/extensions/rfp/generate/runners/templates.rb
|
|
59
|
+
- lib/legion/extensions/rfp/ingest.rb
|
|
60
|
+
- lib/legion/extensions/rfp/ingest/client.rb
|
|
61
|
+
- lib/legion/extensions/rfp/ingest/helpers/client.rb
|
|
62
|
+
- lib/legion/extensions/rfp/ingest/runners/corpus.rb
|
|
63
|
+
- lib/legion/extensions/rfp/ingest/runners/documents.rb
|
|
64
|
+
- lib/legion/extensions/rfp/ingest/runners/parser.rb
|
|
65
|
+
- lib/legion/extensions/rfp/review.rb
|
|
66
|
+
- lib/legion/extensions/rfp/review/client.rb
|
|
67
|
+
- lib/legion/extensions/rfp/review/helpers/client.rb
|
|
68
|
+
- lib/legion/extensions/rfp/review/runners/approvals.rb
|
|
69
|
+
- lib/legion/extensions/rfp/review/runners/comments.rb
|
|
70
|
+
- lib/legion/extensions/rfp/review/runners/workflows.rb
|
|
71
|
+
- lib/legion/extensions/rfp/version.rb
|
|
72
|
+
homepage: https://github.com/LegionIO/lex-rfp
|
|
73
|
+
licenses:
|
|
74
|
+
- MIT
|
|
75
|
+
metadata:
|
|
76
|
+
homepage_uri: https://github.com/LegionIO/lex-rfp
|
|
77
|
+
source_code_uri: https://github.com/LegionIO/lex-rfp
|
|
78
|
+
documentation_uri: https://github.com/LegionIO/lex-rfp
|
|
79
|
+
changelog_uri: https://github.com/LegionIO/lex-rfp/blob/main/CHANGELOG.md
|
|
80
|
+
bug_tracker_uri: https://github.com/LegionIO/lex-rfp/issues
|
|
81
|
+
rubygems_mfa_required: 'true'
|
|
82
|
+
rdoc_options: []
|
|
83
|
+
require_paths:
|
|
84
|
+
- lib
|
|
85
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
|
86
|
+
requirements:
|
|
87
|
+
- - ">="
|
|
88
|
+
- !ruby/object:Gem::Version
|
|
89
|
+
version: '3.4'
|
|
90
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
|
91
|
+
requirements:
|
|
92
|
+
- - ">="
|
|
93
|
+
- !ruby/object:Gem::Version
|
|
94
|
+
version: '0'
|
|
95
|
+
requirements: []
|
|
96
|
+
rubygems_version: 3.6.9
|
|
97
|
+
specification_version: 4
|
|
98
|
+
summary: LEX Rfp
|
|
99
|
+
test_files: []
|