Skip to main content

WIZARD_SKILL

Constant WIZARD_SKILL 

Source
const WIZARD_SKILL: &str = "---\nname: wizard\ndescription: Generate an interactive bash wizard that walks a person through steps only they can perform - provisioning infrastructure, setting up credentials or CI secrets, walking an unfamiliar third-party dashboard, or running a one-off migration or cutover - driven through this seat\'s terminal, opening dashboards in the forge browser, finding a credential in settings or, when the session carries that family, the vault before asking, and recording the stage so a handoff can resume it. Don\'t invoke this for steps the agent can perform itself.\ndisable-model-invocation: false\n---\n\n# Wizard\n\nA **wizard** is a bash script that walks a person, step by step, through a manual procedure\nthat\'s tedious to do by hand and tedious to re-explain to an agent every time. It opens each\ndestination, says exactly what to do, captures the values, writes them where they belong\n(`.env`, `gh secret`, `gh variable`), confirms before anything irreversible, and shows how many\nstages are left. It might configure third-party services, run a one-off migration, or move the\nproject from one state to another.\n\nThe UX is already solved by [template.sh](template.sh): stage-by-stage progress, confirmation\ngates, hidden secret entry, idempotent `.env` upserts, `gh secret`/`gh variable` writes, and a\nclosing summary. **Your job is only to scope the procedure and author its stages.** The library\nabove the `STAGES` marker is identical in every wizard; that consistency is the point, so never\nhand-edit it.\n\nA wizard is ephemeral by default: built for one run, saved to a scratch or `scripts/` path, and\ndeleted when the job\'s done. Commit it only when the person wants a repeatable setup path that\nshould live in the repo.\n\n## Who runs it, and where\n\n**The agent runs the wizard in this seat\'s own terminal; the person only performs the stages\nthat need a human.** Do not hand the script over for them to run by themselves.\n\n- `terminal__open` gives the seat a terminal: a real PTY on the person\'s own shell, in the\n  session\'s cwd. Run the wizard there, not from a background command - the hidden entry and the\n  confirmation gates need a terminal.\n- `terminal__read` shows its screen and `terminal__write` types into it. Use them to follow the\n  run and to answer anything the script asks that you already know.\n- `terminal__hand_off` gives the keyboard to the person for the one thing only they can do - a\n  password, a `sudo` confirmation, a sign-in, a value only they have. **You are blind while the\n  card is parked**: `terminal__read` and `terminal__write` are refused until they answer. Read\n  the outcome back with `terminal__read` afterwards and never assume what they typed.\n- `terminal__close` when the wizard is done, so the shell it held goes away.\n\nThe tool descriptions carry the arguments and the exact behaviour; read them there rather than\nfrom this page.\n\n## Destinations: this seat\'s browser\n\nWhen a stage sends the person to a dashboard, open it in the seat\'s browser and hand the tab\nover. That is the plan: never send them to their own browser and never print a bare URL for\nthem to retype.\n\n- `browser_navigate` opens the page in this session\'s own tab, in the profile forge resolves\n  from the org and project.\n- `browser_hand_off` raises that tab on their screen and waits. Use it when they must sign in\n  or click something you cannot: they act on the very page you prepared. Their answer lowers\n  it; it does not close the tab.\n\n`open_url` in the script is the fallback for when no browser is available: it opens the URL in\nwhatever the machine has. It is the safety net, not the plan. Where you do not know the current\npage or the exact control, say so and check the docs or ask - never invent UI steps that may\nnot exist.\n\n## Credentials: settings, then the vault, then ask\n\nBefore a stage asks the person for a value, look for it in this order:\n\n1. **`settings__get`** when the value is a key in `forge.toml`. `settings__index` lists what\n   exists and `settings__get` answers the effective value; use it for anything forge itself is\n   configured with.\n2. **`vault__search`, then `vault__get`**, when it is a stored credential and your tool list\n   carries the vault family. The search answers metadata only, so reveal the one field you need\n   with `vault__get`. If the family was withheld from this session, ask your lead for it. If\n   forge has no `[vault]` configured, the vault is not a path for this value at all and hidden\n   entry is.\n3. **`ask_secret` in the terminal** when it is in neither. Hidden entry, in the seat\'s terminal,\n   written straight to where it belongs.\n\nNever ask for a secret in chat, and never write one into a file that is not its destination: a\nkey goes to `.env`, to `gh secret`, to `gh variable`, or to the vault, and nowhere else. A value\nfound in settings or the vault is written to its real destination by its stage, never embedded\nin the script.\n\n## A wizard that outlives the session\n\nA long procedure can outlive the turn that started it. Keep its state in the session\'s project\nmemory directory as a current-state document rewritten in place: a lead at `wizards/<slug>.md`,\na worker in its own `workers/<label>.md` (the seat rule below). It carries:\n\n- the stage the wizard reached, and the stage it is on;\n- every value captured, by name and by destination - never the secret itself;\n- what remains, and what stopped a stage;\n- how to re-run it: the script\'s path and the environment it needs.\n\n**The seat decides where that file lives.** A lead keeps the stage file at `wizards/<slug>.md`;\na worker keeps it in its own `workers/<label>.md` in the same directory, the way the always-on\nrule has it, and tells its lead where it is. A handoff points at whichever of those files the\nseat owns, by path. The handoff procedure itself is the `handoff` skill\'s, not this one\'s.\n\n## Process\n\n### 1. Scope the procedure\n\nWork out every manual step the person must take and every value captured along the way. Read the\nrepo first, don\'t ask cold:\n\n- For setup: `.env`, `.env.example`, `.env.*`, `README`, `docker-compose*`, framework config,\n  and `.github/workflows/*` (every `secrets.*` / `vars.*` reference is a value the wizard must\n  produce).\n- For a migration or transition: the current state, the target state, and the irreversible\n  actions between them.\n\nThen show the person the ordered list of stages and the values each produces, and confirm: they\nmay add, drop, or reorder.\n\n**Done when:** every stage is named in order, and for each captured value you know (a) where the\nperson gets it, (b) where it is written (`.env`, a GitHub secret, both, or nowhere - some stages\nare pure actions), and (c) whether it is secret, for hidden entry, or public. A value that\nalready exists in settings or the vault needs no prompt from the person: the agent types it at\nthe stage\'s own prompt with `terminal__write`, and the stage writes it to its destination as\nusual.\n\n### 2. Map each stage\'s journey\n\nFor each stage, write the precise path a person follows: which page to open, what to do there,\nwhere a value is shown, and which variable it fills - for example \"Dashboard -> Developers -> API\nkeys -> Reveal test key -> copy\". Where you do not actually know the current UI or the exact\ncommand, say so and ask the person or check the docs: never invent steps that may not exist.\n\n**Done when:** every stage traces to concrete instructions a stranger could follow.\n\n### 3. Author the wizard\n\nCopy `template.sh` to the target path. Replace the example stage with one `stage` per step, in\ndependency order. Use the library helpers: `stage`, `say`/`step`, `open_url`, `ask`/`ask_secret`,\n`write_env`, `set_secret`/`set_var`, `pause`/`confirm`. Set `TOTAL_STAGES` to the number of\nstages you wrote.\n\nHold the bar the template sets: open the destination before asking for its value, use\n`ask_secret` for anything secret, `write_env` every persisted value, `set_secret` only the values\nCI actually needs, and `confirm` before any irreversible action. Each `stage` clears the screen so\nonly the current step is visible: keep a stage to one focused task so nothing the person needs\nscrolls away. Don\'t touch the library above the marker.\n\n**A gate needs its own arm.** `confirm` returns non-zero when the answer is no, and a bare call\nwould end the whole wizard there under `set -e`. Give every gate both answers:\n\n```bash\nif confirm \"Delete the old webhook?\"; then\n  delete_webhook\nelse\n  note \"kept the old webhook\"\nfi\n```\n\n**Done when:** the script holds one `stage` per step from step 1, `TOTAL_STAGES` matches, and the\nlibrary is byte-identical to `template.sh` above the marker.\n\n### 4. Verify and run it\n\n- `bash -n <script>`; run `shellcheck` if available.\n- `chmod +x <script>`.\n- Trace it statically first: every value from step 1 is captured and lands where step 1 said, and\n  every `set_secret` name exactly matches a `secrets.*` reference in CI.\n- Then run it in the seat\'s terminal and walk the stages with the person: open each destination\n  in the browser, hand the tab over where they must act, and hand the terminal over where the\n  input is theirs alone. Read the outcome back after every hand-off.\n\n**Done when:** the wizard has run to its closing summary, or the stage it stopped at is recorded\nin the seat\'s own stage file with what remains.\n\n## Boundaries\n\n- Never invent a UI step that may not exist. Say you do not know, then check the docs or ask.\n- One focused task per stage: a stage asking for three unrelated things loses the first one off\n  the top of the screen.\n- A wizard the person asked to keep goes in the repo and gets linked from the README, so the next\n  person runs the script instead of asking again.\n";
Expand description

The wizard skill’s procedure, and the bash library its stages ride.