docs: update README for multi-project vision, add gardener, expand setup
- Remove harb-specific framing — describe as project-agnostic factory - Add gardener agent (was missing from docs entirely) - New Prerequisites section with required vs optional dependencies - Expand Setup with full annotated .env example - Add Agents summary table - Add "project-agnostic" design principle Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
2b3c488f1c
commit
f16df6c53e
1 changed files with 84 additions and 31 deletions
115
README.md
115
README.md
|
|
@ -1,21 +1,43 @@
|
||||||
# 🏭 Dark Factory
|
# Dark Factory
|
||||||
|
|
||||||
Autonomous CI/CD factory for [harb](https://codeberg.org/johba/harb). Three agents, zero supervision needed.
|
Autonomous CI/CD factory. Four agents, zero supervision needed.
|
||||||
|
|
||||||
|
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
|
## Architecture
|
||||||
|
|
||||||
```
|
```
|
||||||
cron (*/10) ──→ factory-poll.sh ← supervisor (bash checks, zero tokens)
|
cron (*/10) ──→ factory-poll.sh ← supervisor (bash checks, zero tokens)
|
||||||
├── all clear? → exit 0
|
├── all clear? → exit 0
|
||||||
└── problem? → claude -p (diagnose, fix, or escalate)
|
└── problem? → claude -p (diagnose, fix, or escalate)
|
||||||
|
|
||||||
cron (*/10) ──→ dev-poll.sh ← pulls ready issues, spawns dev-agent
|
cron (*/10) ──→ dev-poll.sh ← pulls ready issues, spawns dev-agent
|
||||||
└── dev-agent.sh ← claude -p: implement → PR → CI → review → merge
|
└── dev-agent.sh ← claude -p: implement → PR → CI → review → merge
|
||||||
|
|
||||||
cron (*/10) ──→ review-poll.sh ← finds unreviewed PRs, spawns review
|
cron (*/10) ──→ review-poll.sh ← finds unreviewed PRs, spawns review
|
||||||
└── review-pr.sh ← claude -p: review → approve/request changes
|
└── 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
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Prerequisites
|
||||||
|
|
||||||
|
**Required:**
|
||||||
|
|
||||||
|
- [Claude CLI](https://docs.anthropic.com/en/docs/claude-cli) — `claude` in PATH, authenticated
|
||||||
|
- [Codeberg](https://codeberg.org/) account with an API token — the factory 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](https://woodpecker-ci.org/) — local instance connected to your Codeberg repo; the factory 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:**
|
||||||
|
|
||||||
|
- [OpenClaw](https://openclaw.ai/) — escalation notifications; when agents hit something they can't resolve, they send a system event via `openclaw` CLI
|
||||||
|
- [Foundry](https://getfoundry.sh/) (`forge`, `cast`, `anvil`) — only needed if your target project uses Solidity
|
||||||
|
- [Node.js](https://nodejs.org/) — only needed if your target project uses Node
|
||||||
|
|
||||||
## Setup
|
## Setup
|
||||||
|
|
||||||
```bash
|
```bash
|
||||||
|
|
@ -25,14 +47,40 @@ cd dark-factory
|
||||||
|
|
||||||
# 2. Configure
|
# 2. Configure
|
||||||
cp .env.example .env
|
cp .env.example .env
|
||||||
# Fill in your tokens (see .env.example for descriptions)
|
```
|
||||||
|
|
||||||
# 3. Install cron (staggered — supervisor first, then review, then dev)
|
Edit `.env` with your values:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 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)
|
||||||
|
```
|
||||||
|
|
||||||
|
```bash
|
||||||
|
# 3. Install cron (staggered to avoid overlap)
|
||||||
crontab -e
|
crontab -e
|
||||||
# Add:
|
# Add:
|
||||||
# 0,10,20,30,40,50 * * * * /path/to/dark-factory/factory/factory-poll.sh
|
# 0,10,20,30,40,50 * * * * /path/to/dark-factory/factory/factory-poll.sh
|
||||||
# 3,13,23,33,43,53 * * * * /path/to/dark-factory/review/review-poll.sh
|
# 3,13,23,33,43,53 * * * * /path/to/dark-factory/review/review-poll.sh
|
||||||
# 6,16,26,36,46,56 * * * * /path/to/dark-factory/dev/dev-poll.sh
|
# 6,16,26,36,46,56 * * * * /path/to/dark-factory/dev/dev-poll.sh
|
||||||
|
# 15 8 * * * /path/to/dark-factory/gardener/gardener-poll.sh
|
||||||
|
|
||||||
# 4. Verify
|
# 4. Verify
|
||||||
bash factory/factory-poll.sh # should log "all clear"
|
bash factory/factory-poll.sh # should log "all clear"
|
||||||
|
|
@ -42,22 +90,25 @@ bash factory/factory-poll.sh # should log "all clear"
|
||||||
|
|
||||||
```
|
```
|
||||||
dark-factory/
|
dark-factory/
|
||||||
├── .env.example # Template — copy to .env, add secrets
|
├── .env.example # Template — copy to .env, add secrets + project config
|
||||||
├── .gitignore # Excludes .env, logs, state files
|
├── .gitignore # Excludes .env, logs, state files
|
||||||
├── lib/
|
├── lib/
|
||||||
│ ├── env.sh # Shared: load .env, PATH, API helpers
|
│ ├── env.sh # Shared: load .env, PATH, Codeberg/Woodpecker API helpers
|
||||||
│ └── ci-debug.sh # Woodpecker CI log/failure helper
|
│ └── ci-debug.sh # Woodpecker CI log/failure helper
|
||||||
├── dev/
|
├── dev/
|
||||||
│ ├── dev-poll.sh # Cron entry: find ready issues
|
│ ├── dev-poll.sh # Cron entry: find ready issues
|
||||||
│ └── dev-agent.sh # Implementation agent (claude -p)
|
│ └── dev-agent.sh # Implementation agent (claude -p)
|
||||||
├── review/
|
├── review/
|
||||||
│ ├── review-poll.sh # Cron entry: find unreviewed PRs
|
│ ├── review-poll.sh # Cron entry: find unreviewed PRs
|
||||||
│ └── review-pr.sh # Review agent (claude -p)
|
│ └── review-pr.sh # Review agent (claude -p)
|
||||||
|
├── gardener/
|
||||||
|
│ ├── gardener-poll.sh # Cron entry: backlog grooming
|
||||||
|
│ └── best-practices.md # Gardener knowledge base
|
||||||
└── factory/
|
└── factory/
|
||||||
├── factory-poll.sh # Supervisor: health checks + claude -p
|
├── factory-poll.sh # Supervisor: health checks + claude -p
|
||||||
├── PROMPT.md # Supervisor's system prompt
|
├── PROMPT.md # Supervisor's system prompt
|
||||||
├── update-prompt.sh# Self-learning: append to best-practices
|
├── update-prompt.sh # Self-learning: append to best-practices
|
||||||
└── best-practices/ # Progressive disclosure knowledge base
|
└── best-practices/ # Progressive disclosure knowledge base
|
||||||
├── memory.md
|
├── memory.md
|
||||||
├── disk.md
|
├── disk.md
|
||||||
├── ci.md
|
├── ci.md
|
||||||
|
|
@ -67,18 +118,20 @@ dark-factory/
|
||||||
└── git.md
|
└── git.md
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Agents
|
||||||
|
|
||||||
|
| Agent | Trigger | Job |
|
||||||
|
|-------|---------|-----|
|
||||||
|
| **Factory** (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
|
## Design Principles
|
||||||
|
|
||||||
- **Bash for checks, AI for judgment** — health checks are shell scripts; AI is only invoked when something needs diagnosing or fixing
|
- **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
|
- **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
|
- **Progressive disclosure** — the supervisor reads only the best-practices file relevant to the current problem, not all of them
|
||||||
- **Self-improving** — when the AI fixes something new, it appends the lesson to best-practices for next time
|
- **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
|
||||||
|
|
||||||
## Requirements
|
|
||||||
|
|
||||||
- [Claude CLI](https://docs.anthropic.com/en/docs/claude-cli) (`claude` in PATH)
|
|
||||||
- [Foundry](https://getfoundry.sh/) (`forge`, `cast`, `anvil`)
|
|
||||||
- [Woodpecker CI](https://woodpecker-ci.org/) (local instance)
|
|
||||||
- PostgreSQL client (`psql`)
|
|
||||||
- [OpenClaw](https://openclaw.ai/) (for escalation notifications, optional)
|
|
||||||
- `jq`, `curl`, `git`
|
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue