Context
app/core/scenario_renderer/writer.py exposes render_scenario(spec) -> {path: content} —
a pure, in-memory assembler that produces a complete bundle-scenario directory. Nothing
calls it from an API route yet, so a UI-authored scenario cannot actually be deployed.
Scope
Wire the renderer into the v1 deploy path:
-
Render — accept a project/topology, adapt it to a ScenarioSpec, allocate vmids
and IPs, call render_scenario.
-
Materialize — write the tree to
range42-playbooks/scenarios/<name>/.
This location is not negotiable: the deployer-cli hardcodes it in
workspace.symlinks, in SCENARIO_TEMPLATES_DIR, and in scenario discovery. A
generated scenario cannot live in a project repo and be deployed — it must land there
(or be symlinked into it).
-
Commit/push to the scenario repo, then deploy through the existing deployment
flow (/v1/deployments), so the generated scenario runs on the plain runner exactly
like a hand-authored one.
Constraints worth knowing before starting
- Scenario name must match
^[a-z][a-z0-9_]*$ (already enforced in
ScenarioSpec.__post_init__). The deployer derives <name>.setup.sh from the directory
basename, and the TUI parses the workspace name with ^(.+)-([a-z][a-z0-9_]*)$. A
hyphenated or title-cased UI project title — the natural default — breaks both.
hosts.yml cannot be pre-rendered. The four templates/*.j2 files
(ansible-inventory, ssh-config, ansible-vars, vault-example) are a hard deployer-cli
discovery gate. The inventory carries per-workspace Jinja (codename, Proxmox address) and
VM IPs come from ssh-config.j2, not the inventory. The renderer already emits
99%-concrete files with a fixed Jinja frame — keep that property.
_reserved.json must be regenerated after materializing, and
scenarios/_check_reserved.sh should gate the commit. Otherwise a UI-authored scenario
can silently poison the collision ledger.
- Deploy secrets already have a contract (Proxmox token via
/v1/proxmox/hosts, git PAT in
sources, vault_pass.txt + ssh keys in the workspace) — reuse it, don't invent a second one.
Depends on
- The canvas →
ScenarioSpec adapter.
- The VMID/IP allocator.
Acceptance
- A canvas-authored project renders, materializes, commits, and deploys end-to-end.
- The generated scenario is byte-plausible next to a hand-authored one (a reviewer cannot
tell which is which from the directory alone).
_check_reserved.sh passes after the commit.
Context
app/core/scenario_renderer/writer.pyexposesrender_scenario(spec) -> {path: content}—a pure, in-memory assembler that produces a complete bundle-scenario directory. Nothing
calls it from an API route yet, so a UI-authored scenario cannot actually be deployed.
Scope
Wire the renderer into the v1 deploy path:
Render — accept a project/topology, adapt it to a
ScenarioSpec, allocate vmidsand IPs, call
render_scenario.Materialize — write the tree to
range42-playbooks/scenarios/<name>/.This location is not negotiable: the deployer-cli hardcodes it in
workspace.symlinks, inSCENARIO_TEMPLATES_DIR, and in scenario discovery. Agenerated scenario cannot live in a project repo and be deployed — it must land there
(or be symlinked into it).
Commit/push to the scenario repo, then deploy through the existing deployment
flow (
/v1/deployments), so the generated scenario runs on the plain runner exactlylike a hand-authored one.
Constraints worth knowing before starting
^[a-z][a-z0-9_]*$(already enforced inScenarioSpec.__post_init__). The deployer derives<name>.setup.shfrom the directorybasename, and the TUI parses the workspace name with
^(.+)-([a-z][a-z0-9_]*)$. Ahyphenated or title-cased UI project title — the natural default — breaks both.
hosts.ymlcannot be pre-rendered. The fourtemplates/*.j2files(ansible-inventory, ssh-config, ansible-vars, vault-example) are a hard deployer-cli
discovery gate. The inventory carries per-workspace Jinja (codename, Proxmox address) and
VM IPs come from
ssh-config.j2, not the inventory. The renderer already emits99%-concrete files with a fixed Jinja frame — keep that property.
_reserved.jsonmust be regenerated after materializing, andscenarios/_check_reserved.shshould gate the commit. Otherwise a UI-authored scenariocan silently poison the collision ledger.
/v1/proxmox/hosts, git PAT insources,
vault_pass.txt+ ssh keys in the workspace) — reuse it, don't invent a second one.Depends on
ScenarioSpecadapter.Acceptance
tell which is which from the directory alone).
_check_reserved.shpasses after the commit.