factbase 0.0.30 → 0.0.32
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/.github/workflows/license.yml +57 -0
- data/Gemfile +2 -2
- data/Gemfile.lock +5 -5
- data/README.md +7 -5
- data/lib/factbase/syntax.rb +22 -13
- data/lib/factbase/term.rb +41 -1
- data/lib/factbase.rb +1 -1
- data/test/factbase/test_inv.rb +1 -1
- data/test/factbase/test_looged.rb +4 -4
- data/test/factbase/test_pre.rb +1 -1
- data/test/factbase/test_query.rb +10 -0
- data/test/factbase/test_syntax.rb +18 -6
- data/test/factbase/test_term.rb +6 -1
- data/test/test_factbase.rb +2 -2
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA256:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 53e563c36bf3d61f977bbae719a1b6069973a40b28f37ba4e3222f7fbae7091c
|
4
|
+
data.tar.gz: ecd5e6b589ceda68f8a25369e6d7c169500dab90ac6bfca26af5384d0e74bdc9
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 7fc18cb91cd74af7e9e87b0740b10d1409278ce0dc8a7ea589ef8c45a5b61501dbe0706faf012a49862c911c25859d85a93ad1e6e275421af4c3255bcd5d1b2b
|
7
|
+
data.tar.gz: bf4d812092097c9edb40ccd4aeac447b96906bbdbb515696199f9fa229d8e620ba36b2c80435e1d75115c07e5f2bac6029215df0657d03d51ceb42d053f6652c
|
@@ -0,0 +1,57 @@
|
|
1
|
+
# Copyright (c) 2024 Yegor Bugayenko
|
2
|
+
#
|
3
|
+
# Permission is hereby granted, free of charge, to any person obtaining a copy
|
4
|
+
# of this software and associated documentation files (the 'Software'), to deal
|
5
|
+
# in the Software without restriction, including without limitation the rights
|
6
|
+
# to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
7
|
+
# copies of the Software, and to permit persons to whom the Software is
|
8
|
+
# furnished to do so, subject to the following conditions:
|
9
|
+
#
|
10
|
+
# The above copyright notice and this permission notice shall be included in all
|
11
|
+
# copies or substantial portions of the Software.
|
12
|
+
#
|
13
|
+
# THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
14
|
+
# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
15
|
+
# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
16
|
+
# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
17
|
+
# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
18
|
+
# OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
19
|
+
# SOFTWARE.
|
20
|
+
---
|
21
|
+
name: license
|
22
|
+
'on':
|
23
|
+
push:
|
24
|
+
branches:
|
25
|
+
- master
|
26
|
+
pull_request:
|
27
|
+
branches:
|
28
|
+
- master
|
29
|
+
jobs:
|
30
|
+
license:
|
31
|
+
runs-on: ubuntu-22.04
|
32
|
+
steps:
|
33
|
+
- uses: actions/checkout@v4
|
34
|
+
- shell: bash
|
35
|
+
run: |
|
36
|
+
header="Copyright (c) $(date +%Y) Yegor Bugayenko"
|
37
|
+
failed="false"
|
38
|
+
while IFS= read -r file; do
|
39
|
+
if ! grep -q "${header}" "${file}"; then
|
40
|
+
failed="true"
|
41
|
+
echo "⚠️ Copyright header is not found in: ${file}"
|
42
|
+
else
|
43
|
+
echo "File looks good: ${file}"
|
44
|
+
fi
|
45
|
+
done < <(find . -type f \( \
|
46
|
+
-name "Dockerfile" -o \
|
47
|
+
-name "LICENSE.txt" -o \
|
48
|
+
-name "Makefile" -o \
|
49
|
+
-name "Rakefile" -o \
|
50
|
+
-name "*.sh" -o \
|
51
|
+
-name "*.rb" -o \
|
52
|
+
-name "*.fe" -o \
|
53
|
+
-name "*.yml" \
|
54
|
+
\) -print)
|
55
|
+
if [ "${failed}" = "true" ]; then
|
56
|
+
exit 1
|
57
|
+
fi
|
data/Gemfile
CHANGED
@@ -23,10 +23,10 @@
|
|
23
23
|
source 'https://rubygems.org'
|
24
24
|
gemspec
|
25
25
|
|
26
|
-
gem 'minitest', '5.23.
|
26
|
+
gem 'minitest', '5.23.1', require: false
|
27
27
|
gem 'rake', '13.2.1', require: false
|
28
28
|
gem 'rspec-rails', '6.1.2', require: false
|
29
|
-
gem 'rubocop', '1.
|
29
|
+
gem 'rubocop', '1.64.0', require: false
|
30
30
|
gem 'rubocop-performance', '1.21.0', require: false
|
31
31
|
gem 'rubocop-rspec', '2.29.2', require: false
|
32
32
|
gem 'simplecov', '0.22.0', require: false
|
data/Gemfile.lock
CHANGED
@@ -59,7 +59,7 @@ GEM
|
|
59
59
|
crass (~> 1.0.2)
|
60
60
|
nokogiri (>= 1.12.0)
|
61
61
|
loog (0.5.1)
|
62
|
-
minitest (5.23.
|
62
|
+
minitest (5.23.1)
|
63
63
|
mutex_m (0.2.0)
|
64
64
|
nokogiri (1.16.5-arm64-darwin)
|
65
65
|
racc (~> 1.4)
|
@@ -75,7 +75,7 @@ GEM
|
|
75
75
|
racc
|
76
76
|
psych (5.1.2)
|
77
77
|
stringio
|
78
|
-
racc (1.
|
78
|
+
racc (1.8.0)
|
79
79
|
rack (3.0.11)
|
80
80
|
rack-session (2.0.0)
|
81
81
|
rack (>= 3.0.0)
|
@@ -125,7 +125,7 @@ GEM
|
|
125
125
|
rspec-mocks (~> 3.13)
|
126
126
|
rspec-support (~> 3.13)
|
127
127
|
rspec-support (3.13.1)
|
128
|
-
rubocop (1.
|
128
|
+
rubocop (1.64.0)
|
129
129
|
json (~> 2.3)
|
130
130
|
language_server-protocol (>= 3.17.0)
|
131
131
|
parallel (~> 1.10)
|
@@ -181,10 +181,10 @@ PLATFORMS
|
|
181
181
|
|
182
182
|
DEPENDENCIES
|
183
183
|
factbase!
|
184
|
-
minitest (= 5.23.
|
184
|
+
minitest (= 5.23.1)
|
185
185
|
rake (= 13.2.1)
|
186
186
|
rspec-rails (= 6.1.2)
|
187
|
-
rubocop (= 1.
|
187
|
+
rubocop (= 1.64.0)
|
188
188
|
rubocop-performance (= 1.21.0)
|
189
189
|
rubocop-rspec (= 2.29.2)
|
190
190
|
simplecov (= 0.22.0)
|
data/README.md
CHANGED
@@ -14,7 +14,8 @@
|
|
14
14
|
This Ruby gem manages an in-memory database of facts.
|
15
15
|
A fact is simply a map of properties and values.
|
16
16
|
The values are either atomic literals or non-empty sets of literals.
|
17
|
-
It is possible to delete a fact, but impossible to delete a property
|
17
|
+
It is possible to delete a fact, but impossible to delete a property
|
18
|
+
from a fact.
|
18
19
|
|
19
20
|
**ATTENTION**: The current implemention is naive and,
|
20
21
|
because of that, very slow. I will be very happy
|
@@ -55,8 +56,7 @@ assert(f2.query('(eq foo 42)').each.to_a.size == 1)
|
|
55
56
|
|
56
57
|
All terms available in a query:
|
57
58
|
|
58
|
-
* `()`
|
59
|
-
* `(nil)` is false
|
59
|
+
* `(always)` and `(never)` are "true" and "false"
|
60
60
|
* `(not t)` inverses the `t` if it's boolean (exception otherwise)
|
61
61
|
* `(or t1 t2 ...)` returns true if at least one argument is true
|
62
62
|
* `(and t1 t2 ...)` returns true if all arguments are true
|
@@ -73,12 +73,14 @@ All terms available in a query:
|
|
73
73
|
|
74
74
|
There are also terms that match the entire factbase:
|
75
75
|
|
76
|
-
* `(max k)` returns true if the value of `k` property
|
76
|
+
* `(max k)` returns true if the value of `k` property
|
77
|
+
is the largest in the entire factbase
|
77
78
|
* `(min k)` returns true if the value of `k` is the smallest
|
78
79
|
|
79
80
|
## How to contribute
|
80
81
|
|
81
|
-
Read
|
82
|
+
Read
|
83
|
+
[these guidelines](https://www.yegor256.com/2014/04/15/github-guidelines.html).
|
82
84
|
Make sure you build is green before you contribute
|
83
85
|
your pull request. You will need to have
|
84
86
|
[Ruby](https://www.ruby-lang.org/en/) 3.2+ and
|
data/lib/factbase/syntax.rb
CHANGED
@@ -39,17 +39,26 @@ class Factbase::Syntax
|
|
39
39
|
# Convert it to a term.
|
40
40
|
# @return [Term] The term detected
|
41
41
|
def to_term
|
42
|
+
build.simplify
|
43
|
+
rescue StandardError => e
|
44
|
+
raise "#{e.message} in \"#{@query}\""
|
45
|
+
end
|
46
|
+
|
47
|
+
private
|
48
|
+
|
49
|
+
# Convert it to a term.
|
50
|
+
# @return [Term] The term detected
|
51
|
+
def build
|
42
52
|
@tokens ||= to_tokens
|
53
|
+
raise 'No tokens' if @tokens.empty?
|
43
54
|
@ast ||= to_ast(@tokens, 0)
|
44
|
-
raise
|
55
|
+
raise 'Too many terms' if @ast[1] != @tokens.size
|
45
56
|
term = @ast[0]
|
46
|
-
raise
|
47
|
-
raise
|
57
|
+
raise 'No terms found' if term.nil?
|
58
|
+
raise 'Not a term' unless term.is_a?(Factbase::Term)
|
48
59
|
term
|
49
60
|
end
|
50
61
|
|
51
|
-
private
|
52
|
-
|
53
62
|
# Reads the stream of tokens, starting at the +at+ position. If the
|
54
63
|
# token at the position is not a literal (like 42 or "Hello") but a term,
|
55
64
|
# the function recursively calls itself.
|
@@ -58,19 +67,19 @@ class Factbase::Syntax
|
|
58
67
|
# is the term/literal and the second one is the position where the
|
59
68
|
# scanning should continue.
|
60
69
|
def to_ast(tokens, at)
|
61
|
-
raise "Closing too soon at ##{at}
|
70
|
+
raise "Closing too soon at ##{at}" if tokens[at] == :close
|
62
71
|
return [tokens[at], at + 1] unless tokens[at] == :open
|
63
72
|
at += 1
|
64
73
|
op = tokens[at]
|
65
|
-
|
74
|
+
raise 'No token found' if op == :close
|
66
75
|
operands = []
|
67
76
|
at += 1
|
68
77
|
loop do
|
69
|
-
raise "End of token stream at ##{at}
|
78
|
+
raise "End of token stream at ##{at}" if tokens[at].nil?
|
70
79
|
break if tokens[at] == :close
|
71
80
|
(operand, at1) = to_ast(tokens, at)
|
72
|
-
raise "Stuck at position ##{at}
|
73
|
-
raise "Jump back at position ##{at}
|
81
|
+
raise "Stuck at position ##{at}" if at == at1
|
82
|
+
raise "Jump back at position ##{at}" if at1 < at
|
74
83
|
at = at1
|
75
84
|
operands << operand
|
76
85
|
break if tokens[at] == :close
|
@@ -110,12 +119,12 @@ class Factbase::Syntax
|
|
110
119
|
acc += c
|
111
120
|
end
|
112
121
|
end
|
113
|
-
raise
|
122
|
+
raise 'String not closed' if string
|
114
123
|
list.map do |t|
|
115
124
|
if t.is_a?(Symbol)
|
116
125
|
t
|
117
126
|
elsif t.start_with?('\'', '"')
|
118
|
-
raise
|
127
|
+
raise 'String literal can\'t be empty' if t.length <= 2
|
119
128
|
t[1..-2]
|
120
129
|
elsif t.match?(/^[0-9]+$/)
|
121
130
|
t.to_i
|
@@ -124,7 +133,7 @@ class Factbase::Syntax
|
|
124
133
|
elsif t.match?(/^[0-9]{4}-[0-9]{2}-[0-9]{2}T[0-9]{2}:[0-9]{2}:[0-9]{2}Z$/)
|
125
134
|
Time.parse(t)
|
126
135
|
else
|
127
|
-
raise "Wrong symbol format (#{t})
|
136
|
+
raise "Wrong symbol format (#{t})" unless t.match?(/^[a-z][a-zA-Z0-9_]*$/)
|
128
137
|
t.to_sym
|
129
138
|
end
|
130
139
|
end
|
data/lib/factbase/term.rb
CHANGED
@@ -43,6 +43,8 @@ class Factbase::Term
|
|
43
43
|
# @return [bool] TRUE if matches
|
44
44
|
def evaluate(fact)
|
45
45
|
send(@op, fact)
|
46
|
+
rescue NoMethodError => _e
|
47
|
+
raise "Term '#{@op}' is not defined"
|
46
48
|
end
|
47
49
|
|
48
50
|
# Put it into the context: let it see the entire array of maps.
|
@@ -57,6 +59,17 @@ class Factbase::Term
|
|
57
59
|
self
|
58
60
|
end
|
59
61
|
|
62
|
+
# Simplify it if possible.
|
63
|
+
# @return [Factbase::Term] New term or itself
|
64
|
+
def simplify
|
65
|
+
m = "#{@op}_simplify"
|
66
|
+
if respond_to?(m, true)
|
67
|
+
send(m)
|
68
|
+
else
|
69
|
+
self
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
60
73
|
# Turns it into a string.
|
61
74
|
# @return [String] The string of it
|
62
75
|
def to_s
|
@@ -76,11 +89,16 @@ class Factbase::Term
|
|
76
89
|
|
77
90
|
private
|
78
91
|
|
79
|
-
def
|
92
|
+
def always(_fact)
|
80
93
|
assert_args(0)
|
81
94
|
true
|
82
95
|
end
|
83
96
|
|
97
|
+
def never(_fact)
|
98
|
+
assert_args(0)
|
99
|
+
false
|
100
|
+
end
|
101
|
+
|
84
102
|
def not(fact)
|
85
103
|
assert_args(1)
|
86
104
|
!only_bool(the_value(0, fact))
|
@@ -100,6 +118,28 @@ class Factbase::Term
|
|
100
118
|
true
|
101
119
|
end
|
102
120
|
|
121
|
+
def and_or_simplify
|
122
|
+
strs = []
|
123
|
+
ops = []
|
124
|
+
@operands.each do |o|
|
125
|
+
o = o.simplify
|
126
|
+
s = o.to_s
|
127
|
+
next if strs.include?(s)
|
128
|
+
strs << s
|
129
|
+
ops << o
|
130
|
+
end
|
131
|
+
return ops[0] if ops.size == 1
|
132
|
+
Factbase::Term.new(@op, ops)
|
133
|
+
end
|
134
|
+
|
135
|
+
def and_simplify
|
136
|
+
and_or_simplify
|
137
|
+
end
|
138
|
+
|
139
|
+
def or_simplify
|
140
|
+
and_or_simplify
|
141
|
+
end
|
142
|
+
|
103
143
|
def when(fact)
|
104
144
|
assert_args(2)
|
105
145
|
a = @operands[0]
|
data/lib/factbase.rb
CHANGED
data/test/factbase/test_inv.rb
CHANGED
@@ -48,19 +48,19 @@ class TestLooged < Minitest::Test
|
|
48
48
|
fb = Factbase.new
|
49
49
|
fb.insert
|
50
50
|
fb.insert
|
51
|
-
assert_equal(2, Factbase::Looged.new(fb, Loog::NULL).query('()').each(&:to_s))
|
51
|
+
assert_equal(2, Factbase::Looged.new(fb, Loog::NULL).query('(always)').each(&:to_s))
|
52
52
|
end
|
53
53
|
|
54
54
|
def test_returns_int_when_empty
|
55
55
|
fb = Factbase.new
|
56
|
-
assert_equal(0, Factbase::Looged.new(fb, Loog::NULL).query('()').each(&:to_s))
|
56
|
+
assert_equal(0, Factbase::Looged.new(fb, Loog::NULL).query('(always)').each(&:to_s))
|
57
57
|
end
|
58
58
|
|
59
59
|
def test_logs_when_enumerator
|
60
60
|
fb = Factbase::Looged.new(Factbase.new, Loog::NULL)
|
61
|
-
assert_equal(0, fb.query('()').each.to_a.size)
|
61
|
+
assert_equal(0, fb.query('(always)').each.to_a.size)
|
62
62
|
fb.insert
|
63
|
-
assert_equal(1, fb.query('()').each.to_a.size)
|
63
|
+
assert_equal(1, fb.query('(always)').each.to_a.size)
|
64
64
|
end
|
65
65
|
|
66
66
|
def test_proper_logging
|
data/test/factbase/test_pre.rb
CHANGED
data/test/factbase/test_query.rb
CHANGED
@@ -90,6 +90,16 @@ class TestQuery < Minitest::Test
|
|
90
90
|
assert_equal(1, maps.size)
|
91
91
|
end
|
92
92
|
|
93
|
+
def test_deleting_nothing
|
94
|
+
maps = []
|
95
|
+
maps << { 'foo' => [42] }
|
96
|
+
maps << { 'bar' => [4, 5] }
|
97
|
+
maps << { 'bar' => 5 }
|
98
|
+
q = Factbase::Query.new(maps, Mutex.new, '(never)')
|
99
|
+
assert_equal(0, q.delete!)
|
100
|
+
assert_equal(3, maps.size)
|
101
|
+
end
|
102
|
+
|
93
103
|
def test_to_array
|
94
104
|
maps = []
|
95
105
|
maps << { 'foo' => [42] }
|
@@ -41,13 +41,12 @@ class TestSyntax < Minitest::Test
|
|
41
41
|
|
42
42
|
def test_simple_parsing
|
43
43
|
[
|
44
|
-
'()',
|
45
44
|
'(foo)',
|
46
45
|
'(foo (bar) (zz 77) )',
|
47
46
|
"(eq foo \n\n 'Hello, world!'\n)\n",
|
48
47
|
"(eq x 'Hello, \\' \n) \\' ( world!')",
|
49
48
|
"# this is a comment\n(eq foo # test\n 42)\n\n# another comment\n",
|
50
|
-
"(or ( a 4) (b 5) () (and () (c 5) \t\t(r 7 w8s w8is 'Foo')))"
|
49
|
+
"(or ( a 4) (b 5) (always) (and (always) (c 5) \t\t(r 7 w8s w8is 'Foo')))"
|
51
50
|
].each do |q|
|
52
51
|
Factbase::Syntax.new(q).to_term
|
53
52
|
end
|
@@ -67,7 +66,7 @@ class TestSyntax < Minitest::Test
|
|
67
66
|
'(eq t 2024-05-25T19:43:48Z)',
|
68
67
|
'(eq t 3.1415926)',
|
69
68
|
'(eq t 3.0e+21)',
|
70
|
-
"(foo (x (f (t (y 42 'Hey you'))) (
|
69
|
+
"(foo (x (f (t (y 42 'Hey you'))) (never) (r 3)) y z)"
|
71
70
|
].each do |q|
|
72
71
|
assert_equal(q, Factbase::Syntax.new(q).to_term.to_s)
|
73
72
|
end
|
@@ -91,6 +90,7 @@ class TestSyntax < Minitest::Test
|
|
91
90
|
def test_broken_syntax
|
92
91
|
[
|
93
92
|
'',
|
93
|
+
'()',
|
94
94
|
'(foo',
|
95
95
|
'(foo 1) (bar 2)',
|
96
96
|
'some text',
|
@@ -106,9 +106,21 @@ class TestSyntax < Minitest::Test
|
|
106
106
|
')',
|
107
107
|
'"'
|
108
108
|
].each do |q|
|
109
|
-
|
110
|
-
|
111
|
-
|
109
|
+
assert(
|
110
|
+
assert_raises(q) do
|
111
|
+
Factbase::Syntax.new(q).to_term
|
112
|
+
end.message.include?(q)
|
113
|
+
)
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
def test_simplification
|
118
|
+
{
|
119
|
+
'(foo)' => '(foo)',
|
120
|
+
'(and (foo) (foo))' => '(foo)',
|
121
|
+
'(and (foo) (or (and (eq a 1))) (eq a 1) (foo))' => '(and (foo) (eq a 1))'
|
122
|
+
}.each do |s, t|
|
123
|
+
assert_equal(t, Factbase::Syntax.new(s).to_term.to_s)
|
112
124
|
end
|
113
125
|
end
|
114
126
|
end
|
data/test/factbase/test_term.rb
CHANGED
@@ -82,8 +82,13 @@ class TestTerm < Minitest::Test
|
|
82
82
|
assert(!t.evaluate(fact('bar' => [100])))
|
83
83
|
end
|
84
84
|
|
85
|
+
def test_false_matching
|
86
|
+
t = Factbase::Term.new(:never, [])
|
87
|
+
assert(!t.evaluate(fact('foo' => [100])))
|
88
|
+
end
|
89
|
+
|
85
90
|
def test_not_matching
|
86
|
-
t = Factbase::Term.new(:not, [Factbase::Term.new(:
|
91
|
+
t = Factbase::Term.new(:not, [Factbase::Term.new(:always, [])])
|
87
92
|
assert(!t.evaluate(fact('foo' => [100])))
|
88
93
|
end
|
89
94
|
|
data/test/test_factbase.rb
CHANGED
@@ -107,7 +107,7 @@ class TestFactbase < Minitest::Test
|
|
107
107
|
|
108
108
|
def test_all_decorators
|
109
109
|
[
|
110
|
-
Factbase::Rules.new(Factbase.new, '()'),
|
110
|
+
Factbase::Rules.new(Factbase.new, '(always)'),
|
111
111
|
Factbase::Inv.new(Factbase.new) { |_, _| true },
|
112
112
|
Factbase::Pre.new(Factbase.new) { |_| true },
|
113
113
|
Factbase::Looged.new(Factbase.new, Loog::NULL),
|
@@ -126,7 +126,7 @@ class TestFactbase < Minitest::Test
|
|
126
126
|
end
|
127
127
|
d.import(d.export)
|
128
128
|
assert_equal(4, d.size)
|
129
|
-
assert_equal(4, d.query('()').each.to_a.size)
|
129
|
+
assert_equal(4, d.query('(always)').each.to_a.size)
|
130
130
|
end
|
131
131
|
end
|
132
132
|
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: factbase
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.32
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Yegor Bugayenko
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2024-05-
|
11
|
+
date: 2024-05-25 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: json
|
@@ -78,6 +78,7 @@ files:
|
|
78
78
|
- ".gitattributes"
|
79
79
|
- ".github/workflows/actionlint.yml"
|
80
80
|
- ".github/workflows/codecov.yml"
|
81
|
+
- ".github/workflows/license.yml"
|
81
82
|
- ".github/workflows/markdown-lint.yml"
|
82
83
|
- ".github/workflows/pdd.yml"
|
83
84
|
- ".github/workflows/rake.yml"
|