whiletrue 0.1.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/.editorconfig +11 -0
- whiletrue-0.1.0/.envrc +8 -0
- whiletrue-0.1.0/.github/ISSUE_TEMPLATE/task.md +16 -0
- whiletrue-0.1.0/.github/pull_request_template.md +10 -0
- whiletrue-0.1.0/.github/workflows/ci.yml +13 -0
- whiletrue-0.1.0/.github/workflows/release.yml +41 -0
- whiletrue-0.1.0/.gitignore +20 -0
- whiletrue-0.1.0/CHANGELOG.md +25 -0
- whiletrue-0.1.0/CLAUDE.md +19 -0
- whiletrue-0.1.0/LICENSE +21 -0
- whiletrue-0.1.0/PKG-INFO +48 -0
- whiletrue-0.1.0/README.md +23 -0
- whiletrue-0.1.0/devenv.lock +131 -0
- whiletrue-0.1.0/devenv.nix +28 -0
- whiletrue-0.1.0/devenv.yaml +13 -0
- whiletrue-0.1.0/docs/README.md +18 -0
- whiletrue-0.1.0/docs/architecture.md +516 -0
- whiletrue-0.1.0/docs/authoring.md +123 -0
- whiletrue-0.1.0/docs/cli.md +74 -0
- whiletrue-0.1.0/docs/conventions.md +10 -0
- whiletrue-0.1.0/docs/developing.md +77 -0
- whiletrue-0.1.0/docs/getting-started.md +205 -0
- whiletrue-0.1.0/docs/m0-smoke.md +42 -0
- whiletrue-0.1.0/docs/open-questions.md +40 -0
- whiletrue-0.1.0/docs/plan.md +104 -0
- whiletrue-0.1.0/docs/plugins.md +157 -0
- whiletrue-0.1.0/docs/reference.md +176 -0
- whiletrue-0.1.0/docs/spike-interactive.md +44 -0
- whiletrue-0.1.0/docs/todo.md +110 -0
- whiletrue-0.1.0/examples/issue-loop/README.md +26 -0
- whiletrue-0.1.0/examples/issue-loop/agents/fix.md +10 -0
- whiletrue-0.1.0/examples/issue-loop/agents/implement.md +12 -0
- whiletrue-0.1.0/examples/issue-loop/agents/respond.md +11 -0
- whiletrue-0.1.0/examples/issue-loop/whiletrue.yaml +15 -0
- whiletrue-0.1.0/pyproject.toml +104 -0
- whiletrue-0.1.0/scripts/docs_check.py +46 -0
- whiletrue-0.1.0/tests/conftest.py +11 -0
- whiletrue-0.1.0/tests/fixtures/fake_interactive_claude.py +89 -0
- whiletrue-0.1.0/tests/integration/test_cli.py +559 -0
- whiletrue-0.1.0/tests/integration/test_cli_surface.py +50 -0
- whiletrue-0.1.0/tests/integration/test_gates_cli.py +210 -0
- whiletrue-0.1.0/tests/integration/test_interactive_run.py +107 -0
- whiletrue-0.1.0/tests/integration/test_issue_loop.py +196 -0
- whiletrue-0.1.0/tests/integration/test_m3_exit.py +113 -0
- whiletrue-0.1.0/tests/integration/test_ops_cli.py +298 -0
- whiletrue-0.1.0/tests/integration/test_recipes.py +135 -0
- whiletrue-0.1.0/tests/live/test_live_backends.py +85 -0
- whiletrue-0.1.0/tests/unit/basics/test_agent.py +401 -0
- whiletrue-0.1.0/tests/unit/basics/test_exec.py +68 -0
- whiletrue-0.1.0/tests/unit/basics/test_gates.py +101 -0
- whiletrue-0.1.0/tests/unit/basics/test_history.py +78 -0
- whiletrue-0.1.0/tests/unit/basics/test_human.py +463 -0
- whiletrue-0.1.0/tests/unit/basics/test_json_source.py +58 -0
- whiletrue-0.1.0/tests/unit/basics/test_markdown_source.py +62 -0
- whiletrue-0.1.0/tests/unit/basics/test_plugin.py +23 -0
- whiletrue-0.1.0/tests/unit/basics/test_process.py +62 -0
- whiletrue-0.1.0/tests/unit/basics/test_sessions.py +45 -0
- whiletrue-0.1.0/tests/unit/basics/test_shell.py +72 -0
- whiletrue-0.1.0/tests/unit/claude_code/test_endpoint.py +140 -0
- whiletrue-0.1.0/tests/unit/claude_code/test_headless.py +234 -0
- whiletrue-0.1.0/tests/unit/claude_code/test_interactive.py +413 -0
- whiletrue-0.1.0/tests/unit/claude_code/test_panes.py +65 -0
- whiletrue-0.1.0/tests/unit/claude_code/test_plugin_scripts.py +168 -0
- whiletrue-0.1.0/tests/unit/claude_code/test_session.py +339 -0
- whiletrue-0.1.0/tests/unit/claude_code/test_transcript.py +86 -0
- whiletrue-0.1.0/tests/unit/codex/test_runner.py +199 -0
- whiletrue-0.1.0/tests/unit/control/test_control.py +631 -0
- whiletrue-0.1.0/tests/unit/core/test_cache.py +113 -0
- whiletrue-0.1.0/tests/unit/core/test_caps.py +120 -0
- whiletrue-0.1.0/tests/unit/core/test_composite.py +198 -0
- whiletrue-0.1.0/tests/unit/core/test_config.py +241 -0
- whiletrue-0.1.0/tests/unit/core/test_context.py +82 -0
- whiletrue-0.1.0/tests/unit/core/test_duration.py +38 -0
- whiletrue-0.1.0/tests/unit/core/test_events.py +63 -0
- whiletrue-0.1.0/tests/unit/core/test_expr.py +64 -0
- whiletrue-0.1.0/tests/unit/core/test_history_store.py +161 -0
- whiletrue-0.1.0/tests/unit/core/test_lock.py +98 -0
- whiletrue-0.1.0/tests/unit/core/test_memory_store.py +48 -0
- whiletrue-0.1.0/tests/unit/core/test_module.py +131 -0
- whiletrue-0.1.0/tests/unit/core/test_outcomes.py +72 -0
- whiletrue-0.1.0/tests/unit/core/test_registry.py +118 -0
- whiletrue-0.1.0/tests/unit/core/test_replay.py +86 -0
- whiletrue-0.1.0/tests/unit/core/test_runtime.py +683 -0
- whiletrue-0.1.0/tests/unit/core/test_template.py +46 -0
- whiletrue-0.1.0/tests/unit/core/test_validate.py +197 -0
- whiletrue-0.1.0/tests/unit/core/test_wake.py +77 -0
- whiletrue-0.1.0/tests/unit/git/test_git.py +223 -0
- whiletrue-0.1.0/tests/unit/github/test_client.py +222 -0
- whiletrue-0.1.0/tests/unit/github/test_filebacked.py +46 -0
- whiletrue-0.1.0/tests/unit/github/test_plugin.py +331 -0
- whiletrue-0.1.0/tests/unit/github/test_specs.py +35 -0
- whiletrue-0.1.0/tests/unit/opencode/test_runner.py +185 -0
- whiletrue-0.1.0/tests/unit/store_sqlite/test_sqlite_store.py +156 -0
- whiletrue-0.1.0/tests/unit/test_abort.py +76 -0
- whiletrue-0.1.0/tests/unit/test_architecture.py +36 -0
- whiletrue-0.1.0/tests/unit/test_panel.py +168 -0
- whiletrue-0.1.0/tests/unit/tmux/test_controller.py +184 -0
- whiletrue-0.1.0/uv.lock +660 -0
- whiletrue-0.1.0/whiletrue/__init__.py +0 -0
- whiletrue-0.1.0/whiletrue/__main__.py +3 -0
- whiletrue-0.1.0/whiletrue/abort.py +79 -0
- whiletrue-0.1.0/whiletrue/basics/__init__.py +99 -0
- whiletrue-0.1.0/whiletrue/basics/agent.py +249 -0
- whiletrue-0.1.0/whiletrue/basics/comments.py +113 -0
- whiletrue-0.1.0/whiletrue/basics/diff_size.py +80 -0
- whiletrue-0.1.0/whiletrue/basics/exec_.py +84 -0
- whiletrue-0.1.0/whiletrue/basics/history.py +117 -0
- whiletrue-0.1.0/whiletrue/basics/human.py +201 -0
- whiletrue-0.1.0/whiletrue/basics/json_source.py +35 -0
- whiletrue-0.1.0/whiletrue/basics/markdown_source.py +55 -0
- whiletrue-0.1.0/whiletrue/basics/process.py +99 -0
- whiletrue-0.1.0/whiletrue/basics/sessions.py +62 -0
- whiletrue-0.1.0/whiletrue/basics/set_.py +29 -0
- whiletrue-0.1.0/whiletrue/basics/shell.py +98 -0
- whiletrue-0.1.0/whiletrue/basics/wake.py +27 -0
- whiletrue-0.1.0/whiletrue/claude_code/__init__.py +58 -0
- whiletrue-0.1.0/whiletrue/claude_code/endpoint.py +143 -0
- whiletrue-0.1.0/whiletrue/claude_code/headless.py +181 -0
- whiletrue-0.1.0/whiletrue/claude_code/interactive.py +344 -0
- whiletrue-0.1.0/whiletrue/claude_code/learnings.py +32 -0
- whiletrue-0.1.0/whiletrue/claude_code/panes.py +164 -0
- whiletrue-0.1.0/whiletrue/claude_code/plugin/.claude-plugin/plugin.json +5 -0
- whiletrue-0.1.0/whiletrue/claude_code/plugin/hook.py +44 -0
- whiletrue-0.1.0/whiletrue/claude_code/plugin/hooks/hooks.json +81 -0
- whiletrue-0.1.0/whiletrue/claude_code/plugin/mcp_server.py +98 -0
- whiletrue-0.1.0/whiletrue/claude_code/session.py +345 -0
- whiletrue-0.1.0/whiletrue/claude_code/transcript.py +123 -0
- whiletrue-0.1.0/whiletrue/cli/__init__.py +15 -0
- whiletrue-0.1.0/whiletrue/cli/__main__.py +3 -0
- whiletrue-0.1.0/whiletrue/cli/app.py +550 -0
- whiletrue-0.1.0/whiletrue/cli/common.py +36 -0
- whiletrue-0.1.0/whiletrue/cli/gates.py +156 -0
- whiletrue-0.1.0/whiletrue/cli/ops.py +339 -0
- whiletrue-0.1.0/whiletrue/cli/panel.py +198 -0
- whiletrue-0.1.0/whiletrue/cli/registry.py +143 -0
- whiletrue-0.1.0/whiletrue/cli/templates.py +24 -0
- whiletrue-0.1.0/whiletrue/codex/__init__.py +14 -0
- whiletrue-0.1.0/whiletrue/codex/runner.py +243 -0
- whiletrue-0.1.0/whiletrue/control/__init__.py +38 -0
- whiletrue-0.1.0/whiletrue/control/chain.py +61 -0
- whiletrue-0.1.0/whiletrue/control/loop.py +139 -0
- whiletrue-0.1.0/whiletrue/control/map_.py +101 -0
- whiletrue-0.1.0/whiletrue/control/parallel.py +32 -0
- whiletrue-0.1.0/whiletrue/control/retry.py +100 -0
- whiletrue-0.1.0/whiletrue/control/sequence.py +40 -0
- whiletrue-0.1.0/whiletrue/control/switch.py +67 -0
- whiletrue-0.1.0/whiletrue/core/__init__.py +260 -0
- whiletrue-0.1.0/whiletrue/core/caps.py +139 -0
- whiletrue-0.1.0/whiletrue/core/comments.py +80 -0
- whiletrue-0.1.0/whiletrue/core/composite.py +140 -0
- whiletrue-0.1.0/whiletrue/core/config.py +461 -0
- whiletrue-0.1.0/whiletrue/core/context.py +177 -0
- whiletrue-0.1.0/whiletrue/core/duration.py +19 -0
- whiletrue-0.1.0/whiletrue/core/events.py +94 -0
- whiletrue-0.1.0/whiletrue/core/expr.py +85 -0
- whiletrue-0.1.0/whiletrue/core/history.py +83 -0
- whiletrue-0.1.0/whiletrue/core/lock.py +86 -0
- whiletrue-0.1.0/whiletrue/core/memory_store.py +352 -0
- whiletrue-0.1.0/whiletrue/core/module.py +146 -0
- whiletrue-0.1.0/whiletrue/core/outcomes.py +82 -0
- whiletrue-0.1.0/whiletrue/core/registry.py +129 -0
- whiletrue-0.1.0/whiletrue/core/replay.py +58 -0
- whiletrue-0.1.0/whiletrue/core/runner.py +98 -0
- whiletrue-0.1.0/whiletrue/core/runtime.py +538 -0
- whiletrue-0.1.0/whiletrue/core/source.py +45 -0
- whiletrue-0.1.0/whiletrue/core/store.py +207 -0
- whiletrue-0.1.0/whiletrue/core/template.py +60 -0
- whiletrue-0.1.0/whiletrue/core/validate.py +142 -0
- whiletrue-0.1.0/whiletrue/core/wake.py +117 -0
- whiletrue-0.1.0/whiletrue/core/workspace.py +55 -0
- whiletrue-0.1.0/whiletrue/git/__init__.py +31 -0
- whiletrue-0.1.0/whiletrue/git/modules.py +128 -0
- whiletrue-0.1.0/whiletrue/git/workspaces.py +77 -0
- whiletrue-0.1.0/whiletrue/github/__init__.py +30 -0
- whiletrue-0.1.0/whiletrue/github/client.py +269 -0
- whiletrue-0.1.0/whiletrue/github/filebacked.py +87 -0
- whiletrue-0.1.0/whiletrue/github/memory.py +96 -0
- whiletrue-0.1.0/whiletrue/github/plugin.py +343 -0
- whiletrue-0.1.0/whiletrue/github/specs.py +39 -0
- whiletrue-0.1.0/whiletrue/opencode/__init__.py +25 -0
- whiletrue-0.1.0/whiletrue/opencode/runner.py +186 -0
- whiletrue-0.1.0/whiletrue/py.typed +0 -0
- whiletrue-0.1.0/whiletrue/recipes/issue-loop.yaml +59 -0
- whiletrue-0.1.0/whiletrue/recipes/ralph.yaml +14 -0
- whiletrue-0.1.0/whiletrue/recipes/review-pass.yaml +27 -0
- whiletrue-0.1.0/whiletrue/recipes/review-respond.yaml +22 -0
- whiletrue-0.1.0/whiletrue/store_sqlite/__init__.py +6 -0
- whiletrue-0.1.0/whiletrue/store_sqlite/migrations.py +132 -0
- whiletrue-0.1.0/whiletrue/store_sqlite/sqlite_store.py +537 -0
- whiletrue-0.1.0/whiletrue/tmux/__init__.py +11 -0
- whiletrue-0.1.0/whiletrue/tmux/controller.py +197 -0
whiletrue-0.1.0/.envrc
ADDED
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
name: CI
|
|
2
|
+
on:
|
|
3
|
+
push: { branches: [main] }
|
|
4
|
+
pull_request:
|
|
5
|
+
jobs:
|
|
6
|
+
check:
|
|
7
|
+
runs-on: ubuntu-latest
|
|
8
|
+
steps:
|
|
9
|
+
- uses: actions/checkout@v4
|
|
10
|
+
- uses: astral-sh/setup-uv@v5
|
|
11
|
+
with: { enable-cache: true }
|
|
12
|
+
- run: uv sync --all-groups --locked
|
|
13
|
+
- run: uv run poe check
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
name: Release
|
|
2
|
+
# Pushing a tag like v0.1.0 checks, builds and publishes to PyPI (trusted publishing: no token
|
|
3
|
+
# is stored; configure the project on PyPI first), then creates the GitHub release.
|
|
4
|
+
on:
|
|
5
|
+
push:
|
|
6
|
+
tags: ["v*"]
|
|
7
|
+
jobs:
|
|
8
|
+
build:
|
|
9
|
+
runs-on: ubuntu-latest
|
|
10
|
+
steps:
|
|
11
|
+
- uses: actions/checkout@v4
|
|
12
|
+
- uses: astral-sh/setup-uv@v5
|
|
13
|
+
with: { enable-cache: true }
|
|
14
|
+
- run: uv sync --all-groups --locked
|
|
15
|
+
- run: uv run poe check
|
|
16
|
+
- name: The tag must match the package version
|
|
17
|
+
run: test "v$(uv run python -c 'import importlib.metadata as m; print(m.version("whiletrue"))')" = "${GITHUB_REF_NAME}"
|
|
18
|
+
- run: uv build
|
|
19
|
+
- uses: actions/upload-artifact@v4
|
|
20
|
+
with: { name: dist, path: dist/ }
|
|
21
|
+
publish:
|
|
22
|
+
needs: build
|
|
23
|
+
runs-on: ubuntu-latest
|
|
24
|
+
environment: pypi
|
|
25
|
+
permissions:
|
|
26
|
+
id-token: write
|
|
27
|
+
steps:
|
|
28
|
+
- uses: actions/download-artifact@v4
|
|
29
|
+
with: { name: dist, path: dist/ }
|
|
30
|
+
- uses: pypa/gh-action-pypi-publish@release/v1
|
|
31
|
+
github-release:
|
|
32
|
+
needs: publish
|
|
33
|
+
runs-on: ubuntu-latest
|
|
34
|
+
permissions:
|
|
35
|
+
contents: write
|
|
36
|
+
steps:
|
|
37
|
+
- uses: actions/checkout@v4
|
|
38
|
+
- uses: actions/download-artifact@v4
|
|
39
|
+
with: { name: dist, path: dist/ }
|
|
40
|
+
- run: gh release create "$GITHUB_REF_NAME" dist/* --title "$GITHUB_REF_NAME" --notes-file CHANGELOG.md
|
|
41
|
+
env: { GH_TOKEN: "${{ github.token }}" }
|
|
@@ -0,0 +1,20 @@
|
|
|
1
|
+
__pycache__/
|
|
2
|
+
*.py[cod]
|
|
3
|
+
.venv/
|
|
4
|
+
dist/
|
|
5
|
+
.coverage
|
|
6
|
+
coverage/
|
|
7
|
+
.pytest_cache/
|
|
8
|
+
.ruff_cache/
|
|
9
|
+
.whiletrue/
|
|
10
|
+
.env
|
|
11
|
+
.env.*
|
|
12
|
+
.DS_Store
|
|
13
|
+
*.log
|
|
14
|
+
|
|
15
|
+
# devenv / direnv
|
|
16
|
+
.devenv*
|
|
17
|
+
devenv.local.nix
|
|
18
|
+
devenv.local.yaml
|
|
19
|
+
.direnv/
|
|
20
|
+
human-test/
|
|
@@ -0,0 +1,25 @@
|
|
|
1
|
+
# Changelog
|
|
2
|
+
|
|
3
|
+
## 0.1.0 (first release)
|
|
4
|
+
|
|
5
|
+
whiletrue runs configurable pipelines of agentic and deterministic steps around coding agents.
|
|
6
|
+
|
|
7
|
+
**Engine**
|
|
8
|
+
- Typed modules with outcome ports (`ok`, `fail`, `needs_human`, `skip`, `rejected`), a plugin API (entry points), a static validator, and a SQLite-backed runtime with an append-only event log.
|
|
9
|
+
- Control flow: `sequence`, `tap`, `loop`, `map` (optionally parallel), `parallel`, `switch`, `retry`, `try`; CEL expressions; composites with params and ports; recipes `ralph`, `review-pass`, `review-respond`, `issue-loop`.
|
|
10
|
+
- Reproducibility: `whiletrue.lock`, run hashes, result cache, record and `replay`.
|
|
11
|
+
- Parallel items with dependencies, `max_agents`, an item state machine, workspaces (git worktree, directory copy), crash recovery, and `resume`, `rerun`, `cancel`, `logs`, `cost`.
|
|
12
|
+
|
|
13
|
+
**Agent backends**
|
|
14
|
+
- Claude Code: headless (`claude -p`) and interactive (live tmux panes with hooks, an MCP result tool, limits without headless flags, steering).
|
|
15
|
+
- opencode and Codex CLI runners, with structured output and session resume.
|
|
16
|
+
|
|
17
|
+
**People in the loop**
|
|
18
|
+
- `human.approve` gates with park/resume, approve/reject with notes, wake conditions (CLI, file, timer, GitHub review/merge), per-item history, comments that must be answered (`[whiletrue]`-prefixed replies, never resolving human threads), lessons proposed from rejections and steers that need approval, and a tmux control panel.
|
|
19
|
+
|
|
20
|
+
**Integrations**
|
|
21
|
+
- GitHub through the `gh` CLI: issues as items (blocked-by as dependencies, `spec:` links), PRs, sync with base, merge under a lock, review-comment replies. A file-backed fake GitHub for dry runs.
|
|
22
|
+
|
|
23
|
+
**Known limits**
|
|
24
|
+
- The Codex success path has not been run against a live account in CI (only its failure path and a stand-in); the real-GitHub path has been exercised only through a stand-in `gh`.
|
|
25
|
+
- A watching gate keeps its parallel slot; locks are per process; interactive agents ask to trust each new worktree once.
|
|
@@ -0,0 +1,19 @@
|
|
|
1
|
+
# whiletrue — agent guide
|
|
2
|
+
|
|
3
|
+
Local Python orchestrator that runs pipelines around coding agents. Design: `docs/architecture.md`. Plan: `docs/plan.md`. Work order: `docs/todo.md` (numbered; do items in order, tick when done).
|
|
4
|
+
|
|
5
|
+
## Commands
|
|
6
|
+
|
|
7
|
+
Use uv inside the devenv shell (`devenv.nix`, same format as `~/dotfiles/devenv/python`): `devenv shell -- uv run poe <task>`, or `direnv allow` once and run `poe <task>` / `pytest` directly (the venv is `.devenv/state/venv`).
|
|
8
|
+
|
|
9
|
+
- `poe check` — format check, lint, typecheck, tests with coverage, docs check (run before every commit)
|
|
10
|
+
- `poe test` / `poe coverage` / `poe typecheck` / `poe lint` / `poe format` / `poe docs-check`
|
|
11
|
+
|
|
12
|
+
## Rules (see `docs/conventions.md`)
|
|
13
|
+
|
|
14
|
+
- TDD; unit tests in `tests/unit/<pkg>/`, cross-package tests in `tests/integration/` (never beside source); coverage floor is `fail_under` in `pyproject.toml`, ratchet it up, never down.
|
|
15
|
+
- Update user docs and `docs/architecture.md` in the same change as behavior.
|
|
16
|
+
- `whiletrue.core` must not import git, GitHub, tmux, or any agent. Built-ins use only the public plugin API.
|
|
17
|
+
- Track work in `docs/todo.md` (no GitHub issues for now). One todo item (or small group) per commit/PR. The human reviews every line before merge.
|
|
18
|
+
- Never commit or push without showing the user the diff and getting explicit approval.
|
|
19
|
+
- Commit trailer: `Co-Authored-By: Claude Sonnet 5.5 <noreply@anthropic.com>`.
|
whiletrue-0.1.0/LICENSE
ADDED
|
@@ -0,0 +1,21 @@
|
|
|
1
|
+
MIT License
|
|
2
|
+
|
|
3
|
+
Copyright (c) 2026 Darius Singh
|
|
4
|
+
|
|
5
|
+
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
6
|
+
of this software and associated documentation files (the "Software"), to deal
|
|
7
|
+
in the Software without restriction, including without limitation the rights
|
|
8
|
+
to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
|
|
9
|
+
copies of the Software, and to permit persons to whom the Software is
|
|
10
|
+
furnished to do so, subject to the following conditions:
|
|
11
|
+
|
|
12
|
+
The above copyright notice and this permission notice shall be included in all
|
|
13
|
+
copies or substantial portions of the Software.
|
|
14
|
+
|
|
15
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
16
|
+
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
17
|
+
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
|
|
18
|
+
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
19
|
+
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
20
|
+
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
21
|
+
SOFTWARE.
|
whiletrue-0.1.0/PKG-INFO
ADDED
|
@@ -0,0 +1,48 @@
|
|
|
1
|
+
Metadata-Version: 2.5
|
|
2
|
+
Name: whiletrue
|
|
3
|
+
Version: 0.1.0
|
|
4
|
+
Summary: Run configurable loops of agentic and deterministic steps around coding agents.
|
|
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
|
+
Keywords: agents,claude-code,codex,opencode,orchestration,pipelines,ralph
|
|
12
|
+
Classifier: Development Status :: 4 - Beta
|
|
13
|
+
Classifier: Environment :: Console
|
|
14
|
+
Classifier: Intended Audience :: Developers
|
|
15
|
+
Classifier: License :: OSI Approved :: MIT License
|
|
16
|
+
Classifier: Operating System :: POSIX
|
|
17
|
+
Classifier: Programming Language :: Python :: 3.12
|
|
18
|
+
Classifier: Topic :: Software Development :: Build Tools
|
|
19
|
+
Classifier: Typing :: Typed
|
|
20
|
+
Requires-Python: >=3.12
|
|
21
|
+
Requires-Dist: common-expression-language<1,>=0.10
|
|
22
|
+
Requires-Dist: pydantic<3,>=2.9
|
|
23
|
+
Requires-Dist: pyyaml<7,>=6
|
|
24
|
+
Description-Content-Type: text/markdown
|
|
25
|
+
|
|
26
|
+
# whiletrue
|
|
27
|
+
|
|
28
|
+
A local, single-machine Python orchestrator that runs configurable pipelines of agentic and deterministic steps around coding agents such as Claude Code and opencode.
|
|
29
|
+
|
|
30
|
+
> LangGraph builds the agent; whiletrue runs the loop around agents you already have.
|
|
31
|
+
|
|
32
|
+
**Status:** M0 (core engine), M1 (control flow, composites, recipes, replay), M2 (interactive Claude Code in tmux panes) M3 (parallel items in git worktrees, crash recovery) and M4 (GitHub issues and PRs, human gates, review comments, opencode) are built in Python. `whiletrue init | validate | plan | run | resume | rerun | cancel | logs | cost | status | lock | replay | attach | panel | approve | reject | comment | history | learnings` work with the headless and interactive Claude Code runners and opencode. Start with the [reference pipeline](examples/issue-loop/README.md). See [`docs/`](docs/README.md): [getting started](docs/getting-started.md), [authoring guide](docs/authoring.md), [CLI](docs/cli.md), [reference](docs/reference.md), [architecture](docs/architecture.md), [plan](docs/plan.md), [todo](docs/todo.md).
|
|
33
|
+
|
|
34
|
+
## Development
|
|
35
|
+
|
|
36
|
+
See [developing.md](docs/developing.md) and, to extend whiletrue, [plugins.md](docs/plugins.md).
|
|
37
|
+
|
|
38
|
+
Requires [devenv](https://devenv.sh) (or Python 3.12 + [uv](https://docs.astral.sh/uv/)).
|
|
39
|
+
|
|
40
|
+
```bash
|
|
41
|
+
direnv allow # or: devenv shell
|
|
42
|
+
poe check # format check, lint, pyright, tests + coverage, docs check
|
|
43
|
+
whiletrue --help # the CLI, installed editable into .devenv/state/venv
|
|
44
|
+
```
|
|
45
|
+
|
|
46
|
+
## License
|
|
47
|
+
|
|
48
|
+
MIT. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
# whiletrue
|
|
2
|
+
|
|
3
|
+
A local, single-machine Python orchestrator that runs configurable pipelines of agentic and deterministic steps around coding agents such as Claude Code and opencode.
|
|
4
|
+
|
|
5
|
+
> LangGraph builds the agent; whiletrue runs the loop around agents you already have.
|
|
6
|
+
|
|
7
|
+
**Status:** M0 (core engine), M1 (control flow, composites, recipes, replay), M2 (interactive Claude Code in tmux panes) M3 (parallel items in git worktrees, crash recovery) and M4 (GitHub issues and PRs, human gates, review comments, opencode) are built in Python. `whiletrue init | validate | plan | run | resume | rerun | cancel | logs | cost | status | lock | replay | attach | panel | approve | reject | comment | history | learnings` work with the headless and interactive Claude Code runners and opencode. Start with the [reference pipeline](examples/issue-loop/README.md). See [`docs/`](docs/README.md): [getting started](docs/getting-started.md), [authoring guide](docs/authoring.md), [CLI](docs/cli.md), [reference](docs/reference.md), [architecture](docs/architecture.md), [plan](docs/plan.md), [todo](docs/todo.md).
|
|
8
|
+
|
|
9
|
+
## Development
|
|
10
|
+
|
|
11
|
+
See [developing.md](docs/developing.md) and, to extend whiletrue, [plugins.md](docs/plugins.md).
|
|
12
|
+
|
|
13
|
+
Requires [devenv](https://devenv.sh) (or Python 3.12 + [uv](https://docs.astral.sh/uv/)).
|
|
14
|
+
|
|
15
|
+
```bash
|
|
16
|
+
direnv allow # or: devenv shell
|
|
17
|
+
poe check # format check, lint, pyright, tests + coverage, docs check
|
|
18
|
+
whiletrue --help # the CLI, installed editable into .devenv/state/venv
|
|
19
|
+
```
|
|
20
|
+
|
|
21
|
+
## License
|
|
22
|
+
|
|
23
|
+
MIT. See [LICENSE](LICENSE).
|
|
@@ -0,0 +1,131 @@
|
|
|
1
|
+
{
|
|
2
|
+
"nodes": {
|
|
3
|
+
"devenv": {
|
|
4
|
+
"locked": {
|
|
5
|
+
"dir": "src/modules",
|
|
6
|
+
"lastModified": 1792016320,
|
|
7
|
+
"owner": "cachix",
|
|
8
|
+
"repo": "devenv",
|
|
9
|
+
"rev": "03582faca930c95cb28d5d3cd2370325b0072fde",
|
|
10
|
+
"type": "github"
|
|
11
|
+
},
|
|
12
|
+
"original": {
|
|
13
|
+
"dir": "src/modules",
|
|
14
|
+
"owner": "cachix",
|
|
15
|
+
"repo": "devenv",
|
|
16
|
+
"type": "github"
|
|
17
|
+
}
|
|
18
|
+
},
|
|
19
|
+
"flake-compat": {
|
|
20
|
+
"flake": false,
|
|
21
|
+
"locked": {
|
|
22
|
+
"lastModified": 1767039857,
|
|
23
|
+
"owner": "NixOS",
|
|
24
|
+
"repo": "flake-compat",
|
|
25
|
+
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
|
|
26
|
+
"type": "github"
|
|
27
|
+
},
|
|
28
|
+
"original": {
|
|
29
|
+
"owner": "NixOS",
|
|
30
|
+
"repo": "flake-compat",
|
|
31
|
+
"type": "github"
|
|
32
|
+
}
|
|
33
|
+
},
|
|
34
|
+
"flake-compat_2": {
|
|
35
|
+
"flake": false,
|
|
36
|
+
"locked": {
|
|
37
|
+
"lastModified": 1767039857,
|
|
38
|
+
"owner": "edolstra",
|
|
39
|
+
"repo": "flake-compat",
|
|
40
|
+
"rev": "5edf11c44bc78a0d334f6334cdaf7d60d732daab",
|
|
41
|
+
"type": "github"
|
|
42
|
+
},
|
|
43
|
+
"original": {
|
|
44
|
+
"owner": "edolstra",
|
|
45
|
+
"repo": "flake-compat",
|
|
46
|
+
"type": "github"
|
|
47
|
+
}
|
|
48
|
+
},
|
|
49
|
+
"git-hooks": {
|
|
50
|
+
"inputs": {
|
|
51
|
+
"flake-compat": "flake-compat",
|
|
52
|
+
"nixpkgs": [
|
|
53
|
+
"nixpkgs"
|
|
54
|
+
]
|
|
55
|
+
},
|
|
56
|
+
"locked": {
|
|
57
|
+
"lastModified": 1791909798,
|
|
58
|
+
"owner": "cachix",
|
|
59
|
+
"repo": "git-hooks.nix",
|
|
60
|
+
"rev": "1ba1dbfe28738c9a71c266be6efa5b89e75491a9",
|
|
61
|
+
"type": "github"
|
|
62
|
+
},
|
|
63
|
+
"original": {
|
|
64
|
+
"owner": "cachix",
|
|
65
|
+
"repo": "git-hooks.nix",
|
|
66
|
+
"type": "github"
|
|
67
|
+
}
|
|
68
|
+
},
|
|
69
|
+
"nixpkgs": {
|
|
70
|
+
"locked": {
|
|
71
|
+
"lastModified": 1791637130,
|
|
72
|
+
"owner": "NixOS",
|
|
73
|
+
"repo": "nixpkgs",
|
|
74
|
+
"rev": "ca1659429c950a11a565b5764e37a1b704e17ec8",
|
|
75
|
+
"type": "github"
|
|
76
|
+
},
|
|
77
|
+
"original": {
|
|
78
|
+
"owner": "NixOS",
|
|
79
|
+
"ref": "nixpkgs-unstable",
|
|
80
|
+
"repo": "nixpkgs",
|
|
81
|
+
"type": "github"
|
|
82
|
+
}
|
|
83
|
+
},
|
|
84
|
+
"nixpkgs-python": {
|
|
85
|
+
"inputs": {
|
|
86
|
+
"flake-compat": "flake-compat_2",
|
|
87
|
+
"nixpkgs": "nixpkgs_2"
|
|
88
|
+
},
|
|
89
|
+
"locked": {
|
|
90
|
+
"lastModified": 1791208659,
|
|
91
|
+
"owner": "cachix",
|
|
92
|
+
"repo": "nixpkgs-python",
|
|
93
|
+
"rev": "5821ac5267b0dc89e48705407206e3c88ee3e0ad",
|
|
94
|
+
"type": "github"
|
|
95
|
+
},
|
|
96
|
+
"original": {
|
|
97
|
+
"owner": "cachix",
|
|
98
|
+
"repo": "nixpkgs-python",
|
|
99
|
+
"type": "github"
|
|
100
|
+
}
|
|
101
|
+
},
|
|
102
|
+
"nixpkgs_2": {
|
|
103
|
+
"locked": {
|
|
104
|
+
"lastModified": 1782847189,
|
|
105
|
+
"owner": "NixOS",
|
|
106
|
+
"repo": "nixpkgs",
|
|
107
|
+
"rev": "b6018f87da91d19d0ab4cf979885689b469cdd41",
|
|
108
|
+
"type": "github"
|
|
109
|
+
},
|
|
110
|
+
"original": {
|
|
111
|
+
"owner": "NixOS",
|
|
112
|
+
"ref": "nixos-25.11",
|
|
113
|
+
"repo": "nixpkgs",
|
|
114
|
+
"type": "github"
|
|
115
|
+
}
|
|
116
|
+
},
|
|
117
|
+
"root": {
|
|
118
|
+
"inputs": {
|
|
119
|
+
"devenv": "devenv",
|
|
120
|
+
"git-hooks": "git-hooks",
|
|
121
|
+
"nixpkgs": "nixpkgs",
|
|
122
|
+
"nixpkgs-python": "nixpkgs-python",
|
|
123
|
+
"pre-commit-hooks": [
|
|
124
|
+
"git-hooks"
|
|
125
|
+
]
|
|
126
|
+
}
|
|
127
|
+
}
|
|
128
|
+
},
|
|
129
|
+
"root": "root",
|
|
130
|
+
"version": 7
|
|
131
|
+
}
|
|
@@ -0,0 +1,28 @@
|
|
|
1
|
+
{
|
|
2
|
+
pkgs,
|
|
3
|
+
...
|
|
4
|
+
}:
|
|
5
|
+
{
|
|
6
|
+
packages = with pkgs; [
|
|
7
|
+
git
|
|
8
|
+
gh
|
|
9
|
+
tmux
|
|
10
|
+
];
|
|
11
|
+
|
|
12
|
+
languages.python = {
|
|
13
|
+
enable = true;
|
|
14
|
+
version = "3.12";
|
|
15
|
+
uv = {
|
|
16
|
+
enable = true;
|
|
17
|
+
sync.enable = true;
|
|
18
|
+
sync.allGroups = true;
|
|
19
|
+
};
|
|
20
|
+
};
|
|
21
|
+
|
|
22
|
+
scripts.check.exec = "uv run poe check";
|
|
23
|
+
|
|
24
|
+
enterShell = ''
|
|
25
|
+
. .devenv/state/venv/bin/activate
|
|
26
|
+
echo "whiletrue devenv: $(python --version), uv $(uv --version | cut -d' ' -f2)"
|
|
27
|
+
'';
|
|
28
|
+
}
|
|
@@ -0,0 +1,13 @@
|
|
|
1
|
+
inputs:
|
|
2
|
+
nixpkgs:
|
|
3
|
+
url: github:NixOS/nixpkgs/nixpkgs-unstable
|
|
4
|
+
nixpkgs-python:
|
|
5
|
+
url: github:cachix/nixpkgs-python
|
|
6
|
+
|
|
7
|
+
# If you're willing to use a package that's vulnerable
|
|
8
|
+
# permittedInsecurePackages:
|
|
9
|
+
# - "openssl-1.1.1w"
|
|
10
|
+
|
|
11
|
+
# If you have more than one devenv you can merge them
|
|
12
|
+
#imports:
|
|
13
|
+
# - ./backend
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# whiletrue docs
|
|
2
|
+
|
|
3
|
+
| Doc | Purpose |
|
|
4
|
+
| -------------------------------------- | --------------------------------------------------------------------------------- |
|
|
5
|
+
| [architecture.md](architecture.md) | Full design: core model, runtime, state, agents, human gates, packages |
|
|
6
|
+
| [getting-started.md](getting-started.md) | User guide: install, first loop, commands, exit codes, safety defaults |
|
|
7
|
+
| [authoring.md](authoring.md) | Authoring guide: pipelines, composites, agents, choosing a backend |
|
|
8
|
+
| [cli.md](cli.md) | CLI reference: every command, option, exit code and environment variable |
|
|
9
|
+
| [reference.md](reference.md) | User reference: modules, control flow, expressions, composites, recipes, replay |
|
|
10
|
+
| [plugins.md](plugins.md) | Extending whiletrue: modules, strategies, runners, caps, entry points |
|
|
11
|
+
| [developing.md](developing.md) | Contributing: setup, layout, run flow, workflow |
|
|
12
|
+
| [plan.md](plan.md) | Implementation plan: milestones M0–M4, dependencies, exit criteria, risks, spikes |
|
|
13
|
+
| [todo.md](todo.md) | Numbered, ordered implementation checklist (work top to bottom) |
|
|
14
|
+
| [open-questions.md](open-questions.md) | Undecided design questions, each tied to the milestone that forces the decision |
|
|
15
|
+
| [spike-interactive.md](spike-interactive.md) | Findings: plugin hooks and MCP in interactive Claude Code (OQ-1) |
|
|
16
|
+
| [conventions.md](conventions.md) | Engineering conventions, test and docs rules (the non-negotiables made concrete) |
|
|
17
|
+
|
|
18
|
+
Non-negotiables (every change must honor them): human keeps context; maximal test coverage; user and architecture docs stay current; human is accountable for every line.
|