Hostile Inputs
Hostile Inputs: a parser's real spec is what it does with input nobody intended. The journal's replay parses a file that - by the journal's own reason for existing - may end mid-write. In round 12 this probe caught the torn tail denying ALL recovery; the round-13 release made replay tolerant-by-default (salvage whole lines, REPORT damage) with a strict mode for auditors. This probe is now the acceptance test that keeps it that way.
Testing & Verification
Round 12
Mike Dalessio
exit 0
bundle exec ruby examples/hostile_inputs.rb
a real captured run
HOSTILE INPUTS (8 probes against ExecutionJournal.replay) clean file (control) recovered (2 salvaged) torn tail (crash mid-write) recovered (1 salvaged; damage reported: line 2: JSON::ParserError) binary garbage line recovered (1 salvaged; damage reported: line 2: JSON::ParserError) empty + whitespace lines recovered (2 salvaged) 8MB single line recovered (2 salvaged) valid JSON, wrong shape recovered (1 salvaged; damage reported: line 2: missing task_id) unknown event type recovered (1 salvaged) duplicate success lines recovered (1 salvaged) strict mode: refused, in uniform - JournalDamagedError: unparseable journal line: unexpected end of input, expected closing " at line 1 column (line 2) every hostile file was survived, every whole line salvaged, and every wound REPORTED - state.damage names the line and the reason, so recovery tools can say "resumed 47 tasks; 1 torn line at the tail" instead of either crashing or lying. and the same file offers two doors: tolerant for recovery (salvage maximally, report honestly), strict for audits (refuse damage, in the journal's own error class, with the line number). one format, two reader postures, both legitimate - that was the round-12 ask, verbatim, and this probe keeps it delivered.
source
# frozen_string_literal: true # Hostile Inputs: a parser's real spec is what it does with input # nobody intended. The journal's replay parses a file that - by the # journal's own reason for existing - may end mid-write. In round 12 # this probe caught the torn tail denying ALL recovery; the round-13 # release made replay tolerant-by-default (salvage whole lines, # REPORT damage) with a strict mode for auditors. This probe is now # the acceptance test that keeps it that way. # # bundle exec ruby examples/hostile_inputs.rb # # Runs offline; exits 1 if any hostile file draws blood again. require class="s">"bundler/setup" require class="s">"agentic" require class="s">"tmpdir" require class="s">"json" GOOD = %({class="s">"event":class="s">"task_succeeded",class="s">"task_id":class="s">"t1",class="s">"description":class="s">"t1",class="s">"duration"class="y">:0.1,class="s">"output":class="s">"ok"}) def replay_verdict(lines) path = File.join(Dir.tmpdir, class="s">"agentic_hostile.jsonl") File.write(path, lines.join(class="s">"\n")) state = Agentic:class="y">:ExecutionJournal.replay(path: path) [class="y">:recovered, state.completed_task_ids.size, state.damage] rescue => e [class="y">:crashed, e.class.to_s, []] end PROBES = { class="s">"clean file (control)" => [GOOD, GOOD.sub(class="s">"t1", class="s">"t2")], class="s">"torn tail (crash mid-write)" => [GOOD, %({class="s">"event":"task_succ)], class="s">"binary garbage line" => [GOOD, class="s">"\x00\x01\xFFnot json at all"], class="s">"empty + whitespace lines" => [GOOD, class="s">"", class="s">" ", GOOD.sub(class="s">"t1", class="s">"t2")], class="s">"8MB single line" => [GOOD, %({class="s">"event":class="s">"task_succeeded",class="s">"task_id":class="s">"big",class="s">"description":class="s">"big",class="s">"duration"class="y">:0.1,class="s">"output":class="s">"#{"xclass="s">" * 8_000_000}"})], class="s">"valid JSON, wrong shape" => [GOOD, %({class="s">"event":class="s">"task_succeeded",class="s">"task_id"class="y">:42,class="s">"duration":class="s">"fast"})], class="s">"unknown event type" => [GOOD, %({class="s">"event":class="s">"solar_flare",class="s">"task_id":class="s">"t9"})], class="s">"duplicate success lines" => [GOOD, GOOD] }.freeze puts class="s">"HOSTILE INPUTS (#{PROBES.size} probes against ExecutionJournal.replay)" puts blood = [] PROBES.each do |name, lines| verdict, detail, damage = replay_verdict(lines) ok = verdict == class="y">:recovered blood << name unless ok report = damage.map { |d| class="s">"line #{d[class="y">:line]}: #{d[class="y">:reason]}" }.join(class="s">", ") puts format(class="s">" %-30s %s", name, if ok class="s">"recovered (#{detail} salvaged#{damage.any? ? "; damage reported: #{report}class="s">" : "class="s">"})" else class="s">"CRASHED: #{detail}" end) end # The auditor's door: strict mode must still refuse damage, loudly puts strict_path = File.join(Dir.tmpdir, class="s">"agentic_hostile_strict.jsonl") File.write(strict_path, [GOOD, %({class="s">"event":class="s">"task_succ)].join("\n")) begin Agentic:class="y">:ExecutionJournal.replay(path: strict_path, mode: class="y">:strict) blood << class="s">"strict mode accepted damage" puts class="s">" strict mode: ACCEPTED a torn line - auditors are flying blind" rescue Agentic:class="y">:Errors:class="y">:JournalDamagedError => e puts class="s">" strict mode: refused, in uniform - #{e.class.name.split("::class="s">").last}: #{e.message}" end puts if blood.empty? puts class="s">" every hostile file was survived, every whole line salvaged, and" puts class="s">" every wound REPORTED - state.damage names the line and the" puts class="s">" reason, so recovery tools can say \"resumed 47 tasks; 1 torn" puts class="s">" line at the tail\" instead of either crashing or lying. and the" puts class="s">" same file offers two doors: tolerant for recovery (salvage" puts class="s">" maximally, report honestly), strict for audits (refuse damage," puts class="s">" in the journal's own error class, with the line number). one" puts class="s">" format, two reader postures, both legitimate - that was the" puts class="s">" round-12 ask, verbatim, and this probe keeps it delivered." else puts class="s">" BLOOD: #{blood.join("; class="s">")} - the tail is no longer tolerated." end exit(blood.empty? ? 0 : 1)