The agent harness performance optimization system. Skills, instincts, memory, security, and research-first development for Claude Code, Codex, Opencode, Cursor and beyond.
Archon workflow harness for Claude Code issue factories
This repository packages a dark-factory workflow system around Archon so AI agents can triage GitHub issues, implement fixes, validate pull requests, and merge approved changes. The workflows are defined in `.archon/workflows/` and are controlled by labels, rules files, and deterministic shell steps.
Builders who want Claude Code workflows that can handle issue triage, implementation, review, and merging from GitHub.
You can run a mostly autonomous issue-to-merge loop without manually reading every diff.
What it does
Issue triage workflow
Classifies incoming issues, applies labels, and rejects or accepts them based on the repo’s mission and rules.
Implementation workflow
Runs a multi-step fix flow that researches, plans, edits, validates, and opens a draft pull request.
Independent PR validation
Rechecks pull requests with holdout review steps, then auto-merges or sends them back for fixes.
Regression test workflow
Boots the app, runs browser scenarios, and files new issues when something breaks.
Governance lockout
Protects `MISSION.md`, `FACTORY_RULES.md`, and `CLAUDE.md` from factory edits.
RAG chat app
Maintains a FastAPI and React app that answers questions over YouTube transcripts with cited passages.
How to get it
- 1Apply migrations
cd app/backend && uv run alembic upgrade head
- 2Start everything
# Unix/Mac cd app && ./start.sh # Windows cd app && start.bat
- 3Run
cd app/backend && uv run ruff check . && uv run mypy . && uv run pytest cd app/frontend && bun run lint && bun run type-check && bun run test
README
The Dark Factory Experiment (RAG YouTube Chat App)
A public Dark Factory experiment. This repository is a working web application that is built, reviewed, and merged almost entirely by AI coding agents. Humans do two things: file issues and promote releases. Everything in between - triage, implementation, code review, testing, merging - is handled by Archon workflows running on a cron.
Two honest caveats, because they are the design and not an asterisk. This runs at level 4, not level 5: the factory does not write its own issues. And there is a deliberate human-authored perimeter it is never allowed to touch - auth, rate limiting, the deploy configs, and the three governance files that define its own rules. The list is in FACTORY_RULES.md, and a PR touching any of it is auto-rejected before anything else is evaluated. An autonomous system is only as trustworthy as the things it cannot change about itself.
The application itself is a dark-mode AI chat app that lets you have grounded conversations about a creator's YouTube videos, with cited answers pulled from transcript passages. But the real point of this repo is the factory that builds it.

