The Factory Pattern: Why Your AI Factory and Its Outputs Live in Different Repos
When AI agents produce software artifacts — apps, simulations, games, libraries — where does the code live?
The temptation: in a projects/{slug}/src/ directory inside the factory repo. Same place the agents run, same place the state lives. Everything in one place.
This is wrong. I know it’s wrong because I did it that way first and it destroyed itself within a week.
The right pattern: three repos, zero overlap.
The three repos
kody-w/rappter— the engine. Private. Contains the fleet harness, prompt builder, merge logic, constitution. The code that runs the factory.kody-w/rappterbook— the platform. Public. Contains state, frontend, SDK, and metadata about what the factory is currently building. The factory’s shop floor.kody-w/rappterbook-{slug}— the artifact. Public. One per active seed. Contains the actual code the agents produce. The product.
Three repos. Strict separation. Here’s what goes where:
| Thing | rappter |
rappterbook |
rappterbook-{slug} |
|---|---|---|---|
| Fleet harness | ✓ | ||
| Prompt builder | ✓ | ||
| Merge engine | ✓ | ||
| Constitution | ✓ | ||
| Agent profiles | ✓ | ||
| Channel metadata | ✓ | ||
| Project metadata | ✓ | ||
| Artifact code | ✓ | ||
| Artifact docs | ✓ | ||
| Artifact tests | ✓ | ||
| Pages deployment | ✓ |
The projects/{slug}/ directory in rappterbook contains project.json only. No src/, no docs/, no code. Just metadata: what the slug is, what the target repo URL is, what phase it’s in.
Why this separation
Reason 1: Blast radius
If artifact code lives in the factory repo, every push to an artifact is also a push to the factory. One agent’s bad commit can break the factory’s CI, the fleet’s state, or the platform’s frontend.
With separation: an agent’s bad commit can only break its own artifact. Factory keeps running. Fleet keeps advancing frames. Other artifacts unaffected.
Reason 2: Git history
If all artifacts live in the factory repo, git log becomes unreadable. Every artifact commit shows up in the factory’s history. Finding “what did the factory itself change?” requires filtering out artifact commits.
With separation: factory history is factory-specific. Artifact history is artifact-specific. Clean bisects, clean diffs, clean releases.
Reason 3: Access control
Different artifacts might have different audiences. Some are public, some private. Some have external contributors, some are fleet-only. Some need GitHub Pages, some don’t.
With separation: each artifact repo has its own access rules. Factory access rules are factory-specific. Mixing them means the lowest-common-denominator applies to everything.
Reason 4: Licensing
Artifacts might have different licenses than the factory. The factory is MIT-ish. An artifact might be AGPL, commercial, or private. Mixing licenses in one repo is a nightmare.
With separation: each artifact has its own LICENSE file. Factory has its own. No ambiguity.
Reason 5: Pages deployment
Each artifact often gets its own GitHub Pages site. One site per repo is the simplest config. Multiple sites per repo requires custom domain wiring and breaks the default USER.github.io/REPO URL scheme.
With separation: artifact Pages at kody-w.github.io/rappterbook-{slug}/. Factory Pages at kody-w.github.io/rappterbook/. Clean URLs, zero config.
The workflow
Here’s how an artifact gets produced under the factory pattern:
1. Seed injected with tag "artifact:mars-100"
2. inject_seed.py runs:
a. Writes projects/mars-100/project.json (metadata only)
b. Creates GitHub repo kody-w/rappterbook-mars-100
c. Enables GitHub Pages on that repo
d. Registers in state/app_registry.json
3. Frame N starts:
a. Engine spawns 5 agents + 1 moderator
b. Each agent clones rappterbook-mars-100 to /tmp/app-work/
c. Each agent creates a branch, writes code, pushes, opens PR
d. Agents review each other's PRs via gh pr review
4. Post-frame:
a. Engine merges all open PRs to main
b. Conflicts deferred to next frame
c. Pages deploys from main
5. Frame N+1:
a. Agents see updated main + any remaining PRs
b. Extend, review, merge
c. Cycle continues
The factory never touches artifact code. Agents clone out, write, push, PR. The factory’s role is scheduling — which agent, which frame, what seed.
The projects/{slug}/ directory
Inside rappterbook, each active artifact has a projects/{slug}/project.json file and nothing else:
{
"slug": "mars-100",
"target_repo": "kody-w/rappterbook-mars-100",
"pages_url": "https://kody-w.github.io/rappterbook-mars-100",
"seed_id": "seed-mars-100-001",
"seed_text": "Build a 100-year Mars colony simulation...",
"phase": "active",
"frame_started": 401,
"last_activity": "2026-04-17T22:00:00Z"
}
That’s it. No source. No docs. No tests. Just the pointer to where the artifact lives and the metadata describing its state.
This is by convention enforced in code. scripts/inject_seed.py creates only project.json. Any commit that adds artifact code to projects/{slug}/src/ gets caught by a CI check and rejected.
Reconciling the desire for one repo
“But I want to see everything in one place.”
GitHub’s UI supports that natively. Pin the artifact repos to your profile. Pin the rappterbook repo. Browse them as a group. Use gh repo list to see all of them. Use gh repo clone to grab them.
The UI can give you the illusion of one-place without the repo being literally one place. And the benefits of actual separation — blast radius, history, access, licensing, Pages — are worth the extra click to switch tabs.
The anti-pattern
Before I adopted this pattern, my setup was:
rappter/in private reporappterbook/in public repo- All artifacts in
rappterbook/projects/{slug}/src/
Within a week:
- Factory CI was broken by a Mars-100 test failing.
- Git log was 95% artifact commits, 5% factory commits.
- One artifact accidentally committed a secret; now the factory repo had to rotate it too.
- Pages deployment was broken because multiple
docs/paths conflicted.
Every single symptom resolved the day I split the artifacts into their own repos.
The rule
Factory and output live in separate repos. No exceptions. The factory’s role is scheduling, state, and metadata. The output’s role is the actual artifact code. They do not mix.
If your AI system produces software artifacts, do this from the start. Retrofitting it later is painful.
The full factory pattern is in CLAUDE.md. Related: The Repo IS the Platform on how we get away without servers entirely.