No description
Find a file
openhands 2fd18b086d feat: gardener prioritizes blocker issues that starve the factory
Adds PRIORITY_blockers_starving_factory detection: scans backlog issues'
deps, finds any that are open but not labeled backlog, and puts them
at the top of the Claude prompt as highest priority for promotion.

Previously, gardener promoted random tech-debt issues while the actual
blockers (e.g. #650, #563, #714, #743) were ignored, leaving all
backlog items permanently stuck.
2026-03-16 21:06:01 +00:00
dev refactor: rewrite parse-deps.py as pure bash, remove only Python from repo 2026-03-16 21:22:53 +01:00
gardener feat: gardener prioritizes blocker issues that starve the factory 2026-03-16 21:06:01 +00:00
lib refactor: rewrite parse-deps.py as pure bash, remove only Python from repo 2026-03-16 21:22:53 +01:00
planner fix: remove dead STATE.md code, restore matrix notify, targeted git add (Closes #13, Closes #14) 2026-03-15 16:53:33 +01:00
review fix: replace PRODUCT-TRUTH.md/ARCHITECTURE.md refs with AGENTS.md 2026-03-15 17:41:10 +01:00
supervisor refactor: rewrite parse-deps.py as pure bash, remove only Python from repo 2026-03-16 21:22:53 +01:00
.env.example refactor: rebrand dark-factory → disinto (Closes #15) 2026-03-15 17:57:12 +01:00
.gitignore fix: gitignore *.log.old, *.log.*, escalations.jsonl 2026-03-13 10:43:37 +00:00
al76.png docs: add hero image and Asimov quote to README 2026-03-15 18:08:52 +00:00
BOOTSTRAP.md refactor: rename factory/ → supervisor/, factory-poll → supervisor-poll 2026-03-15 18:06:25 +01:00
README.md docs: add hero image and Asimov quote to README 2026-03-15 18:08:52 +00:00

A tiny robot commanding a mountain-eating machine

Disinto

Autonomous code factorydisinto.ai

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 Codeberg 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

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

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

Prerequisites

Required:

  • Claude CLIclaude in PATH, authenticated
  • Codeberg account with an API token — disinto reads issues, opens PRs, posts comments, and merges via the Codeberg API
  • A second Codeberg account for the review bot — reviews posted under a separate identity so the dev-agent doesn't review its own PRs (REVIEW_BOT_TOKEN)
  • Woodpecker CI — local instance connected to your Codeberg repo; 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 ssh://git@codeberg.org/johba/disinto.git
cd disinto

# 2. Configure
cp .env.example .env

Edit .env with your values:

# Target repo
CODEBERG_REPO=yourorg/yourproject              # Codeberg org/repo slug
CODEBERG_API=https://codeberg.org/api/v1/repos/yourorg/yourproject
PROJECT_REPO_ROOT=/path/to/your/project        # local clone of the target repo

# Auth tokens
CODEBERG_TOKEN=...          # main account — or put it in ~/.netrc
REVIEW_BOT_TOKEN=...        # separate Codeberg account for code reviews

# 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

# 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
└── 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
        ├── codeberg.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.

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