Real artifacts, not promises
Everything below is what Rhodd actually writes — plain-text files you can open, diff and commit. Rhodd works without AI; AI becomes safer when Rhodd gives it this explicit state.
One deterministic run
Five real commands, each copy-runnable. No compile step, no infrastructure-as-code flag — just validate, graph, plan, generate, quality.
$ rhodd validate # schema + rules ......... ok
$ rhodd graph # resolve dependencies ... acyclic · 0 cycles
$ rhodd plan # dry-run write set ...... 42 writes
$ rhodd generate # emit baseline + .rhodd/ 38 files
$ rhodd quality # quality gates .......... 9 / 9 passedYour system, as data
The graph is real output — resolved, proved acyclic, and emitted alongside the rest of the .rhodd/ state directory.
- 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.
Inspect every artifact
Each tab is a real file Rhodd generates — the graph, the planned write set, the emitted manifest, ownership records, quality report, and the lock receipt.
{
"schema_version": "rhodd.full_project.graph.v1",
"system_name": "fullstack-saas",
"nodes": [
{ "name": "web", "kind": "app", "runtime": "react-ts-zod", "provides": ["http"], "consumes": ["http"] },
{ "name": "api", "kind": "app", "runtime": "node-nest", "provides": ["http"], "consumes": ["postgres", "redis"] },
{ "name": "audit", "kind": "app", "runtime": "go-http", "provides": ["http"], "consumes": ["http"] },
{ "name": "jobs", "kind": "app", "runtime": "node-worker", "provides": ["worker"], "consumes": ["http", "postgres", "redis"] },
{ "name": "postgres", "kind": "infra", "runtime": "postgres", "provides": ["postgres"] },
{ "name": "redis", "kind": "infra", "runtime": "redis", "provides": ["redis"] }
],
"edges": [
{ "dependent": "api", "dependency": "postgres" },
{ "dependent": "api", "dependency": "redis" },
{ "dependent": "audit", "dependency": "api" },
{ "dependent": "jobs", "dependency": "api" },
{ "dependent": "jobs", "dependency": "postgres" },
{ "dependent": "jobs", "dependency": "redis" },
{ "dependent": "web", "dependency": "api" }
],
"topological_order": ["postgres", "redis", "api", "audit", "jobs", "web"],
"entities": [
{ "name": "User", "owner": "services/api/src/modules/users" },
{ "name": "Session", "owner": "services/api/src/modules/auth" },
{ "name": "BillingAccount", "owner": "services/api/src/modules/billing" },
{ "name": "AuditEvent", "owner": "services/audit" },
{ "name": "JobRun", "owner": "services/jobs" }
]
}{
"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"
]
}{
"system_name": "fullstack-saas",
"target": "full-project",
"file_count": 227,
"files": [
{ "path": ".env.d/api.env", "sha256": "15b77821ca910b64b0e63365b059e275cdc50c3bc53c6c7804a22777694b4af0", "ownership": "generated-only", "apply_policy": "create-or-update", "origin": "required-glue" },
{ "path": ".rhodd/ai/context.md", "sha256": "11d5eed17cd28a2329170cddc381eba4908ea4d4acc6ac4ec71154ab2475f738", "ownership": "generated-only", "apply_policy": "create-or-update", "origin": "required-glue" },
{ "path": ".rhodd/ai/graph.json", "sha256": "6b09ef87cc0a2561b1ce3291cbdaf1e0c6d7483c36479c26565cd74bb3b6deaa", "ownership": "generated-only", "apply_policy": "create-or-update", "origin": "required-glue" },
{ "path": "config/integrations.json", "sha256": "b38218fb03b8d6320ff1235d4f1f8d849d8398b10cb6f9fbbc6461ee778db142", "ownership": "generated-only", "apply_policy": "create-or-update", "origin": "policy-scaffold" },
{ "path": "config/rhodd.local.yaml", "sha256": "0c0fed1a874b2298dc35a6503b89339b27b5207902b51100392fc48a81278469", "ownership": "scaffold-once", "apply_policy": "create-if-absent", "origin": "required-glue" }
],
"_more": "…222 more · 227 files (226 generated-only + 1 scaffold-once)"
}{
"schema_version": "rhodd.full_project.ownership.v1",
"system_name": "fullstack-saas",
"classes": [
{ "name": "generated-only", "description": "Rhodd may create or update through generated manifest and guarded apply.", "apply_policy": "create-or-update" },
{ "name": "scaffold-once", "description": "Rhodd creates the file when absent, then preserves existing destination content.", "apply_policy": "create-if-absent" },
{ "name": "managed-with-regions", "description": "Rhodd may update generated structure while preserving protected user-editable regions.", "apply_policy": "create-or-update" },
{ "name": "user-owned", "description": "Files outside generated ownership evidence are not overwritten by guarded apply.", "apply_policy": "refuse-overwrite" },
{ "name": "metadata-only", "description": "Inspectable state used for explainability and gates; repo apply records it but skips writes.", "apply_policy": "metadata-only" }
],
"rules": [
"Generated manifest records are the source of truth for guarded apply eligibility.",
"Secret values are never emitted; generated env, compose, Kubernetes, and AI files use keys or redacted templates.",
"Provider, Docker Compose, and live Kubernetes execution require explicit user gates outside generation."
],
"boundaries": [
{ "path_prefix": "services/", "owner": "rhodd", "class": "generated-only", "apply_policy": "create-or-update" },
{ "path_prefix": "database/", "owner": "rhodd", "class": "generated-only", "apply_policy": "create-or-update" },
{ "path_prefix": "k8s/", "owner": "rhodd", "class": "generated-only", "apply_policy": "create-or-update" },
{ "path_prefix": ".rhodd/", "owner": "rhodd", "class": "generated-only", "apply_policy": "create-or-update" },
{ "path_prefix": "config/rhodd.local.yaml", "owner": "user-after-first-apply", "class": "scaffold-once", "apply_policy": "create-if-absent" },
{ "path_prefix": "k8s-plan.json", "owner": "rhodd", "class": "metadata-only", "apply_policy": "metadata-only" },
{ "path_prefix": "unlisted files", "owner": "user", "class": "user-owned", "apply_policy": "refuse-overwrite" }
]
}{
"schema_version": "rhodd.generated_project_quality.v1",
"system_name": "fullstack-saas",
"checks": [
{ "name": "frontend-tree", "status": "pass" },
{ "name": "backend-tree", "status": "pass" },
{ "name": "db-prisma-tree", "status": "pass" },
{ "name": "worker-tree", "status": "pass" },
{ "name": "ai-handoff", "status": "pass" },
{ "name": "duplicate-paths", "status": "pass" },
{ "name": "typescript-double-extension", "status": "pass" },
{ "name": "manifest-completeness", "status": "pass" }
]
}{
"schema_version": "rhodd.full_project.lock.v1",
"system_name": "fullstack-saas",
"target": "full-project",
"graph_sha256": "6b09ef87cc0a2561b1ce3291cbdaf1e0c6d7483c36479c26565cd74bb3b6deaa",
"model_sha256": "85e201b6559a46d0e37394927e39a5336f05862445033249ec25ae2b47c20570",
"generation_plan_sha256": "15c261ccaa9efe98c4bcaba7c915ce03099cb99ad8d84cbdb870a12e6fccd97a",
"generated_file_count": 130,
"message": "deterministic full-project lock over graph, model, generation plan, and generated file count"
}Same input, byte-identical output
The lock receipt hashes the input and the generated tree. Re-run with the same input and the output hash is identical — that’s the reproducibility guarantee, on paper.
Export — files, not live deploys
Deployment export writes Argo CD, Flux or generic Kubernetes manifest files. Files, not live deploys — guarded apply is opt-in, and no cluster calls happen by default.
# .rhodd/export/argocd/api.application.yaml
# a generated file — guarded apply is opt-in, no cluster calls by default
apiVersion: argoproj.io/v1alpha1
kind: Application
metadata:
name: api
namespace: argocd
spec:
project: default
source:
repoURL: https://github.com/rhodd-fdn/rhodd
path: k8s/api
destination:
namespace: acme
syncPolicy: {} # manual sync — nothing applies on its ownSee it for yourself.
Install the CLI, compile a baseline, and read every artifact it writes — all on your machine.