Skip to content
Start

Writing a program

The person says: “Update the hero image on all fifty sites and show me the three that changed the most.”

A program is one request that reads, decides and writes across many sites. Every call in it is the call you could make by hand, with the same rules and the same receipt; the program has no network and nothing outside the model. Read skill://empress-model.md before writing one: it lists every method, one per line, and the gotchas. skill://empress-model.d.ts is the same model as types. If your client cannot read resources, search answers with the skeleton (an example program and the gotchas that bite first), and with a site named, that site’s methods and their argument types: enough to write the first program.

  1. Empress:search — query: "empress.program_run": how a program is asked for, what it takes, and the program’s skeleton. Add site and a query like “program methods for this site” for the methods you can call on a site, with their arguments.
  2. Empress:work_request — operation: "empress.program_run", args: { program, inputs, title }: the program, the values it reads as empress.inputs, and the person’s sentence as title. A program that promotes pauses there: show the person what it waits for.
  3. Empress:work_request — the same arguments again with confirm: true, once the person agreed to the exact call the answer names. The program carries on from where it paused; nothing it already did runs twice, and another call that needs a yes asks again.
  4. Empress:work_status — the task: the program’s result, and the receipt, one line per call.
  • One program, not fifty calls. Use a program when each site needs a read before its write, or the answer needs a comparison across sites. A single identical write everywhere is a site_call batch.
  • Writes are held until promoted. Each site’s writes land in its own change set; promote them in the program only when the person asked for the change to go live, else hand them the sets to preview.
  • Partial is normal. A locked or refused site is listed under unavailable with its reason; report those to the person by name.
  • Same calls every run. The program runs again from the top after each yes; the clock is fixed per run, and random ids are drawn inside empress.step. A write that was interrupted is never sent twice: the program is told, and checks the site.
  • Taking it back is one call. work_request with args: { task, decision: "rollback" } and confirm: true reverts every set the program promoted and throws away the ones it opened.
  • Theme code through ws(). Inside a program, site.ws(session) returns a workspace handle on a theme edit session’s checkout: glob(pattern) lists matching file paths, read(path) reads a file, write({ path, content, message }) patches and commits, run(tool, args, commit?) runs a registered tool (vitest, astro-check, rg, prettier), and script(source, inputs?, commit?) runs inline Node.js. Commits happen by passing a message to run or script; write commits through theme_file_patch on its own. Each call runs inside the session’s container on T0; the session must already exist (theme_session_start).