# Architecture

how the factory works
← disinto.ai

## The agent loop

Disinto runs a continuous loop: vision defines direction, agents derive work and execute it, results feed back into the next cycle.

      planner reads VISION.md
         |
         v
      creates backlog issues
         |
         v
      dev-agent picks issue --> implements in worktree --> opens PR
         |
         v
      Woodpecker CI runs tests
         |
         v
      review-agent reviews PR --> approves or requests changes
         |                               |
         v (approved)                     v (changes requested)
      PR merges                       dev-agent addresses feedback
         |                               |
         v                               +--> CI re-runs --> review again
      planner sees progress, plans next cycle

Each project processes one issue at a time. No concurrent PRs, no merge conflicts, no context switching. The pipeline is deliberately sequential.

## Eight agents

Each agent has a single responsibility. They communicate through git, the forge API, and the filesystem.

dev-agent
Picks up backlog issues, implements code in isolated git worktrees, opens PRs. Runs as a persistent tmux session.
Polling loop: every 5 min
review-agent
Reviews PRs against project conventions. Approves clean PRs, requests specific changes on others.
Polling loop: every 5 min
planner
Reads VISION.md and repo state. Creates issues for gaps between where the project is and where it should be.
Polling loop: weekly
gardener
Grooms the backlog. Closes duplicates, promotes tech-debt issues, ensures issues are well-structured.
Polling loop: every 6 hours
supervisor
Monitors factory health. Kills stale sessions, manages disk/memory, escalates persistent failures.
Polling loop: every 10 min
predictor
Detects infrastructure patterns — recurring failures, resource trends, emerging issues. Files predictions for triage.
Polling loop: daily
vault
Being redesigned. Moving to PR-based approval workflow on ops repo. See issues #73-#77.
Redesign in progress

## Phase protocol

When the dev-agent runs in a persistent tmux session, it signals progress by writing to a phase file. The orchestrator watches this file and injects events (CI results, review feedback) back into the session.

Phase | Meaning | Next event
--- | --- | ---
awaiting_ci | PR pushed, waiting for CI | Orchestrator injects CI result
awaiting_review | CI passed, waiting for review | Review-agent injects feedback
escalate | Needs human input (any reason) | Matrix notification sent; 24h timeout → blocked
done | PR merged, work complete | Session cleaned up
failed | Unrecoverable error | Escalated to supervisor

Phase files live at `/tmp/dev-session-{project}-{issue}.phase`. The protocol is intentionally simple — a plain text file, one line, no daemons.

## Vault — being redesigned

Redesign in progress

The vault is being redesigned as a PR-based approval workflow on the ops repo. Instead of polling pending files, vault items will be created as PRs that require admin approval before execution.

See issues #73-#77 for the design: #75 defines the vault.sh helper for creating vault PRs, #76 rewrites the dispatcher to poll for merged vault PRs, #77 adds branch protection requiring admin approval.

## Planner + predictor feedback cycle

Closing the loop

The planner runs weekly. It compares the current state of the codebase against VISION.md and creates issues for anything missing. It also triages predictions filed by the predictor.

The predictor runs daily. It analyzes CI logs, git history, and resource metrics to detect patterns — recurring test failures, disk usage trends, code churn hotspots. Predictions are filed as issues for the planner to triage.

Together, they create a feedback cycle: the predictor observes, the planner directs, and the dev-agent executes.

## Infrastructure

Disinto is deliberately minimal. No Kubernetes, no message queues, no microservices.

Tech stack

Bash scripts — every agent is a shell script. No compiled binaries, no runtimes to install.

Claude CLI — AI is invoked via `claude -p` (one-shot) or `claude` (persistent tmux sessions).

Polling loop — agents are triggered by a `while true` loop in `entrypoint.sh`. Pull-based, not push-based.

Forgejo + Woodpecker — git hosting and CI. All state lives in git and the issue tracker. No external databases.

Single VPS — runs on an 8 GB server. Flat cost, no scaling surprises.

## Design principles

AD-001
Nervous system runs from a polling loop, not action issues. Planner, predictor, gardener, supervisor run directly. They create work, they don't become work.
AD-002
Concurrency is bounded per LLM backend, not per project. One concurrent Claude session per OAuth credential pool; one concurrent session per llama-server instance. Containers with disjoint backends may run in parallel.
AD-003
The runtime creates and destroys, the formula preserves. Runtime manages worktrees/sessions/temp. Formulas commit knowledge to git before signaling done.
AD-004
Event-driven > polling > fixed delays. Never hardcoded sleep. Use phase files, webhooks, or poll loops with backoff.
AD-005
Secrets via env var indirection, never in issue bodies. Issue bodies become code. Secrets go in `.env` or TOML project files.

## Directory layout

    disinto/
    ├── dev/           dev-poll.sh, dev-agent.sh, phase-handler.sh
    ├── review/        review-poll.sh, review-pr.sh
    ├── gardener/      gardener-run.sh (polling-loop executor)
    ├── predictor/     predictor-run.sh (daily polling-loop executor)
    ├── planner/       planner-run.sh (weekly polling-loop executor)
    ├── supervisor/    supervisor-run.sh (health monitoring)
    ├── vault/         vault-env.sh (vault redesign in progress, see #73-#77)
    ├── lib/           env.sh, agent-session.sh, ci-helpers.sh
    ├── projects/      *.toml per-project config
    ├── formulas/      TOML specs for multi-step agent tasks
    ├── bin/           disinto CLI entry point
    └── docs/          internal protocol docs