How it works

Nine stages, one deterministic pass

From a single rhodd.yaml to a locked, reproducible baseline. Every stage is local, inspectable, and emits real artifacts. The four amber stages — model, quality, ownership, handoff — are where a baseline compiler does what a template cannot.

At a glancethe nine stages
01
validate
Schema + rules check
02
model
Build the system model
03
graph
Resolve dependencies
04
plan
Compute write set
05
generate
Emit target artifacts
06
quality
Gates + checks
07
lock
Hash + freeze
08
ownership
Assign boundaries
09
handoff
Context for humans + AI
Differentiator — model, quality, ownership, handoffStandard compile stage
01

validate

Parse the definition and check it against the schema and the rule set. Nothing proceeds until the input is provably well-formed.

rhodd validate
bash
$ rhodd validate
 schema           rhodd.yaml conforms to v0.1
 services         4 declared · kinds resolved
 modules          postgres, redis
 ports            5173, 3000, 8081, 9100 no collisions
 graph            acyclic · 0 cycles
validation passed ready to generate
02

modelDifferentiator

Build the system model — the typed, in-memory representation of every service, module, runtime and relationship. This is the object a template never keeps.

Services
2
web · api
Modules
2
postgres · redis
Runtimes
react-ts-zod · node-nest
Model
typed
in-memory
03

graph

Resolve dependencies into a directed graph and prove it acyclic. The graph is emitted as an artifact — the system as a machine-readable shape.

  • Service node: web (runtime react-ts-zod).
  • Service node: api (runtime node-nest).
  • Service node: audit (runtime go-http).
  • Service node: jobs (runtime node-worker).
  • Module node: postgres.
  • Module node: redis.
  • Edge: web depends on api over http.
  • Edge: audit depends on api over http.
  • Edge: jobs depends on api over http.
  • Edge: api owns postgres.
  • Edge: api owns redis.
  • Edge: jobs depends on postgres.
  • Edge: jobs depends on redis.
  • Graph is acyclic, proven by topological order.
Service nodeModule nodeownsdepends_onacyclic · topological order
04

plan

Compute the full write set before touching disk. A dry-run plan lists every file the compile intends to create, so there are no surprises.

plan.json
json
{
  "system_name": "fullstack-saas",
  "target": "full-project",
  "generationIntent": "greenfield",
  "inputs": ["docker-compose", "envfiles", "kubernetes-plan", "spec-backed-artifacts", "metadata", "ai-handoff"],
  "outputs": [
    { "path": ".env.d/api.env",           "sha256": "15b77821ca910b64b0e63365b059e275cdc50c3bc53c6c7804a22777694b4af0", "ownership": "generated-only", "origin": "required-glue" },
    { "path": ".env.d/web.env",           "sha256": "eefa6c309d8a400eb284e514a07c900865db9032a01b8999df401db5ae48783f", "ownership": "generated-only", "origin": "required-glue" },
    { "path": "README.md",                "sha256": "cd2e13e769b0b00f0275e92cfdcc3f887521f955f5739c31c58165c1f5e2cf68", "ownership": "generated-only", "origin": "required-glue" },
    { "path": "config/integrations.json", "sha256": "b38218fb03b8d6320ff1235d4f1f8d849d8398b10cb6f9fbbc6461ee778db142", "ownership": "generated-only", "origin": "policy-scaffold" },
    { "path": "config/rhodd.local.yaml",  "sha256": "0c0fed1a874b2298dc35a6503b89339b27b5207902b51100392fc48a81278469", "ownership": "scaffold-once", "origin": "required-glue" }
  ],
  "_more": "…222 more · 227 outputs total",
  "safety": [
    "writes only under explicit --out",
    "guarded apply uses generated manifest and refuses user-owned overwrites",
    "kubernetes apply requires --dry-run or --confirm",
    "providers run only through explicit provider run gates"
  ]
}
05

generate

Emit the target artifacts and the .rhodd/ state directory. Deterministic emit means the same model always produces the same files — compose, envfiles, Kubernetes manifests, service scaffolds.

.rhodd/generated
model.json3.4 kb
graph.json2.8 kb
plan.json4.1 kb
manifest.json1.6 kb
ai/# handoff
services/scaffolds
api/
web/
·compose.yamldocker-compose
k8s/manifests
·.env.exampleenvfiles
·.rhodd.lockreproducible
06

qualityDifferentiator

Run quality gates against the generated output — schema, acyclicity, port uniqueness and ownership completeness. A compile that fails a gate fails loudly.

schemagraph-acyclicports-uniqueownership-complete9 / 9 passed
07

lock

Hash inputs and outputs and freeze a lock file. The lock is the reproducibility receipt — re-running with the same inputs yields identical hashes.

input_hash
a91f…3e0c
sha256
output_hash
77bd…12af
sha256
Compiler
rhodd@0.1.0
Reproducible
true
identical on re-run
08

ownershipDifferentiator

Record ownership boundaries from the model: which paths Rhodd generates versus the source you own. The map that keeps a growing system inspectable instead of a free-for-all.

Generated
4 paths
compose · k8s · .rhodd/ · Dockerfile
User-owned
2 globs
services/**/src
Policy
regenerate-generated-only
0 conflicts
09

handoffDifferentiator

Write the .rhodd/ai handoff — the context a future contributor, or an AI agent, reads to continue safely. It is lint-checked with secrets redacted; AI consumes it but never drives the compile, and providers never run by default (skipped unless you pass --include provider).

.rhodd/ai/context.md
md
# Rhodd handoff — for humans and AI

Read order: context → model → graph → generation-plan → ownership → target-matrix

This system was compiled deterministically. Treat the artifacts under `.rhodd/`
as ground truth. Rhodd works without AI; AI becomes safer when it reads this
explicit state instead of guessing.

  .rhodd/ai/
    context.md            system shape + read order (this file)
    prompts/              task-scoped prompts, ready to paste
    tasks/                bounded, checkable units of work
    graph.json            services, modules, edges (acyclic)
    model.json            the resolved system
    generation-plan.json  the write set (dry-run clean)
    ownership.md          generated vs user-owned paths
    target-matrix.md      targets → emitted files

Safety (code-enforced): the handoff is lint-checked and secrets are redacted —
the linter errors on api_key / token / secret / password patterns and never
prints the value. Providers (openai, anthropic, gemini) never run by default;
they are skipped unless you pass `--include provider`, and the run records
"no provider call was made". A deterministic local `fake` provider is available
for offline validation.

That’s the whole loop.

Local-first, deterministic, reproducible — and ready to hand off. Compile your first baseline now.