From 37e507b94e9d66971208d1f82ab5a25b63e5e049 Mon Sep 17 00:00:00 2001 From: Minerva Sky <258328972+minerva-sky@users.noreply.github.com> Date: Sun, 30 Aug 2026 14:03:45 -0400 Subject: [PATCH 1/4] chore: patch-level lockfile sweep (timecop 0.9.11, rspec 3.13.2) Co-Authored-By: Claude Fable 5 --- Gemfile.lock | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index 6b2f484..dd1dffe 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -104,7 +104,7 @@ GEM rake (13.2.1) regexp_parser (2.8.3) rexml (3.4.4) - rspec (3.13.0) + rspec (3.13.2) rspec-core (~> 3.13.0) rspec-expectations (~> 3.13.0) rspec-mocks (~> 3.13.0) @@ -156,7 +156,7 @@ GEM unicode_utils (~> 1.4) strings-ansi (0.2.0) thor (1.3.2) - timecop (0.9.10) + timecop (0.9.11) traces (0.15.2) tty-box (0.7.0) pastel (~> 0.8) From 8a9f3a4b4999b9a3070265b0e5f9b8e3e5b21348 Mon Sep 17 00:00:00 2001 From: Minerva Sky <258328972+minerva-sky@users.noreply.github.com> Date: Sun, 30 Aug 2026 15:04:05 -0400 Subject: [PATCH 2/4] chore: minor-level lockfile sweep + standard 1.56 lint fixes --- Gemfile.lock | 141 ++++++++++++++++---------------- benchmark/boot.rb | 2 +- examples/adaptive_throttle.rb | 2 +- examples/api_surface.rb | 2 +- examples/backoff_conformance.rb | 4 +- examples/capacity_planner.rb | 4 +- examples/circuit_breaker.rb | 2 +- examples/contract_overhead.rb | 2 +- examples/eval_scorers.rb | 2 +- examples/event_prof.rb | 2 +- examples/hostile_inputs.rb | 2 +- examples/impl_shootout.rb | 2 +- examples/money_discipline.rb | 2 +- examples/onboarding_trail.rb | 2 +- examples/one_file_api.rb | 2 +- examples/perf_diff.rb | 2 +- examples/perf_history.rb | 2 +- examples/plan_fortune.rb | 2 +- examples/plan_merge.rb | 4 +- examples/ractor_shareability.rb | 2 +- examples/require_cost.rb | 2 +- examples/rule_shapes.rb | 2 +- examples/three_shapes.rb | 2 +- examples/throughput_knee.rb | 2 +- examples/traffic_dial.rb | 2 +- examples/variance_detective.rb | 2 +- lib/agentic/relation_rules.rb | 2 +- 27 files changed, 99 insertions(+), 100 deletions(-) diff --git a/Gemfile.lock b/Gemfile.lock index dd1dffe..4e2571d 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -22,47 +22,46 @@ GEM specs: addressable (2.9.0) public_suffix (>= 2.0.2, < 8.0) - ast (2.4.2) - async (2.24.0) + ast (2.4.3) + async (2.45.1) console (~> 1.29) fiber-annotation - io-event (~> 1.9) - metrics (~> 0.12) - traces (~> 0.15) - base64 (0.2.0) - bigdecimal (3.1.8) + io-event (~> 1.21) + bigdecimal (3.3.1) cgi (0.5.2) concurrent-ruby (1.3.8) - console (1.30.2) + console (1.37.0) fiber-annotation fiber-local (~> 1.1) json - crack (1.0.0) + crack (1.0.1) bigdecimal rexml - diff-lcs (1.5.1) - dry-configurable (1.2.0) - dry-core (~> 1.0, < 2) + diff-lcs (1.6.2) + dry-configurable (1.4.0) + dry-core (~> 1.0) zeitwerk (~> 2.6) - dry-core (1.0.1) + dry-core (1.2.0) concurrent-ruby (~> 1.0) + logger zeitwerk (~> 2.6) - dry-inflector (1.1.0) - dry-initializer (3.1.1) - dry-logic (1.5.0) + dry-inflector (1.3.1) + dry-initializer (3.2.0) + dry-logic (1.6.0) + bigdecimal concurrent-ruby (~> 1.0) - dry-core (~> 1.0, < 2) + dry-core (~> 1.1) zeitwerk (~> 2.6) - dry-schema (1.13.4) + dry-schema (1.16.0) concurrent-ruby (~> 1.0) dry-configurable (~> 1.0, >= 1.0.1) - dry-core (~> 1.0, < 2) - dry-initializer (~> 3.0) - dry-logic (>= 1.4, < 2) - dry-types (>= 1.7, < 2) + dry-core (~> 1.1) + dry-initializer (~> 3.2) + dry-logic (~> 1.6) + dry-types (~> 1.9, >= 1.9.1) zeitwerk (~> 2.6) - dry-types (1.7.2) - bigdecimal (~> 3.0) + dry-types (1.9.1) + bigdecimal (>= 3.0) concurrent-ruby (~> 1.0) dry-core (~> 1.0) dry-inflector (~> 1.0) @@ -75,89 +74,90 @@ GEM logger faraday-multipart (1.2.0) multipart-post (~> 2.0) - faraday-net_http (3.3.0) - net-http + faraday-net_http (3.4.4) + net-http (~> 0.5) fiber-annotation (0.2.0) fiber-local (1.1.0) fiber-storage fiber-storage (1.0.1) - hashdiff (1.1.1) - io-event (1.10.0) - json (2.7.1) - language_server-protocol (3.17.0.3) + hashdiff (1.2.1) + io-event (1.21.1) + json (2.21.2) + language_server-protocol (3.17.0.6) lint_roller (1.1.0) - logger (1.6.0) - metrics (0.12.2) + logger (1.7.0) multipart-post (2.4.1) - net-http (0.4.1) - uri - ostruct (0.6.1) - parallel (1.24.0) - parser (3.2.2.4) + net-http (0.9.1) + uri (>= 0.11.1) + ostruct (0.6.3) + parallel (1.28.0) + parser (3.3.12.0) ast (~> 2.4.1) racc pastel (0.8.0) tty-color (~> 0.5) - public_suffix (6.0.1) - racc (1.8.0) + prism (1.9.0) + public_suffix (6.0.2) + racc (1.8.1) rainbow (3.1.1) - rake (13.2.1) - regexp_parser (2.8.3) + rake (13.4.2) + regexp_parser (2.12.0) rexml (3.4.4) rspec (3.13.2) rspec-core (~> 3.13.0) rspec-expectations (~> 3.13.0) rspec-mocks (~> 3.13.0) - rspec-core (3.13.0) + rspec-core (3.13.6) rspec-support (~> 3.13.0) - rspec-expectations (3.13.1) + rspec-expectations (3.13.5) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) - rspec-mocks (3.13.1) + rspec-mocks (3.13.8) diff-lcs (>= 1.2.0, < 2.0) rspec-support (~> 3.13.0) - rspec-support (3.13.1) - rubocop (1.57.2) + rspec-support (3.13.7) + rubocop (1.88.2) json (~> 2.3) - language_server-protocol (>= 3.17.0) - parallel (~> 1.10) - parser (>= 3.2.2.4) + language_server-protocol (~> 3.17.0.2) + lint_roller (~> 1.1.0) + parallel (>= 1.10) + parser (>= 3.3.0.2) rainbow (>= 2.2.2, < 4.0) - regexp_parser (>= 1.8, < 3.0) - rexml (>= 3.2.5, < 4.0) - rubocop-ast (>= 1.28.1, < 2.0) + regexp_parser (>= 2.9.3, < 3.0) + rubocop-ast (>= 1.49.0, < 2.0) ruby-progressbar (~> 1.7) - unicode-display_width (>= 2.4.0, < 3.0) - rubocop-ast (1.30.0) - parser (>= 3.2.1.0) - rubocop-performance (1.19.1) - rubocop (>= 1.7.0, < 2.0) - rubocop-ast (>= 0.4.0) - ruby-openai (7.1.0) + unicode-display_width (>= 2.4.0, < 4.0) + rubocop-ast (1.50.0) + parser (>= 3.3.7.2) + prism (~> 1.7) + rubocop-performance (1.26.1) + lint_roller (~> 1.1) + rubocop (>= 1.75.0, < 2.0) + rubocop-ast (>= 1.47.1, < 2.0) + ruby-openai (7.4.0) event_stream_parser (>= 0.3.0, < 2.0.0) faraday (>= 1) faraday-multipart (>= 1) ruby-progressbar (1.13.0) - standard (1.32.1) + standard (1.56.0) language_server-protocol (~> 3.17.0.2) lint_roller (~> 1.0) - rubocop (~> 1.57.2) + rubocop (~> 1.88.0) standard-custom (~> 1.0.0) - standard-performance (~> 1.2) + standard-performance (~> 1.8) standard-custom (1.0.2) lint_roller (~> 1.0) rubocop (~> 1.50) - standard-performance (1.2.1) + standard-performance (1.9.0) lint_roller (~> 1.1) - rubocop-performance (~> 1.19.1) + rubocop-performance (~> 1.26.0) strings (0.2.1) strings-ansi (~> 0.2) unicode-display_width (>= 1.5, < 3.0) unicode_utils (~> 1.4) strings-ansi (0.2.0) - thor (1.3.2) + thor (1.5.0) timecop (0.9.11) - traces (0.15.2) tty-box (0.7.0) pastel (~> 0.8) strings (~> 0.2.0) @@ -176,16 +176,15 @@ GEM pastel (~> 0.8) strings (~> 0.2.0) tty-screen (~> 0.8) - unicode-display_width (2.5.0) + unicode-display_width (2.6.0) unicode_utils (1.4.0) uri (1.1.1) - vcr (6.3.1) - base64 - webmock (3.23.1) + vcr (6.4.0) + webmock (3.26.4) addressable (>= 2.8.0) crack (>= 0.3.2) hashdiff (>= 0.4.0, < 2.0.0) - zeitwerk (2.6.16) + zeitwerk (2.8.3) PLATFORMS arm64-darwin-23 diff --git a/benchmark/boot.rb b/benchmark/boot.rb index 3784cc2..23d8b4b 100644 --- a/benchmark/boot.rb +++ b/benchmark/boot.rb @@ -35,6 +35,6 @@ def measure(label, code) system(RbConfig.ruby, "-I", LIB, "-e", script) || abort("scenario failed: #{label}") end -puts format("%-36s %12s %20s %15s", "scenario", "wall", "allocations", "loaded files") +puts "scenario wall allocations loaded files" puts "-" * 88 SCENARIOS.each { |label, code| measure(label, code) } diff --git a/examples/adaptive_throttle.rb b/examples/adaptive_throttle.rb index 4ea9680..1714412 100644 --- a/examples/adaptive_throttle.rb +++ b/examples/adaptive_throttle.rb @@ -35,7 +35,7 @@ puts "ADAPTIVE THROTTLE (upstream capacity: undisclosed; AIMD will find it)" puts -puts format(" %-7s %-8s %-10s %-24s %s", "batch", "target", "p50", "", "action") +puts " batch target p50 action" Sync do BATCHES.times do |batch| diff --git a/examples/api_surface.rb b/examples/api_surface.rb index df9e744..6852a09 100644 --- a/examples/api_surface.rb +++ b/examples/api_surface.rb @@ -30,7 +30,7 @@ puts "API SURFACE CENSUS (#{CORE.size} core classes vs #{Dir[File.join(__dir__, "*.rb")].size - 1} example programs)" puts -puts format(" %-26s %-9s %-11s %s", "class", "surface", "exercised", "accidental (public, unused by any example)") +puts " class surface exercised accidental (public, unused by any example)" total_surface = 0 total_exercised = 0 diff --git a/examples/backoff_conformance.rb b/examples/backoff_conformance.rb index 08de191..5835e2c 100644 --- a/examples/backoff_conformance.rb +++ b/examples/backoff_conformance.rb @@ -35,7 +35,7 @@ def expected_bounds(strategy, jitter, retry_count) failures = [] puts "BACKOFF CONFORMANCE (seed #{seed}, #{DRAWS} draws per combination)" puts -puts format(" %-13s %-8s %-22s %-22s %s", "strategy", "jitter", "expected", "observed", "verdict") +puts " strategy jitter expected observed verdict" %i[constant linear exponential].each do |strategy| [false, true, :full].each do |jitter| @@ -57,7 +57,7 @@ def expected_bounds(strategy, jitter, retry_count) low, high = expected_bounds(strategy, jitter, RETRY_COUNT) epsilon = 1e-9 - in_bounds = observed.all? { |d| d >= low - epsilon && d <= high + epsilon } + in_bounds = observed.all? { |d| d.between?(low - epsilon, high + epsilon) } spans = jitter == false || (observed.max - observed.min) > (high - low) * 0.8 verdict = if !in_bounds diff --git a/examples/capacity_planner.rb b/examples/capacity_planner.rb index 39023b5..a72efa4 100644 --- a/examples/capacity_planner.rb +++ b/examples/capacity_planner.rb @@ -41,7 +41,7 @@ puts "CAPACITY PLANNER (target: #{TARGET_PER_MINUTE} tickets/min at peak)" puts -puts format(" %-16s %-10s %-10s %-22s %s", "task", "p50", "p95", "lanes needed (p50/p95)", "") +puts " task p50 p95 lanes needed (p50/p95) " lambda_per_sec = TARGET_PER_MINUTE / 60.0 total_p95_lanes = 0 @@ -64,7 +64,7 @@ # --- check the plan against every configured limit ------------------------------- puts " the plan vs. what's actually configured:" -puts format(" %-36s %-8s %s", "limit", "have", "verdict at #{TARGET_PER_MINUTE}/min") +puts " limit have verdict at #{TARGET_PER_MINUTE}/min" verdicts = { "orchestrator concurrency_limit" => (total_p95_lanes <= 8) ? "holds" : "BINDS FIRST - raise to #{total_p95_lanes}", "provider quota (windowed)" => (TARGET_PER_MINUTE <= 90) ? "holds" : "BINDS - 90/min < #{TARGET_PER_MINUTE}/min arrivals, queues grow without bound", diff --git a/examples/circuit_breaker.rb b/examples/circuit_breaker.rb index 67e4a9d..21d416a 100644 --- a/examples/circuit_breaker.rb +++ b/examples/circuit_breaker.rb @@ -70,7 +70,7 @@ def run_scenario(name, ticks, journal_path, &upstream) breaker = Breaker.new puts " #{name}" - puts format(" %-6s %-11s %s", "tick", "breaker", "what happened") + puts " tick breaker what happened" ticks.times do |tick| unless breaker.allow? diff --git a/examples/contract_overhead.rb b/examples/contract_overhead.rb index 419b6bc..2fe33b6 100644 --- a/examples/contract_overhead.rb +++ b/examples/contract_overhead.rb @@ -35,7 +35,7 @@ def spec_with(keys:, relations:) puts "CONTRACT OVERHEAD BENCH (#{ITERATIONS} validations per row)" puts -puts format(" %-26s %-12s %s", "contract", "per call", "share of an #{LLM_CALL_MS.to_i}ms LLM call") +puts " contract per call share of an #{LLM_CALL_MS.to_i}ms LLM call" rows = [ ["3 keys, no rules", spec_with(keys: 3, relations: 0), {field_0: 1, field_1: 2, field_2: 3}], diff --git a/examples/eval_scorers.rb b/examples/eval_scorers.rb index 62e8f27..75f7ba5 100644 --- a/examples/eval_scorers.rb +++ b/examples/eval_scorers.rb @@ -46,7 +46,7 @@ }.freeze PASS_AT = 0.99 # judge scorers may grade partially; everything else is 0-or-1 -NAMES_A_PROBLEM = ->(summary) { (summary.include?("general inquiry") ? 0.0 : 0.6) } +NAMES_A_PROBLEM = ->(summary) { summary.include?("general inquiry") ? 0.0 : 0.6 } NAMES_AN_ACTION = ->(summary) { summary.match?(/request|update/) ? 0.4 : 0.0 } RUBRIC = ->(summary) { NAMES_A_PROBLEM.call(summary) + NAMES_AN_ACTION.call(summary) } diff --git a/examples/event_prof.rb b/examples/event_prof.rb index 367687f..a5455e9 100644 --- a/examples/event_prof.rb +++ b/examples/event_prof.rb @@ -48,7 +48,7 @@ puts "EVENT PROF (task-seconds by tag; wall clock #{(wall * 1000).round}ms, 3 lanes)" puts -puts format(" %-8s %-10s %-8s %-8s %s", "tag", "seconds", "share", "tasks", "worst offender") +puts " tag seconds share tasks worst offender" by_tag.sort_by { |_, v| -v[:seconds] }.each do |tag, stats| share = stats[:seconds] / task_seconds * 100 puts format(" %-8s %6.0fms %5.1f%% %-8d %s (%.0fms) %s", diff --git a/examples/hostile_inputs.rb b/examples/hostile_inputs.rb index dbeabaf..449d38f 100644 --- a/examples/hostile_inputs.rb +++ b/examples/hostile_inputs.rb @@ -48,7 +48,7 @@ def replay_verdict(lines) report = damage.map { |d| "line #{d[:line]}: #{d[:reason]}" }.join(", ") puts format(" %-30s %s", name, if ok - "recovered (#{detail} salvaged#{damage.any? ? "; damage reported: #{report}" : ""})" + "recovered (#{detail} salvaged#{"; damage reported: #{report}" if damage.any?})" else "CRASHED: #{detail}" end) diff --git a/examples/impl_shootout.rb b/examples/impl_shootout.rb index 5767f7c..9dcafd6 100644 --- a/examples/impl_shootout.rb +++ b/examples/impl_shootout.rb @@ -74,7 +74,7 @@ def run_candidate(impl) puts "IMPLEMENTATION SHOOTOUT: #{SPEC.name} (#{EVALS.size} eval cases)" puts -puts format(" %-46s %-12s %s", "case (expected)", "v1 regex", "v2 weights") +puts " case (expected) v1 regex v2 weights" EVALS.each_with_index do |eval_case, index| marks = results.values.map { |r| r[index][:correct] ? "pass" : "FAIL(#{r[index][:got]})" diff --git a/examples/money_discipline.rb b/examples/money_discipline.rb index d64ad56..b5d8656 100644 --- a/examples/money_discipline.rb +++ b/examples/money_discipline.rb @@ -78,7 +78,7 @@ def ledger_invoice(items) puts "MONEY DISCIPLINE (same invoice, two arithmetics)" puts -puts format(" %-12s %-28s %s", "", "float version", "ledger version") +puts " float version ledger version" puts format(" %-12s %-28.14f %s", "subtotal", floats[:subtotal], Money.new(ledger[:subtotal_cents])) puts format(" %-12s %-28.14f %s", "tax", floats[:tax], Money.new(ledger[:tax_cents])) puts format(" %-12s %-28.14f %s", "total", floats[:total], Money.new(ledger[:total_cents])) diff --git a/examples/onboarding_trail.rb b/examples/onboarding_trail.rb index 9fe189f..7be5a22 100644 --- a/examples/onboarding_trail.rb +++ b/examples/onboarding_trail.rb @@ -54,7 +54,7 @@ trail.each_with_index do |room, index| unmet = files[room][:mentions] - trail[0..index] puts format(" %d. %-26s %4d lines %s", index + 1, room, files[room][:lines], ROOM_NOTES[room]) - puts format(" %s", "(mentions #{files[room][:mentions].join(", ")})") if files[room][:mentions].any? + puts " (mentions #{files[room][:mentions].join(", ")})" if files[room][:mentions].any? puts " WARNING: tour visits this before #{unmet.join(", ")}" if unmet.any? end diff --git a/examples/one_file_api.rb b/examples/one_file_api.rb index e0007da..5cd0cda 100644 --- a/examples/one_file_api.rb +++ b/examples/one_file_api.rb @@ -71,7 +71,7 @@ def handle(method, path, body = nil) puts REQUESTS.each do |method, path, body| status, response = handle(method, path, body) - puts " #{method} #{path}#{body ? " #{JSON.generate(body)}" : ""}" + puts " #{method} #{path}#{" #{JSON.generate(body)}" if body}" rendered = JSON.generate(response) rendered = "#{rendered[0, 100]}... (#{rendered.size} bytes)" if rendered.size > 110 puts " -> #{status} #{rendered}" diff --git a/examples/perf_diff.rb b/examples/perf_diff.rb index 8dd8ef9..e1df2fa 100644 --- a/examples/perf_diff.rb +++ b/examples/perf_diff.rb @@ -67,7 +67,7 @@ def critical_path_names(graph, durations) puts "PERF DIFF (noise floor #{NOISE_MS}ms)" puts -puts format(" %-18s %9s %9s %9s %s", "task", "before", "after", "delta", "") +puts " task before after delta " regressions = [] BASELINE.each_key do |name| delta_ms = (after[name] - before[name]) * 1000 diff --git a/examples/perf_history.rb b/examples/perf_history.rb index bbaf3cc..ade5059 100644 --- a/examples/perf_history.rb +++ b/examples/perf_history.rb @@ -61,7 +61,7 @@ def run_release(work, journal: nil, collect: nil) puts "PERF HISTORY (baseline: #{BASELINE_JOURNAL.split("/").last}, noise floor #{NOISE_MS}ms)" puts -puts format(" %-20s %10s %10s %9s", "task", "last release", "this one", "delta") +puts " task last release this one delta" regressions = [] current.each do |name, duration| recorded = baseline[name] diff --git a/examples/plan_fortune.rb b/examples/plan_fortune.rb index 04ca3ad..6c6dafd 100644 --- a/examples/plan_fortune.rb +++ b/examples/plan_fortune.rb @@ -42,7 +42,7 @@ def step(name) "You begin in many places at once, child of parallelism - " \ "your mornings are wide (#{roots} roots)." else - "You begin cautiously (#{roots} root#{(roots == 1) ? "" : "s"}) - " \ + "You begin cautiously (#{roots} root#{"s" unless roots == 1}) - " \ "the fates smile on those who fan out." end diff --git a/examples/plan_merge.rb b/examples/plan_merge.rb index a23a5eb..6530b85 100644 --- a/examples/plan_merge.rb +++ b/examples/plan_merge.rb @@ -76,7 +76,7 @@ def merge(base, ours, theirs) elsif in_base && in_ours && in_theirs [key, base_edges[key]] # unchanged everywhere elsif !in_base - [key, (our_edges[key] || their_edges[key])] # added by one branch + [key, our_edges[key] || their_edges[key]] # added by one branch else [key, (in_ours ? our_edges[key] : their_edges[key])] # kept by one, removed by other -> keep? no: removed wins end @@ -94,7 +94,7 @@ def merge(base, ours, theirs) puts " cleanly merged:" puts " tasks: #{merged["tasks"].join(", ")}" (merged["edges"] - BASE["edges"]).each do |e| - puts " + #{e["from"]} -> #{e["to"]}#{e["label"] ? " (#{e["label"]})" : ""}" + puts " + #{e["from"]} -> #{e["to"]}#{" (#{e["label"]})" if e["label"]}" end puts if conflicts.any? diff --git a/examples/ractor_shareability.rb b/examples/ractor_shareability.rb index 17c26e1..e202d9d 100644 --- a/examples/ractor_shareability.rb +++ b/examples/ractor_shareability.rb @@ -75,7 +75,7 @@ def verdict(value) puts "THE RACTOR SHAREABILITY AUDIT (frozen is not the same promise)" puts -puts format(" %-24s %-8s %-11s %s", "value", "frozen?", "shareable?", "after make_shareable") +puts " value frozen? shareable? after make_shareable" SUBJECTS.each do |name, value| frozen, shareable, after = verdict(value) puts format(" %-24s %-8s %-11s %s", name, frozen, shareable, after) diff --git a/examples/require_cost.rb b/examples/require_cost.rb index 47af4bc..d349b64 100644 --- a/examples/require_cost.rb +++ b/examples/require_cost.rb @@ -51,7 +51,7 @@ def cost_of(target, touch = "") puts "REQUIRE COST REPORT (each row measured in a pristine child process)" puts -puts format(" %-28s %10s %14s %10s", "require", "RSS", "objects", "time") +puts " require RSS objects time" rows = TARGETS.transform_values { |target, touch| cost_of(target, touch || "") } rows.each do |name, cost| puts format(" %-28s %8.1fMB %14d %8.0fms %s", diff --git a/examples/rule_shapes.rb b/examples/rule_shapes.rb index 11e7e90..bc4d6a0 100644 --- a/examples/rule_shapes.rb +++ b/examples/rule_shapes.rb @@ -69,7 +69,7 @@ def projects?(spec) puts "RULE SHAPES: one policy, three representations, four consumers" puts -puts format(" %-22s %-10s %-10s %-12s %s", "shape", "enforced", "explains", "generatable", "projects") +puts " shape enforced explains generatable projects" SHAPES.each do |name, rules| spec = spec_with(rules) puts format(" %-22s %-10s %-10s %-12s %s", diff --git a/examples/three_shapes.rb b/examples/three_shapes.rb index 0be7b06..4ba859e 100644 --- a/examples/three_shapes.rb +++ b/examples/three_shapes.rb @@ -50,7 +50,7 @@ def shape_facts(graph) puts "THREE SHAPES: six tasks x #{(UNIT * 1000).round}ms, concurrency 4" puts -puts format(" %-8s %-10s %-8s %-9s %s", "shape", "wall", "depth", "max fan-in", "the trade") +puts " shape wall depth max fan-in the trade" TRADES = { chain: "trivially debuggable; pays full serial price", diff --git a/examples/throughput_knee.rb b/examples/throughput_knee.rb index 2b095a5..5a71aca 100644 --- a/examples/throughput_knee.rb +++ b/examples/throughput_knee.rb @@ -62,7 +62,7 @@ puts "THROUGHPUT KNEE (#{JOBS} jobs per ceiling; upstream parallelism undisclosed)" puts -puts format(" %-9s %-12s %-14s %-14s %s", "ceiling", "jobs/sec", "service p50", "total p50", "") +puts " ceiling jobs/sec service p50 total p50 " rows.each do |row| bar = "#" * (row[:throughput] / 10).round puts format(" %-9d %8.1f %8.1fms %8.1fms %s", diff --git a/examples/traffic_dial.rb b/examples/traffic_dial.rb index d8a156b..0b30d0d 100644 --- a/examples/traffic_dial.rb +++ b/examples/traffic_dial.rb @@ -34,7 +34,7 @@ puts "TRAFFIC DIAL: rolling out v2, #{FULL_CAPACITY} lanes of traffic total" puts -puts format(" %-8s %-8s %-10s %s", "stage", "lanes", "p50", "verdict") +puts " stage lanes p50 verdict" Sync do stage_index = 0 diff --git a/examples/variance_detective.rb b/examples/variance_detective.rb index 0bed84d..71888f4 100644 --- a/examples/variance_detective.rb +++ b/examples/variance_detective.rb @@ -48,7 +48,7 @@ puts "VARIANCE DETECTIVE (#{RUNS} journaled runs, seed #{seed})" puts -puts format(" %-24s %7s %7s %7s %9s", "task", "p50", "p90", "worst", "p90/p50") +puts " task p50 p90 worst p90/p50" suspects = [] PROFILE.each_key do |name| diff --git a/lib/agentic/relation_rules.rb b/lib/agentic/relation_rules.rb index fbdc4a4..29c4c78 100644 --- a/lib/agentic/relation_rules.rb +++ b/lib/agentic/relation_rules.rb @@ -51,7 +51,7 @@ def validate_declaration!(id, definition, inputs) undeclared = fields.reject { |field| inputs.key?(field) } if undeclared.any? raise ArgumentError, "rule :#{id} (#{relation}) references undeclared " \ - "input#{(undeclared.size == 1) ? "" : "s"} #{undeclared.map(&:inspect).join(", ")}" + "input#{"s" unless undeclared.size == 1} #{undeclared.map(&:inspect).join(", ")}" end if relation == :sum_lte From c9a7319fa534ad78e1edf5221d108cfd4d47ecd8 Mon Sep 17 00:00:00 2001 From: Minerva Sky <258328972+minerva-sky@users.noreply.github.com> Date: Sun, 30 Aug 2026 20:06:09 -0400 Subject: [PATCH 3/4] Pin async/console/io-event to Ruby 3.2-compatible versions async >= 2.38 and console >= 1.35 require Ruby >= 3.3; io-event >= 1.12 requires Ruby >= 3.2.6. CI's floor is 3.2.4, so the minor sweep broke the Ruby 3.2.4 job (bundle exit 5). rspec 610/0, standardrb clean. Co-Authored-By: Claude Fable 5 --- Gemfile | 6 ++++++ Gemfile.lock | 15 +++++++++++---- 2 files changed, 17 insertions(+), 4 deletions(-) diff --git a/Gemfile b/Gemfile index 74f51a6..8c6164a 100644 --- a/Gemfile +++ b/Gemfile @@ -7,6 +7,12 @@ gemspec gem "rake", "~> 13.0" +# CI floor is Ruby 3.2.4: async >= 2.38 / console >= 1.35 need Ruby 3.3, +# io-event >= 1.12 needs Ruby 3.2.6. +gem "async", "<= 2.37.0" +gem "console", "<= 1.34.3" +gem "io-event", "<= 1.11.2" + gem "rspec", "~> 3.0" gem "standard", "~> 1.3" diff --git a/Gemfile.lock b/Gemfile.lock index 4e2571d..e6f959a 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -23,14 +23,16 @@ GEM addressable (2.9.0) public_suffix (>= 2.0.2, < 8.0) ast (2.4.3) - async (2.45.1) + async (2.37.0) console (~> 1.29) fiber-annotation - io-event (~> 1.21) + io-event (~> 1.11) + metrics (~> 0.12) + traces (~> 0.18) bigdecimal (3.3.1) cgi (0.5.2) concurrent-ruby (1.3.8) - console (1.37.0) + console (1.34.3) fiber-annotation fiber-local (~> 1.1) json @@ -81,11 +83,12 @@ GEM fiber-storage fiber-storage (1.0.1) hashdiff (1.2.1) - io-event (1.21.1) + io-event (1.11.2) json (2.21.2) language_server-protocol (3.17.0.6) lint_roller (1.1.0) logger (1.7.0) + metrics (0.15.0) multipart-post (2.4.1) net-http (0.9.1) uri (>= 0.11.1) @@ -158,6 +161,7 @@ GEM strings-ansi (0.2.0) thor (1.5.0) timecop (0.9.11) + traces (0.18.2) tty-box (0.7.0) pastel (~> 0.8) strings (~> 0.2.0) @@ -192,6 +196,9 @@ PLATFORMS DEPENDENCIES agentic! + async (<= 2.37.0) + console (<= 1.34.3) + io-event (<= 1.11.2) rake (~> 13.0) rspec (~> 3.0) standard (~> 1.3) From 7a204a8eb93f3dc61636364b3094aa45a93b2471 Mon Sep 17 00:00:00 2001 From: Minerva Sky <258328972+minerva-sky@users.noreply.github.com> Date: Sun, 30 Aug 2026 20:07:49 -0400 Subject: [PATCH 4/4] Pin dry-configurable <= 1.3.0 for Ruby 3.2 CI dry-configurable 1.4.0 requires Ruby >= 3.3; full lockfile now scanned clean against 3.2.4. rspec 610/0, standardrb clean. Co-Authored-By: Claude Fable 5 --- Gemfile | 5 +++-- Gemfile.lock | 5 +++-- 2 files changed, 6 insertions(+), 4 deletions(-) diff --git a/Gemfile b/Gemfile index 8c6164a..4dd90e9 100644 --- a/Gemfile +++ b/Gemfile @@ -7,10 +7,11 @@ gemspec gem "rake", "~> 13.0" -# CI floor is Ruby 3.2.4: async >= 2.38 / console >= 1.35 need Ruby 3.3, -# io-event >= 1.12 needs Ruby 3.2.6. +# CI floor is Ruby 3.2.4: async >= 2.38 / console >= 1.35 / dry-configurable >= 1.4 +# need Ruby 3.3, io-event >= 1.12 needs Ruby 3.2.6. gem "async", "<= 2.37.0" gem "console", "<= 1.34.3" +gem "dry-configurable", "<= 1.3.0" gem "io-event", "<= 1.11.2" gem "rspec", "~> 3.0" diff --git a/Gemfile.lock b/Gemfile.lock index e6f959a..aea4dce 100644 --- a/Gemfile.lock +++ b/Gemfile.lock @@ -40,8 +40,8 @@ GEM bigdecimal rexml diff-lcs (1.6.2) - dry-configurable (1.4.0) - dry-core (~> 1.0) + dry-configurable (1.3.0) + dry-core (~> 1.1) zeitwerk (~> 2.6) dry-core (1.2.0) concurrent-ruby (~> 1.0) @@ -198,6 +198,7 @@ DEPENDENCIES agentic! async (<= 2.37.0) console (<= 1.34.3) + dry-configurable (<= 1.3.0) io-event (<= 1.11.2) rake (~> 13.0) rspec (~> 3.0)