whiletrue 0.1.0__tar.gz → 0.2.0__tar.gz
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.
- {whiletrue-0.1.0 → whiletrue-0.2.0}/CHANGELOG.md +10 -0
- whiletrue-0.2.0/PKG-INFO +280 -0
- whiletrue-0.2.0/README.md +253 -0
- whiletrue-0.2.0/THIRD_PARTY_NOTICES.md +32 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/docs/README.md +4 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/docs/architecture.md +70 -0
- whiletrue-0.2.0/docs/assets/architecture.svg +51 -0
- whiletrue-0.2.0/docs/assets/demo-real.svg +1 -0
- whiletrue-0.2.0/docs/assets/issue-loop.svg +17 -0
- whiletrue-0.2.0/docs/assets/logo.svg +7 -0
- whiletrue-0.2.0/docs/assets/ralph-loop.svg +17 -0
- whiletrue-0.2.0/docs/assets/rsi-architecture.svg +69 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/docs/cli.md +5 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/docs/getting-started.md +2 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/docs/open-questions.md +8 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/docs/plan.md +26 -2
- {whiletrue-0.1.0 → whiletrue-0.2.0}/docs/reference.md +11 -0
- whiletrue-0.2.0/docs/rsi-plan.md +121 -0
- whiletrue-0.2.0/docs/rsi.md +127 -0
- whiletrue-0.2.0/docs/spike-rsi.md +66 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/docs/todo.md +51 -3
- whiletrue-0.2.0/docs/tutorial.md +250 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/pyproject.toml +6 -4
- whiletrue-0.2.0/scripts/check_provenance.py +63 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/scripts/docs_check.py +4 -1
- whiletrue-0.2.0/tests/fixtures/fake_rsi_claude.py +65 -0
- whiletrue-0.2.0/tests/integration/test_rsi_cli.py +166 -0
- whiletrue-0.2.0/tests/live/test_live_rsi.py +69 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/basics/test_agent.py +29 -1
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/claude_code/test_headless.py +16 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/core/test_runtime.py +39 -0
- whiletrue-0.2.0/tests/unit/rsi/harness2/conftest.py +219 -0
- whiletrue-0.2.0/tests/unit/rsi/harness2/test_apply_adopt.py +340 -0
- whiletrue-0.2.0/tests/unit/rsi/harness2/test_context_library_selection.py +162 -0
- whiletrue-0.2.0/tests/unit/rsi/harness2/test_edges.py +217 -0
- whiletrue-0.2.0/tests/unit/rsi/harness2/test_prompts.py +68 -0
- whiletrue-0.2.0/tests/unit/rsi/harness2/test_runmark_ledger.py +79 -0
- whiletrue-0.2.0/tests/unit/rsi/harness2/test_sessions_proposal.py +133 -0
- whiletrue-0.2.0/tests/unit/rsi/harness2/test_snapshot_trajectory.py +177 -0
- whiletrue-0.2.0/tests/unit/rsi/harness2/test_strategy.py +174 -0
- whiletrue-0.2.0/tests/unit/rsi/harness2/test_tree.py +179 -0
- whiletrue-0.2.0/tests/unit/test_provenance.py +80 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/tmux/test_controller.py +37 -0
- whiletrue-0.2.0/third_party/README.md +7 -0
- whiletrue-0.2.0/third_party/harness2/LICENSE +202 -0
- whiletrue-0.2.0/third_party/harness2/PROVENANCE.md +44 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/uv.lock +1 -1
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/basics/agent.py +12 -2
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/claude_code/headless.py +2 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/cli/app.py +31 -2
- whiletrue-0.2.0/whiletrue/cli/rsi_cmd.py +142 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/core/runner.py +3 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/core/runtime.py +4 -1
- whiletrue-0.2.0/whiletrue/rsi/__init__.py +25 -0
- whiletrue-0.2.0/whiletrue/rsi/harness2/__init__.py +4 -0
- whiletrue-0.2.0/whiletrue/rsi/harness2/adopt.py +113 -0
- whiletrue-0.2.0/whiletrue/rsi/harness2/apply.py +159 -0
- whiletrue-0.2.0/whiletrue/rsi/harness2/config.py +140 -0
- whiletrue-0.2.0/whiletrue/rsi/harness2/context.py +285 -0
- whiletrue-0.2.0/whiletrue/rsi/harness2/env.py +63 -0
- whiletrue-0.2.0/whiletrue/rsi/harness2/ledger.py +128 -0
- whiletrue-0.2.0/whiletrue/rsi/harness2/library.py +206 -0
- whiletrue-0.2.0/whiletrue/rsi/harness2/prompts.py +572 -0
- whiletrue-0.2.0/whiletrue/rsi/harness2/proposal.py +122 -0
- whiletrue-0.2.0/whiletrue/rsi/harness2/rollout.py +156 -0
- whiletrue-0.2.0/whiletrue/rsi/harness2/runmark.py +120 -0
- whiletrue-0.2.0/whiletrue/rsi/harness2/selection.py +118 -0
- whiletrue-0.2.0/whiletrue/rsi/harness2/sessions.py +357 -0
- whiletrue-0.2.0/whiletrue/rsi/harness2/snapshot.py +235 -0
- whiletrue-0.2.0/whiletrue/rsi/harness2/strategy.py +432 -0
- whiletrue-0.2.0/whiletrue/rsi/harness2/surfaces.py +182 -0
- whiletrue-0.2.0/whiletrue/rsi/harness2/trajectory.py +86 -0
- whiletrue-0.2.0/whiletrue/rsi/harness2/tree.py +426 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/tmux/controller.py +13 -0
- whiletrue-0.1.0/PKG-INFO +0 -48
- whiletrue-0.1.0/README.md +0 -23
- {whiletrue-0.1.0 → whiletrue-0.2.0}/.editorconfig +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/.envrc +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/.github/ISSUE_TEMPLATE/task.md +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/.github/pull_request_template.md +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/.github/workflows/ci.yml +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/.github/workflows/release.yml +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/.gitignore +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/CLAUDE.md +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/LICENSE +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/devenv.lock +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/devenv.nix +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/devenv.yaml +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/docs/authoring.md +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/docs/conventions.md +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/docs/developing.md +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/docs/m0-smoke.md +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/docs/plugins.md +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/docs/spike-interactive.md +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/examples/issue-loop/README.md +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/examples/issue-loop/agents/fix.md +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/examples/issue-loop/agents/implement.md +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/examples/issue-loop/agents/respond.md +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/examples/issue-loop/whiletrue.yaml +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/conftest.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/fixtures/fake_interactive_claude.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/integration/test_cli.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/integration/test_cli_surface.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/integration/test_gates_cli.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/integration/test_interactive_run.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/integration/test_issue_loop.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/integration/test_m3_exit.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/integration/test_ops_cli.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/integration/test_recipes.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/live/test_live_backends.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/basics/test_exec.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/basics/test_gates.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/basics/test_history.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/basics/test_human.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/basics/test_json_source.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/basics/test_markdown_source.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/basics/test_plugin.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/basics/test_process.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/basics/test_sessions.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/basics/test_shell.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/claude_code/test_endpoint.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/claude_code/test_interactive.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/claude_code/test_panes.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/claude_code/test_plugin_scripts.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/claude_code/test_session.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/claude_code/test_transcript.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/codex/test_runner.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/control/test_control.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/core/test_cache.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/core/test_caps.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/core/test_composite.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/core/test_config.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/core/test_context.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/core/test_duration.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/core/test_events.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/core/test_expr.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/core/test_history_store.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/core/test_lock.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/core/test_memory_store.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/core/test_module.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/core/test_outcomes.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/core/test_registry.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/core/test_replay.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/core/test_template.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/core/test_validate.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/core/test_wake.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/git/test_git.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/github/test_client.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/github/test_filebacked.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/github/test_plugin.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/github/test_specs.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/opencode/test_runner.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/store_sqlite/test_sqlite_store.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/test_abort.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/test_architecture.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/tests/unit/test_panel.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/__init__.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/__main__.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/abort.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/basics/__init__.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/basics/comments.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/basics/diff_size.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/basics/exec_.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/basics/history.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/basics/human.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/basics/json_source.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/basics/markdown_source.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/basics/process.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/basics/sessions.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/basics/set_.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/basics/shell.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/basics/wake.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/claude_code/__init__.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/claude_code/endpoint.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/claude_code/interactive.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/claude_code/learnings.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/claude_code/panes.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/claude_code/plugin/.claude-plugin/plugin.json +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/claude_code/plugin/hook.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/claude_code/plugin/hooks/hooks.json +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/claude_code/plugin/mcp_server.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/claude_code/session.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/claude_code/transcript.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/cli/__init__.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/cli/__main__.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/cli/common.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/cli/gates.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/cli/ops.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/cli/panel.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/cli/registry.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/cli/templates.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/codex/__init__.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/codex/runner.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/control/__init__.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/control/chain.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/control/loop.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/control/map_.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/control/parallel.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/control/retry.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/control/sequence.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/control/switch.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/core/__init__.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/core/caps.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/core/comments.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/core/composite.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/core/config.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/core/context.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/core/duration.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/core/events.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/core/expr.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/core/history.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/core/lock.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/core/memory_store.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/core/module.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/core/outcomes.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/core/registry.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/core/replay.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/core/source.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/core/store.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/core/template.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/core/validate.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/core/wake.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/core/workspace.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/git/__init__.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/git/modules.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/git/workspaces.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/github/__init__.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/github/client.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/github/filebacked.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/github/memory.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/github/plugin.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/github/specs.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/opencode/__init__.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/opencode/runner.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/py.typed +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/recipes/issue-loop.yaml +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/recipes/ralph.yaml +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/recipes/review-pass.yaml +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/recipes/review-respond.yaml +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/store_sqlite/__init__.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/store_sqlite/migrations.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/store_sqlite/sqlite_store.py +0 -0
- {whiletrue-0.1.0 → whiletrue-0.2.0}/whiletrue/tmux/__init__.py +0 -0
|
@@ -1,5 +1,15 @@
|
|
|
1
1
|
# Changelog
|
|
2
2
|
|
|
3
|
+
## 0.2.0
|
|
4
|
+
|
|
5
|
+
- **Recursive self-improvement (`rsi`), off by default.** The Harness² method (Xu et al., arXiv:2610.14224) ported into `whiletrue.rsi.harness2`: isolated rollouts, improver sessions that edit the harness, composition, blind selection, a per-domain experience library, human-approved adoption, `rsi.budget_usd` and the R = 4k / P = 3k budget identity. New: top-level `rsi:` setting, strategy `rsi.harness2`, `whiletrue rsi status|diff|library|adopt|reset`. Claude Code and Codex surfaces. Apache-2.0 code keeps its headers; see THIRD_PARTY_NOTICES.md. Guide: docs/rsi.md.
|
|
6
|
+
- Core: a scope can redirect its steps to another directory (`cwd`), runners can pass raw messages (`RunContext.on_raw`), agents expose an event tap, and the item scope has `project_dir`.
|
|
7
|
+
|
|
8
|
+
## 0.1.1
|
|
9
|
+
|
|
10
|
+
- Fixed: parallel interactive items raced to create the tmux session. The loser failed with `duplicate session` and that error was fed to the agent as its previous failure. Session and pane creation now run one at a time, and parallel agents share one window grid.
|
|
11
|
+
- Docs: a new README with a recording of a real run, architecture and flow diagrams, and a step-by-step tutorial (`docs/tutorial.md`).
|
|
12
|
+
|
|
3
13
|
## 0.1.0 (first release)
|
|
4
14
|
|
|
5
15
|
whiletrue runs configurable pipelines of agentic and deterministic steps around coding agents.
|
whiletrue-0.2.0/PKG-INFO
ADDED
|
@@ -0,0 +1,280 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: whiletrue
|
|
3
|
+
Version: 0.2.0
|
|
4
|
+
Summary: Local orchestrator that runs pipelines of agent and deterministic steps around Claude Code, opencode and Codex, with gates, human approval, parallel git worktrees and crash-safe resume.
|
|
5
|
+
Project-URL: Repository, https://github.com/dariussingh/whiletrue
|
|
6
|
+
Project-URL: Changelog, https://github.com/dariussingh/whiletrue/blob/main/CHANGELOG.md
|
|
7
|
+
Project-URL: Documentation, https://github.com/dariussingh/whiletrue/tree/main/docs
|
|
8
|
+
Author: Darius Singh
|
|
9
|
+
License-Expression: MIT
|
|
10
|
+
License-File: LICENSE
|
|
11
|
+
License-File: THIRD_PARTY_NOTICES.md
|
|
12
|
+
License-File: third_party/harness2/LICENSE
|
|
13
|
+
Keywords: agents,ai-agents,claude-code,codex,coding-agents,git-worktree,human-in-the-loop,opencode,orchestration,pipelines,ralph,recursive-self-improvement,tmux
|
|
14
|
+
Classifier: Development Status :: 4 - Beta
|
|
15
|
+
Classifier: Environment :: Console
|
|
16
|
+
Classifier: Intended Audience :: Developers
|
|
17
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
18
|
+
Classifier: Operating System :: POSIX
|
|
19
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
20
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
21
|
+
Classifier: Typing :: Typed
|
|
22
|
+
Requires-Python: >=3.12
|
|
23
|
+
Requires-Dist: common-expression-language<1,>=0.10
|
|
24
|
+
Requires-Dist: pydantic<3,>=2.9
|
|
25
|
+
Requires-Dist: pyyaml<7,>=6
|
|
26
|
+
Description-Content-Type: text/markdown
|
|
27
|
+
|
|
28
|
+
<div align="center">
|
|
29
|
+
|
|
30
|
+
<img src="docs/assets/logo.svg" alt="whiletrue logo" width="96" height="96">
|
|
31
|
+
|
|
32
|
+
# whiletrue
|
|
33
|
+
|
|
34
|
+
**The loop around your coding agents.**
|
|
35
|
+
|
|
36
|
+
Run pipelines of agentic and deterministic steps around Claude Code, opencode and Codex, locally, with gates, humans in the loop, and crash-safe resume.
|
|
37
|
+
|
|
38
|
+
[](https://pypi.org/project/whiletrue/)
|
|
39
|
+
[](https://pypi.org/project/whiletrue/)
|
|
40
|
+
[](LICENSE)
|
|
41
|
+
[](docs/README.md)
|
|
42
|
+
|
|
43
|
+
</div>
|
|
44
|
+
|
|
45
|
+
> LangGraph builds the agent; whiletrue runs the loop around agents you already have.
|
|
46
|
+
|
|
47
|
+
<div align="center">
|
|
48
|
+
|
|
49
|
+
<img src="docs/assets/demo-real.svg" alt="Recording of a real run: two Claude Code agents work in parallel in tmux panes while a control panel and shell show status, both items pass their pytest gate and park for human approval, then approve and resume finish them" width="900">
|
|
50
|
+
|
|
51
|
+
<sub>A real run, not a mock-up: two Claude Code agents in parallel, a pytest gate, a human approval and a resume, about $0.23 in total. Captured from the live tmux panes; the two tmux windows are drawn side by side.</sub>
|
|
52
|
+
|
|
53
|
+
</div>
|
|
54
|
+
|
|
55
|
+
```bash
|
|
56
|
+
uvx whiletrue init # scaffold a Ralph loop
|
|
57
|
+
uvx whiletrue run # agent -> pytest gate -> repeat until green
|
|
58
|
+
```
|
|
59
|
+
|
|
60
|
+
## Overview
|
|
61
|
+
|
|
62
|
+
Coding agents are good at one task and bad at finishing a backlog unattended. whiletrue is the orchestrator you put around them. You describe the loop in a single `whiletrue.yaml`: which agent does the work, which deterministic gate checks it, when to retry, when to ask a person. whiletrue validates the config before spending a token, runs it, and records every step so you can inspect, replay or resume it.
|
|
63
|
+
|
|
64
|
+
- **Pipelines, not prompts.** Agent steps, shell and git steps, and gates compose with `sequence`, `loop`, `map`, `parallel`, `switch`, `retry`, `try` and `human.approve`. Every loop is bounded.
|
|
65
|
+
- **Any backend.** `claude-code-headless`, `claude-code` (the real interactive CLI in a tmux pane you can type into), `opencode` and `codex`. Mix them in one pipeline.
|
|
66
|
+
- **Many items at once.** One item per task or GitHub issue, each in its own git worktree, with `parallel: N` and a cap on live agent sessions.
|
|
67
|
+
- **Humans in the loop.** A gate parks an item until a person approves, rejects or comments; other items keep running. Every review comment gets an answer.
|
|
68
|
+
- **Durable.** State lives in SQLite. Kill the process at any point and `whiletrue resume` replays finished steps instead of redoing them; side effects (PRs, merges, replies) happen exactly once.
|
|
69
|
+
- **Local.** One machine, no server, no account. Everything is a file in your repo plus `.whiletrue/`.
|
|
70
|
+
|
|
71
|
+
## Contents
|
|
72
|
+
|
|
73
|
+
- [Install](#install)
|
|
74
|
+
- [Quickstart](#quickstart)
|
|
75
|
+
- [Architecture](#architecture)
|
|
76
|
+
- [Concepts](#concepts)
|
|
77
|
+
- [Examples](#examples)
|
|
78
|
+
- [Backends](#backends)
|
|
79
|
+
- [CLI](#cli)
|
|
80
|
+
- [Documentation](#documentation)
|
|
81
|
+
- [Development](#development)
|
|
82
|
+
- [License](#license)
|
|
83
|
+
|
|
84
|
+
## Install
|
|
85
|
+
|
|
86
|
+
Requires Python 3.12+ and at least one agent CLI on your `PATH` ([Claude Code](https://claude.com/claude-code), [opencode](https://opencode.ai) or [Codex](https://github.com/openai/codex)). `git` is needed for worktrees, `tmux` for interactive agents, and `gh` for the GitHub integration.
|
|
87
|
+
|
|
88
|
+
```bash
|
|
89
|
+
uv tool install whiletrue # or: pip install whiletrue
|
|
90
|
+
whiletrue --help
|
|
91
|
+
|
|
92
|
+
uvx whiletrue --help # or run it without installing
|
|
93
|
+
```
|
|
94
|
+
|
|
95
|
+
If an agent CLI is not on `PATH`, set `WHILETRUE_CLAUDE_BIN`, `WHILETRUE_OPENCODE_BIN` or `WHILETRUE_CODEX_BIN`.
|
|
96
|
+
|
|
97
|
+
## Quickstart
|
|
98
|
+
|
|
99
|
+
```bash
|
|
100
|
+
cd my-project
|
|
101
|
+
whiletrue init # writes whiletrue.yaml and agents/ralph.md
|
|
102
|
+
whiletrue validate # config, wiring, limits and safety rules; spends nothing
|
|
103
|
+
whiletrue plan # prints the expanded step tree; spends nothing
|
|
104
|
+
whiletrue run # runs it
|
|
105
|
+
whiletrue status # steps, outcomes and cost of the latest run
|
|
106
|
+
```
|
|
107
|
+
|
|
108
|
+
The scaffold is a Ralph loop. The agent runs in a fresh context, a deterministic `pytest` gate checks the result, and the loop repeats (at most 5 times) until the gate is green:
|
|
109
|
+
|
|
110
|
+
```yaml
|
|
111
|
+
# whiletrue.yaml
|
|
112
|
+
name: ralph
|
|
113
|
+
pipeline:
|
|
114
|
+
loop:
|
|
115
|
+
max: 5 # every loop is bounded; `max: unbounded` is an explicit opt-out
|
|
116
|
+
do:
|
|
117
|
+
- agent: { uses: ./agents/ralph.md }
|
|
118
|
+
- gate.shell: { run: "pytest" }
|
|
119
|
+
```
|
|
120
|
+
|
|
121
|
+
```markdown
|
|
122
|
+
---
|
|
123
|
+
# agents/ralph.md
|
|
124
|
+
agent: ralph
|
|
125
|
+
runner: claude-code-headless
|
|
126
|
+
permission_mode: acceptEdits
|
|
127
|
+
tools: [Read, Edit, Write, "Bash(pytest*)", "Bash(git *)"]
|
|
128
|
+
limits: { budget_usd: 2, turns: 40, wall: 20m }
|
|
129
|
+
---
|
|
130
|
+
Work through the next unfinished item in TODO.md. Make the tests pass.
|
|
131
|
+
|
|
132
|
+
Failure output from the previous attempt (empty on the first try):
|
|
133
|
+
{{iter.previous}}
|
|
134
|
+
```
|
|
135
|
+
|
|
136
|
+
Every agent must declare `limits`; `validate` refuses the config otherwise.
|
|
137
|
+
|
|
138
|
+
## Architecture
|
|
139
|
+
|
|
140
|
+
<img src="docs/assets/architecture.svg" alt="Architecture: whiletrue.yaml and the CLI drive the core engine (loader, scheduler, pipeline runtime, park and resume, plugin registry, SQLite store); built-in plugins connect it to agent CLIs, git, GitHub and tmux" width="900">
|
|
141
|
+
|
|
142
|
+
The core knows nothing about git, GitHub, tmux or any agent. Every integration is a plugin built on the public plugin API, including the optional `rsi` layer, so you can add your own ([plugins](docs/plugins.md), [architecture](docs/architecture.md)).
|
|
143
|
+
|
|
144
|
+
## Concepts
|
|
145
|
+
|
|
146
|
+
| Concept | What it is |
|
|
147
|
+
| --- | --- |
|
|
148
|
+
| **Pipeline** | A list of steps, or one strategy, in `whiletrue.yaml`. |
|
|
149
|
+
| **Step** | An action: `agent`, a shell command, a git or GitHub operation, a gate. Pure, deterministic, agentic or side-effecting. |
|
|
150
|
+
| **Strategy** | Control flow over steps: `sequence`, `tap`, `loop`, `map`, `parallel`, `switch`, `retry`, `try`, `human.approve`. |
|
|
151
|
+
| **Outcome ports** | Every step ends on `ok`, `fail`, `needs_human`, `skip` or `rejected`. `wires:` routes a port to another step; back-wires make loops. |
|
|
152
|
+
| **Item** | One unit of work from a `source:` (`json`, `markdown_tasks`, `github_issues`). Items run in parallel, in dependency order. |
|
|
153
|
+
| **Workspace** | Per-item checkout: `git-worktree`, `dir-copy` or `none`. |
|
|
154
|
+
| **Gate** | A deterministic check, or a human decision, that an item must pass. |
|
|
155
|
+
| **Recipe** | A ready-made composite: `ralph`, `review-pass`, `review-respond`, `issue-loop`. |
|
|
156
|
+
| **Run record** | The SQLite log of steps, parks, effects, comments and cost that makes replay and resume possible. |
|
|
157
|
+
|
|
158
|
+
Details: [reference](docs/reference.md), [authoring guide](docs/authoring.md), [architecture](docs/architecture.md).
|
|
159
|
+
|
|
160
|
+
## Examples
|
|
161
|
+
|
|
162
|
+
### A Ralph loop
|
|
163
|
+
|
|
164
|
+
<img src="docs/assets/ralph-loop.svg" alt="Ralph loop: agent in a fresh context, then a pytest gate; green ends the loop, red feeds the output back to the agent" width="900">
|
|
165
|
+
|
|
166
|
+
This is what `whiletrue init` scaffolds. See the YAML under [Quickstart](#quickstart).
|
|
167
|
+
|
|
168
|
+
### Review loop with a read-only reviewer
|
|
169
|
+
|
|
170
|
+
```yaml
|
|
171
|
+
pipeline:
|
|
172
|
+
composite:
|
|
173
|
+
uses: "recipe:review-pass"
|
|
174
|
+
params: { reviewer: ./agents/review.md, fixer: ./agents/fix.md, max_rounds: 3 }
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
### A backlog in parallel worktrees
|
|
178
|
+
|
|
179
|
+
```yaml
|
|
180
|
+
parallel: 4
|
|
181
|
+
max_agents: 4
|
|
182
|
+
source: { markdown_tasks: { path: TASKS.md } } # - [ ] Title {#id after=other}
|
|
183
|
+
workspace: { git-worktree: { branch: "wt/{{item.id}}" } }
|
|
184
|
+
pipeline:
|
|
185
|
+
loop:
|
|
186
|
+
max: 5
|
|
187
|
+
do:
|
|
188
|
+
- agent: { uses: ./agents/implement.md }
|
|
189
|
+
- gate.shell: { run: "pytest" }
|
|
190
|
+
```
|
|
191
|
+
|
|
192
|
+
### A human gate on a pull request
|
|
193
|
+
|
|
194
|
+
```yaml
|
|
195
|
+
- id: review
|
|
196
|
+
human.approve:
|
|
197
|
+
what: pr
|
|
198
|
+
wake: { any: [cli, { github.pr_review: any }] }
|
|
199
|
+
do:
|
|
200
|
+
- composite: { uses: "recipe:review-respond", params: { responder: ./agents/respond.md } }
|
|
201
|
+
wires: { rejected: fix }
|
|
202
|
+
```
|
|
203
|
+
|
|
204
|
+
```bash
|
|
205
|
+
whiletrue run # parks at the gate and exits with code 2
|
|
206
|
+
whiletrue status # lists what is waiting
|
|
207
|
+
whiletrue approve 12 # or: reject 12 --note "what to change"
|
|
208
|
+
whiletrue resume # finished steps are replayed, never redone
|
|
209
|
+
```
|
|
210
|
+
|
|
211
|
+
### The reference pipeline: issues with a human in the loop
|
|
212
|
+
|
|
213
|
+
[`examples/issue-loop`](examples/issue-loop/README.md) takes every issue in a GitHub milestone from open to merged: implement in a worktree, run the gate, open a PR, answer review comments, merge, close. You review every PR, and every comment you leave gets an answer.
|
|
214
|
+
|
|
215
|
+
<img src="docs/assets/issue-loop.svg" alt="Issue loop flow: implement with retry and a gate, open a PR, a human review gate with comment replies and a fix branch on rejection, then sync, a merge approval and the merge" width="900">
|
|
216
|
+
|
|
217
|
+
## Backends
|
|
218
|
+
|
|
219
|
+
Choose per agent with `runner:`.
|
|
220
|
+
|
|
221
|
+
| Runner | Runs | Notes |
|
|
222
|
+
| --- | --- | --- |
|
|
223
|
+
| `claude-code-headless` | `claude -p` | Default. Budget, turns and wall limits enforced. |
|
|
224
|
+
| `claude-code` | Interactive Claude Code in a tmux pane | Watch it, type into it (recorded as a *steer*). Submits through a bundled MCP tool and hooks. |
|
|
225
|
+
| `opencode` | `opencode run` | Structured output checked against the step's cap. |
|
|
226
|
+
| `codex` | `codex exec` | Sandbox derived from `permission_mode`. No budget enforcement. |
|
|
227
|
+
|
|
228
|
+
Structured `outputs:` work on all of them. See [choosing a backend](docs/authoring.md#choosing-a-backend).
|
|
229
|
+
|
|
230
|
+
## CLI
|
|
231
|
+
|
|
232
|
+
| Command | Purpose |
|
|
233
|
+
| --- | --- |
|
|
234
|
+
| `init`, `validate`, `plan` | Scaffold, check and preview a pipeline without spending tokens. |
|
|
235
|
+
| `run`, `resume`, `rerun`, `cancel` | Start, continue after a park or crash, redo, or stop items. |
|
|
236
|
+
| `status`, `logs`, `cost`, `replay` | Inspect runs, steps and spend; replay a recorded run. |
|
|
237
|
+
| `approve`, `reject`, `comment` | Decide human gates and talk to waiting items. |
|
|
238
|
+
| `attach`, `panel` | Open the tmux session and the live control panel. |
|
|
239
|
+
| `history`, `learnings` | Audit trail and approved lessons for future agents. |
|
|
240
|
+
| `lock` | Show or clear the run lock. |
|
|
241
|
+
|
|
242
|
+
Full reference: [docs/cli.md](docs/cli.md). New here? Follow the [tutorial](docs/tutorial.md).
|
|
243
|
+
|
|
244
|
+
## Documentation
|
|
245
|
+
|
|
246
|
+
Start at [docs/README.md](docs/README.md).
|
|
247
|
+
|
|
248
|
+
- [Tutorial](docs/tutorial.md): from an empty folder to your own loop with gates, a reviewer, parallel tasks and a human approval.
|
|
249
|
+
- [Getting started](docs/getting-started.md): a longer walkthrough, including interactive agents, gates and parallel items.
|
|
250
|
+
- [Authoring guide](docs/authoring.md): writing pipelines and agents.
|
|
251
|
+
- [Reference](docs/reference.md): every module, strategy, provider and config key.
|
|
252
|
+
- [CLI](docs/cli.md) and [plugins](docs/plugins.md): the command line and extending whiletrue.
|
|
253
|
+
- [Architecture](docs/architecture.md), [plan](docs/plan.md), [todo](docs/todo.md) and [changelog](CHANGELOG.md).
|
|
254
|
+
|
|
255
|
+
## Development
|
|
256
|
+
|
|
257
|
+
Requires [devenv](https://devenv.sh) (or Python 3.12 + [uv](https://docs.astral.sh/uv/)). See [developing.md](docs/developing.md).
|
|
258
|
+
|
|
259
|
+
```bash
|
|
260
|
+
git clone https://github.com/dariussingh/whiletrue && cd whiletrue
|
|
261
|
+
direnv allow # or: devenv shell
|
|
262
|
+
poe check # format check, lint, pyright, tests + coverage, docs check
|
|
263
|
+
whiletrue --help # installed editable into .devenv/state/venv
|
|
264
|
+
```
|
|
265
|
+
|
|
266
|
+
Live tests against real agent CLIs are opt-in: `WHILETRUE_LIVE=1 uv run pytest tests/live -v`.
|
|
267
|
+
|
|
268
|
+
## Recursive self-improvement
|
|
269
|
+
|
|
270
|
+
Optional and off by default: `rsi: true` lets whiletrue improve the harness around your agent (prompts, skills, subagents) item by item with the Propose, Probe, Compose method from Harness², using isolated rollouts, blind selection and a per-domain experience library. A person approves what is adopted. It multiplies agent spend (about 7 times at `k: 1`) and is capped by `budget_usd`. See [docs/rsi.md](docs/rsi.md). Next: Gemini CLI support.
|
|
271
|
+
|
|
272
|
+
<img src="docs/assets/rsi-architecture.svg" alt="rsi architecture: task-level recursion per item (reference rollouts, propose, INV and DOM candidates, compose, blind selection, apply) and harnessing-level recursion across items (reflect, human adoption, experience library)" width="900">
|
|
273
|
+
|
|
274
|
+
## Acknowledgements and citation
|
|
275
|
+
|
|
276
|
+
The `rsi` feature builds on **Harness²: Recursive Agent Harnessing for an Open World** (Xu et al., Google Research, 2026; [arXiv:2610.14224](https://arxiv.org/abs/2610.14224), [code](https://github.com/google-research/harness2), Apache-2.0). If you use `rsi` in research, please cite the paper (BibTeX in [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)). whiletrue is an independent project, not affiliated with Google or the Harness² authors.
|
|
277
|
+
|
|
278
|
+
## License
|
|
279
|
+
|
|
280
|
+
MIT. See [LICENSE](LICENSE). Third-party code under `third_party/`, benchmarks, and datasets retain their upstream licenses; see [third-party notices](THIRD_PARTY_NOTICES.md).
|
|
@@ -0,0 +1,253 @@
|
|
|
1
|
+
<div align="center">
|
|
2
|
+
|
|
3
|
+
<img src="docs/assets/logo.svg" alt="whiletrue logo" width="96" height="96">
|
|
4
|
+
|
|
5
|
+
# whiletrue
|
|
6
|
+
|
|
7
|
+
**The loop around your coding agents.**
|
|
8
|
+
|
|
9
|
+
Run pipelines of agentic and deterministic steps around Claude Code, opencode and Codex, locally, with gates, humans in the loop, and crash-safe resume.
|
|
10
|
+
|
|
11
|
+
[](https://pypi.org/project/whiletrue/)
|
|
12
|
+
[](https://pypi.org/project/whiletrue/)
|
|
13
|
+
[](LICENSE)
|
|
14
|
+
[](docs/README.md)
|
|
15
|
+
|
|
16
|
+
</div>
|
|
17
|
+
|
|
18
|
+
> LangGraph builds the agent; whiletrue runs the loop around agents you already have.
|
|
19
|
+
|
|
20
|
+
<div align="center">
|
|
21
|
+
|
|
22
|
+
<img src="docs/assets/demo-real.svg" alt="Recording of a real run: two Claude Code agents work in parallel in tmux panes while a control panel and shell show status, both items pass their pytest gate and park for human approval, then approve and resume finish them" width="900">
|
|
23
|
+
|
|
24
|
+
<sub>A real run, not a mock-up: two Claude Code agents in parallel, a pytest gate, a human approval and a resume, about $0.23 in total. Captured from the live tmux panes; the two tmux windows are drawn side by side.</sub>
|
|
25
|
+
|
|
26
|
+
</div>
|
|
27
|
+
|
|
28
|
+
```bash
|
|
29
|
+
uvx whiletrue init # scaffold a Ralph loop
|
|
30
|
+
uvx whiletrue run # agent -> pytest gate -> repeat until green
|
|
31
|
+
```
|
|
32
|
+
|
|
33
|
+
## Overview
|
|
34
|
+
|
|
35
|
+
Coding agents are good at one task and bad at finishing a backlog unattended. whiletrue is the orchestrator you put around them. You describe the loop in a single `whiletrue.yaml`: which agent does the work, which deterministic gate checks it, when to retry, when to ask a person. whiletrue validates the config before spending a token, runs it, and records every step so you can inspect, replay or resume it.
|
|
36
|
+
|
|
37
|
+
- **Pipelines, not prompts.** Agent steps, shell and git steps, and gates compose with `sequence`, `loop`, `map`, `parallel`, `switch`, `retry`, `try` and `human.approve`. Every loop is bounded.
|
|
38
|
+
- **Any backend.** `claude-code-headless`, `claude-code` (the real interactive CLI in a tmux pane you can type into), `opencode` and `codex`. Mix them in one pipeline.
|
|
39
|
+
- **Many items at once.** One item per task or GitHub issue, each in its own git worktree, with `parallel: N` and a cap on live agent sessions.
|
|
40
|
+
- **Humans in the loop.** A gate parks an item until a person approves, rejects or comments; other items keep running. Every review comment gets an answer.
|
|
41
|
+
- **Durable.** State lives in SQLite. Kill the process at any point and `whiletrue resume` replays finished steps instead of redoing them; side effects (PRs, merges, replies) happen exactly once.
|
|
42
|
+
- **Local.** One machine, no server, no account. Everything is a file in your repo plus `.whiletrue/`.
|
|
43
|
+
|
|
44
|
+
## Contents
|
|
45
|
+
|
|
46
|
+
- [Install](#install)
|
|
47
|
+
- [Quickstart](#quickstart)
|
|
48
|
+
- [Architecture](#architecture)
|
|
49
|
+
- [Concepts](#concepts)
|
|
50
|
+
- [Examples](#examples)
|
|
51
|
+
- [Backends](#backends)
|
|
52
|
+
- [CLI](#cli)
|
|
53
|
+
- [Documentation](#documentation)
|
|
54
|
+
- [Development](#development)
|
|
55
|
+
- [License](#license)
|
|
56
|
+
|
|
57
|
+
## Install
|
|
58
|
+
|
|
59
|
+
Requires Python 3.12+ and at least one agent CLI on your `PATH` ([Claude Code](https://claude.com/claude-code), [opencode](https://opencode.ai) or [Codex](https://github.com/openai/codex)). `git` is needed for worktrees, `tmux` for interactive agents, and `gh` for the GitHub integration.
|
|
60
|
+
|
|
61
|
+
```bash
|
|
62
|
+
uv tool install whiletrue # or: pip install whiletrue
|
|
63
|
+
whiletrue --help
|
|
64
|
+
|
|
65
|
+
uvx whiletrue --help # or run it without installing
|
|
66
|
+
```
|
|
67
|
+
|
|
68
|
+
If an agent CLI is not on `PATH`, set `WHILETRUE_CLAUDE_BIN`, `WHILETRUE_OPENCODE_BIN` or `WHILETRUE_CODEX_BIN`.
|
|
69
|
+
|
|
70
|
+
## Quickstart
|
|
71
|
+
|
|
72
|
+
```bash
|
|
73
|
+
cd my-project
|
|
74
|
+
whiletrue init # writes whiletrue.yaml and agents/ralph.md
|
|
75
|
+
whiletrue validate # config, wiring, limits and safety rules; spends nothing
|
|
76
|
+
whiletrue plan # prints the expanded step tree; spends nothing
|
|
77
|
+
whiletrue run # runs it
|
|
78
|
+
whiletrue status # steps, outcomes and cost of the latest run
|
|
79
|
+
```
|
|
80
|
+
|
|
81
|
+
The scaffold is a Ralph loop. The agent runs in a fresh context, a deterministic `pytest` gate checks the result, and the loop repeats (at most 5 times) until the gate is green:
|
|
82
|
+
|
|
83
|
+
```yaml
|
|
84
|
+
# whiletrue.yaml
|
|
85
|
+
name: ralph
|
|
86
|
+
pipeline:
|
|
87
|
+
loop:
|
|
88
|
+
max: 5 # every loop is bounded; `max: unbounded` is an explicit opt-out
|
|
89
|
+
do:
|
|
90
|
+
- agent: { uses: ./agents/ralph.md }
|
|
91
|
+
- gate.shell: { run: "pytest" }
|
|
92
|
+
```
|
|
93
|
+
|
|
94
|
+
```markdown
|
|
95
|
+
---
|
|
96
|
+
# agents/ralph.md
|
|
97
|
+
agent: ralph
|
|
98
|
+
runner: claude-code-headless
|
|
99
|
+
permission_mode: acceptEdits
|
|
100
|
+
tools: [Read, Edit, Write, "Bash(pytest*)", "Bash(git *)"]
|
|
101
|
+
limits: { budget_usd: 2, turns: 40, wall: 20m }
|
|
102
|
+
---
|
|
103
|
+
Work through the next unfinished item in TODO.md. Make the tests pass.
|
|
104
|
+
|
|
105
|
+
Failure output from the previous attempt (empty on the first try):
|
|
106
|
+
{{iter.previous}}
|
|
107
|
+
```
|
|
108
|
+
|
|
109
|
+
Every agent must declare `limits`; `validate` refuses the config otherwise.
|
|
110
|
+
|
|
111
|
+
## Architecture
|
|
112
|
+
|
|
113
|
+
<img src="docs/assets/architecture.svg" alt="Architecture: whiletrue.yaml and the CLI drive the core engine (loader, scheduler, pipeline runtime, park and resume, plugin registry, SQLite store); built-in plugins connect it to agent CLIs, git, GitHub and tmux" width="900">
|
|
114
|
+
|
|
115
|
+
The core knows nothing about git, GitHub, tmux or any agent. Every integration is a plugin built on the public plugin API, including the optional `rsi` layer, so you can add your own ([plugins](docs/plugins.md), [architecture](docs/architecture.md)).
|
|
116
|
+
|
|
117
|
+
## Concepts
|
|
118
|
+
|
|
119
|
+
| Concept | What it is |
|
|
120
|
+
| --- | --- |
|
|
121
|
+
| **Pipeline** | A list of steps, or one strategy, in `whiletrue.yaml`. |
|
|
122
|
+
| **Step** | An action: `agent`, a shell command, a git or GitHub operation, a gate. Pure, deterministic, agentic or side-effecting. |
|
|
123
|
+
| **Strategy** | Control flow over steps: `sequence`, `tap`, `loop`, `map`, `parallel`, `switch`, `retry`, `try`, `human.approve`. |
|
|
124
|
+
| **Outcome ports** | Every step ends on `ok`, `fail`, `needs_human`, `skip` or `rejected`. `wires:` routes a port to another step; back-wires make loops. |
|
|
125
|
+
| **Item** | One unit of work from a `source:` (`json`, `markdown_tasks`, `github_issues`). Items run in parallel, in dependency order. |
|
|
126
|
+
| **Workspace** | Per-item checkout: `git-worktree`, `dir-copy` or `none`. |
|
|
127
|
+
| **Gate** | A deterministic check, or a human decision, that an item must pass. |
|
|
128
|
+
| **Recipe** | A ready-made composite: `ralph`, `review-pass`, `review-respond`, `issue-loop`. |
|
|
129
|
+
| **Run record** | The SQLite log of steps, parks, effects, comments and cost that makes replay and resume possible. |
|
|
130
|
+
|
|
131
|
+
Details: [reference](docs/reference.md), [authoring guide](docs/authoring.md), [architecture](docs/architecture.md).
|
|
132
|
+
|
|
133
|
+
## Examples
|
|
134
|
+
|
|
135
|
+
### A Ralph loop
|
|
136
|
+
|
|
137
|
+
<img src="docs/assets/ralph-loop.svg" alt="Ralph loop: agent in a fresh context, then a pytest gate; green ends the loop, red feeds the output back to the agent" width="900">
|
|
138
|
+
|
|
139
|
+
This is what `whiletrue init` scaffolds. See the YAML under [Quickstart](#quickstart).
|
|
140
|
+
|
|
141
|
+
### Review loop with a read-only reviewer
|
|
142
|
+
|
|
143
|
+
```yaml
|
|
144
|
+
pipeline:
|
|
145
|
+
composite:
|
|
146
|
+
uses: "recipe:review-pass"
|
|
147
|
+
params: { reviewer: ./agents/review.md, fixer: ./agents/fix.md, max_rounds: 3 }
|
|
148
|
+
```
|
|
149
|
+
|
|
150
|
+
### A backlog in parallel worktrees
|
|
151
|
+
|
|
152
|
+
```yaml
|
|
153
|
+
parallel: 4
|
|
154
|
+
max_agents: 4
|
|
155
|
+
source: { markdown_tasks: { path: TASKS.md } } # - [ ] Title {#id after=other}
|
|
156
|
+
workspace: { git-worktree: { branch: "wt/{{item.id}}" } }
|
|
157
|
+
pipeline:
|
|
158
|
+
loop:
|
|
159
|
+
max: 5
|
|
160
|
+
do:
|
|
161
|
+
- agent: { uses: ./agents/implement.md }
|
|
162
|
+
- gate.shell: { run: "pytest" }
|
|
163
|
+
```
|
|
164
|
+
|
|
165
|
+
### A human gate on a pull request
|
|
166
|
+
|
|
167
|
+
```yaml
|
|
168
|
+
- id: review
|
|
169
|
+
human.approve:
|
|
170
|
+
what: pr
|
|
171
|
+
wake: { any: [cli, { github.pr_review: any }] }
|
|
172
|
+
do:
|
|
173
|
+
- composite: { uses: "recipe:review-respond", params: { responder: ./agents/respond.md } }
|
|
174
|
+
wires: { rejected: fix }
|
|
175
|
+
```
|
|
176
|
+
|
|
177
|
+
```bash
|
|
178
|
+
whiletrue run # parks at the gate and exits with code 2
|
|
179
|
+
whiletrue status # lists what is waiting
|
|
180
|
+
whiletrue approve 12 # or: reject 12 --note "what to change"
|
|
181
|
+
whiletrue resume # finished steps are replayed, never redone
|
|
182
|
+
```
|
|
183
|
+
|
|
184
|
+
### The reference pipeline: issues with a human in the loop
|
|
185
|
+
|
|
186
|
+
[`examples/issue-loop`](examples/issue-loop/README.md) takes every issue in a GitHub milestone from open to merged: implement in a worktree, run the gate, open a PR, answer review comments, merge, close. You review every PR, and every comment you leave gets an answer.
|
|
187
|
+
|
|
188
|
+
<img src="docs/assets/issue-loop.svg" alt="Issue loop flow: implement with retry and a gate, open a PR, a human review gate with comment replies and a fix branch on rejection, then sync, a merge approval and the merge" width="900">
|
|
189
|
+
|
|
190
|
+
## Backends
|
|
191
|
+
|
|
192
|
+
Choose per agent with `runner:`.
|
|
193
|
+
|
|
194
|
+
| Runner | Runs | Notes |
|
|
195
|
+
| --- | --- | --- |
|
|
196
|
+
| `claude-code-headless` | `claude -p` | Default. Budget, turns and wall limits enforced. |
|
|
197
|
+
| `claude-code` | Interactive Claude Code in a tmux pane | Watch it, type into it (recorded as a *steer*). Submits through a bundled MCP tool and hooks. |
|
|
198
|
+
| `opencode` | `opencode run` | Structured output checked against the step's cap. |
|
|
199
|
+
| `codex` | `codex exec` | Sandbox derived from `permission_mode`. No budget enforcement. |
|
|
200
|
+
|
|
201
|
+
Structured `outputs:` work on all of them. See [choosing a backend](docs/authoring.md#choosing-a-backend).
|
|
202
|
+
|
|
203
|
+
## CLI
|
|
204
|
+
|
|
205
|
+
| Command | Purpose |
|
|
206
|
+
| --- | --- |
|
|
207
|
+
| `init`, `validate`, `plan` | Scaffold, check and preview a pipeline without spending tokens. |
|
|
208
|
+
| `run`, `resume`, `rerun`, `cancel` | Start, continue after a park or crash, redo, or stop items. |
|
|
209
|
+
| `status`, `logs`, `cost`, `replay` | Inspect runs, steps and spend; replay a recorded run. |
|
|
210
|
+
| `approve`, `reject`, `comment` | Decide human gates and talk to waiting items. |
|
|
211
|
+
| `attach`, `panel` | Open the tmux session and the live control panel. |
|
|
212
|
+
| `history`, `learnings` | Audit trail and approved lessons for future agents. |
|
|
213
|
+
| `lock` | Show or clear the run lock. |
|
|
214
|
+
|
|
215
|
+
Full reference: [docs/cli.md](docs/cli.md). New here? Follow the [tutorial](docs/tutorial.md).
|
|
216
|
+
|
|
217
|
+
## Documentation
|
|
218
|
+
|
|
219
|
+
Start at [docs/README.md](docs/README.md).
|
|
220
|
+
|
|
221
|
+
- [Tutorial](docs/tutorial.md): from an empty folder to your own loop with gates, a reviewer, parallel tasks and a human approval.
|
|
222
|
+
- [Getting started](docs/getting-started.md): a longer walkthrough, including interactive agents, gates and parallel items.
|
|
223
|
+
- [Authoring guide](docs/authoring.md): writing pipelines and agents.
|
|
224
|
+
- [Reference](docs/reference.md): every module, strategy, provider and config key.
|
|
225
|
+
- [CLI](docs/cli.md) and [plugins](docs/plugins.md): the command line and extending whiletrue.
|
|
226
|
+
- [Architecture](docs/architecture.md), [plan](docs/plan.md), [todo](docs/todo.md) and [changelog](CHANGELOG.md).
|
|
227
|
+
|
|
228
|
+
## Development
|
|
229
|
+
|
|
230
|
+
Requires [devenv](https://devenv.sh) (or Python 3.12 + [uv](https://docs.astral.sh/uv/)). See [developing.md](docs/developing.md).
|
|
231
|
+
|
|
232
|
+
```bash
|
|
233
|
+
git clone https://github.com/dariussingh/whiletrue && cd whiletrue
|
|
234
|
+
direnv allow # or: devenv shell
|
|
235
|
+
poe check # format check, lint, pyright, tests + coverage, docs check
|
|
236
|
+
whiletrue --help # installed editable into .devenv/state/venv
|
|
237
|
+
```
|
|
238
|
+
|
|
239
|
+
Live tests against real agent CLIs are opt-in: `WHILETRUE_LIVE=1 uv run pytest tests/live -v`.
|
|
240
|
+
|
|
241
|
+
## Recursive self-improvement
|
|
242
|
+
|
|
243
|
+
Optional and off by default: `rsi: true` lets whiletrue improve the harness around your agent (prompts, skills, subagents) item by item with the Propose, Probe, Compose method from Harness², using isolated rollouts, blind selection and a per-domain experience library. A person approves what is adopted. It multiplies agent spend (about 7 times at `k: 1`) and is capped by `budget_usd`. See [docs/rsi.md](docs/rsi.md). Next: Gemini CLI support.
|
|
244
|
+
|
|
245
|
+
<img src="docs/assets/rsi-architecture.svg" alt="rsi architecture: task-level recursion per item (reference rollouts, propose, INV and DOM candidates, compose, blind selection, apply) and harnessing-level recursion across items (reflect, human adoption, experience library)" width="900">
|
|
246
|
+
|
|
247
|
+
## Acknowledgements and citation
|
|
248
|
+
|
|
249
|
+
The `rsi` feature builds on **Harness²: Recursive Agent Harnessing for an Open World** (Xu et al., Google Research, 2026; [arXiv:2610.14224](https://arxiv.org/abs/2610.14224), [code](https://github.com/google-research/harness2), Apache-2.0). If you use `rsi` in research, please cite the paper (BibTeX in [THIRD_PARTY_NOTICES.md](THIRD_PARTY_NOTICES.md)). whiletrue is an independent project, not affiliated with Google or the Harness² authors.
|
|
250
|
+
|
|
251
|
+
## License
|
|
252
|
+
|
|
253
|
+
MIT. See [LICENSE](LICENSE). Third-party code under `third_party/`, benchmarks, and datasets retain their upstream licenses; see [third-party notices](THIRD_PARTY_NOTICES.md).
|
|
@@ -0,0 +1,32 @@
|
|
|
1
|
+
# Third-party notices
|
|
2
|
+
|
|
3
|
+
whiletrue is MIT licensed (see [LICENSE](LICENSE)). Third-party code under `third_party/`, benchmarks and datasets retain their upstream licenses.
|
|
4
|
+
|
|
5
|
+
## Harness²
|
|
6
|
+
|
|
7
|
+
The `rsi` feature builds on **Harness²: Recursive Agent Harnessing for an Open World** (Xu et al., Google Research, 2026; [arXiv:2610.14224](https://arxiv.org/abs/2610.14224), [code](https://github.com/google-research/harness2), Apache-2.0). If you use `rsi` in research, please cite the paper (BibTeX below). whiletrue is an independent project, not affiliated with Google or the Harness² authors.
|
|
8
|
+
|
|
9
|
+
The optional recursive self-improvement feature (`rsi`) is built on the method and code of Harness² by Google Research. The method code is ported and refactored into this repository as `whiletrue.rsi.harness2`; users install no extra dependency.
|
|
10
|
+
|
|
11
|
+
- Source: https://github.com/google-research/harness2 (pinned commit `1cfe254e8d25b15f37048c3730134686abe60335`)
|
|
12
|
+
- License: Apache License 2.0. The license text is at [third_party/harness2/LICENSE](third_party/harness2/LICENSE).
|
|
13
|
+
- Copyright 2026 Google LLC.
|
|
14
|
+
- Each ported file in `whiletrue/rsi/harness2/` keeps its upstream copyright header and carries a notice that it was modified. The files, their upstream paths and the modifications are listed in [third_party/harness2/PROVENANCE.md](third_party/harness2/PROVENANCE.md). Those files are licensed under Apache-2.0, not MIT.
|
|
15
|
+
- Not taken: the benchmark runners, patches and datasets in the upstream repository (JobBench, LAB, WorkBuddy-Bench). They have their own licenses, and the WorkBuddy-derived code includes a territorial limitation on use. whiletrue does not copy, bundle or redistribute them.
|
|
16
|
+
|
|
17
|
+
Please cite the paper if you use `rsi` in research:
|
|
18
|
+
|
|
19
|
+
```bibtex
|
|
20
|
+
@misc{xu2026harness2,
|
|
21
|
+
title = {Harness$^2$: Recursive Agent Harnessing for an Open World},
|
|
22
|
+
author = {Xu, Ruiyao and Chen, Yanfei and CuiZhu, Zhongying and Dalvi Mishra, Bhavana and Ming, Yifei and Yu, Han and Han, Rujun and Lee, Chen-Yu and Pfister, Tomas},
|
|
23
|
+
year = {2026},
|
|
24
|
+
eprint = {2610.14224},
|
|
25
|
+
archivePrefix = {arXiv},
|
|
26
|
+
primaryClass = {cs.AI},
|
|
27
|
+
doi = {10.48550/arXiv.2610.14224},
|
|
28
|
+
url = {https://arxiv.org/abs/2610.14224}
|
|
29
|
+
}
|
|
30
|
+
```
|
|
31
|
+
|
|
32
|
+
whiletrue is an independent project. It is not affiliated with or endorsed by Google or the Harness² authors.
|
|
@@ -4,14 +4,18 @@
|
|
|
4
4
|
| -------------------------------------- | --------------------------------------------------------------------------------- |
|
|
5
5
|
| [architecture.md](architecture.md) | Full design: core model, runtime, state, agents, human gates, packages |
|
|
6
6
|
| [getting-started.md](getting-started.md) | User guide: install, first loop, commands, exit codes, safety defaults |
|
|
7
|
+
| [tutorial.md](tutorial.md) | Tutorial: install, first loop, then build your own gates, review, parallel and human steps |
|
|
7
8
|
| [authoring.md](authoring.md) | Authoring guide: pipelines, composites, agents, choosing a backend |
|
|
8
9
|
| [cli.md](cli.md) | CLI reference: every command, option, exit code and environment variable |
|
|
10
|
+
| [rsi.md](rsi.md) | Recursive self-improvement: turn it on, what it costs, adoption, limits |
|
|
9
11
|
| [reference.md](reference.md) | User reference: modules, control flow, expressions, composites, recipes, replay |
|
|
10
12
|
| [plugins.md](plugins.md) | Extending whiletrue: modules, strategies, runners, caps, entry points |
|
|
11
13
|
| [developing.md](developing.md) | Contributing: setup, layout, run flow, workflow |
|
|
14
|
+
| [rsi-plan.md](rsi-plan.md) | Execution plan for M5: Harness² recursive self-improvement and the Gemini CLI backend |
|
|
12
15
|
| [plan.md](plan.md) | Implementation plan: milestones M0–M4, dependencies, exit criteria, risks, spikes |
|
|
13
16
|
| [todo.md](todo.md) | Numbered, ordered implementation checklist (work top to bottom) |
|
|
14
17
|
| [open-questions.md](open-questions.md) | Undecided design questions, each tied to the milestone that forces the decision |
|
|
18
|
+
| [spike-rsi.md](spike-rsi.md) | Findings: Harness² method, what is ported, concept mapping and decisions |
|
|
15
19
|
| [spike-interactive.md](spike-interactive.md) | Findings: plugin hooks and MCP in interactive Claude Code (OQ-1) |
|
|
16
20
|
| [conventions.md](conventions.md) | Engineering conventions, test and docs rules (the non-negotiables made concrete) |
|
|
17
21
|
|