AGENTS.md - Development Guide
๐ฏ Project Overview
This project is a RubyGem managed with the kettle-rb toolchain.
Minimum Supported Ruby: See the gemspec required_ruby_version constraint.
Local Development Ruby: See mise.toml for the version used in local development (typically the latest stable Ruby).
Modular Gemfile Architecture
Gemfiles are split into modular components under gemfiles/modular/. Each component handles a specific concern (coverage, style, debug, etc.). The main Gemfile loads these modular components via eval_gemfile.
Gemfiles in the project, including modular ones, can utilize a *_local.gemfile counterpart pattern enabled via an ENV flag. This uses nomono to load sibling gems in the same workspace.
โ ๏ธ AI Agent Terminal Limitations
Use mise for Project Environment
CRITICAL: The canonical project environment lives in mise.toml, with local overrides in .env.local loaded via dotenvy.
โ ๏ธ Watch for trust prompts: After editing mise.toml or .env.local, mise may require trust to be refreshed before commands can load the project environment. Until that trust step is handled, commands can appear hung or produce no output, which can look like terminal access is broken.
Recovery rule: If a mise exec command goes silent or appears hung, assume mise trust is the first thing to check. Recover by running:
mise trust -C /path/to/project
mise exec -C /path/to/project -- bundle exec kettle-test
Do this before spending time on unrelated debugging; in this workspace pattern, silent mise commands are usually a trust problem first.
โ
CORRECT โ Run self-contained commands with mise exec:
mise exec -C /path/to/project -- bundle exec kettle-test
โ CORRECT โ If you need shell syntax first, load the environment in the same command:
eval "$(mise env -C /path/to/project -s bash)" && bundle exec kettle-test
โ WRONG โ Do not rely on a previous command changing directories:
cd /path/to/project
bundle exec rspec
โ WRONG โ A chained cd does not give directory-change hooks time to update the environment:
cd /path/to/project && bundle exec rspec
Prefer Internal Tools Over Terminal
โ PREFERRED โ Use internal tools:
-
grep_searchinstead ofgrepcommand -
file_searchinstead offindcommand -
read_fileinstead ofcatcommand -
list_dirinstead oflscommand -
replace_string_in_fileorcreate_fileinstead ofsed/ manual editing
โ AVOID when possible:
-
run_in_terminalfor information gathering
Only use terminal for:
- Running tests (
bundle exec kettle-test) - Installing dependencies (
bundle install) - Simple commands that do not require much shell escaping
- Running scripts (prefer writing a script over a complicated command with shell escaping)
When you do run tests, keep the full output visible so you can inspect failures completely.
๐๏ธ Architecture
Toolchain Dependencies
This gem is part of the kettle-rb ecosystem. Key development tools:
| Tool | Purpose |
|---|---|
kettle-dev |
Development dependency: Rake tasks, release tooling, CI helpers |
kettle-test |
Test infrastructure: RSpec helpers, stubbed_env, timecop |
kettle-jem |
Template management and gem scaffolding |
Executables (from kettle-dev)
| Executable | Purpose |
|---|---|
kettle-release |
Full gem release workflow |
kettle-pre-release |
Pre-release validation |
kettle-changelog |
Changelog generation |
kettle-dvcs |
DVCS (git) workflow automation |
kettle-commit-msg |
Commit message validation |
kettle-check-eof |
EOF newline validation |
๐ Project Structure
lib/
โโโ <gem_namespace>/ # Main library code
โ โโโ version.rb # Version constant (managed by kettle-release)
spec/
โโโ fixtures/ # Test fixture files (NOT auto-loaded)
โโโ support/
โ โโโ classes/ # Helper classes for specs
โ โโโ shared_contexts/ # Shared RSpec contexts
โโโ spec_helper.rb # RSpec configuration (loaded by .rspec)
gemfiles/
โโโ modular/ # Modular Gemfile components
โ โโโ coverage.gemfile # SimpleCov dependencies
โ โโโ debug.gemfile # Debugging tools
โ โโโ documentation.gemfile # YARD/documentation
โ โโโ optional.gemfile # Optional dependencies
โ โโโ rspec.gemfile # RSpec testing
โ โโโ style.gemfile # RuboCop/linting
โ โโโ x_std_libs.gemfile # Extracted stdlib gems
โโโ ruby_*.gemfile # Per-Ruby-version Appraisal Gemfiles
โโโ Appraisal.root.gemfile # Root Gemfile for Appraisal builds
.git-hooks/
โโโ commit-msg # Commit message validation hook
โโโ prepare-commit-msg # Commit message preparation
โโโ commit-subjects-goalie.txt # Commit subject prefix filters
โโโ footer-template.erb.txt # Commit footer ERB template
๐ง Development Workflows
Running Commands
Always make commands self-contained. Use mise exec -C /home/pboling/src/kettle-rb/prism-merge -- ... so the command gets the project environment in the same invocation.
If the command is complicated write a script in local tmp/ and then run the script.
Running Tests
Always run specs via kettle-test (provided by kettle-test). It runs bundle exec rspec,
captures all output to tmp/kettle-test/rspec-TIMESTAMP.log, and prints a structured highlight block:
timing, seed, pass/fail count, failing examples, and SimpleCov coverage percentages.
Full suite:
mise exec -C /path/to/project -- bundle exec kettle-test
For single file, targeted, or partial spec runs the coverage threshold must be disabled.
Use the K_SOUP_COV_MIN_HARD=false environment variable to disable hard failure:
mise exec -C /path/to/project -- env K_SOUP_COV_MIN_HARD=false bundle exec kettle-test spec/path/to/spec.rb
Template Management (kettle-jem)
Run the kettle-jem templater to sync project files with the latest template:
# Standard run (quiet, non-interactive โ the default)
mise exec -C /path/to/project -- bundle exec rake kettle:jem:install
# Verbose output (see per-file detail)
mise exec -C /path/to/project -- env KETTLE_JEM_VERBOSE=true bundle exec rake kettle:jem:install
# Interactive mode (prompt before each change)
mise exec -C /path/to/project -- bundle exec rake kettle:jem:install force=false
Current defaults (no flags needed):
-
quiet=true โ only phase summary lines shown; use
--verboseorKETTLE_JEM_VERBOSE=trueto opt out -
force=true โ non-interactive; use
--interactiveorforce=falseto opt out -
allowed=true โ env file changes auto-accepted; set
allowed=falseto require review
Building & Installing Locally
To test local code changes across sibling repos, rebuild and reinstall the gem:
cd /path/to/gem && rm -rf *.gem && SKIP_GEM_SIGNING=true gem build *.gemspec && gem install --force *.gem
-
SKIP_GEM_SIGNING=truebypasses the PEM passphrase prompt for signed gemspecs. -
--forceoverwrites the currently installed version. - Always rebuild and reinstall before verifying cross-repo behaviour.
Coverage Reports
mise exec -C /path/to/project -- bin/rake coverage
mise exec -C /path/to/project -- bin/kettle-soup-cover -d
Key ENV variables (set in mise.toml, with local overrides in .env.local):
-
K_SOUP_COV_DO=trueโ Enable coverage -
K_SOUP_COV_MIN_LINEโ Line coverage threshold -
K_SOUP_COV_MIN_BRANCHโ Branch coverage threshold -
K_SOUP_COV_MIN_HARD=trueโ Fail if thresholds not met
Code Quality
mise exec -C /path/to/project -- bundle exec rake reek
mise exec -C /path/to/project -- bundle exec rubocop-gradual
Releasing
bin/kettle-pre-release # Validate everything before release
bin/kettle-release # Full release workflow
๐ Project Conventions
Freeze Block Preservation
Template updates preserve custom code wrapped in freeze blocks:
# kettle-jem:freeze
# ... custom code preserved across template runs ...
# kettle-jem:unfreeze
Modular Gemfile Architecture
Gemfiles are split into modular components under gemfiles/modular/. Each component handles a specific concern (coverage, style, debug, etc.). The main Gemfile loads these modular components via eval_gemfile.
Forward Compatibility with **options
CRITICAL: All constructors and public API methods that accept keyword arguments MUST include **options as the final parameter for forward compatibility.
๐งช Testing Patterns
Test Infrastructure
- Uses
kettle-testfor RSpec helpers (stubbed_env, block_is_expected, silent_stream, timecop) - Uses
Dir.mktmpdirfor isolated filesystem tests - Spec helper is loaded by
.rspecโ never addrequire "spec_helper"to spec files
Environment Variable Helpers
before do
stub_env("MY_ENV_VAR" => "value")
end
before do
hide_env("HOME", "USER")
end
Dependency Tags
Use dependency tags to conditionally skip tests when optional dependencies are not available:
RSpec.describe SomeClass, :prism_merge do
# Skipped if prism-merge is not available
end
๐ซ Common Pitfalls
-
NEVER pipe test output through
head/tailโ Run tests without truncation so you can inspect the full output. -
README.md is mostly auto-generated by kettle-jem โ Only the following sections may be edited by hand or by agents:
## ๐ป Synopsis## โ๏ธ Configuration## ๐ง Basic Usage
All other sections (badges, installation, FLOSS funding, security, contributing, versioning, license, etc.) are managed by the kettle-jem template and will be overwritten on the next templating run. Do not edit them.