context_spook 0.0.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: ea37f8f7f6d8653e96ccf73795be9702b4f10401c0a5ff13ae78d1ae89adabdd
4
+ data.tar.gz: 14a65612ee0e4598bd5797d9d542fee108f143452520752b4047281724bb92fb
5
+ SHA512:
6
+ metadata.gz: 8d4ca846a041fd61065d31e533cce3c56b06aaaa9eb438b9f462df8e58397d61588b1b8f734f36a9dec182444839763c8248fa375ed1df393c71fc679d613781
7
+ data.tar.gz: f9b13a0d717542832c44db2fefe328188780c9f465424631594da657478db15747df7f7a4ccd7335bad90c5d6611a77c87cbcae2264188e478997ba77eede026
data/Gemfile ADDED
@@ -0,0 +1,5 @@
1
+ # vim: set filetype=ruby et sw=2 ts=2:
2
+
3
+ source 'https://rubygems.org'
4
+
5
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,19 @@
1
+ Copyright Florian Frank
2
+
3
+ Permission is hereby granted, free of charge, to any person obtaining a copy of
4
+ this software and associated documentation files (the “Software”), to deal in
5
+ the Software without restriction, including without limitation the rights to
6
+ use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies
7
+ of the Software, and to permit persons to whom the Software is furnished to do
8
+ 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.
data/README.md ADDED
@@ -0,0 +1,155 @@
1
+ # ContextSpook
2
+
3
+ ContextSpook is a Ruby library that collects and organizes project information
4
+ to help AI assistants understand codebases better. It provides a
5
+ domain-specific language (DSL) for describing project context, which can then
6
+ be exported as structured JSON data.
7
+
8
+ The DSL is general-purpose and can be used for any kind of project or
9
+ collection of files, whether software development, documentation, research
10
+ data, educational materials, creative projects, or any other type of organized
11
+ information. The `contexts/project.rb` example below demonstrates how to
12
+ describe a Ruby project, but the same principles apply across many different
13
+ domains.
14
+
15
+ ## Installation
16
+
17
+ Add this line to your application's Gemfile:
18
+
19
+ ```ruby
20
+ gem 'context_spook'
21
+ ```
22
+
23
+ And then execute:
24
+ ```bash
25
+ $ bundle install
26
+ ```
27
+
28
+ Or install it yourself as:
29
+ ```bash
30
+ $ gem install context_spook
31
+ ```
32
+
33
+ ## Usage
34
+
35
+ Create a `contexts/project.rb` file that describes your project context using
36
+ the DSL in a context definition file:
37
+
38
+ ```ruby
39
+ # contexts/project.rb
40
+ context do
41
+ variable branch: `git rev-parse --abbrev-ref HEAD`.chomp
42
+
43
+ namespace "structure" do
44
+ command "tree lib", tags: %w[ project_structure ]
45
+ end
46
+
47
+ namespace "lib" do
48
+ Dir['lib/**/*.rb'].each do |filename|
49
+ file filename, tags: 'lib'
50
+ end
51
+ end
52
+
53
+ namespace "spec" do
54
+ Dir['spec/**/*.rb'].each do |filename|
55
+ file filename, tags: 'spec'
56
+ end
57
+ end
58
+
59
+ namespace "gems" do
60
+ file 'context_spook.gemspec'
61
+ file 'Gemfile'
62
+ file 'Gemfile.lock'
63
+ end
64
+
65
+ file 'Rakefile', tags: 'gem_hadar'
66
+
67
+ file 'README.md', tags: 'documentation'
68
+
69
+ meta ruby: RUBY_DESCRIPTION
70
+
71
+ meta code_coverage: JSON.load_file('coverage/coverage_context.json') rescue nil
72
+ end
73
+ ```
74
+
75
+ ### Programmatic Usage
76
+
77
+ Now you can generate the context from the file, and store it as JSON in Ruby.
78
+
79
+ ```ruby
80
+ context = ContextSpook::generate_context('contexts/project.rb')
81
+ File.write 'context.json', context.to_json
82
+ ```
83
+
84
+ ### CLI Usage
85
+
86
+ Generate context and save to file:
87
+
88
+ ```bash
89
+ ./bin/context_spook contexts/project.rb > context.json
90
+ ```
91
+
92
+ Or pipe directly to another tool:
93
+
94
+ ```
95
+ ./bin/context_spook contexts/project.rb | ollama_chat_send
96
+ ```
97
+
98
+ You will see two orange warning messages, that demonstrates how errors like
99
+ missing files or commands with failing exit codes are handled.
100
+
101
+ ## What Gets Collected
102
+
103
+ The DSL collects various types of project information:
104
+
105
+ - **Variables**: Key-value pairs (e.g., git branch)
106
+ - **Files**: Content, size, line count, and tags for each file
107
+ - **Commands**: Shell command outputs with exit codes and working directory
108
+ - **Metadata**: Project-wide attributes (e.g., Ruby version, coverage data)
109
+
110
+ ## Intended Use Case
111
+
112
+ The generated JSON is designed to be sent to Language Model assistants to
113
+ provide them with comprehensive context about your codebase. This helps AI
114
+ assistants understand:
115
+
116
+ - The project structure and file organization
117
+ - Key source files and their contents
118
+ - Command outputs that reveal project state
119
+ - Metadata about the development environment
120
+ - Coverage information for code quality
121
+
122
+ ## Example Output Structure
123
+
124
+ ```json
125
+ {
126
+ "files": {
127
+ "lib/context_spook.rb": {
128
+ "namespace": "lib",
129
+ "content": "...",
130
+ "size": 1234,
131
+ "lines": 56,
132
+ "tags": ["lib"]
133
+ }
134
+ },
135
+ "commands": {
136
+ "tree lib": {
137
+ "namespace": "structure",
138
+ "output": "lib\n├── context_spook\n│ └── generator.rb\n└── context_spook.rb\n\n2 directories, 3 files",
139
+ "exit_code": 0,
140
+ "working_directory": "/path/to/project"
141
+ }
142
+ },
143
+ "metadata": {
144
+ "ruby": "ruby 3.1.0 ...",
145
+ "code_coverage": { ... }
146
+ },
147
+ "variables": {
148
+ "branch": "main"
149
+ }
150
+ }
151
+ ```
152
+
153
+ ## License
154
+
155
+ The gem is available as open source under the terms of the [MIT License](./LICENSE)
data/Rakefile ADDED
@@ -0,0 +1,40 @@
1
+ # vim: set filetype=ruby et sw=2 ts=2:
2
+
3
+ require 'gem_hadar'
4
+
5
+ GemHadar do
6
+ name 'context_spook'
7
+ module_type :module
8
+ author 'Florian Frank'
9
+ email 'flori@ping.de'
10
+ homepage "https://github.com/flori/context_spook"
11
+ summary "#{name} collects project context for AI"
12
+ executables 'context_spook'
13
+
14
+ description <<~EOT
15
+ #{name} is a library that collects and organizes project
16
+ information to help AI assistants understand codebases better.
17
+ EOT
18
+
19
+ test_dir 'spec'
20
+ ignore '.*.sw[pon]', 'pkg', 'Gemfile.lock', '.AppleDouble', '.bundle',
21
+ '.yardoc', 'doc', 'tags', 'errors.lst', 'cscope.out', 'coverage', 'tmp',
22
+ 'yard'
23
+ package_ignore '.all_images.yml', '.tool-versions', '.gitignore', 'VERSION',
24
+ '.rspec', *Dir.glob('.github/**/*', File::FNM_DOTMATCH)
25
+ readme 'README.md'
26
+
27
+ required_ruby_version '~> 3.1'
28
+
29
+ dependency 'tins', '~>1.39'
30
+ dependency 'json', '~>2.0'
31
+ dependency 'term-ansicolor', '~> 1.11'
32
+ development_dependency 'all_images', '~> 0.6'
33
+ development_dependency 'rspec', '~> 3.2'
34
+ development_dependency 'debug'
35
+ development_dependency 'simplecov'
36
+
37
+ licenses << 'MIT'
38
+
39
+ clobber 'coverage'
40
+ end
data/bin/context_spook ADDED
@@ -0,0 +1,8 @@
1
+ #!/usr/bin/env ruby
2
+
3
+ require 'context_spook'
4
+
5
+ filename = ARGV.shift or fail 'require context definition file as first argument'
6
+ context_json = ContextSpook.generate_context(filename).to_json
7
+ STDERR.puts "Now outputting #{context_json.size} bytes of JSON context."
8
+ puts context_json
@@ -0,0 +1,35 @@
1
+ # -*- encoding: utf-8 -*-
2
+ # stub: context_spook 0.0.0 ruby lib
3
+
4
+ Gem::Specification.new do |s|
5
+ s.name = "context_spook".freeze
6
+ s.version = "0.0.0".freeze
7
+
8
+ s.required_rubygems_version = Gem::Requirement.new(">= 0".freeze) if s.respond_to? :required_rubygems_version=
9
+ s.require_paths = ["lib".freeze]
10
+ s.authors = ["Florian Frank".freeze]
11
+ s.date = "1980-01-02"
12
+ s.description = "context_spook is a library that collects and organizes project\ninformation to help AI assistants understand codebases better.\n".freeze
13
+ s.email = "flori@ping.de".freeze
14
+ s.executables = ["context_spook".freeze]
15
+ s.extra_rdoc_files = ["README.md".freeze, "lib/context_spook.rb".freeze, "lib/context_spook/generator.rb".freeze, "lib/context_spook/version.rb".freeze]
16
+ s.files = ["Gemfile".freeze, "LICENSE".freeze, "README.md".freeze, "Rakefile".freeze, "bin/context_spook".freeze, "context_spook.gemspec".freeze, "contexts/project.rb".freeze, "lib/context_spook.rb".freeze, "lib/context_spook/generator.rb".freeze, "lib/context_spook/version.rb".freeze, "spec/context_spook/generator_spec.rb".freeze, "spec/spec_helper.rb".freeze]
17
+ s.homepage = "https://github.com/flori/context_spook".freeze
18
+ s.licenses = ["MIT".freeze]
19
+ s.rdoc_options = ["--title".freeze, "ContextSpook - context_spook collects project context for AI".freeze, "--main".freeze, "README.md".freeze]
20
+ s.required_ruby_version = Gem::Requirement.new("~> 3.1".freeze)
21
+ s.rubygems_version = "3.6.9".freeze
22
+ s.summary = "context_spook collects project context for AI".freeze
23
+ s.test_files = ["spec/context_spook/generator_spec.rb".freeze, "spec/spec_helper.rb".freeze]
24
+
25
+ s.specification_version = 4
26
+
27
+ s.add_development_dependency(%q<gem_hadar>.freeze, ["~> 2.0".freeze])
28
+ s.add_development_dependency(%q<all_images>.freeze, ["~> 0.6".freeze])
29
+ s.add_development_dependency(%q<rspec>.freeze, ["~> 3.2".freeze])
30
+ s.add_development_dependency(%q<debug>.freeze, [">= 0".freeze])
31
+ s.add_development_dependency(%q<simplecov>.freeze, [">= 0".freeze])
32
+ s.add_runtime_dependency(%q<tins>.freeze, ["~> 1.39".freeze])
33
+ s.add_runtime_dependency(%q<json>.freeze, ["~> 2.0".freeze])
34
+ s.add_runtime_dependency(%q<term-ansicolor>.freeze, ["~> 1.11".freeze])
35
+ end
@@ -0,0 +1,37 @@
1
+ context do
2
+ variable branch: `git rev-parse --abbrev-ref HEAD`.chomp
3
+
4
+ namespace "structure" do
5
+ command "tree lib", tags: %w[ project_structure ]
6
+ end
7
+
8
+ namespace "lib" do
9
+ Dir['lib/**/*.rb'].each do |filename|
10
+ file filename, tags: 'lib'
11
+ end
12
+ end
13
+
14
+ namespace "spec" do
15
+ Dir['spec/**/*.rb'].each do |filename|
16
+ file filename, tags: 'spec'
17
+ end
18
+ end
19
+
20
+ namespace "gems" do
21
+ file 'context_spook.gemspec'
22
+ file 'Gemfile'
23
+ file 'Gemfile.lock'
24
+ end
25
+
26
+ command 'false', tags: 'failure'
27
+
28
+ file 'nixda', tags: 'failure'
29
+
30
+ file 'Rakefile', tags: [ 'gem_hadar' ]
31
+
32
+ file 'README.md', tags: [ 'documentation' ]
33
+
34
+ meta ruby: RUBY_DESCRIPTION
35
+
36
+ meta code_coverage: JSON.load_file('coverage/coverage_context.json') rescue nil
37
+ end
@@ -0,0 +1,230 @@
1
+ require 'tins/xt'
2
+ require 'term/ansicolor'
3
+ require 'json'
4
+
5
+
6
+ # The ContextSpook module serves as a namespace container for collecting and
7
+ # organizing project information for AI assistance.
8
+ module ContextSpook
9
+ include DSLKit::Interpreter
10
+
11
+ # The generate_context method processes a context definition file and returns
12
+ # the resulting context object.
13
+ #
14
+ # This method reads the content of a specified file, parses it using the
15
+ # generator's parsing mechanism, and extracts the configured context from the
16
+ # parsed result.
17
+ #
18
+ # @param filename [ String ] the path to the context definition file to be processed
19
+ #
20
+ # @return [ ContextSpook::Generator::Context ] the context object generated
21
+ # from the file contents
22
+ def self.generate_context(filename)
23
+ Generator.send(:new).send(:parse, File.read(filename)).context
24
+ end
25
+
26
+ # The Generator class provides a DSL parser that interprets context
27
+ # definition files and constructs structured context objects containing
28
+ # project metadata, file contents, command outputs, and variables for AI
29
+ # assistance.
30
+ class Generator
31
+ private_class_method :new
32
+
33
+ # The initialize method sets up the object by evaluating the provided block in the object's context.
34
+ #
35
+ # @param block [ Proc ] A block of code to be evaluated within the object's context.
36
+ # If no block is given, the method does nothing.
37
+ def initialize(&block)
38
+ block and instance_eval(&block)
39
+ end
40
+
41
+ # The context method creates or returns a context object.
42
+ #
43
+ # @param block [ Proc ] optional block to initialize the context
44
+ #
45
+ # @return [ Context ] the context object
46
+ def context(&block)
47
+ if block
48
+ @context and raise ArgumentError, "only one context allowed"
49
+ @context = Context.new(&block)
50
+ else
51
+ @context
52
+ end
53
+ end
54
+
55
+ # The Context class represents and manages project context data, providing
56
+ # structured storage for file contents, command outputs, variables, and
57
+ # metadata that can be serialized to JSON for AI assistance.
58
+ class Context
59
+ include Tins::Scope
60
+ include Tins::DSLAccessor
61
+ include Term::ANSIColor
62
+
63
+ # The initialize method sets up the object by evaluating a block in the
64
+ # object's context.
65
+ #
66
+ # @param block [ Proc ] A block to be evaluated within the object's context.
67
+ def initialize(&block)
68
+ block and instance_eval(&block)
69
+ end
70
+
71
+ # The namespace method creates a scoped block with a given name.
72
+ #
73
+ # @param name [ Object ] the name to scope the block with
74
+ #
75
+ # @yield [ block ] executes the block within the created scope
76
+ def namespace(name, &block)
77
+ name = name.to_sym
78
+ scope_block(name) do
79
+ instance_eval(&block)
80
+ end
81
+ nil
82
+ end
83
+
84
+ # The variables method sets up a DSL accessor for managing a collection of
85
+ # variables.
86
+ #
87
+ # @param default [ Hash ] the default variables to initialize with
88
+ dsl_accessor :variables do
89
+ {}
90
+ end
91
+
92
+ # The variable method assigns key-value pairs to the variables hash.
93
+ #
94
+ # @param v [ Hash ] a hash containing variable names as keys and their
95
+ # values
96
+ def variable(**v)
97
+ v.each do |name, value|
98
+ variables[name.to_sym] = value
99
+ end
100
+ nil
101
+ end
102
+
103
+ # The metadata method sets up a DSL accessor for metadata configuration.
104
+ #
105
+ # @param default [ Object ] the default value for the metadata, `{}`
106
+ dsl_accessor :metadata do
107
+ {}
108
+ end
109
+
110
+ # The meta method assigns metadata key-value pairs to the metadata hash.
111
+ #
112
+ # @param m [ Hash ] a hash of metadata key-value pairs to be added
113
+ def meta(**m)
114
+ m.each do |name, value|
115
+ metadata[name.to_sym] = value
116
+ end
117
+ nil
118
+ end
119
+
120
+ # The files method sets up a DSL accessor for providing files.
121
+ #
122
+ # @param default [ Hash ] the default files hash
123
+ dsl_accessor :files do
124
+ {}
125
+ end
126
+
127
+ # The file method associates a file with the current scope and stores its
128
+ # content.
129
+ #
130
+ # It reads the specified file and creates an entry in the files hash with
131
+ # the file's content, along with its namespace and optional tags.
132
+ #
133
+ # @param filename [ String ] the path to the file to be read and stored
134
+ # @param tags [ Array<String>, nil ] optional array of tags to associate with the file
135
+ #
136
+ # @return [ Hash ] the created file entry with content, namespace, and tags
137
+ def file(filename, tags: nil)
138
+ content = File.read(filename)
139
+ files[filename] = {
140
+ namespace: scope_top,
141
+ content:,
142
+ size: content.size,
143
+ lines: content.lines.size,
144
+ tags: (Array(tags) if tags),
145
+ }.compact
146
+ nil
147
+ rescue Errno::ENOENT => e
148
+ warn "Reading #{filename.inspect} caused #{e.class}: #{e}"
149
+ end
150
+
151
+ # The commands method sets up a DSL accessor for provided command outputs.
152
+ #
153
+ # @param value [ Hash ] the hash of commands to be set
154
+ dsl_accessor :commands, {}
155
+
156
+ # The command method executes a shell command and stores its result.
157
+ #
158
+ # This method runs a given shell command and records the output, exit code,
159
+ # working directory, and optional tags in the commands hash.
160
+ #
161
+ # @param shell_command [ String ] the shell command to execute
162
+ # @param tags [ Array<String>, nil ] optional array of tags to associate
163
+ # with the command
164
+ #
165
+ # @return [ Hash ] the stored command result including output, exit code,
166
+ # and metadata
167
+ def command(shell_command, tags: nil)
168
+ output = `#{shell_command}`
169
+ exit_code = $?&.exitstatus.to_i
170
+ if exit_code != 0
171
+ warn "Executing #{shell_command.inspect} resulted in exit code #{exit_code}."
172
+ end
173
+ commands[shell_command] = {
174
+ namespace: scope_top,
175
+ output:,
176
+ exit_code:,
177
+ working_directory: Dir.pwd,
178
+ tags: (Array(tags) if tags),
179
+ }.compact
180
+ nil
181
+ end
182
+
183
+ # The to_json method converts the object to a JSON representation by
184
+ # first generating its hash form and then serializing that hash into JSON
185
+ # format.
186
+ def to_json(*)
187
+ as_json.to_json(*)
188
+ end
189
+
190
+ # The as_json method converts the context's files, commands, and metadata
191
+ # into a hash representation.
192
+ #
193
+ # @return [ Hash ] a hash containing the files, commands, and metadata
194
+ def as_json(*)
195
+ {
196
+ files:,
197
+ commands:,
198
+ metadata:,
199
+ variables:
200
+ }
201
+ end
202
+
203
+ private
204
+
205
+ # The warn method enhances warning messages by applying colored
206
+ # formatting before passing them to the superclass implementation.
207
+ #
208
+ # @param msgs [ Array ] an array of message objects to be formatted and warned
209
+ def warn(*msgs)
210
+ msgs.map! { |m| color(208) { m } }
211
+ super(*msgs, uplevel: 1)
212
+ end
213
+ end
214
+
215
+ private
216
+
217
+ # The parse method processes the given source code by interpreting it
218
+ # within the current binding context, allowing for dynamic evaluation and
219
+ # configuration setup.
220
+ #
221
+ # @param source [ String ] the source code to be parsed and interpreted
222
+ #
223
+ # @return [ ContextSpook::Generator ] returns self to allow for method
224
+ # chaining after parsing
225
+ def parse(source)
226
+ interpret_with_binding source, binding
227
+ self
228
+ end
229
+ end
230
+ end
@@ -0,0 +1,8 @@
1
+ module ContextSpook
2
+ # ContextSpook version
3
+ VERSION = '0.0.0'
4
+ VERSION_ARRAY = VERSION.split('.').map(&:to_i) # :nodoc:
5
+ VERSION_MAJOR = VERSION_ARRAY[0] # :nodoc:
6
+ VERSION_MINOR = VERSION_ARRAY[1] # :nodoc:
7
+ VERSION_BUILD = VERSION_ARRAY[2] # :nodoc:
8
+ end
@@ -0,0 +1,4 @@
1
+ module ContextSpook
2
+ end
3
+ require 'context_spook/version'
4
+ require 'context_spook/generator'
@@ -0,0 +1,52 @@
1
+ require 'spec_helper'
2
+
3
+ describe ContextSpook::Generator do
4
+ let :context do
5
+ ContextSpook.generate_context('contexts/project.rb')
6
+ end
7
+
8
+ it 'context can be generated' do
9
+ expect(context).to be_a described_class::Context
10
+ expect(context.metadata[:ruby]).to eq RUBY_DESCRIPTION
11
+ end
12
+
13
+ it 'context be transformed to JSON if loaded' do
14
+ context_as_json = context.to_json
15
+ expect(context_as_json.size).to be > 1024
16
+ expect(JSON(context_as_json)).to be_a Hash
17
+ end
18
+
19
+ describe 'Context' do
20
+
21
+ it 'can have variables' do
22
+ expect(context.variables[:branch]).to be_present
23
+ end
24
+
25
+ it 'can have files' do
26
+ file = context.files['lib/context_spook.rb']
27
+ expect(file).to be_present
28
+ expect(file[:content]).to be_present
29
+ expect(file[:size]).to be > 0
30
+ expect(file[:lines]).to be > 0
31
+ expect(file[:namespace]).to eq :lib
32
+ expect(file[:tags]).to eq %w[ lib ]
33
+ end
34
+
35
+ it 'can have commands' do
36
+ command = context.commands['tree lib']
37
+ expect(command).to be_present
38
+ expect(command[:working_directory]).to eq Dir.pwd
39
+ expect(command[:exit_code]).to be_present
40
+ if command[:exit_code] == 0
41
+ expect(command[:output]).to be_present
42
+ else
43
+ expect(command[:output]).not_to be_present
44
+ end
45
+ expect(command[:tags]).to eq %w[ project_structure ]
46
+ end
47
+
48
+ it 'can have metada' do
49
+ expect(context.metadata[:ruby]).to eq RUBY_DESCRIPTION
50
+ end
51
+ end
52
+ end
@@ -0,0 +1,19 @@
1
+ require 'gem_hadar/simplecov'
2
+ GemHadar::SimpleCov.start
3
+ require 'rspec'
4
+ require 'tins/xt/expose'
5
+ begin
6
+ require 'debug'
7
+ rescue LoadError
8
+ end
9
+ require 'context_spook'
10
+
11
+ # The asset method constructs a file path by joining the directory of the
12
+ # current file, an 'assets' subdirectory, and the provided filename.
13
+ #
14
+ # @param name [ String ] the name of the asset file to be located
15
+ #
16
+ # @return [ String ] the complete file path to the asset
17
+ def asset(name)
18
+ File.join(__dir__, 'assets', name)
19
+ end
metadata ADDED
@@ -0,0 +1,176 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: context_spook
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Florian Frank
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: gem_hadar
14
+ requirement: !ruby/object:Gem::Requirement
15
+ requirements:
16
+ - - "~>"
17
+ - !ruby/object:Gem::Version
18
+ version: '2.0'
19
+ type: :development
20
+ prerelease: false
21
+ version_requirements: !ruby/object:Gem::Requirement
22
+ requirements:
23
+ - - "~>"
24
+ - !ruby/object:Gem::Version
25
+ version: '2.0'
26
+ - !ruby/object:Gem::Dependency
27
+ name: all_images
28
+ requirement: !ruby/object:Gem::Requirement
29
+ requirements:
30
+ - - "~>"
31
+ - !ruby/object:Gem::Version
32
+ version: '0.6'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: !ruby/object:Gem::Requirement
36
+ requirements:
37
+ - - "~>"
38
+ - !ruby/object:Gem::Version
39
+ version: '0.6'
40
+ - !ruby/object:Gem::Dependency
41
+ name: rspec
42
+ requirement: !ruby/object:Gem::Requirement
43
+ requirements:
44
+ - - "~>"
45
+ - !ruby/object:Gem::Version
46
+ version: '3.2'
47
+ type: :development
48
+ prerelease: false
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "~>"
52
+ - !ruby/object:Gem::Version
53
+ version: '3.2'
54
+ - !ruby/object:Gem::Dependency
55
+ name: debug
56
+ requirement: !ruby/object:Gem::Requirement
57
+ requirements:
58
+ - - ">="
59
+ - !ruby/object:Gem::Version
60
+ version: '0'
61
+ type: :development
62
+ prerelease: false
63
+ version_requirements: !ruby/object:Gem::Requirement
64
+ requirements:
65
+ - - ">="
66
+ - !ruby/object:Gem::Version
67
+ version: '0'
68
+ - !ruby/object:Gem::Dependency
69
+ name: simplecov
70
+ requirement: !ruby/object:Gem::Requirement
71
+ requirements:
72
+ - - ">="
73
+ - !ruby/object:Gem::Version
74
+ version: '0'
75
+ type: :development
76
+ prerelease: false
77
+ version_requirements: !ruby/object:Gem::Requirement
78
+ requirements:
79
+ - - ">="
80
+ - !ruby/object:Gem::Version
81
+ version: '0'
82
+ - !ruby/object:Gem::Dependency
83
+ name: tins
84
+ requirement: !ruby/object:Gem::Requirement
85
+ requirements:
86
+ - - "~>"
87
+ - !ruby/object:Gem::Version
88
+ version: '1.39'
89
+ type: :runtime
90
+ prerelease: false
91
+ version_requirements: !ruby/object:Gem::Requirement
92
+ requirements:
93
+ - - "~>"
94
+ - !ruby/object:Gem::Version
95
+ version: '1.39'
96
+ - !ruby/object:Gem::Dependency
97
+ name: json
98
+ requirement: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - "~>"
101
+ - !ruby/object:Gem::Version
102
+ version: '2.0'
103
+ type: :runtime
104
+ prerelease: false
105
+ version_requirements: !ruby/object:Gem::Requirement
106
+ requirements:
107
+ - - "~>"
108
+ - !ruby/object:Gem::Version
109
+ version: '2.0'
110
+ - !ruby/object:Gem::Dependency
111
+ name: term-ansicolor
112
+ requirement: !ruby/object:Gem::Requirement
113
+ requirements:
114
+ - - "~>"
115
+ - !ruby/object:Gem::Version
116
+ version: '1.11'
117
+ type: :runtime
118
+ prerelease: false
119
+ version_requirements: !ruby/object:Gem::Requirement
120
+ requirements:
121
+ - - "~>"
122
+ - !ruby/object:Gem::Version
123
+ version: '1.11'
124
+ description: |
125
+ context_spook is a library that collects and organizes project
126
+ information to help AI assistants understand codebases better.
127
+ email: flori@ping.de
128
+ executables:
129
+ - context_spook
130
+ extensions: []
131
+ extra_rdoc_files:
132
+ - README.md
133
+ - lib/context_spook.rb
134
+ - lib/context_spook/generator.rb
135
+ - lib/context_spook/version.rb
136
+ files:
137
+ - Gemfile
138
+ - LICENSE
139
+ - README.md
140
+ - Rakefile
141
+ - bin/context_spook
142
+ - context_spook.gemspec
143
+ - contexts/project.rb
144
+ - lib/context_spook.rb
145
+ - lib/context_spook/generator.rb
146
+ - lib/context_spook/version.rb
147
+ - spec/context_spook/generator_spec.rb
148
+ - spec/spec_helper.rb
149
+ homepage: https://github.com/flori/context_spook
150
+ licenses:
151
+ - MIT
152
+ metadata: {}
153
+ rdoc_options:
154
+ - "--title"
155
+ - ContextSpook - context_spook collects project context for AI
156
+ - "--main"
157
+ - README.md
158
+ require_paths:
159
+ - lib
160
+ required_ruby_version: !ruby/object:Gem::Requirement
161
+ requirements:
162
+ - - "~>"
163
+ - !ruby/object:Gem::Version
164
+ version: '3.1'
165
+ required_rubygems_version: !ruby/object:Gem::Requirement
166
+ requirements:
167
+ - - ">="
168
+ - !ruby/object:Gem::Version
169
+ version: '0'
170
+ requirements: []
171
+ rubygems_version: 3.6.9
172
+ specification_version: 4
173
+ summary: context_spook collects project context for AI
174
+ test_files:
175
+ - spec/context_spook/generator_spec.rb
176
+ - spec/spec_helper.rb