The Helpful 404
The Helpful 404: every system has three doors where users arrive with a typo - the URL, the config file, and the CLI - and at all three the system is holding the complete list of correct answers at the exact moment it says "not found." Spending one Levenshtein pass there converts a dead end into a one-keystroke fix. This example wires the framework's own Suggestions engine into all three doors, and proves the discipline that makes suggestions trustworthy: the CONSERVATISM …
Observability & Ops
Round 20
Yuki Nishijima
exit 0
bundle exec ruby examples/helpful_404.rb
a real captured run
THE HELPFUL 404 (the system was holding the answer key when it said not-found) router /userz/42 -> 404 /userz/42 - did you mean /users/:id? router /xyzzy -> 404 /xyzzy config max_retrys -> unknown key 'max_retrys' - did you mean 'max_retries'? config databese_url -> unknown key 'databese_url' cli stauts -> no command 'stauts' - did you mean 'status'? cli shipit -> no command 'shipit' score: 3 typos rescued, 3 strangers given honest silence. three doors, one engine, one discipline. the engine is the framework's own Suggestions module - the same Levenshtein that fixes contract keys fixes URLs and subcommands, because a typo doesn't care what layer it's in. the discipline is conservatism: the threshold scales with word length, so 'stauts' finds 'status' but 'shipit' finds nothing - a wrong suggestion ships a confused user somewhere CONFIDENTLY, which is strictly worse than a plain 404. and the reason this feature is so cheap that skipping it is a choice: at the moment any system says 'not found', it is HOLDING the complete list of things that exist - routes, schema keys, commands. the error message is a UI. spend the Levenshtein.
source
# frozen_string_literal: true # The Helpful 404: every system has three doors where users arrive # with a typo - the URL, the config file, and the CLI - and at all # three the system is holding the complete list of correct answers # at the exact moment it says "not found." Spending one Levenshtein # pass there converts a dead end into a one-keystroke fix. This # example wires the framework's own Suggestions engine into all # three doors, and proves the discipline that makes suggestions # trustworthy: the CONSERVATISM rule. Garbage gets silence, because # a wrong suggestion is worse than none - it sends a confused user # somewhere confidently. # # bundle exec ruby examples/helpful_404.rb # # Runs offline; exits 1 unless every typo gets the right hint and # every stranger gets honest silence. require class="s">"bundler/setup" require class="s">"agentic" Agentic.logger.level = class="y">:fatal ROUTES = [class="s">"/users/class="y">:id", class="s">"/orders/class="y">:id", class="s">"/invoices", class="s">"/settings", class="s">"/health"].freeze CONFIG_SCHEMA = [class="s">"max_retries", class="s">"timeout_ms", class="s">"pool_size", class="s">"log_level"].freeze CLI_COMMANDS = [class="s">"status", class="s">"deploy", class="s">"rollback", class="s">"logs", class="s">"console"].freeze # One engine, three doors. Each door normalizes its own shape, then # asks the same question: closest valid name within the budget? DOORS = { class="s">"router" => { candidates: ROUTES.map { |r| r.split(class="s">"/")[1] }, normalize: ->(input) { input.split(class="s">"/")[1].to_s }, render: ->(input, hit) { hit ? class="s">"404 #{input} - did you mean /#{hit}#{ROUTES.find { |r| r.include?(hit) }[/\/:\w+/]}?" : class="s">"404 #{input}" } }, class="s">"config" => { candidates: CONFIG_SCHEMA, normalize: ->(input) { input }, render: ->(input, hit) { hit ? class="s">"unknown key '#{input}' - did you mean '#{hit}'?" : class="s">"unknown key '#{input}'" } }, class="s">"cli" => { candidates: CLI_COMMANDS, normalize: ->(input) { input }, render: ->(input, hit) { hit ? class="s">"no command '#{input}' - did you mean '#{hit}'?" : class="s">"no command '#{input}'" } } }.freeze TRIALS = [ {door: class="s">"router", input: class="s">"/userz/42", expect_hint: class="s">"users"}, {door: class="s">"router", input: class="s">"/xyzzy", expect_hint: nil}, # a stranger; silence {door: class="s">"config", input: class="s">"max_retrys", expect_hint: class="s">"max_retries"}, {door: class="s">"config", input: class="s">"databese_url", expect_hint: nil}, # not close to anything we have {door: class="s">"cli", input: class="s">"stauts", expect_hint: class="s">"status"}, {door: class="s">"cli", input: class="s">"shipit", expect_hint: nil} # aspirational; silence ].freeze orchestrator = Agentic:class="y">:PlanOrchestrator.new(concurrency_limit: 3) trial_tasks = TRIALS.map do |trial| task = Agentic:class="y">:Task.new(description: class="s">"#{trial[class="y">:door]}: #{trial[class="y">:input]}", agent_spec: {class="s">"name" => trial[class="y">:door], class="s">"instructions" => class="s">"help"}) orchestrator.add_task(task, agent: ->(_t) { door = DOORS[trial[class="y">:door]] hit = Agentic:class="y">:Suggestions.suggest(door[class="y">:normalize].call(trial[class="y">:input]), door[class="y">:candidates]) {message: door[class="y">:render].call(trial[class="y">:input], hit), hit: hit} }) task end result = orchestrator.execute_plan puts class="s">"THE HELPFUL 404 (the system was holding the answer key when it said not-found)" puts failures = [] TRIALS.each_with_index do |trial, i| outcome = result.task_result(trial_tasks[i].id).output status = (outcome[class="y">:hit]&.to_s == trial[class="y">:expect_hint]&.to_s) ? class="s">"ok" : class="s">"WRONG" failures << class="s">"#{trial[class="y">:door]} #{trial[class="y">:input]}: suggested #{outcome[class="y">:hit].inspect}, wanted #{trial[class="y">:expect_hint].inspect}" unless status == class="s">"ok" puts format(class="s">" %-8s %-14s -> %s", trial[class="y">:door], trial[class="y">:input], outcome[class="y">:message]) end puts hints_given = TRIALS.count { |t| t[class="y">:expect_hint] } puts class="s">" score: #{hints_given} typos rescued, #{TRIALS.size - hints_given} strangers given honest silence." puts puts class="s">" three doors, one engine, one discipline. the engine is the" puts class="s">" framework's own Suggestions module - the same Levenshtein that" puts class="s">" fixes contract keys fixes URLs and subcommands, because a typo" puts class="s">" doesn't care what layer it's in. the discipline is conservatism:" puts class="s">" the threshold scales with word length, so 'stauts' finds 'status'" puts class="s">" but 'shipit' finds nothing - a wrong suggestion ships a confused" puts class="s">" user somewhere CONFIDENTLY, which is strictly worse than a plain" puts class="s">" 404. and the reason this feature is so cheap that skipping it is" puts class="s">" a choice: at the moment any system says 'not found', it is" puts class="s">" HOLDING the complete list of things that exist - routes, schema" puts class="s">" keys, commands. the error message is a UI. spend the Levenshtein." exit(failures.empty? ? 0 : 1)