No description
Find a file
openhands f716a75351 fix: Preserve worktrees on crash for debugging (#726)
On crash (PHASE:crashed or non-zero exit), preserve the worktree and log
its location instead of destroying it unconditionally. Successful sessions
still clean up normally. Supervisor runs housekeeping to remove stale
crashed worktrees older than 24h.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
2026-03-26 13:41:33 +00:00
.codeberg/ISSUE_TEMPLATE chore: add issue templates (bug, feature, refactor) 2026-03-21 11:50:03 +00:00
.woodpecker Remove exec agent — replaced by OpenClaw skill + vault API (#722) 2026-03-26 10:36:27 +01:00
action fix: Preserve worktrees on crash for debugging (#726) 2026-03-26 13:41:33 +00:00
bin fix: Set CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC in factory sessions and disinto init (#725) 2026-03-26 13:21:22 +00:00
dev fix: Preserve worktrees on crash for debugging (#726) 2026-03-26 13:41:33 +00:00
docker/agents fix: shared Claude OAuth credentials in containers — mount + flock to prevent token rotation race (#693) 2026-03-25 17:48:21 +00:00
docs fix: feat: observable addressables — engagement measurement for deployed artifacts (#718) 2026-03-26 11:57:19 +00:00
evidence/engagement fix: feat: observable addressables — engagement measurement for deployed artifacts (#718) 2026-03-26 11:57:19 +00:00
formulas fix: Planner files vault items for human-blocked constraints (#723) 2026-03-26 13:01:36 +00:00
gardener fix: update AGENTS.md docs and handle stale PHASE:escalate in gardener 2026-03-26 10:32:04 +00:00
lib fix: Preserve worktrees on crash for debugging (#726) 2026-03-26 13:41:33 +00:00
planner fix: Planner files vault items for human-blocked constraints (#723) 2026-03-26 13:01:36 +00:00
predictor chore: gardener housekeeping 2026-03-26 2026-03-26 06:06:51 +00:00
projects fix: escalation notifications should @mention human on Matrix (#624) 2026-03-24 19:21:46 +00:00
review chore: gardener housekeeping 2026-03-26 2026-03-26 06:06:51 +00:00
site fix: address review — error fallback, schema consistency, line-level recovery (#718) 2026-03-26 12:47:18 +00:00
skill fix: Update skill package: init flow, docker default, system requirements, git mirror (#735) 2026-03-26 11:18:55 +00:00
state fix: feat: active-state files — per-cron guard with self-off semantics (#622) 2026-03-23 21:46:59 +00:00
supervisor fix: Preserve worktrees on crash for debugging (#726) 2026-03-26 13:41:33 +00:00
tests fix: add change-password handler to smoke test docker mock (#665) 2026-03-25 11:54:41 +00:00
vault chore: gardener housekeeping 2026-03-26 2026-03-26 06:06:51 +00:00
.env.example fix: Set CLAUDE_CODE_DISABLE_NONESSENTIAL_TRAFFIC in factory sessions and disinto init (#725) 2026-03-26 13:21:22 +00:00
.gitignore fix: Encrypt secrets at rest with SOPS + age (#613) 2026-03-23 18:58:33 +00:00
.shellcheckrc fix: feat: Woodpecker CI pipeline with ShellCheck + duplicate code detection (#45) 2026-03-17 10:02:58 +00:00
AGENTS.md Remove exec agent — replaced by OpenClaw skill + vault API (#722) 2026-03-26 10:36:27 +01:00
BOOTSTRAP.md fix: feat: add Woodpecker agent to docker-compose stack — enable CI pipeline execution (#670) 2026-03-25 14:07:27 +00:00
README.md fix: ship: publish disinto skill to ClawHub registry (#711) 2026-03-26 10:59:45 +00:00
RESOURCES.example.md fix: Replace Codeberg dependency with local Forgejo instance (#611) 2026-03-23 16:57:12 +00:00
RESOURCES.md chore: seed RESOURCES.md — factory capability inventory 2026-03-21 16:20:10 +00:00
VISION.md vision: factory primitives — resources, addressables, observables (#708) 2026-03-26 07:37:55 +01:00

A tiny robot commanding a mountain-eating machine

Disinto

Autonomous code factorydisinto.ai

ClawHub

A mining robot, lost and confused, builds a Disinto from scrap —
a device so powerful it vaporizes three-quarters of a mountain on a single battery.

— Isaac Asimov, "Robot AL-76 Goes Astray" (1942)


Point it at a git repo with a Woodpecker CI pipeline and it will pick up issues, implement them, review PRs, and keep the system healthy — all on its own.

Architecture

cron (*/10) ──→ supervisor-poll.sh    ← supervisor (bash checks, zero tokens)
                 ├── all clear? → exit 0
                 └── problem? → claude -p (diagnose, fix, or escalate)

cron (*/10) ──→ dev-poll.sh        ← pulls ready issues, spawns dev-agent
                 └── dev-agent.sh   ← claude -p: implement → PR → CI → review → merge

cron (*/10) ──→ review-poll.sh     ← finds unreviewed PRs, spawns review
                 └── review-pr.sh   ← claude -p: review → approve/request changes

cron (daily) ──→ gardener-poll.sh  ← backlog grooming (duplicates, stale, tech-debt)
                  └── claude -p: triage → promote/close/escalate

cron (weekly) ──→ planner-poll.sh  ← gap-analyse VISION.md, create backlog issues
                   └── claude -p: update AGENTS.md → create issues

cron (*/30) ──→ vault-poll.sh    ← safety gate for dangerous/irreversible actions
                 └── claude -p: classify → auto-approve/reject or escalate

systemd ──→ matrix_listener.sh   ← long-poll daemon for human replies
              └── dispatches thread replies → supervisor/gardener/dev/review/vault

all agents ──→ matrix_send()     ← status updates, escalations, merge notifications

Prerequisites

Required:

  • Claude CLIclaude in PATH, authenticated
  • Docker — for provisioning a local Forgejo instance (or a running Forgejo/Gitea instance)
  • Woodpecker CI — local instance connected to your forge; disinto monitors pipelines, retries failures, and queries the Woodpecker Postgres DB directly
  • PostgreSQL client (psql) — for Woodpecker DB queries (pipeline status, build counts)
  • jq, curl, git

Optional:

  • Matrix homeserver (Dendrite or Synapse) — real-time notifications, escalation threads with human-in-the-loop replies
  • Foundry (forge, cast, anvil) — only needed if your target project uses Solidity
  • Node.js — only needed if your target project uses Node

Setup

# 1. Clone
git clone https://github.com/johba/disinto.git
cd disinto

# 2. Bootstrap a project (provisions local Forgejo, creates tokens, clones repo)
disinto init https://github.com/yourorg/yourproject

Or configure manually — edit .env with your values:

# Forge (auto-populated by disinto init)
FORGE_URL=http://localhost:3000        # local Forgejo instance
FORGE_TOKEN=...             # dev-bot token
FORGE_REVIEW_TOKEN=...      # review-bot token

# Woodpecker CI
WOODPECKER_SERVER=http://localhost:8000
WOODPECKER_TOKEN=...
WOODPECKER_DB_PASSWORD=...
WOODPECKER_DB_USER=woodpecker
WOODPECKER_DB_HOST=127.0.0.1
WOODPECKER_DB_NAME=woodpecker

# Tuning
CLAUDE_TIMEOUT=7200         # max seconds per Claude invocation (default: 2h)
# 3. Install cron (staggered to avoid overlap)
crontab -e
# Add:
#   0,10,20,30,40,50 * * * * /path/to/disinto/supervisor/supervisor-poll.sh
#   3,13,23,33,43,53 * * * * /path/to/disinto/review/review-poll.sh
#   6,16,26,36,46,56 * * * * /path/to/disinto/dev/dev-poll.sh
#   15 8 * * *                /path/to/disinto/gardener/gardener-poll.sh
#   0,30 * * * *              /path/to/disinto/vault/vault-poll.sh
#   0 9 * * 1                 /path/to/disinto/planner/planner-poll.sh

# 4. Verify
bash supervisor/supervisor-poll.sh   # should log "all clear"

Directory Structure

disinto/
├── .env.example          # Template — copy to .env, add secrets + project config
├── .gitignore            # Excludes .env, logs, state files
├── lib/
│   ├── env.sh              # Shared: load .env, PATH, API helpers, matrix_send()
│   ├── ci-debug.sh         # Woodpecker CI log/failure helper
│   ├── matrix_listener.sh  # Matrix long-poll daemon (dispatches replies)
│   └── matrix_listener.service  # systemd unit for the listener
├── dev/
│   ├── dev-poll.sh       # Cron entry: find ready issues
│   └── dev-agent.sh      # Implementation agent (claude -p)
├── review/
│   ├── review-poll.sh    # Cron entry: find unreviewed PRs
│   └── review-pr.sh      # Review agent (claude -p)
├── gardener/
│   ├── gardener-poll.sh  # Cron entry: backlog grooming
│   └── best-practices.md # Gardener knowledge base
├── planner/
│   ├── planner-poll.sh   # Cron entry: weekly vision gap analysis
│   └── (formula-driven)  # run-planner.toml executed by action-agent
├── vault/
│   ├── vault-poll.sh     # Cron entry: process pending dangerous actions
│   ├── vault-agent.sh    # Classifies and routes actions (claude -p)
│   ├── vault-fire.sh     # Executes an approved action
│   ├── vault-reject.sh   # Marks an action as rejected
│   └── PROMPT.md         # System prompt for vault agent
└── supervisor/
    ├── supervisor-poll.sh   # Supervisor: health checks + claude -p
    ├── PROMPT.md         # Supervisor's system prompt
    ├── update-prompt.sh  # Self-learning: append to best-practices
    └── best-practices/   # Progressive disclosure knowledge base
        ├── memory.md
        ├── disk.md
        ├── ci.md
        ├── forge.md
        ├── dev-agent.md
        ├── review-agent.md
        └── git.md

Agents

Agent Trigger Job
Supervisor Every 10 min Health checks (RAM, disk, CI, git). Calls Claude only when something is broken. Self-improving via best-practices/.
Dev Every 10 min Picks up backlog-labeled issues, creates a branch, implements, opens a PR, monitors CI, responds to review, merges.
Review Every 10 min Finds PRs without review, runs Claude-powered code review, approves or requests changes.
Gardener Daily Grooms the issue backlog: detects duplicates, promotes tech-debt to backlog, closes stale issues, escalates ambiguous items.
Planner Weekly Updates AGENTS.md documentation to reflect recent code changes, then gap-analyses VISION.md vs current state and creates up to 5 backlog issues for the highest-leverage gaps.
Vault Every 30 min Safety gate for dangerous or irreversible actions. Classifies pending actions via Claude: auto-approve, auto-reject, or escalate to a human via Matrix.

Design Principles

  • Bash for checks, AI for judgment — polling and health checks are shell scripts; Claude is only invoked when something needs diagnosing or deciding
  • Pull over push — dev-agent derives readiness from merged dependencies, not labels or manual assignment
  • Progressive disclosure — the supervisor reads only the best-practices file relevant to the current problem, not all of them
  • Self-improving — when Claude fixes something new, the lesson is appended to best-practices for next time
  • Project-agnostic — all project-specific values (repo, paths, CI IDs) come from .env, not hardcoded scripts

Runtime constraints

Disinto is intentionally opinionated about its own runtime. These are hard constraints, not preferences:

  • Debian + GNU userland — all scripts target Debian with standard GNU tools (bash, awk, sed, date, timeout). No portability shims for macOS or BSD.
  • Shell + a small set of runtimes — every agent is a bash script. The only interpreted runtimes used by disinto core are python3 (TOML parsing in lib/load-project.sh, JSON state tracking in dev/dev-poll.sh, recipe matching in gardener/gardener-poll.sh) and claude (the AI CLI). No Ruby, Perl, or other runtimes. Do not add new runtime dependencies without a strong justification.
  • Few, powerful dependencies — required non-standard tools: jq, curl, git, tmux, psql, and python3 (≥ 3.11 for tomllib; or install tomli for older Pythons). Adding anything beyond this list requires justification.
  • Node.js and Foundry are target-project dependencies — if your target repo uses Node or Solidity, install those on the host. They are not part of disinto's core and must not be assumed present in disinto scripts.

The goal: any Debian machine with the prerequisites listed above can run disinto. Keep it that way.