Demos
Each directory under demos/ is one umbra demo. It is a guardfile over a
real tool, the commands typed on camera, and the exit code and output each command
must show. A demo is a test first and a clip second, so a clip never shows a refusal
that verify did not check.
A demo holds structure only. Its words come from umbra's own refusals and from the
guardfile's reason strings, never from prose written for the clip.
Layout
backlog.kdl-target <slug> tool=<binary>, one line per demo that should exist.<slug>/demo.kdl- the manifest.<slug>/.umbra/<tool>.guardfile.{kdl,yaml,toml}- the policy, once per format..render/- ignored. The workspace,result.json, the clip, and the review sheet.
The manifest
demo git-read-only {
tool git
state minted
formats kdl yaml toml
frame cols=80 rows=14
setup {
git-init
file "notes.txt" "draft\n"
}
step "git push" exit=2 shows="is withheld"
}
state-minted,approved,bounced, orpublished. Only a human moves it pastminted.formats- the guardfile formats the policy ships in, all three by default. The first is the one filmed.frame- the terminal in columns and rows. Verify fails any output that would wrap or scroll off.setup-git-init,file <path> <body>, andguardfile <path>, which copies the policy into view.step- one command, its exit code, and a substring its output must contain.
Minting one
Run these from demos/.
just nextprints the first queued slug, andjust new <slug>scaffolds it.- Write the guardfile and the steps. Read replacement first.
just verify <slug>until it passes. Three formats take about 80 seconds.just render <slug>verifies, then records the clip. Openlast.pngand look.just sheetwrites.render/index.html, the page a reviewer approves from.
One policy, three formats
Verify installs the policy once per format and runs every step against each. It fails
unless the three transcripts match byte for byte, so a clip filmed in KDL stands for
the YAML and TOML twins too. The review sheet has a kdl, yaml and toml switch, and
the f key cycles it, flipping every card's guardfile at once.
The exec grammar has no YAML or TOML schema yet, so exec, replace, withhold and
deny-flag ride the kdl escape inside wrap. A top-level withhold list is
dropped without an error for an exec wrap, and verify catches the divergence if a
demo writes one.
Which umbra
Verify builds umbra from the checkout demos/ sits in and locks against it with
--umbra-replace, so a demo tests the umbra beside it rather than an installed
release. An exit code that changes on main fails the demo that pinned the old one.
What a step can reach
Every step runs with HOME inside the workspace, so no operator config or credential
reaches a demo. A step exits the way it would for a caller with no login, which is why
a demo shows refusals rather than remote reads.
Recording
VHS is pinned to v0.11.0 as a go tool in demos/go.mod, because v0.12.0 exits 0
and writes no file
(charmbracelet/vhs#787). Render
therefore probes the clip itself rather than trusting the exit code.
Off-camera lines type at 1ms, since at the on-camera speed the hidden env line alone cost 23 seconds a render. Width and height round to even, because libx264 refuses an odd dimension and vhs then leaves a zero-byte mp4 behind a clean exit.
just gif <slug> converts a rendered clip for markdown, which cannot embed mp4. It
stays out of render because encoding both formats doubled every render's cost.
A rerun renames the previous workspace aside before deleting it. Back-to-back runs
intermittently lost a RemoveAll race inside the previous run's HOME, and a rename
cannot.
Corpora
The same harness also generates labelled call corpora for measurement. See corpora.