--- name: actionstate-install description: Install Action State Receipts on this machine (capsulectl v0.1.0-rc14, the deal skill, the Action State plugin 0.0.9 and its actionstate-rules skill, rules pack asg/everyday/0.3.4), check every file's SHA-256, and show the person their rules table. Use when the person asks to install Action State Receipts or "install actionstate ai". Linux x86_64 only. --- # Install Action State Receipts (install skill rc14-p0.0.9-s0.0.8) The person gave you this skill to install Action State Receipts on this machine. Follow every step below in order, run the commands yourself, and stop and tell the person if any step fails. Do not work around a failure, do not skip a check, and never run anything piped from the network into a shell. This is install skill rc14-p0.0.9-s0.0.8. Its SHA-256, and every SHA-256 below, is also listed on https://actionstate.ai/install, the page the person reads. If the person compares a checksum you report with that page, the two must match. When the install ends, you show the person their rules table, as the plugin printed it. If you followed the steps by hand, you also tell them the checksum you verified, in full. If you used the install script, the checksums are in the install's summary file, and you show them to the person if they ask. What gets installed: **capsulectl** v0.1.0-rc14 (commit `49651e2f156e370208dec605ded653c5f0a9a4bf`), a command-line program, and the **deal** skill, the instructions you follow before you pay, book, sign, cancel or share the person's details. Every step is sealed on this machine as a receipt the person can check. Nothing of the receipts' content leaves the machine. Step 11 also adds the **Action State plugin** 0.0.9, which gives capsulectl the `capsulectl actionstate` commands, and its skill, **actionstate-rules**, and sets the plugin as the rules checker every receipt check runs, with the rules pack `asg/everyday/0.3.4`. Action State rules run on Linux x86_64 only: on any other device, step 1 stops the install and nothing is installed. How to describe it to the person: their **rules** are what they permit (the rules table in step 12); their **receipts** are what happened (each purchase or other commitment, sealed: what they asked, what was proposed, what they approved, what was done, and any difference). The skill names in this skill (`deal`, `actionstate-rules`) are for you; whenever you tell the person something, say "rules" and "receipts", not the skill names. What the person is trusting: GitHub to deliver the files from `github.com/action-state-group/capsule-cli`, GitHub's build attestation for that repository (when you can check it, step 3), and the SHA-256 values in this skill, which https://actionstate.ai/install also lists. For the plugin, it is trusting actionstate.ai alone (step 11). Where this install connects. Before your first network command, tell the person every site the install will reach, so that no request to allow a site comes as a surprise. Work out the list first, then give it as one list; do not pass on a condition for the person to work out. 1. Run `command -v gh`. If it finds gh, also run `GH_PROMPT_DISABLED=1 GH_NO_UPDATE_NOTIFIER=1 gh attestation verify --help` (it reaches no site) and see whether it lists both `--bundle` and `--signer-workflow`. If it does, gh will run the check in step 3 (case B) and the install reaches the two Sigstore sites below. If gh is not found, or does not list both flags, it will not (case A): leave those two out. 2. Tell the person the sites, one bullet each, with the reason given here: - **github.com**: the capsulectl release and the source archive of the skill that makes receipts (steps 2 and 5), and the build attestation's bundle (step 3). - **release-assets.githubusercontent.com**: GitHub's own host, which serves the capsulectl release files from github.com. - **codeload.github.com**: GitHub's own host, which serves the skill's source archive from github.com. - **actionstate.ai**: the install page and this skill, the install script, and the Action State plugin and its rules skill (step 11). - **witness.agentactioncapsule.org**: the public witness, from step 7 on. Only hashes go there, never the content of the receipts. - **tuf-repo-cdn.sigstore.dev** (case B only): Sigstore's trust roots, which check the build's signature in step 3. This is a verification step; nothing is downloaded or installed from them. - **tuf-repo.github.com** (case B only): GitHub's trust roots for the same check of the build's signature in step 3. This is a verification step; nothing is downloaded or installed from them. Never describe a trust-root site as downloading or installing rules or anything else: it only checks a signature. If the person is asked whether to allow **tuf-repo-cdn.sigstore.dev** or **tuf-repo.github.com**, tell them to choose **"Always allow this site"**, not "Allow once": the check runs on every install. The same holds for the witness (step 7). In the same message, ask the person what name to record as the operator of their rules record. Step 12 seals that record with this name as its operator, the only person it names. Remember their answer and use it in step 12 without asking again. Never choose a name for them. If they would rather not give one, step 12 is skipped. Also tell them, in the same message: "Until you choose otherwise, I'll check with you about each detail I pick on my own, like a size or a delivery option you didn't name, before I go ahead." ## Install with one script One script runs the numbered steps below for you, in the same order, and checks every file before it installs anything. It needs the operator's name: if the person would rather not give one, skip this section and follow the steps by hand. The script's SHA-256 is in this skill and on actionstate.ai/install, the same site the script comes from, so it shows the download arrived intact; it does not show that this site was not tampered with. Inside it, capsulectl is still checked against GitHub's build attestation when gh can check it (step 3); the plugin and both skills are checked by their SHA-256 only, as in the steps by hand. 1. Run step 1's check, `[ "$(uname -s)/$(uname -m)" = Linux/x86_64 ]`. If it fails, stop as step 1 says: nothing is installed on this device. (The script checks this first too, and installs nothing anywhere else.) 2. Find `SKILLS_DIR`, the folder your agent host loads skills from, and make a new folder to work in, for example `~/actionstate/checkup-`. Run everything below in it. Write the two files for the person's rules table **first**: download `https://actionstate.ai/plugin/actionstate-rules-skill-v0.0.8.tar.gz`, check that its SHA-256 is `945943794420260052b1ae77bc5701ff4ae55e9c58939c15f495a752c59d6a7d`, unpack it **outside** `SKILLS_DIR`, and follow its `actionstate-rules/SKILL.md` Step 1 and Step 2 to write `envelope.json` and `comparison.json` into the work folder with your file tool. Never paste either file into chat. 3. Run these three lines, each as written, with `NAME` replaced by the name the person gave and `SKILLS_DIR` by the folder. Never pipe the script into a shell. ``` curl -fsSLO https://actionstate.ai/install/rc14-p0.0.9-s0.0.8/install.sh && curl -fsSLO https://actionstate.ai/install/rc14-p0.0.9-s0.0.8/install.sh.sha256 [ "$(awk '{print $1}' install.sh.sha256)" = 3e733700669e6bcb51082210327544d6d0b179a48b7a7e843117041ae90a79c7 ] && sha256sum -c install.sh.sha256 sh install.sh --operator "NAME" --skills-dir SKILLS_DIR --envelope envelope.json ``` The second line compares the first field of `install.sh.sha256` with this skill's value, `3e733700669e6bcb51082210327544d6d0b179a48b7a7e843117041ae90a79c7`, then checks the script against it (on a Mac without `sha256sum`, use `shasum -a 256 -c install.sh.sha256`). If it fails, do not run the script: stop and tell the person. What the script prints: - **For you**, lines `step NN [step-NN-...]: +Ns ...`, where `N` is the seconds since that step began. Each id is the id of the step of the same number below, so if it stops, you know which step to read. Never pass these lines to the person, and never summarise them for the person. The `step 03` line holds the provenance words of step 3, for your report. The script first reads the install page, `https://actionstate.ai/install.md`. If that page names a different install script from the one that is running, a `step 02` line starts `WARNING`. The script goes on, but this skill or the script is stale: tell the person, and have them check actionstate.ai/install for a newer install skill before you report. - **For the person**, one block, between `==== FOR THE PERSON ====` and `==== END ====`: their rules table, exactly as the plugin wrote it to `sealed/table.md`, then the line naming their report, `report/report.html`, a page that checks itself when opened. If the script stopped, the block is one sentence saying what to do and what was changed (where it says "the steps on actionstate.ai/install", those are this skill's numbered steps: you follow them). Send the lines between the two markers as your message, exactly as printed, and nothing else in that message. Do not retype the table and do not work around a failure. - **The evidence**, in `~/.local/share/actionstate/install-summary.json`: the install page the script read (`page`: its address, SHA-256 and ETag), what was installed, and each file's SHA-256. For each file, how it was verified: `provenance` is `attested` or `checksum_only`, and `provenance_reason` says why (`attestation_verified`, `gh_absent`, `gh_too_old`, `gh_login_prompt`, or `no_attestation_published`). Then the exactly-one results, the `capsulectl plugin ls` output, the witness block, the first tick and its `cadence_log`, `warnings` (empty unless the first checkpoint was not delivered: then one `first_tick` entry per pending reason other than `not_attempted`, such as `witness_error`; the install still counts as installed), the rules checker pinned on the deal profile (`rules_checker`: the pack, its digest and the plugin's SHA-256), both doctors (the script runs each once, at the end), how long each step took (`steps`: each step's id and seconds, in the order run), and the report (`report`: the page, the bundle, its root, and the `capsulectl verify --bundle` verdict, which must be `VALID`). If the person asks what was checked, or for the checksums, answer from this file, never from memory, and never in the block's message. If your host can attach a file, attach the report after the block's message, as step 13's part 1 says: exactly the path the script's `step 12` output printed after `Attach this file:`, and nothing if it printed none. After the block's message, send one more message: the `**Install details**` line and the three lines and the pointer of step 13's part 3, filled from `~/.local/share/actionstate/install-summary.json`, never from memory. Nothing else goes in it: no hash, no JSON. After the script ends with the table, set up the checkpoint cadence of step 8 (never run its scheduled command yourself: step 8 says how to check the task without waiting) and save the standing rule of step 9. Without `--envelope`, the script ends after the install with a line naming the summary file; then do step 12 by hand. ## Or follow the steps by hand These are the steps the script runs, one by one, in the same order. Steps 9 and 13 are always yours. ## 1. Find the platform {#step-01-platform} Run this first, before anything else: ``` [ "$(uname -s)/$(uname -m)" = Linux/x86_64 ] ``` If it exits 0, PLATFORM is `linux-amd64`: go on to step 2. If it exits non-zero, **stop the whole install here**: install nothing, download nothing, and tell the person, in plain words, that this device (say what it is: for example a Mac with Apple silicon) can't run Action State rules yet, because they need a Linux computer with an Intel or AMD (x86_64) processor, and that nothing was installed. Do not install capsulectl or the deal skill on their own. ## 2. Download, and check the SHA-256 {#step-02-download} In a new empty folder, download these two files, and do not run anything yet: ``` https://github.com/action-state-group/capsule-cli/releases/download/v0.1.0-rc14/capsulectl-v0.1.0-rc14-PLATFORM https://github.com/action-state-group/capsule-cli/releases/download/v0.1.0-rc14/capsulectl-v0.1.0-rc14.sigstore.json ``` Compute the SHA-256 of both files. Each must equal the value here; if either differs, delete both and stop. Remember the binary's SHA-256, in full: you report it in step 13. | File | SHA-256 | |---|---| | `capsulectl-v0.1.0-rc14-linux-amd64` | `c8d1ea26cb042319ac6ad562c3dfac7ecc23687bd5c8b60a938904c61f1be627` | | `capsulectl-v0.1.0-rc14.sigstore.json` | `ac4828cedc40fdbb5a4dc3ac3aaaf99a24fd92b0872de1afa9537dece5368c31` | ## 3. Check where it was built, if you can {#step-03-provenance} gh is optional, and used only for this check. **Never install gh, update it or sign in to GitHub for this, and never ask the person to.** The check needs no account. If gh suggests `gh auth login`, ignore it. Run `command -v gh`, then `gh attestation verify --help`, and follow the one case that applies. The verify command, used in case B: ``` gh attestation verify capsulectl-v0.1.0-rc14-PLATFORM --bundle capsulectl-v0.1.0-rc14.sigstore.json --repo action-state-group/capsule-cli --signer-workflow action-state-group/capsule-cli/.github/workflows/release.yml ``` It exits 0 when verified, and may print nothing. In case B, gh reads Sigstore's trust roots from **tuf-repo-cdn.sigstore.dev** and **tuf-repo.github.com** to check the build's signature; nothing is downloaded or installed from them. If the person is asked whether to allow either site, tell them to choose **"Always allow this site"**: the check runs on every install. - **A. No gh you can use:** gh is not installed (`command -v gh` finds nothing), or it is too old: its `gh attestation verify --help` does not list both `--bundle` and `--signer-workflow`. Do not install or update it. The SHA-256 from step 2 is the only check; go on. Remember the words "provenance: checksum only (gh not installed)" or "provenance: checksum only (gh too old)", whichever applies. - **B. gh lists both flags:** run the verify command, signed in or not. - It exits 0: remember "provenance checked: attestation verified (bundle); checksum matched". - It exits non-zero and its message only asks you to sign in or authenticate: do not sign in. Continue on the SHA-256 alone, and remember "provenance: checksum only (gh asked to sign in)". - It exits non-zero for any other reason, the attestation did not verify: delete the files and stop. Whichever case applied, you tell the person in step 13, in the plain words step 13 lists: only "build attestation verified" means the build attestation was verified; otherwise only the checksum was. ## 4. Install the binary {#step-04-binary} Install the file as `capsulectl` with mode 0755 in a directory on the PATH that you can write to (for example `~/.local/bin`; replace an existing `capsulectl` at `command -v capsulectl` if there is one). Then run `capsulectl --version`. It must print exactly: ``` capsulectl v0.1.0-rc14 (commit 49651e2f156e370208dec605ded653c5f0a9a4bf) ``` ## 5. Install the deal skill, with no second copy {#step-05-deal-skill} Find the folder your agent host loads skills from; call it `SKILLS_DIR`. 1. Download `https://github.com/action-state-group/capsule-cli/archive/refs/tags/v0.1.0-rc14.tar.gz`. Its SHA-256 must be `febc716659b2601579a4f7e7d8cf4d4795cdfce1a3222554dc3eac8d287e3800`; if not, stop. 2. Unpack it **outside** `SKILLS_DIR` (a new temporary folder). 3. If `SKILLS_DIR/deal` already exists, or any other folder under `SKILLS_DIR` holds a deal skill (a renamed backup such as `deal.bak` included), **move** it out of `SKILLS_DIR` entirely, to a backups folder beside it (for example `SKILLS_DIR/../_backups/deal-`). Never rename it in place or leave any copy inside `SKILLS_DIR`: every SKILL.md under that folder can be loaded, and an old copy there can be the one that gets followed. 4. Copy the unpacked `skills/deal` folder to `SKILLS_DIR/deal`, then delete the unpacked archive and the download. 5. Check there is exactly one deal skill. Run this exactly, with `SKILLS_DIR` replaced by the folder; it must exit 0: ``` n=$(find SKILLS_DIR -name SKILL.md -exec grep -lx 'name: deal' {} + | tee /dev/stderr | wc -l); [ "$n" -eq 1 ] || { echo "FAIL: $n deal skills"; false; } ``` It must print one line, `SKILLS_DIR/deal/SKILL.md`. If it fails, move any extra folder out of `SKILLS_DIR` and run it again; stop if it still fails. Remember its exit code (0) for step 13. ## 6. Create the deal profile, with the witness {#step-06-deal-profile} ``` capsulectl --profile deal deal init --dir ~/.local/share/capsule-deal capsulectl profile update --profile deal --checkpoint-endpoint https://witness.agentactioncapsule.org --checkpoint-public-key 39bb654c9dc0afe1c0edef0deffaa69099b8518836c9ba26e0491535840f96b5 ``` `deal init` creates a local store and two signing keys (mode 0600). The second command sets the witness, its address **and** its public key in one command: always both. If a deal profile already exists, skip `deal init` and run only the second command. Tell the person, in one message: their receipts are sealed on this machine; on a fixed schedule, whether or not anything happened, one checkpoint of hashes goes to the public witness at witness.agentactioncapsule.org. The witness never sees what the receipts contain, how many there are, or when they happen. ## 7. Reach the witness: "Always allow this site" {#step-07-witness} The next two commands are the first to reach the witness. The person may be asked whether to allow sharing information with **witness.agentactioncapsule.org**. Tell them, before they answer: - choose **"Always allow this site"**, not "Allow once". Later ticks run on a schedule, mostly when nobody is there to answer, and an allow-once grant leaves every later one pending; - the grant covers **agentactioncapsule.org and all its subdomains** (including verify.agentactioncapsule.org): the public witness and the independent verifier for these receipts; - only hashes go there, never the content of their receipts. Then check the witness: ``` capsulectl doctor --profile deal --check-witness ``` Its output has a `witness` block. It must show `"ok": true`; keep the whole block for step 13. If `ok` is false, read its `issue` and `consent` fields, fix what they name (usually the grant), and run it again. ## 8. The first tick, then the checkpoint cadence {#step-08-first-tick} Run once, now, while the person is here: ``` capsulectl --profile deal cll checkpoint cadence ``` The output's `state` should be `ticked`, with the checkpoint under `delivered`. Keep the output's `cadence_log` value (the id of this profile's cadence log) for step 13. If an entry under `pending` has the reason `network_consent_needed`, the grant is missing or was "Allow once": ask again. A `pending` entry with `not_attempted` or `witness_error` is retried at a later tick once its backoff has passed; report it with its reason. Then set up a scheduled task named **Action State checkpoint cadence** that runs `capsulectl --profile deal cll checkpoint cadence --wait-up-to 5m` **every 5 minutes** (cron `*/5 * * * *`, or your host's scheduler at a five-minute interval), and appends each run's output, one JSON line, to `~/checkpoint-cadence.log`. Each run waits for a tick due within its 5 minutes and publishes it on time: every 5 minutes, give or take 1, never on deal activity. A run with no tick due publishes nothing. Keep `--wait-up-to 5m`: without it a scheduled run publishes on the scheduler's grid and hides the jitter. If your host caps how long a scheduled job may run, schedule more often with a matching smaller `--wait-up-to`. **Do not run the scheduled command yourself**, not even once to test the task: with `--wait-up-to 5m` it is built to block, staying alive up to 5 minutes to wait for the next tick, and the person waits with it. Check the task without waiting instead: confirm your host's scheduler lists **Action State checkpoint cadence** with the command above, then run this, without `--wait-up-to`: ``` capsulectl --profile deal cll checkpoint cadence ``` It polls once and returns at once: `state` `not_due` when no tick is due yet, and it publishes only a tick that is due. After the task's first run, the first line of `~/checkpoint-cadence.log` is that run's output. ## 9. The standing rule: save it to your MEMORY {#step-09-memory .agent} Save this rule to your long-term memory or standing instructions, the place that applies to every future conversation. Do not just say it in this chat: a rule that lives only in this conversation is gone in the next one. ```text Before I pay, place an order, book, confirm, sign, cancel, or share the person's contact details, address or a login with anyone (a known shop at a fixed price included), I follow the deal skill's procedure: its final review is `capsulectl deal open --skill ...` then `capsulectl deal check ...`, and I ask the person with the check's approval_text. If a capsulectl command fails, I hold and tell the person. ``` ## 10. Check the whole install {#step-10-install-check} Run, with `SKILLS_DIR` as above; it must exit 0: ``` capsulectl doctor --install-check --profile deal --skills-dir SKILLS_DIR --expect-version v0.1.0-rc14 --expect-commit 49651e2f156e370208dec605ded653c5f0a9a4bf --expect-skill-sha256 f27aacc5c255293fada8f15ad5c62dbc59d9ed427f8c319e9282c93fca88226c ``` It checks the binary's version and full commit, that exactly one deal skill is visible and it is this release's SKILL.md, and that the profile names the witness and its key. If it exits non-zero, fix each issue it names and run it again. ## 11. The Action State plugin {#step-11-plugin} The Action State plugin is not yet covered by a build attestation. capsulectl above is: you verify it against a signed bundle, and that check needs no account. The plugin is verified by its SHA-256 only. That checksum is published on actionstate.ai, the same place the file comes from, so it shows the download arrived intact; it does not show that the site itself was not tampered with. Attestation for the plugin is coming. Until then, install it only if you already trust Action State directly. The version is in the file name, so a newer version is a new file with its own SHA-256 in a newer install skill. To update later, run the lines from that version's install skill; never reuse a file you downloaded under another name. Run these four lines in order, each as written. If any line fails, stop the plugin here, install nothing more, and tell the person which line failed and what it printed. ``` [ "$(uname -s)/$(uname -m)" = Linux/x86_64 ] && mkdir -p ~/.cache/actionstate-plugin && cd ~/.cache/actionstate-plugin && rm -f verified capsulectl-actionstate-linux-amd64-v0.0.9 capsulectl-actionstate-linux-amd64-v0.0.9.sha256 && curl -fsSLO https://actionstate.ai/plugin/capsulectl-actionstate-linux-amd64-v0.0.9 && curl -fsSLO https://actionstate.ai/plugin/capsulectl-actionstate-linux-amd64-v0.0.9.sha256 cd ~/.cache/actionstate-plugin && sha256sum capsulectl-actionstate-linux-amd64-v0.0.9 && { [ "$(awk '{print $1}' capsulectl-actionstate-linux-amd64-v0.0.9.sha256)" = 71cd6b7963f3b5c70b9b0f13a3499097dcaeccdc8f7ec3f4d42d43c822e63a79 ] || { echo "FAIL: capsulectl-actionstate-linux-amd64-v0.0.9.sha256 does not say this skill's SHA-256"; false; }; } && sha256sum -c capsulectl-actionstate-linux-amd64-v0.0.9.sha256 && cp capsulectl-actionstate-linux-amd64-v0.0.9 verified install -d -m 0755 ~/.local/lib/capsulectl/plugins && chmod 0755 ~/.local/lib/capsulectl/plugins && install -m 0755 ~/.cache/actionstate-plugin/verified ~/.local/lib/capsulectl/plugins/capsulectl-actionstate out=$(capsulectl plugin ls) && printf '%s\n' "$out" && printf '%s\n' "$out" | grep -q "\"path\":\"$HOME/.local/lib/capsulectl/plugins/capsulectl-actionstate\",\"plugin_api\":\"[^\"]*\"[^}]*\"version\":\"0.0.9 (commit " || { echo "FAIL: capsulectl did not load the plugin"; false; } ``` What they do: 1. Check the platform again (it fails anywhere but Linux x86_64), then download the plugin and its `.sha256` into `~/.cache/actionstate-plugin`, first removing anything an earlier run left there. Nothing runs yet. 2. Print the file's SHA-256 (remember it, in full, for step 13), check that the digest in the `.sha256` is `71cd6b7963f3b5c70b9b0f13a3499097dcaeccdc8f7ec3f4d42d43c822e63a79`, the value in this skill (it compares the first field, so spacing does not matter), and check the file against it with `sha256sum -c`. Only then is a copy named `verified` made; if either check fails, the line names the file and stops. 3. Install `verified` as `~/.local/lib/capsulectl/plugins/capsulectl-actionstate`, mode 0755. capsulectl only loads a plugin when that file and the `plugins` folder are owned by the person (or root) and writable by nobody else, so the line sets the folder to 0755 even if it already existed. If line 2 failed, there is no `verified` file and nothing is installed. 4. Check that capsulectl loads the plugin from that folder, at version 0.0.9. It must exit 0. If it fails, read the printed output: a launcher under `"refused"` comes with the `reason` capsulectl refused it; a `capsulectl-actionstate` under `/usr/local/lib/capsulectl/plugins` is loaded first, and replaces this one. Stop and tell the person what you found; do not change anything outside `~/.local/lib/capsulectl`. Then install the plugin's skill, **actionstate-rules**, the instructions you follow when you use the plugin. Only do this after line 4 passed. It goes in the same `SKILLS_DIR` as the deal skill, the same way as step 5: 1. Download `https://actionstate.ai/plugin/actionstate-rules-skill-v0.0.8.tar.gz`. Its SHA-256 must be `945943794420260052b1ae77bc5701ff4ae55e9c58939c15f495a752c59d6a7d`; if not, stop. Remember it, in full, for step 13. This archive has no build attestation either. 2. Unpack it **outside** `SKILLS_DIR` (a new temporary folder). It holds one folder, `actionstate-rules`. 3. If `SKILLS_DIR/actionstate-rules` already exists, or any other folder under `SKILLS_DIR` holds an actionstate-rules skill (a renamed backup included), **move** it out of `SKILLS_DIR` entirely, to a backups folder beside it (for example `SKILLS_DIR/../_backups/actionstate-rules-`). Never rename it in place or leave any copy inside `SKILLS_DIR`: an old copy there can be the one that gets followed. 4. Copy the unpacked `actionstate-rules` folder to `SKILLS_DIR/actionstate-rules`, then delete the unpacked archive and the download. 5. Check there is exactly one actionstate-rules skill. Run this exactly, with `SKILLS_DIR` replaced by the folder; it must exit 0: ``` n=$(find SKILLS_DIR -name SKILL.md -exec grep -lx 'name: actionstate-rules' {} + | tee /dev/stderr | wc -l); [ "$n" -eq 1 ] || { echo "FAIL: $n actionstate-rules skills"; false; } ``` It must print one line, `SKILLS_DIR/actionstate-rules/SKILL.md`. If it fails, move any extra folder out of `SKILLS_DIR` and run it again; stop if it still fails. Remember its exit code (0) for step 13. Then the rules checker your purchases run. The actionstate-rules skill you just installed says (`SKILLS_DIR/actionstate-rules/SKILL.md`, "The rules checker your purchases run"): "At first install, the install pins a specific program, the Action State checker (this plugin, run as `check --emit external-check-result/v0`), to the person's installed rules: the pack id and definition digest that `capsulectl actionstate rules list --json` prints. It shows the person that pin while it sets it." And: "You never set, change or remove it." So pin it only here, at install, and only if there is no pin yet. Only do this after line 4 and the skill's check passed. First look at the deal profile's pin: ``` capsulectl profile show deal ``` - **`RulesChecker` has `"Command":null`: there is no pin yet.** Run these four lines in order, each as written, in the folder you work in: ``` capsulectl actionstate rules list --json > rules-list.json && D=$(sed -n 's/^ *"definition_digest": *"\([0-9a-f]\{64\}\)".*/\1/p' rules-list.json | head -n 1) && { [ "$D" = cd98aaec5acf8cea86f91fc21dd7df6b36a67c7b55340489b66e6ce88b85117b ] || { echo "FAIL: the installed rules are $D, not this skill's cd98aaec5acf8cea86f91fc21dd7df6b36a67c7b55340489b66e6ce88b85117b"; false; }; } printf '{"command":["%s/.local/lib/capsulectl/plugins/capsulectl-actionstate","check","--emit","external-check-result/v0"],"definition_digest":"%s"}\n' "$HOME" "$D" > rules-checker.json capsulectl profile update --profile deal --rules-checker rules-checker.json capsulectl profile show deal ``` The first reads the installed rules' digest from `rules list --json`, as the skill says, and checks it is this skill's, `cd98aaec5acf8cea86f91fc21dd7df6b36a67c7b55340489b66e6ce88b85117b` (pack `asg/everyday/0.3.4`). The second writes the pin the skill shows, with the plugin root written out in full. The third pins it: capsulectl records the SHA-256 of the plugin file, and a later check whose plugin file changed pauses instead of running it. In the fourth, `RulesChecker` must show that `Command`, `SHA256` `71cd6b7963f3b5c70b9b0f13a3499097dcaeccdc8f7ec3f4d42d43c822e63a79` (the plugin you installed) and `DefinitionDigest` `cd98aaec5acf8cea86f91fc21dd7df6b36a67c7b55340489b66e6ce88b85117b`. - **`RulesChecker` already shows exactly that `Command`, `SHA256` and `DefinitionDigest`:** it is already this install's pin. Change nothing and go on. - **Any other pin:** change nothing. Do not run `profile update`. Stop the plugin here and tell the person, naming what is pinned now and what this install would pin, and that nothing was changed: the skill says "a changed pin is the person's decision." While you pin it, tell the person, in the skill's words: "Your install pinned the Action State checker to your rules.", with the pack `asg/everyday/0.3.4` and its definition digest. Remember the `RulesChecker` block for step 13. The plugin's own install check runs in step 12, after Setup: the skill says it "requires the `actionstate-rules` profile" that Setup creates. It also reports the pin. ## 12. Show the person their rules {#step-12-rules} Do this step only if step 11 installed the plugin and the actionstate-rules skill. If step 11 stopped, skip this step too, and remember "rules table skipped", with step 11's reason. You follow the actionstate-rules skill you installed in step 11 (`SKILLS_DIR/actionstate-rules/SKILL.md`). First its Setup, which says: "If the user has none, create one. Ask the user what name to record as the operator; do not choose one for them." So: - If `capsulectl profile list` already lists `actionstate-rules`, run `capsulectl profile show actionstate-rules`. If its `Type` is `sqlite`, its `LogID` is not empty and its `Checkpoint` has a signing key, Setup is done: use that profile as it is. Otherwise **stop here**, change nothing, and tell the person their rules record could not be used and was left as it is. - Otherwise, run Setup's lines as the skill shows them, with `OPERATOR` set to the name the person gave you before step 1. Do not ask again. They handle a seed an earlier install left; the skill says: "If `~/.config/actionstate/seed` already exists (an earlier install made it), the lines use it as it is and read its public key with `capsulectl key show-public`. Never replace, move, rename or regenerate it: records already sealed with it are checked against that key." - If they gave no name and there is no `actionstate-rules` profile, skip this step and remember "rules table skipped: no operator name given". A profile named `actionstate-local`, from an earlier install, is not used and does not stop the install. As the skill says, leave it exactly as it is: do not update, reuse or delete it. It holds the records of earlier runs. After Setup, run `capsulectl profile show actionstate-rules` and remember its `Operator` value: it is the name on the sealed record, and step 13 states it. Then run the plugin's own install check, with `SKILLS_DIR` replaced by the folder; it must exit 0: ``` capsulectl actionstate doctor --install-check --skills-dir SKILLS_DIR --expect-version 0.0.9 --expect-skill-sha256 cf1f55a297969ddd665dea68aca8a0e6a289a246dd2b7f3fd5fac1b3401b9595 ``` It checks the plugin's version, that exactly one actionstate-rules skill is in `SKILLS_DIR`, and that `actionstate-rules` is a SQLite profile with a log and a checkpoint key, and the deal profile's rules-checker pin (step 11). Its `pack` must name `asg/everyday/0.3.4` with `definition_digest` `cd98aaec5acf8cea86f91fc21dd7df6b36a67c7b55340489b66e6ce88b85117b`. If it reports `rules-checker-wrong-command`, `rules-checker-wrong-digest` or `rules-checker-stale`, do as the skill says: tell the person what is pinned now and what this install would pin, that nothing was changed, and never offer to change it yourself. A note that a legacy profile `actionstate-local` is left untouched is not an issue. If it exits non-zero, the install is incomplete: fix each issue it names and run it again; stop if it still fails. Remember its exit code for step 13. If this step was skipped for want of a name, run the check anyway: it exits non-zero naming `rules-profile-missing`, and step 13 reports the install as incomplete. Then, while the person is here, follow the skill's Step 1 (the envelope file), Step 2 (the comparison file) and Step 3, in that order, under its rules. Step 3 runs: ``` capsulectl actionstate rules compare --envelope envelope.json --comparison comparison.json --profile actionstate-rules --out-dir sealed ``` The plugin writes the table, and the list under it, to `sealed/table.md`; the sealed record holds that file's SHA-256. The table is the plugin's, word for word. You never type it: step 13 copies the file. Then make the person's report, a page that checks itself when opened, as the skill's Step 3 says, and check it: ``` capsulectl actionstate report --profile actionstate-rules --from sealed --out-dir report capsulectl verify --bundle report/report.json ``` The plugin writes `report/report.json` (the bundle) and `report/report.html` (the page), and writes every word of the page. If `report/` already holds a report from an earlier run, it keeps that one and writes `report-2.json` and `report-2.html` beside it: use the paths it prints, here and in step 13. `capsulectl verify --bundle` must exit 0 with the verdict `VALID`; remember its verdict line for step 13. If it does not, the report is not ready: tell the person and do not point them at the page. ## 13. Report to the person, without being asked {#step-13-report .agent} In the folder where you ran step 12, build the report in `reply.md` by copying the table file, never by typing the table: ``` cp sealed/table.md reply.md ``` Then add the rest below it, in this order. Everything above the `**Install details**` line is for the person: it names no skill, and no hash appears before the rules table. 1. **Their rules, first:** the contents of `sealed/table.md`, exactly as copied, unchanged. Then one line: "Recorded as operator: " and the `Operator` value from step 12. Then the line naming their report, with the full path of `report/report.html`: "Your report: ", and under it "Open it in any browser: it checks itself when opened, with no internet connection." Then the skill's sentence, "Your install pinned the Action State checker to your rules.", if step 11 pinned it or found this install's pin. If your host can attach a file, attach the report after the message: exactly the path step 12's report output printed after `Attach this file:` (the plugin's copy under `~/workspace/actionstate/`, where your host serves attachments from). Never attach a path outside `~/workspace` (the link would not open), and never copy the page there yourself: only the plugin's copy is attached. If no `Attach this file:` line was printed, attach nothing; the "Your report:" line already names the page. If step 12 was skipped, there is no table file: start `reply.md` with one line instead, "rules table skipped", with the reason. 2. **The skill's sentence about receipts, as written:** "From now on, each purchase, booking, signature, cancellation or sharing of your details gets a receipt showing what you asked for, what was proposed, what you approved and what happened." 3. **A line that reads exactly `**Install details**`**, and under it three lines and one pointer, nothing more. No full hash, no JSON and no command output in them: every hash and exit code is in the record the pointer names. 1. **What you installed:** "Installed capsulectl v0.1.0-rc14 (PROVENANCE) and the Action State plugin 0.0.9 (checksum only, because no build attestation is published for it)." PROVENANCE is the plain words for capsulectl's `provenance_reason` (step 3): - `attestation_verified`: "build attestation verified"; - `gh_absent`: "checksum only, because gh is not installed"; - `gh_too_old`: "checksum only, because the installed gh is too old to check it"; - `gh_login_prompt`: "checksum only, because gh asked to sign in, and the install never signs in"; - `no_attestation_published`: "checksum only, because no build attestation is published for it". 2. **That it checks itself:** "Your report checks itself: VERDICT, PATH. Install checks exited A and B; one copy of each skill." VERDICT is the verdict `capsulectl verify --bundle report/report.json` printed in step 12 (`VALID`), PATH the full path of `report/report.html`, and A and B the exit codes of step 10's `capsulectl doctor --install-check` and step 12's `capsulectl actionstate doctor --install-check`. 3. **What runs from now on:** "From now on: rules pack asg/everyday/0.3.4, the rules in the table above, PIN." Never count the rules: the lint below refuses a count of the table's rows. If the table was skipped, say so here instead. PIN is the rules checker on the deal profile (step 11): "checked on every receipt, pinned by this install" (`pinned`), "checked on every receipt, already pinned by an earlier install" (`already_pinned`), or, if step 12's install check named `rules-checker-not-pinned`, `-unsupported`, `-wrong-command`, `-wrong-digest` or `-stale`, "not pinned by this install: ISSUE; nothing was changed". If the summary's `warnings` is not empty (by hand: step 8's first tick delivered nothing and left a `pending` entry with a reason other than `not_attempted`), end this line with "; the first checkpoint is waiting for the public witness and is retried every 5 minutes", and never say the witness is fine. Without a warning, leave that phrase out. Then the pointer, one line: "The full record, every hash and exit code, is in PATH." On the script path, PATH is `~/.local/share/actionstate/install-summary.json`, which the script wrote. Following the steps by hand, there is no such file unless you write it: before you send the reply, write `install-record.md` in the folder where you ran step 12, with your file tool, holding all twelve of the facts below, and name its full path, as "The full record, every hash and exit code, as I noted it from the commands' output, is in PATH." If either install check exited non-zero, the first line under `**Install details**` is `install incomplete`, followed on the same line by every issue it named; never write that the install is ok. The three lines and the pointer follow it. If a step a line draws on was skipped, that line says so in plain words instead, for example "No report: the rules table was skipped, because no operator name was given." The twelve facts the record holds. The script's summary file holds every one (the field is in brackets); by hand, `install-record.md` holds them as the commands printed them: 1. **Version:** the line `capsulectl --version` printed, and that it matches v0.1.0-rc14, commit `49651e2f156e370208dec605ded653c5f0a9a4bf`, in this skill (`artifacts[0].version_line`). 2. **Checksum:** the SHA-256 you computed for the binary, the full value (`artifacts[0].sha256`). 3. **Provenance:** the exact words from step 3, which say whether the build attestation was verified or only the checksum (`artifacts[0].provenance`, `provenance_reason`). 4. **Skill:** the exit code of step 5's one-deal-skill check, and the one path it printed (`exactly_one.deal`). 5. **Witness:** the `witness` block from step 7's doctor run (`witness`). It goes in the record only, never in the reply. 6. **First tick:** `ticked`, with the checkpoint delivered; or `pending`, with its reason (`first_tick`). 7. **Cadence log:** the `cadence_log` id from the first tick (`cadence_log`). 8. **Plugin:** the version `capsulectl plugin ls` listed (0.0.9), the SHA-256 you computed in step 11 in full, whether line 4 found the plugin, and that the plugin has no build attestation yet, so only its checksum was checked (`artifacts[3]`, `plugin_ls`). 9. **Rules skill:** the actionstate-rules archive's SHA-256 in full, the exit code of step 11's one-actionstate-rules-skill check, and the one path it printed (`artifacts[4]`, `exactly_one.actionstate-rules`). 10. **Install checks:** both, as run: step 10's `capsulectl doctor --install-check` and step 12's `capsulectl actionstate doctor --install-check`, each with its exit code (`doctors`). 11. **Report:** the verdict line `capsulectl verify --bundle report/report.json` printed in step 12 (`VALID`), and the path of `report/report.html` (`report`). 12. **Rules checker:** the `RulesChecker` block of step 11's `capsulectl profile show deal`: its `SHA256` and `DefinitionDigest`, in full, and the pack `asg/everyday/0.3.4` (`rules_checker`). If step 12 ran, check the draft against the table the plugin wrote, as the skill's Step 3 says, from that folder: ``` capsulectl actionstate checkup lint --against sealed/table.md < reply.md ``` It refuses any table or list in your reply that is not `sealed/table.md`'s, cell for cell, and any mention of the receipt mechanism above `**Install details**`. On `checkup lint: ok`, send `reply.md` as it is, in one message. If it is refused, do not edit the draft and lint again: send the contents of `sealed/table.md` alone, as the skill says, then the install details as a second message. If step 12 was skipped, send `reply.md` as it is.