2026-03-17 18:53:15 +00:00
|
|
|
# Disinto — Agent Instructions
|
|
|
|
|
|
|
|
|
|
## What this repo is
|
|
|
|
|
|
2026-03-17 23:11:40 +01:00
|
|
|
Disinto is an autonomous code factory. It manages five agents (dev, review,
|
|
|
|
|
gardener, supervisor, planner) that pick up issues from Codeberg, implement
|
|
|
|
|
them, review PRs, plan from the vision, and keep the system healthy — all
|
|
|
|
|
via cron and `claude -p`.
|
2026-03-17 18:53:15 +00:00
|
|
|
|
|
|
|
|
See `README.md` for the full architecture and `BOOTSTRAP.md` for setup.
|
|
|
|
|
|
|
|
|
|
## Directory layout
|
|
|
|
|
|
|
|
|
|
```
|
|
|
|
|
disinto/
|
|
|
|
|
├── dev/ dev-poll.sh, dev-agent.sh — issue implementation
|
|
|
|
|
├── review/ review-poll.sh, review-pr.sh — PR review
|
|
|
|
|
├── gardener/ gardener-poll.sh — backlog grooming
|
2026-03-17 23:11:40 +01:00
|
|
|
├── planner/ planner-poll.sh, planner-agent.sh — vision gap analysis
|
2026-03-17 18:53:15 +00:00
|
|
|
├── supervisor/ supervisor-poll.sh — health monitoring
|
|
|
|
|
├── lib/ env.sh, ci-debug.sh, matrix_listener.sh
|
|
|
|
|
├── projects/ *.toml — per-project config
|
|
|
|
|
└── docs/ Protocol docs (PHASE-PROTOCOL.md, etc.)
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
## Tech stack
|
|
|
|
|
|
|
|
|
|
- **Shell**: bash (all agents are bash scripts)
|
|
|
|
|
- **AI**: `claude -p` (one-shot) or `claude` (interactive/tmux sessions)
|
|
|
|
|
- **CI**: Woodpecker CI (queried via REST API + Postgres)
|
|
|
|
|
- **VCS**: Codeberg (git + Gitea REST API)
|
|
|
|
|
- **Notifications**: Matrix (optional)
|
|
|
|
|
|
|
|
|
|
## Coding conventions
|
|
|
|
|
|
|
|
|
|
- All scripts start with `#!/usr/bin/env bash` and `set -euo pipefail`
|
|
|
|
|
- Source shared environment: `source "$(dirname "$0")/../lib/env.sh"`
|
|
|
|
|
- Log to `$LOGFILE` using the `log()` function from env.sh or defined locally
|
|
|
|
|
- Never hardcode secrets — all come from `.env` or TOML project files
|
|
|
|
|
- ShellCheck must pass (CI runs `shellcheck` on all `.sh` files)
|
|
|
|
|
- Avoid duplicate code — shared helpers go in `lib/`
|
|
|
|
|
|
|
|
|
|
## How to lint and test
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
# ShellCheck all scripts
|
2026-03-17 19:21:01 +00:00
|
|
|
shellcheck dev/dev-poll.sh dev/dev-agent.sh dev/phase-test.sh \
|
|
|
|
|
review/review-poll.sh review/review-pr.sh \
|
|
|
|
|
gardener/gardener-poll.sh \
|
|
|
|
|
supervisor/supervisor-poll.sh supervisor/update-prompt.sh \
|
2026-03-18 02:05:54 +00:00
|
|
|
lib/env.sh lib/ci-debug.sh lib/ci-helpers.sh lib/load-project.sh \
|
2026-03-17 18:53:15 +00:00
|
|
|
lib/parse-deps.sh lib/matrix_listener.sh
|
|
|
|
|
|
|
|
|
|
# Run phase protocol test
|
|
|
|
|
bash dev/phase-test.sh
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
---
|
|
|
|
|
|
|
|
|
|
## Phase-Signaling Protocol (for persistent tmux sessions)
|
|
|
|
|
|
|
|
|
|
When running as a **persistent tmux session** (issue #80+), Claude must signal
|
|
|
|
|
the orchestrator at each phase boundary by writing to a well-known file.
|
|
|
|
|
|
|
|
|
|
### Phase file path
|
|
|
|
|
|
|
|
|
|
```
|
2026-03-17 19:27:11 +00:00
|
|
|
/tmp/dev-session-{project}-{issue}.phase
|
2026-03-17 18:53:15 +00:00
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### Required phase sentinels
|
|
|
|
|
|
|
|
|
|
Write exactly one of these lines (with `>`, not `>>`) when a phase ends:
|
|
|
|
|
|
|
|
|
|
```bash
|
|
|
|
|
PHASE_FILE="/tmp/dev-session-${PROJECT_NAME:-project}-${ISSUE:-0}.phase"
|
|
|
|
|
|
|
|
|
|
# After pushing a PR branch — waiting for CI
|
|
|
|
|
echo "PHASE:awaiting_ci" > "$PHASE_FILE"
|
|
|
|
|
|
|
|
|
|
# After CI passes — waiting for review
|
|
|
|
|
echo "PHASE:awaiting_review" > "$PHASE_FILE"
|
|
|
|
|
|
|
|
|
|
# Blocked on human decision (ambiguous spec, architectural question)
|
|
|
|
|
echo "PHASE:needs_human" > "$PHASE_FILE"
|
|
|
|
|
|
|
|
|
|
# PR is merged and issue is done
|
|
|
|
|
echo "PHASE:done" > "$PHASE_FILE"
|
|
|
|
|
|
|
|
|
|
# Unrecoverable failure
|
|
|
|
|
printf 'PHASE:failed\nReason: %s\n' "describe what failed" > "$PHASE_FILE"
|
|
|
|
|
```
|
|
|
|
|
|
|
|
|
|
### When to write each phase
|
|
|
|
|
|
|
|
|
|
1. **After `git push origin $BRANCH`** → write `PHASE:awaiting_ci`
|
|
|
|
|
2. **After receiving "CI passed" injection** → write `PHASE:awaiting_review`
|
|
|
|
|
3. **After receiving review feedback** → address it, push, write `PHASE:awaiting_review`
|
|
|
|
|
4. **After receiving "Approved" injection** → merge (or wait for orchestrator to merge), write `PHASE:done`
|
|
|
|
|
5. **When stuck on human-only decision** → write `PHASE:needs_human`, then wait for input
|
|
|
|
|
6. **When a step fails unrecoverably** → write `PHASE:failed`
|
|
|
|
|
|
|
|
|
|
### Crash recovery
|
|
|
|
|
|
|
|
|
|
If this session was restarted after a crash, the orchestrator will inject:
|
|
|
|
|
- The issue body
|
|
|
|
|
- `git diff` of work completed before the crash
|
|
|
|
|
- The last known phase
|
|
|
|
|
- Any CI results or review comments
|
|
|
|
|
|
|
|
|
|
Read that context, then resume from where you left off. The git worktree is
|
|
|
|
|
the checkpoint — your code changes survived the crash.
|
|
|
|
|
|
|
|
|
|
### Full protocol reference
|
|
|
|
|
|
|
|
|
|
See `docs/PHASE-PROTOCOL.md` for the complete spec including the orchestrator
|
|
|
|
|
reaction matrix and sequence diagram.
|