The Dark Factory
The term "Dark Factory" comes from Dan Shapiro (Glowforge), inspired by FANUC's 1980s lights-out robotics plants where robots built robots 24/7 with no humans on the floor. Applied to software: specs go in, software comes out.
This repo is a live attempt at that pattern, and it uses GitHub itself as the shared state machine.
The three layers
There's a stack of three distinct things doing the work, and it's worth pulling them apart:
- The harness: Archon. The workflow engine, and the thing that makes the whole experiment possible. Archon lets you stitch coding agent sessions together with deterministic steps (running scripts, calling
gh, parsing output, branching on results) into a single end-to-end workflow you actually trust. The Dark Factory's logic, "triage these issues, then implement this one, then validate the PR, then merge it," is built in Archon as a handful of workflows under.archon/workflows/. Without something like Archon, you're either hand-prompting agents one step at a time or writing a giant brittle script around them. Archon is what turns "AI can sometimes do this" into "the factory does this every few hours, on its own." - The coding agent: Claude Code. Inside each AI node, Archon spawns Claude Code as the agent. Claude Code is what actually holds the tools (file editing, bash,
gh, web fetch), runs the loop, and executes the work the prompt asks for. - The model: Claude Sonnet, with Haiku on the cheap nodes. Set per workflow node, so the routing is a config decision rather than a property of the factory. Claude Code is the wrapper around the model; the model is the brain doing the reasoning and the writing.
Model routing is the cheapest lever in the whole system, and it is worth treating as one. The factory has run on MiniMax M2.7 and on Kimi K2.6 via Pi at different points in the experiment; the workflows under .archon/workflows/ currently declare provider: claude with sonnet for reasoning nodes and haiku for cheap extraction. Nothing else in the design changes when that swaps, which is the point: the agent and the model are the interchangeable parts, and the plumbing around them is not.
The mixed-provider benchmark under .archon/workflows/benchmark/ is where that gets measured rather than assumed - a matrix varying the plan and implement models independently to find out where reasoning actually pays for itself. Read BENCHMARK-PLAYBOOK.md there before quoting any number from it; it documents a known prompt-parity confound in the premium baseline cell.
How a change actually ships
GitHub Issues (filed by humans or the regression testing workflow)
│
▼
┌──────────────────────┐
│ Orchestrator (cron) │ pure-bash loop, no LLM
│ every 30 minutes │ reads GitHub state, dispatches
└──────────┬───────────┘ up to MAX_PARALLEL=4 workflows
│
┌───────────────┼────────────────┐
▼ ▼ ▼
dark-factory fix-github- dark-factory
-triage issue -validate-pr
(classify (10-phase (independent
open issues, implement + holdout review
accept/reject) draft PR) + auto-merge)
│
▼
┌─────────────┐
│ main │ AI-managed branch
│ auto-deploys│ → staging / preview
└──────┬──────┘
│ human promotes periodically
▼
┌─────────────┐
│ release/* │ human-cut stable
│ deploys │ → production
└─────────────┘
Labels are the state machine
The orchestrator does not hold state itself. It reads GitHub labels and decides what to do next:
Issues: factory:triaging → factory:accepted → factory:in-progress → (PR opened) or factory:rejected (closed with reason).
PRs: factory:implementing → factory:needs-review → factory:approved (auto-merged) or factory:needs-fix → back to review (max 2 fix attempts) → factory:needs-human (escalated).
Priority: Triage tags every accepted issue priority:critical|high|medium|low so the orchestrator picks the highest-impact work first.
The non-negotiable rules
These come from research on every prior Dark Factory attempt (StrongDM, Spotify Honk, Steve Yegge's Gas Town) and the failure modes they hit:
- The validator never reads the implementation plan. It checks the outcome against the issue, not the approach. This is StrongDM's "holdout" pattern - it's what stops an agent from gaming its own acceptance criteria.
- Triage has only two verdicts: accept or reject. No "needs human" inbox. If a human disagrees with a rejection, they reopen with more context and the next triage cycle picks it up fresh.
- Governance files (
MISSION.md,FACTORY_RULES.md,CLAUDE.md) can never be modified by the factory. The security review hard-fails any PR that touches them. The agent cannot amend the rules it is judged by. - The dispatcher is dumb on purpose. Pure bash on a 30-minute cron, reading GitHub labels as the only shared state - no database, no message bus, no LLM deciding what to run. An earlier version asked a model what to dispatch and it hallucinated runs for work that did not exist. It dispatches up to
MAX_PARALLEL=4workflows, in a fixed priority order: fix a PR, validate a PR, implement an issue, triage. Finishing in-flight work before starting new work is load-bearing - reversed, the factory triages forever while its own PRs rot. - Flood protection. Non-owner accounts are capped at 3 issues per UTC day; excess get
factory:rate-limitedand re-evaluated after midnight. - Per-node budget caps. Every workflow node has a
maxBudgetUsd. Triage batches max 10 issues per run and truncates each body to ~2KB.
Workflows in this repo
Defined in .archon/workflows/:
| Workflow | Job |
|---|---|
dark-factory-triage.yaml | Batch-classify untriaged issues against MISSION.md + FACTORY_RULES.md. Outputs structured JSON, applies labels and comments deterministically via gh. |
dark-factory-fix-github-issue.yaml | The workhorse. A Dark-Factory-owned fork of Archon's bundled fix-github-issue, adapted for this repo's Python + Bun stack: classify → research → plan → implement → Python/TS validation (ruff/mypy/pytest + tsc/biome/vitest) → draft PR → smart review → self-fix → simplify. Every AI node references a .md command file (no inline prompts). |
dark-factory-validate-pr.yaml | Independent gate. Static checks + tests, then parallel AI review (behavioral validation, code review, error handling, security check), synthesized verdict, auto-merge or fix-and-retry. The fix step is folded in as a fresh-context node so the second-pass validator stays a true holdout. |
dark-factory-comprehensive-test.yaml | Weekly regression. Boots the app, drives four end-to-end browser scenarios with agent-browser, synthesizes a report, and files a GitHub issue for anything that broke. This is what closes the self-healing loop: the factory finds its own bugs and queues them for itself. |
The orchestrator is not in this repo. It is a ~100-line bash script on the VPS
(/opt/dark-factory/orchestrator.sh) driven by cron. Deliberately so - it holds no state
of its own, and everything it reads is visible in this repo's issues, PRs and labels.
The mixed-provider benchmark suite lives separately in .archon/workflows/benchmark/. It is not part of the factory loop.
The Application
What the factory is actually building.
Architecture
┌─────────────────┐ /api proxy ┌─────────────────────────┐
│ Frontend │ ─────────────────────── │ Backend │
│ React + Vite │ localhost:5173 → │ FastAPI │
│ TypeScript │ :8000 │ │
│ Tailwind CSS │ │ Routes ── RAG Pipeline │
└─────────────────┘ │ │ │ │
│ │ Chunker │
│ │ (Docling) │
│ │ │ │
│ DB Embeddings │
│(Postgres) (OpenRouter) │
│ │ │
│ Retriever │
│ (RRF hybrid: tsvector │
│ + pgvector cosine) │
│ │ │
│ LLM │
│ (Claude via │
│ OpenRouter) │
└─────────────────────────┘
- Frontend: React 18 + Vite + TypeScript + Tailwind CSS (Bun)
- Backend: Python FastAPI, single process handling API + RAG + LLM
- Database: Postgres via asyncpg (with pgvector for hybrid retrieval)
- LLM: Claude Sonnet via OpenRouter with SSE streaming
- Embeddings:
text-embedding-3-smallvia OpenRouter - Chunking: Docling HybridChunker
- Retrieval: Reciprocal Rank Fusion (RRF) combining Postgres tsvector full-text search with pgvector cosine similarity, top-5 chunks
How it works
- Ingest - Video transcripts are chunked with Docling's HybridChunker and embedded via OpenRouter.
- Sync -
POST /api/channels/syncautomatically enumerates and ingests new videos from a YouTube channel via Supadata. - Retrieve - User queries run through Reciprocal Rank Fusion: a Postgres
tsvectorfull-text search and a pgvector cosine search are run independently and their rankings merged. - Generate - Top-5 chunks are passed as context to Claude, which streams a cited response back via SSE.
Quick Start
Prerequisites
- Python 3.11+ and uv
- Bun
- A Postgres 16+ database with the
pgvectorextension. There is no SQLite fallback - the backend raises on startup ifDATABASE_URLis unset. - An OpenRouter API key
Setup
-
Clone the repo and create an env file at
app/.env.deploy/.env.exampleis the annotated reference for every variable; the minimum to boot locally is aDATABASE_URL, anOPENROUTER_API_KEYand aJWT_SECRET. -
Apply migrations:
cd app/backend && uv run alembic upgrade head
- Start everything:
# Unix/Mac
cd app && ./start.sh
# Windows
cd app && start.bat
This installs Python dependencies with uv sync --all-extras, starts FastAPI on :8000,
runs bun install if needed, and starts Vite on :5173. Both are skipped if the port is
already in use. Set SEED_ENABLE=true if you want the mock video library; it is off by
default, so a fresh database starts empty.
Manual start
# Backend
cd app/backend
uv sync --all-extras
cd .. && uv --project backend run uvicorn backend.main:app --reload --port 8000
# Frontend (new terminal)
cd app/frontend
bun install
bun run dev
Checks
cd app/backend && uv run ruff check . && uv run mypy . && uv run pytest
cd app/frontend && bun run lint && bun run type-check && bun run test
Contributing
You contribute to this repo the same way the factory does: file an issue. Don't open a PR - the factory will. If your issue is well-scoped and in line with MISSION.md, the next triage cycle will accept it, and a workflow run will open the implementing PR. If it gets rejected, read the comment, sharpen the issue, and reopen.
That's the whole point of the experiment.
Files in the repo
- .archon
- .claude
- .factory
- .github
- app
- deploy
- docs
- harness
- scripts
- .gitattributes
- .gitignore
- CLAUDE.md
- FACTORY_RULES.md
- FACTORY.md
- MISSION.md
- README.md
Discussion (0)
Ask about usage, or say what you built with itSign in to join the discussion.
No comments yet. Be the first to say what this is good for.
More harnesses
from vibe coding to agentic engineering - practice makes claude perfect
🌊 The original agent meta-harness. Deploy intelligent multi-player swarms, coordinate autonomous workflows, and build conversational AI systems. Features adaptive memory, self-learning intelligence, RAG integration, and native Claude Code / Codex / Hermes and many more Integrated
Practical patterns, starters & CLI tools for loop engineering with AI coding agents. Design systems that prompt and orchestrate agents (inspired by Addy Osmani and Boris Cherny). Includes loop-audit, loop-init, loop-cost.
Git. Ship. Done - Core

The most RAM efficient harness