robot_lab-to 0.2.6
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +7 -0
- data/.envrc +1 -0
- data/.github/workflows/deploy-github-pages.yml +52 -0
- data/.loki +21 -0
- data/.quality/reek_baseline.txt +17 -0
- data/.rubocop.yml +7 -0
- data/CHANGELOG.md +67 -0
- data/CLAUDE.md +74 -0
- data/COMMITS.md +27 -0
- data/README.md +352 -0
- data/Rakefile +132 -0
- data/bin/robot-to +14 -0
- data/docs/about/changelog.md +82 -0
- data/docs/assets/architecture.svg +110 -0
- data/docs/assets/images/robot_lab-to.jpg +0 -0
- data/docs/assets/iteration-loop.svg +97 -0
- data/docs/concepts/evals.md +254 -0
- data/docs/concepts/iteration-loop.md +128 -0
- data/docs/concepts/notes.md +91 -0
- data/docs/concepts/run-state.md +93 -0
- data/docs/concepts/stop-conditions.md +111 -0
- data/docs/concepts/verification.md +75 -0
- data/docs/configuration/cli.md +111 -0
- data/docs/configuration/index.md +93 -0
- data/docs/configuration/settings.md +270 -0
- data/docs/getting-started/anatomy-of-a-run.md +111 -0
- data/docs/getting-started/installation.md +78 -0
- data/docs/getting-started/quick-start.md +105 -0
- data/docs/index.md +96 -0
- data/docs/local-models/guardrails.md +117 -0
- data/docs/local-models/index.md +88 -0
- data/docs/local-models/ollama.md +122 -0
- data/docs/local-models/tools.md +92 -0
- data/docs/reference/architecture.md +139 -0
- data/examples/01_basic_usage/.gitignore +9 -0
- data/examples/01_basic_usage/README.md +173 -0
- data/examples/01_basic_usage/basic_usage.rb +386 -0
- data/examples/02_advanced_usage/.gitignore +8 -0
- data/examples/02_advanced_usage/README.md +117 -0
- data/examples/02_advanced_usage/advanced_usage.rb +308 -0
- data/examples/02_advanced_usage/quality_gate.rb +99 -0
- data/examples/03_scored/.gitignore +2 -0
- data/examples/03_scored/README.md +117 -0
- data/examples/03_scored/scored_run.rb +325 -0
- data/examples/04_prose/.gitignore +2 -0
- data/examples/04_prose/README.md +43 -0
- data/examples/04_prose/prompts_dir/grade_message.md +14 -0
- data/examples/04_prose/prompts_dir/judge.md +11 -0
- data/examples/04_prose/prompts_dir/outline_criteria.md +9 -0
- data/examples/04_prose/prompts_dir/outline_objective.md +11 -0
- data/examples/04_prose/prompts_dir/section_criteria.md +7 -0
- data/examples/04_prose/prompts_dir/sections_objective.md +14 -0
- data/examples/04_prose/prose_run.rb +302 -0
- data/lib/robot_lab/to/atomic_file.rb +69 -0
- data/lib/robot_lab/to/backoff.rb +46 -0
- data/lib/robot_lab/to/cli.rb +176 -0
- data/lib/robot_lab/to/commit_manager.rb +135 -0
- data/lib/robot_lab/to/config/defaults.yml +27 -0
- data/lib/robot_lab/to/config.rb +86 -0
- data/lib/robot_lab/to/decision.rb +40 -0
- data/lib/robot_lab/to/decision_manager.rb +193 -0
- data/lib/robot_lab/to/errors.rb +30 -0
- data/lib/robot_lab/to/evals/base.rb +23 -0
- data/lib/robot_lab/to/evals/code.rb +77 -0
- data/lib/robot_lab/to/evals/context.rb +17 -0
- data/lib/robot_lab/to/evals/factory.rb +84 -0
- data/lib/robot_lab/to/evals/null.rb +17 -0
- data/lib/robot_lab/to/evals/prose.rb +110 -0
- data/lib/robot_lab/to/evals/score.rb +22 -0
- data/lib/robot_lab/to/exit_summary.rb +75 -0
- data/lib/robot_lab/to/guards/checkpoint.rb +84 -0
- data/lib/robot_lab/to/guards/grader_lock.rb +62 -0
- data/lib/robot_lab/to/guards/path_resolution.rb +61 -0
- data/lib/robot_lab/to/guards/quality_monitor.rb +113 -0
- data/lib/robot_lab/to/guards/read_before_edit.rb +83 -0
- data/lib/robot_lab/to/guards/run_store.rb +31 -0
- data/lib/robot_lab/to/guards/write_guard.rb +71 -0
- data/lib/robot_lab/to/guards.rb +54 -0
- data/lib/robot_lab/to/iteration_result.rb +29 -0
- data/lib/robot_lab/to/jsonl_logger.rb +59 -0
- data/lib/robot_lab/to/notes_manager.rb +121 -0
- data/lib/robot_lab/to/orchestrator.rb +642 -0
- data/lib/robot_lab/to/prompt_builder.rb +208 -0
- data/lib/robot_lab/to/run.rb +109 -0
- data/lib/robot_lab/to/stop_conditions.rb +71 -0
- data/lib/robot_lab/to/tools/bash.rb +75 -0
- data/lib/robot_lab/to/tools/edit.rb +52 -0
- data/lib/robot_lab/to/tools/file_tool.rb +32 -0
- data/lib/robot_lab/to/tools/read.rb +57 -0
- data/lib/robot_lab/to/tools/request_decision.rb +66 -0
- data/lib/robot_lab/to/tools/submit_result.rb +50 -0
- data/lib/robot_lab/to/tools/write.rb +32 -0
- data/lib/robot_lab/to/verifier.rb +63 -0
- data/lib/robot_lab/to/version.rb +7 -0
- data/lib/robot_lab/to.rb +81 -0
- data/mkdocs.yml +145 -0
- metadata +175 -0
data/Rakefile
ADDED
|
@@ -0,0 +1,132 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'bundler/gem_tasks'
|
|
4
|
+
require 'rake/testtask'
|
|
5
|
+
|
|
6
|
+
Rake::TestTask.new(:test) do |t|
|
|
7
|
+
t.libs << 'test'
|
|
8
|
+
t.libs << 'lib'
|
|
9
|
+
t.test_files = FileList['test/**/*_test.rb', 'test/**/test_*.rb'].exclude('**/*_helper.rb')
|
|
10
|
+
t.verbose = true
|
|
11
|
+
t.ruby_opts << '-rtest_helper'
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
task default: :test
|
|
15
|
+
|
|
16
|
+
desc 'Run tests with verbose output'
|
|
17
|
+
task :test_verbose do
|
|
18
|
+
ENV['TESTOPTS'] = '--verbose'
|
|
19
|
+
Rake::Task[:test].invoke
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
desc 'Run a single test file'
|
|
23
|
+
task :test_file, [:file] do |_t, args|
|
|
24
|
+
ruby "test/#{args[:file]}"
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
desc 'Check code complexity with Flog (warn >=20, fail >=50)'
|
|
28
|
+
task :flog_check do
|
|
29
|
+
require 'flog'
|
|
30
|
+
|
|
31
|
+
method_warn = 20.0
|
|
32
|
+
method_fail = 50.0
|
|
33
|
+
|
|
34
|
+
flogger = Flog.new(all: true)
|
|
35
|
+
flogger.flog(*Dir.glob('lib/**/*.rb'))
|
|
36
|
+
|
|
37
|
+
warnings = []
|
|
38
|
+
failures = []
|
|
39
|
+
|
|
40
|
+
flogger.each_by_score do |method, score|
|
|
41
|
+
next if method.end_with?('#none')
|
|
42
|
+
|
|
43
|
+
if score > method_fail
|
|
44
|
+
failures << "#{format('%.1f', score)}: #{method}"
|
|
45
|
+
elsif score > method_warn
|
|
46
|
+
warnings << "#{format('%.1f', score)}: #{method}"
|
|
47
|
+
end
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
unless warnings.empty?
|
|
51
|
+
puts "\nFlog warnings (#{method_warn}–#{method_fail}) — target for future refactoring:"
|
|
52
|
+
warnings.each { |v| puts " #{v}" }
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
if failures.empty?
|
|
56
|
+
puts "\nFlog: no methods exceed the failure threshold (>=#{method_fail})"
|
|
57
|
+
else
|
|
58
|
+
puts "\nFlog failures (>=#{method_fail}) — must be refactored:"
|
|
59
|
+
failures.each { |v| puts " #{v}" }
|
|
60
|
+
abort "\nFlog quality gate failed: #{failures.size} method(s) exceed #{method_fail}"
|
|
61
|
+
end
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
desc 'Check for structural code duplication with Flay (mass >= 50)'
|
|
65
|
+
task :flay_check do
|
|
66
|
+
require 'flay'
|
|
67
|
+
|
|
68
|
+
mass_threshold = 50
|
|
69
|
+
|
|
70
|
+
flay = Flay.new({ mass: mass_threshold, diff: false, verbose: false, summary: false, timeout: 60 })
|
|
71
|
+
flay.process(*Dir.glob('lib/**/*.rb'))
|
|
72
|
+
flay.analyze
|
|
73
|
+
|
|
74
|
+
if flay.hashes.empty?
|
|
75
|
+
puts "\nFlay: no structural duplication detected (mass >= #{mass_threshold})"
|
|
76
|
+
else
|
|
77
|
+
puts "\nFlay found structural duplication (mass >= #{mass_threshold}):"
|
|
78
|
+
flay.report
|
|
79
|
+
abort "\nFlay quality gate failed: #{flay.hashes.length} pattern(s) detected"
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
desc 'Run all quality checks: tests (with coverage), RuboCop, Flog, and Flay'
|
|
84
|
+
task :quality do
|
|
85
|
+
gates = [
|
|
86
|
+
['Tests + Coverage', 'bundle exec rake test'],
|
|
87
|
+
['RuboCop', 'bundle exec rubocop'],
|
|
88
|
+
['Flog Complexity', 'bundle exec rake flog_check'],
|
|
89
|
+
['Flay Duplication', 'bundle exec rake flay_check']
|
|
90
|
+
]
|
|
91
|
+
|
|
92
|
+
results = gates.map do |label, command|
|
|
93
|
+
puts "\n#{'=' * 60}"
|
|
94
|
+
puts "Quality Gate: #{label}"
|
|
95
|
+
puts '=' * 60
|
|
96
|
+
[label, system(command) ? :pass : :fail]
|
|
97
|
+
end
|
|
98
|
+
|
|
99
|
+
green = ->(s) { "\e[32m#{s}\e[0m" }
|
|
100
|
+
red = ->(s) { "\e[31m#{s}\e[0m" }
|
|
101
|
+
width = results.map { |label, _| label.length }.max
|
|
102
|
+
|
|
103
|
+
puts "\n#{'=' * 60}"
|
|
104
|
+
puts 'Quality Gate Summary'
|
|
105
|
+
puts '=' * 60
|
|
106
|
+
results.each do |label, status|
|
|
107
|
+
badge = status == :pass ? green.call('PASS') : red.call('FAIL')
|
|
108
|
+
puts " [#{badge}] #{label.ljust(width)}"
|
|
109
|
+
end
|
|
110
|
+
puts '-' * 60
|
|
111
|
+
|
|
112
|
+
passed = results.count { |_, s| s == :pass }
|
|
113
|
+
failed = results.count { |_, s| s == :fail }
|
|
114
|
+
tally = "#{passed} passed, #{failed} failed"
|
|
115
|
+
puts " #{failed.zero? ? green.call(tally) : red.call(tally)}"
|
|
116
|
+
puts '=' * 60
|
|
117
|
+
|
|
118
|
+
abort "\n#{red.call('Quality gate failed.')}" unless failed.zero?
|
|
119
|
+
puts "\n#{green.call('All quality gates passed.')}"
|
|
120
|
+
end
|
|
121
|
+
|
|
122
|
+
namespace :docs do
|
|
123
|
+
desc 'Build MkDocs documentation'
|
|
124
|
+
task :build do
|
|
125
|
+
sh 'mkdocs build'
|
|
126
|
+
end
|
|
127
|
+
|
|
128
|
+
desc 'Serve MkDocs documentation locally on http://localhost:8000'
|
|
129
|
+
task :serve do
|
|
130
|
+
sh 'mkdocs serve'
|
|
131
|
+
end
|
|
132
|
+
end
|
data/bin/robot-to
ADDED
|
@@ -0,0 +1,14 @@
|
|
|
1
|
+
#!/usr/bin/env ruby
|
|
2
|
+
# frozen_string_literal: true
|
|
3
|
+
|
|
4
|
+
# Activate bundler if running from the gem's own dev environment.
|
|
5
|
+
if File.exist?(File.expand_path("../Gemfile", __dir__))
|
|
6
|
+
require "bundler/setup"
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
require "robot_lab"
|
|
10
|
+
require "robot_lab/to"
|
|
11
|
+
|
|
12
|
+
Signal.trap("INT") { exit 130 }
|
|
13
|
+
|
|
14
|
+
RobotLab::To::CLI.run(ARGV)
|
|
@@ -0,0 +1,82 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
All notable changes to `robot_lab-to` are documented here. The format is based on
|
|
4
|
+
[Keep a Changelog](https://keepachangelog.com/), and the project follows
|
|
5
|
+
[Conventional Commits](https://www.conventionalcommits.org/) (see `COMMITS.md`).
|
|
6
|
+
|
|
7
|
+
## Unreleased
|
|
8
|
+
|
|
9
|
+
### Added
|
|
10
|
+
|
|
11
|
+
- **Evals: orchestrator-owned scoring.** An `Eval` scores each iteration's
|
|
12
|
+
working tree and returns a `Score(gate_ok, improved, met_target, value, detail,
|
|
13
|
+
output)` — the deciding authority for commit/rollback and, for measurable
|
|
14
|
+
objectives, for when the run is done — instead of the robot's self-reported
|
|
15
|
+
`should_fully_stop`. See [Evals](../concepts/evals.md).
|
|
16
|
+
- `Evals::Code` — measured/deterministic: the existing `--verify-command`
|
|
17
|
+
floor plus an optional `--measure CMD` (a command printing a number,
|
|
18
|
+
higher is better) and `--target FLOAT`. Fully backward compatible: with no
|
|
19
|
+
`--measure`, behaves exactly like the original verify-only gate.
|
|
20
|
+
- `Evals::Prose` — judged/pairwise: an LLM judge (`--judge-model`, defaults
|
|
21
|
+
to `--model`) compares the working tree against the last committed
|
|
22
|
+
version and rules it `better`/`worse`/`same`; an optional `--floor CMD`
|
|
23
|
+
gates mechanizable checks before the judge is called.
|
|
24
|
+
- `Evals::Null` — the default when nothing is configured; preserves the
|
|
25
|
+
original "commit any reported success" behavior exactly.
|
|
26
|
+
- `--eval NAME`, `--stop-on-plateau N`, `--[no-]require-improvement`, and
|
|
27
|
+
Ruby-API extension points (`RobotLab::To.register_eval`, an instance
|
|
28
|
+
responding to `#score`, or a bare proc, all passable as `eval:`).
|
|
29
|
+
- `require_improvement` (default **true**) rolls back a gate-passing
|
|
30
|
+
iteration that doesn't beat the parent's score, keeping the branch
|
|
31
|
+
strictly descending.
|
|
32
|
+
- `--stop-on-plateau N` — a new stop condition: abort after `N` iterations
|
|
33
|
+
with no committed improvement. The primary terminator for `Evals::Prose`,
|
|
34
|
+
which never sets a measurable target.
|
|
35
|
+
- `PromptBuilder` **Score Feedback** section — for scored runs, tells each
|
|
36
|
+
iteration's robot the best score committed so far, the target, and
|
|
37
|
+
whether recent attempts plateaued, so each attempt is a hypothesis
|
|
38
|
+
against the target instead of a blind guess.
|
|
39
|
+
- **`GraderLock` guard — grader lockdown.** Refuses `write`/`edit`/`bash` against
|
|
40
|
+
an eval's own grading criteria (`Evals::Prose#protected_paths`'s `--spec`, plus
|
|
41
|
+
any `--protect-path GLOB`), so the robot cannot "win" by rewriting the
|
|
42
|
+
criteria it is scored against. Unlike the small-model guardrails, it is always
|
|
43
|
+
installed when protected paths exist — independent of `--local-guards`. See
|
|
44
|
+
[Evals: Guarding the grader](../concepts/evals.md#guarding-the-grader-graderlock).
|
|
45
|
+
- **`write_guard` config (Ruby-only, default `true`).** Lets a `--local-guards`
|
|
46
|
+
run opt out of `Guards::WriteGuard` (`write_guard: false`) so the robot can
|
|
47
|
+
freely overwrite a file it is iteratively rewriting whole, e.g. a prose draft.
|
|
48
|
+
See [Guardrails](../local-models/guardrails.md#write-guard).
|
|
49
|
+
- **Local-model support.** Drive a local Ollama model end-to-end with
|
|
50
|
+
`--local-guards` and `--no-stream`. See [Local Models](../local-models/index.md).
|
|
51
|
+
- **Built-in workspace tools** (`read`, `write`, `edit`, `bash`) attached when
|
|
52
|
+
`--local-guards` is set. See [Built-in Tools](../local-models/tools.md).
|
|
53
|
+
- **Small-model guardrails** — `write-guard`, `read-before-edit`, `checkpoint`,
|
|
54
|
+
and `quality-monitor` hooks. See [Guardrails](../local-models/guardrails.md).
|
|
55
|
+
- **`stream` setting** (`--no-stream`) — disable response streaming, required for
|
|
56
|
+
Ollama tool calls; tokens are then accounted from each iteration's result.
|
|
57
|
+
- This documentation site.
|
|
58
|
+
|
|
59
|
+
### Fixed
|
|
60
|
+
|
|
61
|
+
- Tools were passed to `RobotLab.build` via `tools:` (a name allowlist filter)
|
|
62
|
+
instead of `local_tools:` (the instance list), so the `submit_iteration_result`
|
|
63
|
+
tool was never attached to the robot. Now passed via `local_tools:`, with a
|
|
64
|
+
regression test asserting the built robot exposes the tool.
|
|
65
|
+
|
|
66
|
+
## 0.1.0
|
|
67
|
+
|
|
68
|
+
Initial release.
|
|
69
|
+
|
|
70
|
+
### Added
|
|
71
|
+
|
|
72
|
+
- Autonomous overnight loop (`Orchestrator`): fresh robot per iteration, commit on
|
|
73
|
+
success, `git reset --hard` on failure.
|
|
74
|
+
- `SubmitResult` tool and `IterationResult` value object.
|
|
75
|
+
- Cross-iteration memory via `notes.md` (`NotesManager`).
|
|
76
|
+
- Stop conditions: `--max-iterations`, `--max-tokens`,
|
|
77
|
+
`--max-consecutive-failures`, and natural-language `--stop-when`.
|
|
78
|
+
- Independent verification gate (`--verify-command`, `Verifier`).
|
|
79
|
+
- Interruptible exponential `Backoff` for transient-error retries.
|
|
80
|
+
- JSONL event log (`JsonlLogger`) and post-run `ExitSummary`.
|
|
81
|
+
- `robot-to` CLI and `RobotLab::To.run` programmatic entry point.
|
|
82
|
+
- `Config` cascade (`myway_config`): defaults → user file → env → CLI.
|
|
@@ -0,0 +1,110 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 900 640" font-family="Helvetica, Arial, sans-serif" role="img" aria-label="robot-to architecture">
|
|
2
|
+
<defs>
|
|
3
|
+
<marker id="a" markerWidth="9" markerHeight="9" refX="7" refY="3" orient="auto" markerUnits="strokeWidth">
|
|
4
|
+
<path d="M0,0 L7,3 L0,6 Z" fill="#94a3b8"/>
|
|
5
|
+
</marker>
|
|
6
|
+
</defs>
|
|
7
|
+
<style>
|
|
8
|
+
.t { fill:#ffffff; font-size:13px; font-weight:600; }
|
|
9
|
+
.s { fill:#e2e8f0; font-size:10px; }
|
|
10
|
+
.hd { fill:#cbd5e1; font-size:12px; font-weight:700; letter-spacing:.5px; }
|
|
11
|
+
.lg { fill:#cbd5e1; font-size:11px; }
|
|
12
|
+
</style>
|
|
13
|
+
|
|
14
|
+
<!-- CLI / entry -->
|
|
15
|
+
<rect x="360" y="16" width="180" height="46" rx="10" fill="#0ea5e9"/>
|
|
16
|
+
<text x="450" y="38" text-anchor="middle" class="t">robot-to CLI / To.run</text>
|
|
17
|
+
<text x="450" y="54" text-anchor="middle" class="s">CLI · Config (myway_config)</text>
|
|
18
|
+
<line x1="450" y1="62" x2="450" y2="86" stroke="#94a3b8" stroke-width="2" marker-end="url(#a)"/>
|
|
19
|
+
|
|
20
|
+
<!-- Orchestrator -->
|
|
21
|
+
<rect x="330" y="88" width="240" height="52" rx="10" fill="#475569"/>
|
|
22
|
+
<text x="450" y="110" text-anchor="middle" class="t">Orchestrator</text>
|
|
23
|
+
<text x="450" y="127" text-anchor="middle" class="s">main loop · setup → iterate → finalize</text>
|
|
24
|
+
|
|
25
|
+
<!-- collaborators row -->
|
|
26
|
+
<text x="60" y="172" class="hd">PER-RUN COLLABORATORS</text>
|
|
27
|
+
<g>
|
|
28
|
+
<rect x="40" y="184" width="150" height="46" rx="9" fill="#6366f1"/>
|
|
29
|
+
<text x="115" y="205" text-anchor="middle" class="t">PromptBuilder</text>
|
|
30
|
+
<text x="115" y="221" text-anchor="middle" class="s">per-iteration system prompt</text>
|
|
31
|
+
|
|
32
|
+
<rect x="200" y="184" width="150" height="46" rx="9" fill="#f59e0b"/>
|
|
33
|
+
<text x="275" y="205" text-anchor="middle" class="t">CommitManager</text>
|
|
34
|
+
<text x="275" y="221" text-anchor="middle" class="s">git via Open3 (no shell)</text>
|
|
35
|
+
|
|
36
|
+
<rect x="360" y="184" width="150" height="46" rx="9" fill="#a855f7"/>
|
|
37
|
+
<text x="435" y="205" text-anchor="middle" class="t">NotesManager</text>
|
|
38
|
+
<text x="435" y="221" text-anchor="middle" class="s">notes.md memory</text>
|
|
39
|
+
|
|
40
|
+
<rect x="520" y="184" width="150" height="46" rx="9" fill="#64748b"/>
|
|
41
|
+
<text x="595" y="205" text-anchor="middle" class="t">StopConditions</text>
|
|
42
|
+
<text x="595" y="221" text-anchor="middle" class="s">iters · tokens · failures</text>
|
|
43
|
+
|
|
44
|
+
<rect x="680" y="184" width="160" height="46" rx="9" fill="#64748b"/>
|
|
45
|
+
<text x="760" y="205" text-anchor="middle" class="t">Verifier</text>
|
|
46
|
+
<text x="760" y="221" text-anchor="middle" class="s">independent test gate</text>
|
|
47
|
+
</g>
|
|
48
|
+
<g>
|
|
49
|
+
<rect x="120" y="244" width="150" height="46" rx="9" fill="#64748b"/>
|
|
50
|
+
<text x="195" y="265" text-anchor="middle" class="t">Backoff</text>
|
|
51
|
+
<text x="195" y="281" text-anchor="middle" class="s">interruptible retry</text>
|
|
52
|
+
|
|
53
|
+
<rect x="280" y="244" width="150" height="46" rx="9" fill="#64748b"/>
|
|
54
|
+
<text x="355" y="265" text-anchor="middle" class="t">JsonlLogger</text>
|
|
55
|
+
<text x="355" y="281" text-anchor="middle" class="s">run.log events</text>
|
|
56
|
+
|
|
57
|
+
<rect x="440" y="244" width="150" height="46" rx="9" fill="#64748b"/>
|
|
58
|
+
<text x="515" y="265" text-anchor="middle" class="t">ExitSummary</text>
|
|
59
|
+
<text x="515" y="281" text-anchor="middle" class="s">post-run report</text>
|
|
60
|
+
|
|
61
|
+
<rect x="600" y="244" width="150" height="46" rx="9" fill="#a855f7"/>
|
|
62
|
+
<text x="675" y="265" text-anchor="middle" class="t">Run</text>
|
|
63
|
+
<text x="675" y="281" text-anchor="middle" class="s">run state object</text>
|
|
64
|
+
</g>
|
|
65
|
+
<line x1="450" y1="140" x2="450" y2="180" stroke="#94a3b8" stroke-width="2" marker-end="url(#a)"/>
|
|
66
|
+
|
|
67
|
+
<!-- robot -->
|
|
68
|
+
<text x="60" y="330" class="hd">PER-ITERATION ROBOT (RobotLab)</text>
|
|
69
|
+
<rect x="330" y="342" width="240" height="50" rx="10" fill="#3b82f6"/>
|
|
70
|
+
<text x="450" y="364" text-anchor="middle" class="t">RobotLab::Robot</text>
|
|
71
|
+
<text x="450" y="380" text-anchor="middle" class="s">RubyLLM agent · persistent chat</text>
|
|
72
|
+
<line x1="450" y1="290" x2="450" y2="340" stroke="#94a3b8" stroke-width="2" marker-end="url(#a)"/>
|
|
73
|
+
|
|
74
|
+
<!-- tools -->
|
|
75
|
+
<rect x="120" y="420" width="150" height="46" rx="9" fill="#16a34a"/>
|
|
76
|
+
<text x="195" y="441" text-anchor="middle" class="t">SubmitResult</text>
|
|
77
|
+
<text x="195" y="457" text-anchor="middle" class="s">reports iteration result</text>
|
|
78
|
+
|
|
79
|
+
<rect x="290" y="420" width="320" height="46" rx="9" fill="#16a34a"/>
|
|
80
|
+
<text x="450" y="441" text-anchor="middle" class="t">File tools — read · write · edit · bash</text>
|
|
81
|
+
<text x="450" y="457" text-anchor="middle" class="s">attached only when local_guards is on</text>
|
|
82
|
+
<line x1="420" y1="392" x2="240" y2="418" stroke="#94a3b8" stroke-width="2" marker-end="url(#a)"/>
|
|
83
|
+
<line x1="460" y1="392" x2="460" y2="418" stroke="#94a3b8" stroke-width="2" marker-end="url(#a)"/>
|
|
84
|
+
|
|
85
|
+
<!-- guards -->
|
|
86
|
+
<text x="630" y="412" class="hd">GUARDRAILS (Hooks)</text>
|
|
87
|
+
<rect x="630" y="420" width="250" height="92" rx="10" fill="#dc2626"/>
|
|
88
|
+
<text x="755" y="440" text-anchor="middle" class="t">RobotLab::Hook guards</text>
|
|
89
|
+
<text x="755" y="460" text-anchor="middle" class="s">write_guard · read_before_edit</text>
|
|
90
|
+
<text x="755" y="476" text-anchor="middle" class="s">checkpoint · quality_monitor</text>
|
|
91
|
+
<text x="755" y="496" text-anchor="middle" class="s">intercept tool calls for small models</text>
|
|
92
|
+
<line x1="610" y1="450" x2="628" y2="455" stroke="#94a3b8" stroke-width="2" marker-end="url(#a)"/>
|
|
93
|
+
|
|
94
|
+
<!-- run state output -->
|
|
95
|
+
<rect x="290" y="540" width="320" height="60" rx="10" fill="#334155"/>
|
|
96
|
+
<text x="450" y="562" text-anchor="middle" class="t">.robot_lab_to/runs/<run_id>/</text>
|
|
97
|
+
<text x="450" y="580" text-anchor="middle" class="s">notes.md · run.log (JSONL) · checkpoints/</text>
|
|
98
|
+
<text x="450" y="595" text-anchor="middle" class="s">+ git branch robot-to/<slug></text>
|
|
99
|
+
<line x1="450" y1="466" x2="450" y2="538" stroke="#94a3b8" stroke-width="2" marker-end="url(#a)"/>
|
|
100
|
+
|
|
101
|
+
<!-- legend -->
|
|
102
|
+
<g transform="translate(40,548)">
|
|
103
|
+
<rect x="0" y="0" width="14" height="11" rx="3" fill="#475569"/><text x="20" y="9" class="lg">orchestrator / control</text>
|
|
104
|
+
<rect x="0" y="18" width="14" height="11" rx="3" fill="#3b82f6"/><text x="20" y="27" class="lg">robot / LLM</text>
|
|
105
|
+
<rect x="0" y="36" width="14" height="11" rx="3" fill="#16a34a"/><text x="20" y="45" class="lg">tools</text>
|
|
106
|
+
<rect x="140" y="0" width="14" height="11" rx="3" fill="#dc2626"/><text x="160" y="9" class="lg">guardrails</text>
|
|
107
|
+
<rect x="140" y="18" width="14" height="11" rx="3" fill="#a855f7"/><text x="160" y="27" class="lg">memory / state</text>
|
|
108
|
+
<rect x="140" y="36" width="14" height="11" rx="3" fill="#f59e0b"/><text x="160" y="45" class="lg">git</text>
|
|
109
|
+
</g>
|
|
110
|
+
</svg>
|
|
Binary file
|
|
@@ -0,0 +1,97 @@
|
|
|
1
|
+
<svg xmlns="http://www.w3.org/2000/svg" viewBox="0 0 880 720" font-family="Helvetica, Arial, sans-serif" role="img" aria-label="The robot-to iteration loop">
|
|
2
|
+
<!-- transparent background: no background rect -->
|
|
3
|
+
<defs>
|
|
4
|
+
<marker id="arrow" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth">
|
|
5
|
+
<path d="M0,0 L8,3 L0,6 Z" fill="#94a3b8"/>
|
|
6
|
+
</marker>
|
|
7
|
+
<marker id="arrowGreen" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth">
|
|
8
|
+
<path d="M0,0 L8,3 L0,6 Z" fill="#22c55e"/>
|
|
9
|
+
</marker>
|
|
10
|
+
<marker id="arrowRed" markerWidth="10" markerHeight="10" refX="8" refY="3" orient="auto" markerUnits="strokeWidth">
|
|
11
|
+
<path d="M0,0 L8,3 L0,6 Z" fill="#ef4444"/>
|
|
12
|
+
</marker>
|
|
13
|
+
</defs>
|
|
14
|
+
|
|
15
|
+
<style>
|
|
16
|
+
.label { fill: #ffffff; font-size: 14px; font-weight: 600; }
|
|
17
|
+
.sub { fill: #e2e8f0; font-size: 11px; }
|
|
18
|
+
.edge { fill: #cbd5e1; font-size: 12px; font-weight: 600; }
|
|
19
|
+
.legend{ fill: #cbd5e1; font-size: 12px; }
|
|
20
|
+
</style>
|
|
21
|
+
|
|
22
|
+
<!-- setup -->
|
|
23
|
+
<rect x="300" y="20" width="280" height="54" rx="10" fill="#475569"/>
|
|
24
|
+
<text x="440" y="42" text-anchor="middle" class="label">setup_run</text>
|
|
25
|
+
<text x="440" y="60" text-anchor="middle" class="sub">create branch · init notes.md · base commit</text>
|
|
26
|
+
<line x1="440" y1="74" x2="440" y2="100" stroke="#94a3b8" stroke-width="2" marker-end="url(#arrow)"/>
|
|
27
|
+
|
|
28
|
+
<!-- build robot -->
|
|
29
|
+
<rect x="300" y="102" width="280" height="54" rx="10" fill="#3b82f6"/>
|
|
30
|
+
<text x="440" y="124" text-anchor="middle" class="label">build fresh Robot</text>
|
|
31
|
+
<text x="440" y="142" text-anchor="middle" class="sub">system prompt + notes + tools (per iteration)</text>
|
|
32
|
+
<line x1="440" y1="156" x2="440" y2="182" stroke="#94a3b8" stroke-width="2" marker-end="url(#arrow)"/>
|
|
33
|
+
|
|
34
|
+
<!-- run -->
|
|
35
|
+
<rect x="300" y="184" width="280" height="54" rx="10" fill="#3b82f6"/>
|
|
36
|
+
<text x="440" y="206" text-anchor="middle" class="label">robot.run — do work via tools</text>
|
|
37
|
+
<text x="440" y="224" text-anchor="middle" class="sub">read/write/edit/bash · then submit_result</text>
|
|
38
|
+
<line x1="440" y1="238" x2="440" y2="264" stroke="#94a3b8" stroke-width="2" marker-end="url(#arrow)"/>
|
|
39
|
+
|
|
40
|
+
<!-- submitted? -->
|
|
41
|
+
<polygon points="440,266 560,310 440,354 320,310" fill="#64748b"/>
|
|
42
|
+
<text x="440" y="306" text-anchor="middle" class="label">submitted?</text>
|
|
43
|
+
<text x="440" y="324" text-anchor="middle" class="sub">called submit_result</text>
|
|
44
|
+
<!-- no -> nudge -->
|
|
45
|
+
<line x1="560" y1="310" x2="650" y2="310" stroke="#94a3b8" stroke-width="2" marker-end="url(#arrow)"/>
|
|
46
|
+
<text x="600" y="300" text-anchor="middle" class="edge">no</text>
|
|
47
|
+
<rect x="650" y="284" width="190" height="52" rx="10" fill="#475569"/>
|
|
48
|
+
<text x="745" y="306" text-anchor="middle" class="label">nudge robot</text>
|
|
49
|
+
<text x="745" y="323" text-anchor="middle" class="sub">re-ask up to max_submit_nudges</text>
|
|
50
|
+
<path d="M745,284 C745,240 620,250 560,290" fill="none" stroke="#94a3b8" stroke-width="2" stroke-dasharray="4 3" marker-end="url(#arrow)"/>
|
|
51
|
+
|
|
52
|
+
<!-- success? -->
|
|
53
|
+
<line x1="440" y1="354" x2="440" y2="384" stroke="#94a3b8" stroke-width="2" marker-end="url(#arrow)"/>
|
|
54
|
+
<text x="455" y="372" class="edge">yes</text>
|
|
55
|
+
<polygon points="440,386 560,430 440,474 320,430" fill="#64748b"/>
|
|
56
|
+
<text x="440" y="426" text-anchor="middle" class="label">success?</text>
|
|
57
|
+
<text x="440" y="444" text-anchor="middle" class="sub">+ verify_command</text>
|
|
58
|
+
|
|
59
|
+
<!-- success path: verify ok -> commit -->
|
|
60
|
+
<line x1="440" y1="474" x2="440" y2="504" stroke="#22c55e" stroke-width="2" marker-end="url(#arrowGreen)"/>
|
|
61
|
+
<text x="455" y="492" class="edge">pass</text>
|
|
62
|
+
<rect x="300" y="506" width="280" height="54" rx="10" fill="#22c55e"/>
|
|
63
|
+
<text x="440" y="528" text-anchor="middle" class="label">git add -A & commit</text>
|
|
64
|
+
<text x="440" y="546" text-anchor="middle" class="sub">one focused change committed</text>
|
|
65
|
+
|
|
66
|
+
<!-- failure path: reset -->
|
|
67
|
+
<line x1="320" y1="430" x2="150" y2="430" stroke="#ef4444" stroke-width="2" marker-end="url(#arrowRed)"/>
|
|
68
|
+
<text x="235" y="420" text-anchor="middle" class="edge">fail / no submit</text>
|
|
69
|
+
<rect x="20" y="404" width="130" height="52" rx="10" fill="#ef4444"/>
|
|
70
|
+
<text x="85" y="426" text-anchor="middle" class="label">git reset</text>
|
|
71
|
+
<text x="85" y="443" text-anchor="middle" class="sub">--hard + clean</text>
|
|
72
|
+
|
|
73
|
+
<!-- notes update (purple) collects both paths -->
|
|
74
|
+
<line x1="440" y1="560" x2="440" y2="588" stroke="#94a3b8" stroke-width="2" marker-end="url(#arrow)"/>
|
|
75
|
+
<path d="M85,456 C85,600 250,600 298,600" fill="none" stroke="#94a3b8" stroke-width="2" marker-end="url(#arrow)"/>
|
|
76
|
+
<rect x="300" y="590" width="280" height="50" rx="10" fill="#a855f7"/>
|
|
77
|
+
<text x="440" y="612" text-anchor="middle" class="label">append to notes.md</text>
|
|
78
|
+
<text x="440" y="629" text-anchor="middle" class="sub">cross-iteration memory</text>
|
|
79
|
+
|
|
80
|
+
<!-- stop conditions -->
|
|
81
|
+
<line x1="440" y1="640" x2="440" y2="664" stroke="#94a3b8" stroke-width="2" marker-end="url(#arrow)"/>
|
|
82
|
+
<rect x="300" y="666" width="280" height="44" rx="10" fill="#475569"/>
|
|
83
|
+
<text x="440" y="693" text-anchor="middle" class="label">stop conditions met? — else loop ↻</text>
|
|
84
|
+
|
|
85
|
+
<!-- loop back arrow -->
|
|
86
|
+
<path d="M300,688 C120,688 120,129 298,129" fill="none" stroke="#94a3b8" stroke-width="2" stroke-dasharray="6 4" marker-end="url(#arrow)"/>
|
|
87
|
+
<text x="95" y="410" text-anchor="middle" class="edge" transform="rotate(-90 95 410)">next iteration</text>
|
|
88
|
+
|
|
89
|
+
<!-- legend -->
|
|
90
|
+
<g transform="translate(620,560)">
|
|
91
|
+
<rect x="0" y="0" width="16" height="12" rx="3" fill="#3b82f6"/><text x="22" y="10" class="legend">robot / LLM</text>
|
|
92
|
+
<rect x="0" y="22" width="16" height="12" rx="3" fill="#22c55e"/><text x="22" y="32" class="legend">commit (success)</text>
|
|
93
|
+
<rect x="0" y="44" width="16" height="12" rx="3" fill="#ef4444"/><text x="22" y="54" class="legend">rollback (failure)</text>
|
|
94
|
+
<rect x="0" y="66" width="16" height="12" rx="3" fill="#a855f7"/><text x="22" y="76" class="legend">notes / memory</text>
|
|
95
|
+
<rect x="0" y="88" width="16" height="12" rx="3" fill="#475569"/><text x="22" y="98" class="legend">orchestrator control</text>
|
|
96
|
+
</g>
|
|
97
|
+
</svg>
|