Gumroad Prod Console
antiwork/gumroad
Execute read-only Ruby/Rails commands against Gumroad's production database for debugging and investigation.
Expand Rigor's core/stdlib folding coverage for a named class, module, or method family.
$ npx skills add rigortype/rigor --skill rigor-type-coverage-uplift -a claude-codeProject install by default; add -g for ~/.claude/skills/.
$ gh skill install rigortype/rigor rigor-type-coverage-uplift --agent claude-codeProject scope by default; add --scope user for a personal install. Needs GitHub CLI 2.90.0 or later (public preview).
$ git clone --depth 1 https://github.com/rigortype/rigor.git skills-src && mkdir -p .claude/skills && cp -r skills-src/.claude/skills/rigor-type-coverage-uplift .claude/skills/rigor-type-coverage-uplift && rm -rf skills-srcUse ~/.claude/skills/ instead of .claude/skills for a personal install. The folder must contain SKILL.md.
Claude Code skills documentation · loads skills from .claude/skills/
Install the "rigor-type-coverage-uplift" agent skill from https://github.com/rigortype/rigor/tree/master/.claude/skills/rigor-type-coverage-uplift into .claude/skills/rigor-type-coverage-uplift/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "rigor-type-coverage-uplift", then confirm the skill loads.Claude Code copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$skill-installer install https://github.com/rigortype/rigor/tree/master/.claude/skills/rigor-type-coverage-upliftType this inside Codex. $skill-installer <name> installs a curated skill from openai/skills. The installer writes to $CODEX_HOME/skills (default ~/.codex/skills). Restart Codex if the skill does not show up.
$ npx skills add rigortype/rigor --skill rigor-type-coverage-uplift -a codexProject install goes to .agents/skills/; add -g for ~/.codex/skills/.
$ gh skill install rigortype/rigor rigor-type-coverage-uplift --agent codexProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/rigortype/rigor.git skills-src && mkdir -p .agents/skills && cp -r skills-src/.claude/skills/rigor-type-coverage-uplift .agents/skills/rigor-type-coverage-uplift && rm -rf skills-srcUse ~/.agents/skills/ instead of .agents/skills for a personal install.
Codex skills documentation · loads skills from .agents/skills/
Install the "rigor-type-coverage-uplift" agent skill from https://github.com/rigortype/rigor/tree/master/.claude/skills/rigor-type-coverage-uplift into .agents/skills/rigor-type-coverage-uplift/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "rigor-type-coverage-uplift", then confirm the skill loads.Codex copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add rigortype/rigor --skill rigor-type-coverage-uplift -a cursorProject install goes to .agents/skills/; add -g for ~/.cursor/skills/.
$ gh skill install rigortype/rigor rigor-type-coverage-uplift --agent cursorProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/rigortype/rigor.git skills-src && mkdir -p .cursor/skills && cp -r skills-src/.claude/skills/rigor-type-coverage-uplift .cursor/skills/rigor-type-coverage-uplift && rm -rf skills-srcUse ~/.cursor/skills/ instead of .cursor/skills for a personal install.
Cursor skills documentation · loads skills from .cursor/skills/, .agents/skills/, .claude/skills/, .codex/skills/
Install the "rigor-type-coverage-uplift" agent skill from https://github.com/rigortype/rigor/tree/master/.claude/skills/rigor-type-coverage-uplift into .cursor/skills/rigor-type-coverage-uplift/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "rigor-type-coverage-uplift", then confirm the skill loads.Cursor copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gemini skills install https://github.com/rigortype/rigor.git --path .claude/skills/rigor-type-coverage-uplift--scope user (default) or --scope workspace; --path is the subfolder of the repo that holds the skill; --consent skips the security confirmation prompt.
$ npx skills add rigortype/rigor --skill rigor-type-coverage-uplift -a gemini-cliProject install goes to .agents/skills/; add -g for ~/.gemini/skills/.
$ gh skill install rigortype/rigor rigor-type-coverage-uplift --agent gemini-cliProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/rigortype/rigor.git skills-src && mkdir -p .gemini/skills && cp -r skills-src/.claude/skills/rigor-type-coverage-uplift .gemini/skills/rigor-type-coverage-uplift && rm -rf skills-srcUse ~/.gemini/skills/ instead of .gemini/skills for a personal install, then run /skills reload.
Gemini CLI skills documentation · loads skills from .gemini/skills/, .agents/skills/
Install the "rigor-type-coverage-uplift" agent skill from https://github.com/rigortype/rigor/tree/master/.claude/skills/rigor-type-coverage-uplift into .gemini/skills/rigor-type-coverage-uplift/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "rigor-type-coverage-uplift", then confirm the skill loads.Gemini CLI copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ gh skill install rigortype/rigor rigor-type-coverage-upliftInstalls for Copilot at project scope by default; add --scope user for a personal install. Preview a skill first with gh skill preview. Needs GitHub CLI 2.90.0 or later (public preview).
$ npx skills add rigortype/rigor --skill rigor-type-coverage-uplift -a github-copilotProject install goes to .agents/skills/; add -g for ~/.copilot/skills/.
$ git clone --depth 1 https://github.com/rigortype/rigor.git skills-src && mkdir -p .github/skills && cp -r skills-src/.claude/skills/rigor-type-coverage-uplift .github/skills/rigor-type-coverage-uplift && rm -rf skills-srcUse ~/.copilot/skills/ instead of .github/skills for a personal install. Commit .github/skills so cloud agent and code review can use it.
GitHub Copilot skills documentation · loads skills from .github/skills/, .claude/skills/, .agents/skills/
Install the "rigor-type-coverage-uplift" agent skill from https://github.com/rigortype/rigor/tree/master/.claude/skills/rigor-type-coverage-uplift into .github/skills/rigor-type-coverage-uplift/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "rigor-type-coverage-uplift", then confirm the skill loads.GitHub Copilot copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
$ npx skills add rigortype/rigor --skill rigor-type-coverage-uplift -a opencodeOpenCode documents no install command of its own. Project install goes to .agents/skills/; add -g for ~/.config/opencode/skills/.
$ gh skill install rigortype/rigor rigor-type-coverage-uplift --agent opencodeProject scope by default (.agents/skills/); add --scope user for a personal install.
$ git clone --depth 1 https://github.com/rigortype/rigor.git skills-src && mkdir -p .opencode/skills && cp -r skills-src/.claude/skills/rigor-type-coverage-uplift .opencode/skills/rigor-type-coverage-uplift && rm -rf skills-srcUse ~/.config/opencode/skills/ instead of .opencode/skills for a personal install.
OpenCode skills documentation · loads skills from .opencode/skills/, .claude/skills/, .agents/skills/
Install the "rigor-type-coverage-uplift" agent skill from https://github.com/rigortype/rigor/tree/master/.claude/skills/rigor-type-coverage-uplift into .opencode/skills/rigor-type-coverage-uplift/ in this project. Copy the whole folder (SKILL.md and every file beside it), keep the folder name "rigor-type-coverage-uplift", then confirm the skill loads.OpenCode copies the folder itself, the same result as the manual copy. Check what it changed before you commit it.
rigor-type-coverage-upliftExpand Rigor's core/stdlib folding coverage for a named class, module, or method family.
Rigor Type Coverage Uplift is an agent skill from rigortype/rigor. Expand Rigor's core/stdlib folding coverage for a named class, module, or method family. Use when implementing or auditing ConstantFolding, ShapeDispatch, or singleton-folding support; not for ordinary type inference or user-project annotations.
Its SKILL.md is about 5.6k tokens, which your agent loads only when the skill is triggered. It is a single SKILL.md file with no bundled scripts.
It sits in Development. It works with Ruby. The repository describes itself as: Inference-first static analysis for Ruby. The licence is MPL-2.0.
3 steps, taken from the step headings in SKILL.md.
Read from SKILL.md and the folder at commit 57a67cf. It shows what the files ask for, not the result of running them.
Pre-approves nothing: there is no allowed-tools line, so your agent's usual permission prompts apply.
From allowed-tools in the SKILL.md frontmatter.
Shell commands in SKILL.md call:
nixbundlemakerubyFrom the folder's file list and the shell code blocks in SKILL.md.
No URLs in SKILL.md.
From URLs in SKILL.md, links to its own repository left out.
Names no API keys, tokens, secrets or passwords.
From names ending in _API_KEY, _TOKEN, _SECRET, _KEY or _PASSWORD in SKILL.md.
Rigor Type Coverage Uplift loads about 5.6k tokens when it runs. Until then it costs about 69 tokens; SKILL.md has 2,000 words of instructions outside code blocks.
Estimates: characters ÷ 4, the usual rule of thumb; real counts depend on the model's tokenizer. Scripts and assets cost tokens only if the agent reads them.
The automated check found no risky patterns in SKILL.md.
Automated static check — not a guarantee. Review scripts before installing. It scans the text of SKILL.md for risky patterns (piping downloads into a shell, reading credential files, hidden Unicode, destructive commands); files beside SKILL.md are not scanned.
The full file from rigortype/rigor at commit 57a67cf, republished under its MPL-2.0 licence (© rigortype). 2,000 words, ~5,551 tokens.
.claude/skills/rigor-type-coverage-uplift/SKILL.md (or your agent's skills folder).A contributor workflow for systematically discovering, prioritising, and implementing precision improvements across Rigor's method-dispatch pipeline. The flow has three phases:
Rigor's method-dispatch pipeline resolves receiver.method(args) through ordered tiers. For a
given call site, the first tier that returns a non-nil type wins. The order is defined by
dispatch_precise_tiers in lib/rigor/inference/method_dispatcher.rb; read it before relying on
this summary:
DataFolding / StructFolding — Data / Struct value objects
meta-introspection — `Singleton[*].new` and other class-object lifts
ConstantFolding — scalar constant receivers (String, Integer, Float, bool, nil, Regexp, Symbol)
LiteralStringFolding — mutable literal-string concatenation
ShapeDispatch — structural types (Tuple, HashShape, Difference, Size-carrying Nominals)
STDLIB_SINGLETON_FOLDERS — one folder per stdlib singleton receiver (File, Shellwords, Math, …)
Kernel intrinsics — Kernel / Object methods (puts, pp, raise, …)
MethodFolding, ReduceFolding, ArrayToHFolding, BlockFolding
RbsDispatch — RBS envelope (fallback, always non-nil)A "coverage gap" is any method where the RBS fallback gives a wide type (String, Integer,
Array[T], …) when a precise Constant[T] or Tuple or Refined type could be returned
because all the relevant arguments are statically known.
The underlying design documents:
docs/adr/3-type-representation.mddocs/type-specification/imported-built-in-types.mddocs/adr/5-robustness-principle.mdUse Ruby's reflection API to get only the methods that belong to a specific class or module, stripping inherited noise:
# Instance methods of a class
"".methods - Object.new.methods # String-specific
0.methods - Object.new.methods # Integer-specific (Numeric + Integer)
0.0.methods - Object.new.methods # Float-specific
true.methods - Object.new.methods # TrueClass
[].methods - Object.new.methods # Array
{}.methods - Object.new.methods # Hash
require "set"; Set.new.methods - Object.new.methods # Set
# Class / module functions (singleton methods)
Math.methods - Module.methods # Math module functions
Shellwords.methods - Module.methods # Shellwords
CGI.methods - Module.methods # CGI
URI.methods - Module.methods # URI
Regexp.methods - Class.methods # Regexp class methodsRun this inside nix develop --command bundle exec ruby -e '…' so the environment
matches the project's Ruby 4.0.5.
For instance methods on scalar types, inspect:
lib/rigor/inference/method_dispatcher/constant_folding.rb
— STRING_UNARY, STRING_BINARY, INTEGER_UNARY, FLOAT_UNARY, BOOL_UNARY, BOOL_BINARY,
NUMERIC_BINARY, plus the named handlers try_fold_string_format,
try_fold_string_array_unary / _binary, invoke_unary, invoke_binary.For structural types (Tuple, HashShape, Size-carrying Nominals), inspect:
lib/rigor/inference/method_dispatcher/shape_dispatch.rb
— TUPLE_HANDLERS, HASH_SHAPE_HANDLERS, SIZE_RETURNING_NOMINALS, dispatch_difference.For stdlib module functions, look for a dedicated *_folding.rb sibling registered in
STDLIB_SINGLETON_FOLDERS (e.g. file_folding.rb for Singleton["File"],
shellwords_folding.rb for Singleton["Shellwords"]).
For block-based methods, inspect:
lib/rigor/inference/method_dispatcher/block_folding.rbUse the four-symbol legend:
| Symbol | Meaning |
|---|---|
| ✅ | Already implemented — ConstantFolding, ShapeDispatch, BlockFolding, or another tier. |
| 🔷 | Another tier is sufficient — e.g. LiteralStringFolding for <</concat, RBS for a wide but correct return. |
| 🔲 | Gap — a Constant[T] / Tuple / Refined result is achievable and would increase precision. |
| 🚫 | Out of scope — mutating methods, Enumerator-returning stubs, platform-dependent, or non-deterministic. |
Write docs/notes/<YYYYMMDD>-<type>-method-coverage.md (or a multi-type file if the scope is
broad). Follow the format of:
docs/notes/20260522-hash-method-coverage.md
— 101 Hash methods, per-method status, per-method note.docs/notes/20260522-type-method-coverage.md
— String / Integer / Float / bool / Array / Tuple / Set.Minimum required sections per type:
"".methods - Object.new.methods, version stamp).| method | status | note |.For stdlib module functions, split into two separate files:
Deterministic (Math, Shellwords, Regexp.escape, CGI escape/unescape, URI
encode/decode) → …-stdlib-deterministic-module-coverage.md
See: docs/notes/20260522-stdlib-deterministic-module-coverage.md
Non-deterministic / out-of-scope (SecureRandom, Random, FileUtils, Marshal, GC,
Base64, Digest) → …-stdlib-nondeterministic-module-coverage.md
See: docs/notes/20260522-stdlib-nondeterministic-module-coverage.md
The split matters: the deterministic doc becomes the implementation backlog; the non-deterministic doc records the exclusion rationale so the question is never re-litigated.
Intermediate reports as parallelisation artifacts. The coverage doc is not mandatory for simple single-method additions, but it is invaluable when the scope spans 20+ methods or involves multiple implementation tiers. A complete coverage doc lets two agents work independently: one handles Tier A (UNARY/BINARY set additions), another handles Tier B (new module-function folding). Producing the doc as a first commit before any implementation is the recommended approach.
Once the coverage doc exists, walk the 🔲 entries and assign each to exactly one of four tiers. This is the decision-heavy step; the implementation itself is largely mechanical once the tier is chosen.
Use when: the method takes a scalar receiver (Constant[String], Constant[Integer], etc.)
with zero or one additional scalar argument, and invoke_unary / invoke_binary can evaluate
it by simply calling the method on the unwrapped Ruby value.
invoke_unary calls value.public_send(method_name) and wraps the result in Constant[T].
invoke_binary calls value.public_send(method_name, other_value).
Required conditions:
Object).!-suffix, no in-place change).String, Integer, Float, TrueClass, FalseClass,
NilClass) so it wraps cleanly in Constant[T].invoke_unary / invoke_binary — that is acceptable for static
errors like division-by-zero on literal 0).To add a method:
constant_folding.rb:
STRING_UNARY, STRING_BINARY, INTEGER_UNARY, FLOAT_UNARY, BOOL_UNARY, BOOL_BINARY,
or NUMERIC_BINARY.invoke_unary / invoke_binary pick up the new entry
automatically.Example — String#chop (Tier A):
STRING_UNARY = Set[
:capitalize, :chomp, :chop, # ← add :chop here
…
].freezeNUMERIC_BINARY is shared by Integer and Float: adding a Symbol there makes it available to
both. Integer-only operations (&, |, ^, <<, >>) can be added to NUMERIC_BINARY
safely — if a Float receiver calls them, invoke_binary rescues the NoMethodError and returns
nil, falling through to the RBS tier. No separate Integer-only binary set is needed.
Use when: the receiver is a structural type (Tuple, HashShape, or a Difference like
non-empty-string) and the precise result depends on the shape, not just the scalar value.
To add a method:
method_name: :handler_method_name entry to TUPLE_HANDLERS or HASH_SHAPE_HANDLERS
in shape_dispatch.rb.(receiver_type, args) and returns the precise
type or nil.Example — Tuple#last (Tier B):
TUPLE_HANDLERS = {
…
:last => :tuple_last,
}.freeze
def tuple_last(tuple, _method_name, args)
return nil if args.size > 1
tuple.elements.last # Constant[T] element type
endHandler signature: every handler receives
(receiver, method_name, args)— three positional parameters. The dispatch call issend(handler, receiver, method_name, args)(seedispatch_tuple/dispatch_hash_shape). A handler written asdef h(tuple, args)silently receivesmethod_nameinargsandargsis bound tonil, causing mysterious nil-related bugs. Use_method_nameif you do not need it.
Use when: the method takes a block and the precise return type depends on evaluating the
block's body over element types (e.g. Array#map, Array#select, Hash#transform_values).
These are already handled by BlockFolding and the ExpressionTyper block-evaluation path.
New block methods fit here by registering in block_folding.rb. This tier is complex; reach for
it only when the block return type is genuinely needed for a downstream narrowing.
Use when: the receiver is a module or class constant (e.g. Math, CGI, Regexp) called
as a singleton, and the folding logic cannot be expressed as a simple UNARY/BINARY set entry.
Receiver identification: at dispatch time, Math in Math.sqrt(4.0) resolves to a
Type::Singleton object. Guard with:
SingletonFolding.receiver?(receiver, "Math")Pattern to follow: ShellwordsFolding is the canonical reference
(lib/rigor/inference/method_dispatcher/shellwords_folding.rb). Structure:
module MathFolding
MATH_UNARY_METHODS = Set[:sqrt, :exp, :log, :log2, :log10, :sin, :cos, :tan, …].freeze
MATH_BINARY_METHODS = Set[:atan2, :hypot, :ldexp, :log, …].freeze
module_function
def try_dispatch(context)
method_name = context.method_name
return nil unless SingletonFolding.receiver?(context.receiver, "Math")
return nil unless MATH_UNARY_METHODS.include?(method_name) ||
MATH_BINARY_METHODS.include?(method_name)
fold_math(method_name, context.args)
end
def fold_math(method_name, args)
# validate arg count and types, then:
# Math.public_send(method_name, *unwrapped_args)
# wrap result in Constant[T] or Tuple
end
endTo wire a new Tier D module:
lib/rigor/inference/method_dispatcher/<name>_folding.rb exposing try_dispatch(context).require_relative "method_dispatcher/<name>_folding" in method_dispatcher.rb.STDLIB_SINGLETON_FOLDERS as "<ClassName>" => <Name>Folding. The table is
consulted only for Singleton receivers, so no ordering decision is needed.The test harness selects the RBS environment based on fixture layout:
spec/integration/fixtures/<name>.rb → Environment.default (RBS core only; no
stdlib libraries). Shellwords, Math, CGI, URI, Digest, etc. are not in RBS core and will
not be found.spec/integration/fixtures/<name>/demo.rb → Environment.for_project (loads
DEFAULT_LIBRARIES, which includes shellwords, uri, json, digest, and others).Rule: any fixture that exercises a stdlib module not in RBS core MUST be a directory fixture.
Using a flat fixture causes all type lookups to return Dynamic[top], making every test pass
vacuously.
DEFAULT_LIBRARIES includes (as of Ruby 4.0.5):
shellwords, benchmark, base64, did_you_mean, pathname, json, yaml, fileutils,
uri, digest, securerandom, logger, tempfile, tmpdir, open-uri, …
assert_type(expected_string, expr) calls expr_type.describe(:short) which calls
value.inspect on Constant values. inspect doubles backslashes.
describe(:short) returns only value.inspect — the bare "..." form with no wrapper.
%(Constant["hello.world"]) as the first argument to assert_type is always wrong; it checks
against Constant["hello.world"] (a string that starts with the letter C) which will never
match describe(:short).
When an expected string contains backslashes, use single-quoted literals and count carefully:
assert_type argument | String it checks against |
|---|---|
'"hello\\\\ world"' | "hello\\ world" (two chars: \ + ) |
'"hello\\ world"' | "hello\ world" (one char: \ ) — wrong |
Rule of thumb: to assert a string whose inspect has N visible backslashes, write 2N backslashes
inside a single-quoted Ruby string literal as the first argument to assert_type.
Regexp results require extra attention because the chain has three steps:
Regexp.escape introduces one backslash per escaped meta-character → inspect doubles each →
the single-quoted source must double again:
Regexp.escape("a.b") # value: "a\.b" — 1 backslash
# describe(:short) = "a\\.b" — 2 backslashes (inspect doubled)
assert_type('"a\\\\.b"', …) # ✓ 4 source backslashes → 2 actual → matches
assert_type('"a\\.b"', …) # ✗ 2 source backslashes → 1 actual → mismatchFor a value with multiple escaped characters (Regexp.escape("[a-z]") has three backslashes):
assert_type('"\\\\[a\\\\-z\\\\]"', Regexp.escape("[a-z]")) # ✓ 4 per group = 12 totalWhen in doubt, read the got: field from an assert_type mismatch error — it shows the
actual.inspect value. The content between the outermost \" delimiters in got: is
exactly what belongs between the '" and "' of the correct single-quoted argument.
A fold method that can raise at inference time should rescue and return nil to defer to the
RBS tier:
def fold_split(args)
# … validate args …
Shellwords.split(arg.value)
rescue ArgumentError
nil # unmatched quotes — let RBS return Array[String]
endNever let fold methods propagate exceptions to the inference engine.
When a fold returns a Tuple of potentially unbounded size (e.g. Shellwords.split on a long
command), cap the result:
SPLIT_LIMIT = 64
tokens = Shellwords.split(arg.value)
return nil if tokens.size > SPLIT_LIMITSTRING_ARRAY_LIFT_LIMIT in ConstantFolding uses the same pattern; keep the convention
consistent.
Use rigor coverage --format json to get a before/after machine-readable precision score.
Run once before implementation begins and again after each slice to confirm the uplift is real:
# Before implementing the slice:
nix develop --command \
bundle exec exe/rigor coverage --format json \
spec/integration/fixtures/<name>/demo.rb > /tmp/before.json
# After implementing:
nix develop --command \
bundle exec exe/rigor coverage --format json \
spec/integration/fixtures/<name>/demo.rb > /tmp/after.json
# Compare:
ruby -r json -e '
b = JSON.parse(File.read("/tmp/before.json"))["summary"]
a = JSON.parse(File.read("/tmp/after.json"))["summary"]
puts "precise_ratio: #{(b["precise_ratio"]*100).round(2)}% → #{(a["precise_ratio"]*100).round(2)}%"
puts "dynamic_opaque: #{b["dynamic_opaque_count"]} → #{a["dynamic_opaque_count"]}"
'For a broader signal (impact on all of lib/):
nix develop --command \
bundle exec exe/rigor coverage libmake coverage enforces the precision floor set by its --threshold in the Makefile — any
slice that regresses precision below it fails CI.
After every implementation slice:
nix develop --command make verify-changedmake verify-changed is the local gate; the full gate (tests, lint, check, check-plugins) is CI
on the Draft PR. CI's self-check runs rigor check lib — Rigor's self-check must stay clean.
If the self-check surfaces new diagnostics in lib/, the cause is almost always:
:leaf but is actually
mutating.After implementing a 🔲 item:
docs/notes/…-coverage.md — change the symbol from 🔲 to ✅.Before declaring a coverage-uplift slice done:
HANDLERS entry + private handler method in shape_dispatch.rb.*_folding.rb file following the ShellwordsFolding pattern;
require_relative added to method_dispatcher.rb; registered in STDLIB_SINGLETON_FOLDERS.spec/rigor/inference/method_dispatcher/.spec/integration/fixtures/<name>/demo.rb (directory form for
stdlib modules; flat form for core types). Create together with the describe block
below — a fixture file with no spec wiring is dead code and will never catch regressions.spec/integration/type_construction_spec.rb.UPDATE_SNAPSHOTS=1 bundle exec rspec spec/integration/precision_snapshot_spec.rb.
Run this whenever you add or modify a fixture — the golden files in spec/integration/snapshots/
must reflect the new precise types or the CI snapshot gate will fail.make verify-changed clean locally; CI green on the Draft PR (it runs make coverage too).changelog.d/<section>/ (user-visible description of the new folds).The ShellwordsFolding
module is the canonical worked example of Tier D (new singleton-folding module):
Coverage doc produced:
docs/notes/20260522-stdlib-deterministic-module-coverage.md
— §2 Shellwords lists escape/shellescape, split/shellsplit/shellwords, join/shelljoin as 🔲
with receiver identification notes and fixture considerations.
Module file:
lib/rigor/inference/method_dispatcher/shellwords_folding.rb
— try_dispatch(context) guards with SingletonFolding.receiver?(receiver, "Shellwords").
— fold_escape, fold_split, fold_join each validate argument count and type before
calling the real Shellwords method and wrapping the result.
Registered in STDLIB_SINGLETON_FOLDERS in method_dispatcher.rb.
Unit spec:
spec/rigor/inference/method_dispatcher/shellwords_folding_spec.rb
— 27 examples covering each method, its aliases, non-constant inputs, arity guards, and a
split → join round-trip.
Integration fixture (directory form, for Environment.for_project):
spec/integration/fixtures/shellwords_folding/demo.rb
— assert_type calls demonstrating all three method groups and the fallback-to-RBS behaviour
for non-constant inputs.
Integration spec wired in type_construction_spec.rb.
Coverage doc updated: Shellwords section in
docs/notes/20260522-stdlib-deterministic-module-coverage.md
changed to ✅.
The whole slice — doc, implementation, unit spec, integration fixture, spec wiring, changelog — was one commit.
© rigortype, MPL-2.0. Rendered from Markdown: HTML in the file is shown as text, images as links, and headings moved down two levels. Raw file
Just SKILL.md in .claude/skills/rigor-type-coverage-uplift of rigortype/rigor.
Open the folder on GitHubat commit 57a67cf
Rigor Type Coverage Uplift next to the 5 skills that share the most tags, products or categories with it. Stars are the repository's; “used in” counts other GitHub owners with a copy.
| Skill | Stars | Used in | Tokens | Auto-check | Licence | Repo updated |
|---|---|---|---|---|---|---|
| Rigor Type Coverage Uplift this skillrigortype/rigor | 106 | — | ~5.6k | Automated safety check: Pass | MPL-2.0 | |
| Gumroad Prod Consoleantiwork/gumroad | 9.8k | — | ~2.9k | Automated safety check: Notes | MIT | |
| Fastlane Pull Request Reviewfastlane/fastlane | 42k | — | ~550 | Automated safety check: Pass | MIT | |
| Dependency UpdaterAsvarox/allkaraoke | 261 | 4 repos | ~3.5k | Automated safety check: Pass | MIT | |
| Wise APIlineofflight/frankfurter | 2k | — | ~1.1k | Automated safety check: Pass | MIT | |
| Write RbsDataDog/dd-trace-rb | 417 | — | ~805 | Automated safety check: Pass | Custom licence |
antiwork/gumroad
Execute read-only Ruby/Rails commands against Gumroad's production database for debugging and investigation.
fastlane/fastlane
Reviews a fastlane pull request against its linked issue and the project guides, separating blocking from non-blocking findings and handling vulnerabilities privately.
Asvarox/allkaraoke
Smart dependency management for any language. An agent skill from Asvarox/allkaraoke.
lineofflight/frankfurter
A skill your agent uses when querying Wise for exchange rates (real-time or historical), validating Frankfurter rates against Wise mid-market, debugging rate discrepancies, or when the user mentions…
DataDog/dd-trace-rb
A skill your agent uses when writing, reviewing, or modifying RBS type signatures (sig//.rbs, vendor/rbs//.rbs, or inline : annotations) or running Steep – e.g.
ruby-git/ruby-git
Addresses unresolved pull request review threads and suppressed (low-confidence) Copilot review comments on the current branch, folds each fix into the…
rigortype/rigor
Measure Rigor's baseline drift across the tagged history of a real OSS Ruby project.
rigortype/rigor
Adjudicate a rigor unused report safely before proposing dead-code removal.
rigortype/rigor
Reduce an existing .rigor-baseline.yml rule by rule by triaging sites, fixing or intentionally suppressing them, and regenerating the baseline.
rigortype/rigor
Validate that a project's Rigor configuration, plugins, paths, and baseline are actually healthy.
rigortype/rigor
Author a new Rigor plugin, choosing plugins/ for production support or examples/ for a contract walkthrough.
rigortype/rigor
Author a Rigor plugin in an adopting project or standalone rigor- gem for a DSL, framework, or metaprogramming pattern.
Works with
Categories
Expand Rigor's core/stdlib folding coverage for a named class, module, or method family. Rigor Type Coverage Uplift is an agent skill from rigortype/rigor. Expand Rigor's core/stdlib folding coverage for a named class, module, or method family.
Rigor Type Coverage Uplift fits situations like: auditing ConstantFolding; singleton-folding support; not for ordinary type inference; user-project annotations.
Run `npx skills add rigortype/rigor --skill rigor-type-coverage-uplift -a claude-code`. Or copy the skill folder (.claude/skills/rigor-type-coverage-uplift in rigortype/rigor) into .claude/skills/rigor-type-coverage-uplift in your project. Claude Code loads it when a task matches its description.
Run `npx skills add rigortype/rigor --skill rigor-type-coverage-uplift -a codex`. Or copy the skill folder (.claude/skills/rigor-type-coverage-uplift in rigortype/rigor) into .agents/skills/rigor-type-coverage-uplift in your project. Codex loads it when a task matches its description.
Cursor, Gemini CLI, GitHub Copilot and OpenCode also load SKILL.md folders. With the skills CLI, run `npx skills add rigortype/rigor --skill rigor-type-coverage-uplift -a cursor` (or -a gemini-cli, github-copilot or opencode for the others). To copy it by hand, put the folder in .cursor/skills/rigor-type-coverage-uplift, .gemini/skills/rigor-type-coverage-uplift, .github/skills/rigor-type-coverage-uplift and .opencode/skills/rigor-type-coverage-uplift in your project.
Going by SKILL.md and its folder, Rigor Type Coverage Uplift needs the command-line tools its instructions call (nix, bundle, make and ruby).
SKILL.md contains no URLs. Any network use would come from the scripts or tools the agent runs. This is read from the text; nothing was executed.
Our automated static check of SKILL.md found no risky patterns, such as piping downloads into a shell, reading credential files or hidden Unicode. It is not a guarantee. Review the folder before installing.
Rigor Type Coverage Uplift is published under the MPL-2.0 licence (the repository's licence). It allows redistribution, so the full SKILL.md is shown on this page.
About 5.6k tokens (SKILL.md is roughly 22k characters). Agents keep only the skill's name and description in context until a task matches; then they load SKILL.md in full.
Skills that share tags, products or a category with Rigor Type Coverage Uplift: Gumroad Prod Console (antiwork/gumroad, 9.8k stars), Fastlane Pull Request Review (fastlane/fastlane, 42k stars), Dependency Updater (Asvarox/allkaraoke, 261 stars) and Wise API (lineofflight/frankfurter, 2k stars). The comparison table on this page puts their stars, adoption, token cost, safety result and licence side by side.
rigortype (a GitHub organization) maintains it in rigortype/rigor, which has 106 GitHub stars. The repository holds 36 skills in this directory. The repository was last updated on October 8, 2026.
Source: rigortype/rigor on GitHub. Facts on this page come from the repository at the commit we read; the author's words are quoted as theirs.