Skip to main content

operator-bootstrap

This skill should be used when a merge leaves two or more operator steps blocked on one credential: generate a runnable staged bootstrap.sh an agent runs, not a prose checklist.

Informações da origem

Repositório
jikig-ai/soleur
Última atividade na origem
2 de outubro de 2026 às 06:54
Idioma detectado do SKILL.md
inglês
Estrelas
16
Forks
5

Opções de instalação

Por padrão, está selecionado o prompt que primeiro revisa a origem. Você pode mudar para um comando direto ou baixar uma cópia local.

Revise os arquivos de origem

Leia o SKILL.md e os arquivos complementares exibidos pelo SkillsMP antes de decidir se vai instalar.

Explorador de arquivos
2 arquivos

Exibindo SKILL.md

SKILL.md
Instruções da origem · Visualização somente leitura
name
operator-bootstrap
description
This skill should be used when a merge leaves two or more operator steps blocked on one credential: generate a runnable staged bootstrap.sh an agent runs, not a prose checklist.
<!-- grok-harness-invoke:start --> **Grok Build (`plugins/soleur/lib/harness.ts` `invokeSkill()`):** Read this SKILL.md in this process and run it to completion. A one-segment `soleur:<name>` in this document names a SKILL — on Grok Build, Read `plugins/soleur/skills/<name>/SKILL.md` in this process; it is not a nested tool_use. A multi-segment id such as `soleur:<domain>:<name>` names an AGENT: spawn it, never Read it, and on Grok Build spawn_subagent takes the id with its colons replaced by hyphens (`agentIdToGrokSubagentType`). **Claude Code:** Skill tool for a skill (`soleur:<name>`), Task tool with `subagent_type` for an agent. Forbidden is executing a subset, not the Read. <!-- grok-harness-invoke:end --> <!-- Inspired by mattpocock/skills/skills/engineering/wizard/ (MIT, Copyright (c) 2026 Matt Pocock). --> # Operator Bootstrap — generate the script, not the checklist Two hard rules already mandate the artifact this skill produces. `hr-multi-step-post-merge-bootstrap-script` says a post-merge deferral with two or more steps ships as a runnable script; `hr-ship-message-no-operator-checklist` says the ship message does not hand the founder a checklist. This skill authors that script. It does **not** author the machinery: every script it produces `source`s `plugins/soleur/scripts/lib/operator-script.sh`, which is where the stage table, the plan and receipt gate, the secret handling, the `.env` upsert, the prompt classes and the run ledger live. **The script is run by an agent, one stage at a time, with no terminal** (ADR-264). The person never opens a terminal and is never handed a command list. Their acknowledgement of each production write is the harness approval prompt on the exact command the agent is about to run. §Running a generated script is the protocol. ## The library header is the contract **The library is one file. The skill authors only stages. Never hand-edit the library.** Everything a generated script may rely on is documented **once**, in the header of `plugins/soleur/scripts/lib/operator-script.sh`, and is not restated here: - **Sourcing preconditions** (`set -euo pipefail` first; the xtrace/TLS prologue duplicated *above* the `source` line; required binaries) — header §"SOURCING PRECONDITIONS". - **The library invariant** (it never expands a secret-shaped name; secrets arrive as positional parameters; credential *entry* stays in the generated script) — header §"LIBRARY INVARIANT". - **The staged contract and the approval receipt** (stage table, plan, digest, one-time receipt, the order inside `soleur_op_stage_gate`) — header §"Staged contract" and §"Approval receipts". - **The prompt classes** and their non-interactive behaviour — header §"Prompts". - **Exit codes and stdout markers**, including exit 75, `SOLEUR_BOOTSTRAP_LIB_MISSING` and `SOLEUR_BOOTSTRAP_LIB_INCOMPATIBLE` — header §"EXIT CODES" and §"STDOUT MARKERS". - **The API contract** (`SOLEUR_OP_LIB_API`) — header §"API CONTRACT". When the header and this file disagree, the header is right and this file has drifted. ## The staged contract in one screen A generated script carries the header line `# SOLEUR-GENERATED-OPERATOR-SCRIPT v2` on line 2. The approval hook recognises a script by that line (a v1 script never gets a receipt), never by file name. ```text bash SCRIPT --list the stages (static, needs no login) bash SCRIPT --stage NAME a READ stage runs; a WRITE stage prints its plan bash SCRIPT --stage NAME --apply --plan-digest D [--rotate-token] the approved write ``` - There is **no run-all mode and no `--yes`**. A missing `--stage` exits 64. - A **read** stage only reads and reports. A **write** stage first prints a **plan** and changes nothing: `SOLEUR_BOOTSTRAP_PLAN stage= operations= digest=`, one `SOLEUR_BOOTSTRAP_PLAN_OP` per change, the stage's `SOLEUR_BOOTSTRAP_IMPACT` and `SOLEUR_BOOTSTRAP_ROLLBACK` sentences, and an `SOLEUR_BOOTSTRAP_APPLY_COMMAND` line followed by the exact command to run. - `--apply --plan-digest D` performs the write. The script **recomputes** the plan and compares the digest, so what runs is what was shown; a mismatch exits 75 `SOLEUR_BOOTSTRAP_PLAN_DRIFT` with nothing written. - The **receipt**: a plugin PreToolUse hook (`plugins/soleur/hooks/operator-stage-approval.sh`) mints a one-time record when the harness shows the person the exact command, and rewrites the command to carry `SOLEUR_APPROVAL_NONCE`. The script consumes the record before its first write. An environment variable or a flag set by the agent is never an approval. No valid receipt: exit 75, nothing written. - **Keep the `.env` beside the script.** "Satisfied" and `verify` read the recorded slugs there (it is gitignored). A fresh checkout without it turns a satisfied stage into a rotation plan and makes `verify` report a healthy vendor state as failed: run `verify` from the checkout that ran the stages. - **Stages are idempotent.** A re-run of a satisfied stage changes nothing and needs no approval: its plan has `operations=0`, so skip `--apply`. - Markers (stdout): `SOLEUR_BOOTSTRAP_STAGE_DECL stage= class=` (read or write); `_PLAN`; `_PLAN_OP`; `_IMPACT`; `_ROLLBACK`; `_APPLY_COMMAND stage= approval_digest=`; `_APPROVAL_REQUIRED stage= approval_digest= surface=`; `_APPROVAL_INVALID stage= reason=` (one of `no-record`, `expired`, `digest-mismatch`, `consumed`, `algo`, `perms`, `format`); `_PLAN_DRIFT stage=`; `_PRECONDITION_FAILED stage= need=`; `_STAGE_REQUIRED`, `_UNKNOWN_STAGE stage=` and `_PLAN_DIGEST_REQUIRED stage=` (exit 64, your own invocation was wrong); `_MISSING_BINARY bin=`; `_STAGE_OK stage= changed=` (0 or 1, with `approval=` set to `harness-receipt` or `tty-ack` after a write); `_STAGE_FAILED stage= rc=`; `_LIB_INCOMPATIBLE need=stage-1`. - Exit codes: 75 approval required, invalid or plan drift (nothing written); 64 missing input; 78 refused under xtrace; 1 the stage failed. **What the approval does and does not guard** (say it this way, in plain words): the approval guards against an agent acting on a mistaken instruction, not against a compromised one. Never write that a human approves every production write without that qualifier. ## Process ### 1. Scope the procedure Read the deferral that triggered this. Name, in order, every step the founder must take before the merged change is live. Stop when the list is complete, not when it is convenient. Then apply the ladder **before** deciding anything is a step at all: **environment variable → Doppler → MCP/CLI/REST → prompt.** `hr-exhaust-all-automated-options-before` ends with *"prompt for creds not in Doppler"* — the prompt is the last rung of the ladder, not an exception to it. A value that is missing and is not a credential is a hard failure with a named remedy, never a prompt. If fewer than two steps survive the ladder, do not generate a script. Say so. ### 2. Map each stage's journey One stage per step. For each, write down five things before writing any code: - **its class** — `read` (it only reads) or `write` (it changes production); - **what the person is told** — for a write stage, one plain sentence of impact and one of rollback, written for a founder, which become the stage's `# SOLEUR-STAGE` line; - **what it needs** — the value, and where on the ladder it comes from; - **how it knows it is already done** — the precondition. Every stage opens with an "already satisfied?" check. This is what makes re-run idempotent over a non-idempotent create, and it is why there is **no resume index**: re-running a stage *is* resume, because a satisfied stage declares no operation and skips itself; - **how it proves it worked** — the verification. A stage that attests without verifying attests nothing. The last stage of every script is a `verify` **read** stage that prints names only and derives its result from vendor state; its stdout markers are the closure evidence. ### 3. Author the stages Copy [`template.sh`](./template.sh) to the location in §Where, keep everything above the `STAGES` banner, and replace the example stages. Rules: - **Stage lines.** Declare each stage once, in the table near the top of the script, as a comment line of the form `# SOLEUR-STAGE name|class|impact|rollback` (class is `read` or `write`). One plain sentence each for impact and rollback, no `|` inside them. `--list`, the dispatcher and the approval hook all read these same lines, and the person sees the impact and rollback in the approval prompt, so they are the only place those words are written. - **Functions.** A read stage is `read_<name>()`. A write stage is a pair: `plan_<name>()` (read-only) and `apply_<name>()` (the writes; it runs only after the gate returned). `-` in a stage name becomes `_` in the function name. - **A plan names operations and targets, never a value.** `soleur_op_plan_op <op-name> <target-name>` once per change the stage would make; the targets are container, slug and secret NAMES. The digest covers exactly this list, and the agent relays it, so a value in it would leak. - **A satisfied stage declares no operation.** Then the plan prints `operations=0`, no approval is asked and `--apply` changes nothing. - **Later stages re-prove earlier stages' work.** Stages are separately addressable, so a stage whose precondition is another stage's output calls `soleur_op_precondition_failed <stage> <need-stage> "<sentence>"` (marker `SOLEUR_BOOTSTRAP_PRECONDITION_FAILED stage= need=`) instead of trusting that the earlier one ran. - **A stage never calls `soleur_op_ack_or_die`.** That helper needs a typed `yes` at a terminal and makes the stage unrunnable by an agent. The gate is `soleur_op_stage_gate`, called by the template's dispatcher, not by the stage; a stage that gates itself is a defect the guard fails. - **Bake the library path.** The template carries a placeholder line `SOLEUR_OP_LIB_BAKED="__SOLEUR_OP_LIB_BAKED__"`. The generator MUST replace it with the absolute path of the library resolved at generation time, because the generated script lives in the founder's repository where `CLAUDE_PLUGIN_ROOT` may be unset and no relative path to the plugin exists: ```bash LIB="$(realpath "${CLAUDE_PLUGIN_ROOT}/scripts/lib/operator-script.sh")" sed -i "s|^SOLEUR_OP_LIB_BAKED=.*|SOLEUR_OP_LIB_BAKED=\"${LIB}\"|" knowledge-base/project/specs/feat-<name>/bootstrap.sh ``` Anchor on the assignment line, as above — a global replace of the placeholder would be harmless today (the resolution loop deliberately does not spell it) but is not the documented form. - **Never echo a secret variable** for progress. That is the documented `hr-never-paste-secrets-via-bang-prefix` leak path, whose Why cites a live prd-JWT leak. - **Credential entry stays a class-1 ladder rung** in the generated script (`read -rs` behind the library's TTY gate — copy the shape from `provision-hetzner.sh`; the ladder tries the environment and Doppler first). With no terminal the script exits 64 naming what to set up, and the agent never asks for the secret in chat. `soleur_op_value` is for non-secret ladder values (a region, an account id); it echoes its input. - **Write secrets through `soleur_op_gh_secret_set`** (stdin) and non-secrets through `soleur_op_gh_variable_set` (argv, and it refuses secret-shaped names). Do not merge them. - **Write `.env` values through `soleur_op_env_upsert`.** It is exact-key: the trailing `=` is what stops an upsert of `X_API_KEY` from removing `X_API_KEY_SECRET`. - **Keep the dispatcher.** The template's `dispatch_stage` is the one place that applies the staged contract and records the stage the template's one `EXIT` trap reports on: a stop inside a stage prints `SOLEUR_BOOTSTRAP_STAGE_FAILED stage= rc=` and one plain sentence, and settles the stage in the ledger as `failed` with the exit code (exit 75 settles as `refused` and adds nothing). - **A destructive stage's precondition asks the vendor, never only a local marker written after the create.** Between "create succeeded" and "marker written" an interruption leaves a resource the next run cannot see, and it creates a second one. Keep the template's two controls: the vendor-side read and the `*_ATTEMPTED` marker written *before* the create, which stops a re-run and sends the person to the vendor console (`--reset <KEY>_ATTEMPTED` clears it once they have looked). - **A marker the script writes is not proof of vendor state, and "already satisfied" must be read from the vendor.** Write the marker that skips a stage only AFTER the write and its verification succeed; treat an unreadable list as INCONCLUSIVE (stop), never as "absent"; confirm a revoke by re-listing, not by its exit code; and when exactly one vendor object exists that the script cannot show is the stored one, replace it new-before-old instead of dead-ending. Environment secrets are write-only, so a name listing proves nothing about the value (#9321). - **Name skip variables by convention, and let `usage()` derive the list.** A class-1 value is `SOLEUR_BOOTSTRAP_<WHAT>` (`SOLEUR_BOOTSTRAP_ACCOUNT_ID`); a class-3 barrier is `SOLEUR_BOOTSTRAP_SKIP_<WHAT>_BARRIER`. The template's `--help` greps its own `soleur_op_value` / `soleur_op_barrier` call sites for the list, so a prompt added on a line of its own is documented without editing `usage()`. Keep each call on one line for that reason. - **Open a URL with `soleur_op_open_url`.** It prints the URL first and never branches on the opener's exit code, so a headless box degrades to "here is the URL" instead of to a failed stage. `SOLEUR_OP_NO_OPEN=1` prints the URL and launches nothing (CI, test harnesses). ### 4. Verify and hand off Drive the generated script the way an agent will, with stdin closed: 1. `--list` prints every stage with its class. 2. Every **read** stage runs with the class-1 skip variables set and exits 0, or with none set and exits 64 printing `SOLEUR_BOOTSTRAP_INPUT_REQUIRED` naming the **first** skip variable — before any read, never after. 3. Every **write** stage prints its plan with no mutating call, and `--apply` with no receipt exits 75 and writes nothing. `plugins/soleur/test/operator-agent-runnable.test.sh` does this for every v2 script in the tree (§Guards), and also drives every vendor call through a stub that counts anything not on its read-verb allowlist as a write: a `read_*` or `plan_*` function that writes is a defect, because the hook asks about `--apply` only, and the approval prompt is the one place a person sees a write. Then read the ledger beside the script (`bootstrap-runs.jsonl`): every stage that ran has a `begin` and a `settle` line. Hand off by **running the stages yourself** per §Running a generated script, not by giving the person a script path to run. ## Running a generated script This is the AGENT PROTOCOL. A person with no terminal can complete a bootstrap with it, because the agent does every step and the person only answers the approval prompt. 1. **List.** Run `bash <script> --list` and read the `SOLEUR_BOOTSTRAP_STAGE_DECL` lines. This needs no library and no login. 2. **Run the read stages** (class `read`) in order, one `bash <script> --stage <name>` each. 3. **For each write stage**, run `bash <script> --stage <name>` first. This prints the plan and changes nothing. If it prints `operations=0`, the stage is already satisfied: **skip the apply**. 4. **Relay the impact and rollback.** Tell the person, in plain words and **verbatim from the script's own `SOLEUR_BOOTSTRAP_IMPACT` and `SOLEUR_BOOTSTRAP_ROLLBACK` lines**, what the write will change and how it is undone, **before** issuing the apply. Compose no impact or rollback sentence of your own: the words the person reads are the words that were approved. 5. **Announce it (headless or unknown entrypoint only).** State `SOLEUR_BOOTSTRAP_APPROVAL_PENDING stage=<s>` in your reply. In a headless session the approval hook defers silently; this line is what makes the wait visible. In an interactive session the prompt itself is the announcement: skip this step. 6. **Issue exactly** `bash <script> --stage <name> --apply --plan-digest <d>` (plus `--rotate-token` only if the plan was produced with it) as **ONE simple command**: no pipe, `;`, `&&`, redirect, substitution or glob. The one accepted prefix is a leading `cd <dir> &&`. Use the line the plan printed after `SOLEUR_BOOTSTRAP_APPLY_COMMAND`. 7. **Let the harness prompt carry the approval.** The person sees the exact command (the hook has rewritten it to carry the receipt) and decides. **Never** set an environment variable, a flag or a file to approve; **never** pipe `yes`; **never** ask for a secret in chat. 8. After the last write stage, run the `verify` stage and keep its stdout markers: they are the closure evidence for the follow-through issue. **Surfaces.** Claude Code interactive (the terminal, the VS Code extension, the Desktop app): the permission prompt on the exact command. Headless, `-p` or one-shot: the hook defers and mints nothing; state `SOLEUR_BOOTSTRAP_APPROVAL_PENDING stage=<s>` in your reply (headless only), and a person runs `claude --resume` and approves at the prompt. There is no variable, setting or file that approves it; never suggest one. `bypassPermissions`, `dontAsk` and auto modes: the hook denies. The script itself accepts a typed `yes` only from a person at their own terminal with no agent harness around it, so never allocate a pseudo-terminal to answer it. Harnesses without the hook (Codex, Devin cloud, Grok) and the web app: the script exits 75 and writes nothing; say "this surface cannot make production changes yet" and **never** tell the person to open a terminal (the web approval adapter is #9388; per-harness adapters are #9389). **The scheduled follow-through sweeper never runs `--apply`.** A receipt expires after five minutes and a person must approve the prompt, which an unattended runner cannot satisfy. The follow-through issue's `auto_command:` for a staged script is attended-only: it names `--list` plus this protocol, and the issue closes on the `verify` stage's stdout markers pasted into a comment. ### Outcome table
Ver no GitHub
Este SKILL.md e muito grande, entao o SkillsMP mostra aqui apenas a primeira secao. Ver no GitHub