[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6H60EXYDCPSD1QGC89HM0ZC":3,"skill-same:01M6H60EXYDCPSD1QGC89HM0ZC":75},{"skillNo":4,"name":5,"nameZh":6,"description":7,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":16,"categories":17,"keywords":26,"publishedAt":47,"linkOnly":48,"markdownContent":49,"markdownBody":50,"frontMatter":51,"refName":52,"commitSha":53,"skillDirectory":54,"forksCount":55,"repositoryHtmlUrl":56,"repositoryHomepageUrl":6,"ownerHtmlUrl":57,"ownerBlogUrl":58,"ownerDescription":59,"updatedAt":60,"install":61,"resources":74},"01M6H60EXYDCPSD1QGC89HM0ZC","smoke-curl-install-and-test-e2e",null,"Clean-room end-to-end smoke test of a PUBLISHED release. Curl-installs the latest release binary from GitHub, does a full `podman system reset --force`, runs `tillandsias --debug --init` from a pristine state, and (if init is clean) launches `tillandsias --cloud 8007342\u002Ftillandsias --opencode` with ONE short fixed smoke prompt (run the credential guard, reply with a fixed token; never the \u002Fmeta-orchestration loop, 1941-smkp). Every issue observed — by this skill's agent during install\u002Freset\u002Finit, or by the agent's one turn inside the forge — is filed as a plan\u002Fissues work packet for later pickup by \u002Fadvance-work-from-plan.","8007342\u002Ftillandsias","8007342","https:\u002F\u002Favatars.githubusercontent.com\u002Fu\u002F162944123?v=4","01M6H5SFAKAV1RH8MY0C9X2SZZ","Tlatoāni","01M6H5SFF2BBW9HGM3DXAZ84TG",6,"GPL-3.0","https:\u002F\u002Fgithub.com\u002F8007342\u002Ftillandsias\u002Fblob\u002Fmain\u002Fskills\u002Fsmoke-curl-install-and-test-e2e\u002FSKILL.md",[18,23],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000008","测试与质量","SCENARIO","使用场景",{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},"01JBSEEDCAT000000000000023","Skill与智能体开发",[27,28,29,30,31,32,33,34,35,36,37,38,39,40,41,42,43,44,45,46],"test","smoke curl install and test e2e","smoke","install","curl","e2e","Meta","forge","loop","plan","work","issues","short","podman","never","init","clean","end","reset","orchestration","2026-11-10 10:12:30",false,"---\nname: smoke-curl-install-and-test-e2e\ndescription: Clean-room end-to-end smoke test of a PUBLISHED release. Curl-installs the latest release binary from GitHub, does a full `podman system reset --force`, runs `tillandsias --debug --init` from a pristine state, and (if init is clean) launches `tillandsias --cloud 8007342\u002Ftillandsias --opencode` with ONE short fixed smoke prompt (run the credential guard, reply with a fixed token; never the \u002Fmeta-orchestration loop, 1941-smkp). Every issue observed — by this skill's agent during install\u002Freset\u002Finit, or by the agent's one turn inside the forge — is filed as a plan\u002Fissues work packet for later pickup by \u002Fadvance-work-from-plan.\n---\n\n# Smoke: Curl-Install and Test End-to-End\n\nThis skill validates that a **published release** actually works for a real\noperator starting from nothing. It is the acceptance gate that catches what\n`.\u002Fbuild.sh --ci-full` cannot: problems that only appear when the signed,\ndownloadable artifact bootstraps the whole enclave from a wiped host substrate.\n\n## Authority\n\n`methodology.yaml` remains the source of truth. This skill is an executable\nrunbook; it does not redefine release, trace, or coordination policy. Findings\nbecome `plan\u002Fissues\u002F` work packets so they flow through the normal\n`\u002Fadvance-work-from-plan` worker loop.\n\n---\n\n## Host Matrix\n\n| Host | Installer | Destructive substrate | Re-provision |\n|---|---|---|---|\n| immutable Linux | `scripts\u002Finstall.sh` via release curl URL | `podman system reset --force` | `tillandsias --debug --init` |\n| mutable Linux | `scripts\u002Finstall.sh` via release curl URL | `podman system reset --force` | `tillandsias --debug --init` |\n| macOS | `scripts\u002Finstall-macos.sh` via release curl URL — **launches the tray and begins VM provisioning; not a download test (1281-pgit)** | remove Tillandsias app state\u002Fcache VM dirs | installed tray `--provision` + `--diagnose --json` |\n| Windows | `scripts\u002Finstall-windows.ps1` release path when available | `wsl --unregister tillandsias`, runtime-cache purge BY NAME (`%USERPROFILE%\\.cache\\tillandsias`, `%APPDATA%\\tillandsias`; never `%LOCALAPPDATA%\\tillandsias\\wsl-build`, the builder distro — 1295-b4i8), plus `vault-shamir-share-v1` + `vault-root-token-v1` cleared from Credential Manager (keeping `tillandsias-vm-uuid`) | installed tray provision\u002Fdiagnose — implemented by the §3 \"Windows\" block (`--provision-once`, `--status-once --json` polled to Ready, `--diagnose --json` LAST) |\n\nThis is the only e2e install skill allowed on immutable Linux.\n\n## DESTRUCTIVE — read before running\n\nOn Linux, Step 2 runs **`podman system reset --force`**, which irreversibly\ndeletes ALL Podman state for this user: every container, image, volume, network,\nand secret — including:\n\n- the `tillandsias-vault-data` volume (Vault's sealed store),\n- every project mirror volume (`tillandsias-mirror-*`),\n- all locally built enclave images (proxy\u002Fgit\u002Finference\u002Fforge) — these get\n  **rebuilt from scratch on the next `--init`, which can take many minutes**.\n\nOn a DEDICATED SMOKE HOST, wiping Podman is expected and is a required\nprecondition for the release idempotence test.\nPre-authorise the reset by prefixing the reset command with exactly `TILLANDSIAS_DESTRUCTIVE_RESET_OK=1 TILLANDSIAS_SKILL=smoke-curl-install-and-test-e2e` (1462-qvxj). The consent\nengine (1443-9f5w) and the Bash-tool bridge honour ONLY that pair, on bare\nmetal, for a SOFT reset: unset is not `1`, and a skill name alone never\nauthorises a wipe. Without both, the reset is asked, not skipped. With it set,\ndo not ask for confirmation,\ndo not pause for operator timing, and do not skip Step 2 because Podman state\nwill be destroyed. Only block the reset when the environment explicitly sets\n`TILLANDSIAS_DESTRUCTIVE_RESET_OK=0`, in which case file a plan blocker and\npush it.\n\n**That no-pause clause applies to a dedicated smoke host and to nothing else\n(order 1004-vsh2, 2026-09-04).** On an OPERATOR'S WORKSTATION — a machine whose\nguest holds work they have not finished with — Step 2 destroys their Vault\nstore, their project mirrors and their images, and this document cannot consent\non their behalf. Get the operator's authorization for THAT RUN before starting.\nAn orchestrator's or a peer agent's instruction to run this skill is not that\nauthorization: it is a request to run a procedure, not consent to destroy a\nparticular machine's state. The distinction was missed once because this\nsection read as though every host running it were a smoke host; most of the\nfleet's Windows and macOS hosts are workstations.\n\n**`TILLANDSIAS_RESET_KEEP_MODELS=1`** lets this destruction spare the model\ncache (`cache_root()\u002Fmodels`) on the operator's word — opt-in, per run, never\nthe default: the clean room stays clean unless this run asked otherwise (the\n2026-09-13 reset ruling; operator, 2026-09-14: \"let's add the keep models\nflag to our resets\"). Per platform: **Linux** — the podman reset and the\ncredential clearer never touch `~\u002F.cache\u002Ftillandsias\u002Fmodels`, so the flag is\na documented no-op and the models survive regardless. **macOS** — honoured by\n`scripts\u002Fe2e-step2-macos.sh` below, which names the spared directory in its\nresidue line. **Windows** — a no-op until 1182-2vaz moves the weights out of\nthe distro (they live at `\u002Froot\u002F.cache\u002Ftillandsias\u002Fmodels` inside the vhdx\nthat `wsl --unregister` deletes) (operator ruling 2026-09-14; 1181-bkem).\n\nA fresh `--init` re-initializes Vault and re-captures the keychain-held unseal\nshare, so the keychain↔volume resync brick (see git history `738059bc`) is part\nof what this smoke exercises — if init bricks, that is a finding, not a failure\nto hide.\n\n**On Linux this is true only because the reset now CLEARS the host-held\ncredentials (order 900-z3kv). Step 2 runs\n`scripts\u002Fclear-vault-host-credentials.sh` after emptying the store; without it\nthe paragraph above was false.** `podman system reset --force` empties the podman\nstore — containers, volumes AND images — but it does not reach the HOST\nKEYCHAIN. Vault then recovers the pre-existing Shamir share and logs `preserving\nexisting data volume (Shamir share present in keychain)`, so without the clearer the resync path\nabove is **not exercised** — which is what every Linux pass silently carried\nuntil 900-z3kv wired it. Measured independently on two Linux hosts with\ndifferently-aged shares (yoga, created 2026-06-15; lenovinha, created\n2026-07-08), which makes it a property of the Linux lane rather than one host's\ndirty state — and it means every Linux \"clean room\" pass since at least 2026-06\nsilently carried this gap.\n\nRun `scripts\u002Fprobe-credential-cold-state.sh --format=md` and paste its block\ninto the findings file, the way the Windows leg records its hashes. It reports\n`credential-cold` or `credential-warm` from **metadata only** — never\n`secret-tool search --all`, which prints the secret inline and put live tokens\ninto two transcripts on 2026-08-25 — and reports `could-not-run` when the\nquestion cannot be asked, which must never be read as cold.\n\n**Since 1149-vgn2 it checks the host keychain AND\n`~\u002F.cache\u002Ftillandsias\u002Ffallback_*`, and a cold verdict names everything it\nchecked.** It read the keychain alone until then, so pirria — no keychain\nitem, a `fallback_vault-shamir-share-v1` untouched since 2026-09-01 keeping\nevery reset warm — was certified cold, and the verdict's own text claimed the\nresync path was exercised. If the checkout running this skill predates\n1149-vgn2, its cold verdict is keychain-only: do not trust it (drill: plan\u002Fissues\u002Ffleet-restart-2026-09-12.md, 1149-vgn2 fixed: the cold probe now checks the fallback share).\n\n**DECIDED (900-z3kv, operator ruling 2026-09-13): the reset clears the\nhost-held credentials.** Not open — the platform prefers idempotency to\nlegacy support, and `podman system reset --force` is the baseline.\n`scripts\u002Fclear-vault-host-credentials.sh` clears THREE locations: the\nkeychain items `vault-shamir-share-v1` and `vault-root-token-v1`, the\n`~\u002F.cache\u002Ftillandsias\u002Ffallback_*` copies of both, and\n`~\u002F.cache\u002Ftillandsias\u002Fvault-data`. `installation-uuid-v1` is deliberately\nPRESERVED — it anchors the INSTALLATION, and clearing it makes the next vault\nunderivable rather than re-initialized. **Read the clearer's own last line,\nnot the reset's exit code:** a partial clear prints\n`warn:clear-vault-credentials:partial` and still exits 0, which is precisely\nthe state that looks cold and is not (drill: plan\u002Fissues\u002Ffleet-restart-2026-09-12.md, 900-z3kv COMPLETED).\n\n---\n\nOn macOS, the destructive substrate is the Tillandsias Virtualization.framework\nstate and cache directories. On Windows, it is the `tillandsias` WSL2 distro and\ndownload cache.\n\n## 0 — Pre-flight\n\n0. **Shell: every fenced `bash` block in this runbook runs under bash, and the\n   first line of each block asserts it.** `PIPESTATUS` is a bash array; under\n   zsh it expands EMPTY and zsh's `test \"\" -eq 0` is TRUE, so every exit-code\n   assertion below silently passes on a failed step (measured on pirria,\n   2026-09-04: the first install attempt recorded `install_exit=` and walked\n   on — the exact walk-past-a-failed-install 727-kmks wrote the assertions to\n   kill, reintroduced by shell choice; order 1004-fue3). Paste this line at the\n   top of every bash block, or run each block as `bash -c '...'`:\n   ```bash\n[ -n \"${BASH_VERSION:-}\" ] || { echo 'FAIL: run this block under bash — PIPESTATUS is a bash array and zsh expands it empty'; exit 2; }\n   [ -n \"${BASH_VERSION:-}\" ] || { echo 'FAIL: run this block under bash — PIPESTATUS is a bash array and zsh expands it empty'; exit 2; }\n   ```\n   Every assertion on a captured status also checks the capture is NON-EMPTY\n   (`test -n \"$RC\" && test \"$RC\" -eq 0`), so a void capture fails loud even if\n   the guard above is skipped. PowerShell blocks assert `$LASTEXITCODE` and\n   `$?` instead; there is no PIPESTATUS there.\n\n1. **Identify host + branch** (Linux → `linux-next`, macOS → `osx-next`,\n   Windows → `windows-next`). The `--opencode` forge lane is Linux\u002FPodman today.\n2. **Choose the channel and resolve the release under test.** Two channels\n   (plan order 305 + operator directive 2026-07-15):\n   - **`daily` (DEFAULT for routine smoke)** — the newest release *including\n     prereleases* (the latest daily). Routine curl-install smoke tracks the\n     bleeding edge because that is the next promotion candidate.\n   - **`stable` (one-shot after a promotion)** — the newest non-prerelease\n     (what `\u002Freleases\u002Flatest` and the README serve). Run this ONCE right\n     after `scripts\u002Fpromote-stable.sh` promotes a release, to prove the\n     promoted artifact installs; then routine runs go back to `daily`.\n   ```bash\n   awk -v tag=\"${SMOKE_TAG}\" '\n       # 1. An exact row for this tag.\n       $0 ~ \"^\\\\| \" tag \"( |\\\\()\" { print; found=1; next }\n       # 2. A DISTILLED SPAN covering it (order 380). Old series are collapsed\n       #    into one `first … last` row, so a tag inside that range HAS been\n       #    described — just not individually. Without this arm a distilled tag\n       #    is indistinguishable from an undescribed one, and the finding below\n       #    fires falsely on every release old enough to have been compressed.\n       \u002F^\\| v[0-9].* … v[0-9].*DISTILLED\u002F {\n           split($0, c, \"|\"); split(c[2], span, \"…\")\n           lo = span[1]; hi = span[2]\n           gsub(\u002F[^0-9A-Za-z.]\u002F, \"\", lo); gsub(\u002F .*\u002F, \"\", hi); gsub(\u002F[^0-9A-Za-z.]\u002F, \"\", hi)\n           if (tag >= lo && tag \u003C= hi) { print; found=1; distilled=1 }\n       }\n       END {\n           if (!found) print \"NO LEDGER ROW for \" tag\n           else if (distilled) print \"(row is a DISTILLED span, not a per-release row — claims are series-level)\"\n       }\n   ' README.md | tee target\u002Fsmoke-e2e\u002F00-ledger-row.txt\n   ```\n   Note the tag — every filed finding cites it so issues are attributable to a\n   specific published artifact AND channel.\n2b. **Read the release's own ledger row BEFORE testing it** (order 380).\n   `README.md` carries a RELEASE \u002F INTENDED FEATURES \u002F BUGFIXES table, and the\n   row for `$SMOKE_TAG` is the release stating **what it claims to have fixed**:\n\n   ```bash\n   awk -v tag=\"${SMOKE_TAG}\" '\n       # 1. An exact row for this tag.\n       $0 ~ \"^\\\\| \" tag \"( |\\\\()\" { print; found=1; next }\n       # 2. A DISTILLED SPAN covering it (order 380). Old series are collapsed\n       #    into one `first … last` row, so a tag inside that range HAS been\n       #    described — just not individually. Without this arm a distilled tag\n       #    is indistinguishable from an undescribed one, and the finding below\n       #    fires falsely on every release old enough to have been compressed.\n       \u002F^\\| v[0-9].*DISTILLED\u002F {\n           row = $0\n           sub(\u002F^\\| \u002F, \"\", row); split(row, parts, \" … \")\n           lo = parts[1]; hi = parts[2]; sub(\u002F .*$\u002F, \"\", hi)\n           if (tag >= lo && tag \u003C= hi) { print; found=1; distilled=1 }\n       }\n       END {\n           if (!found) print \"NO LEDGER ROW for \" tag\n           else if (distilled) print \"(DISTILLED span — claims are series-level, not per-release)\"\n       }\n   ' README.md | tee target\u002Fsmoke-e2e\u002F00-ledger-row.txt\n   ```\n\n   **Why this is a step and not a courtesy.** Without it the smoke validates a\n   generic property — it installs, it destroys, it re-provisions — against\n   *any* release, and cannot tell whether the specific thing this release says\n   it repaired actually got repaired. The row names orders; those are checkable.\n   On 2026-08-26 the macOS lane verified that `--version` reports the workspace\n   VERSION rather than `0.1.0`, which is precisely what that row claims for\n   635-bhkb — **but by coincidence, because the runbook had just been changed,\n   not because anything directed the run at the claim.**\n\n   Cite the row in the §5 report and state which of its claims this lane\n   exercised, which it could not, and which it did not look at. A claim the\n   lane cannot reach (a Windows fix on the macOS lane) is a legitimate\n   *not-applicable*; a claim it could have checked and did not is a gap in the\n   run, and only naming them separately makes that visible.\n\n   **A MISSING ROW IS A FINDING, NOT A SKIP.** `NO LEDGER ROW for \u003Ctag>` means\n   either the release skill's append step did not run for this release, or the\n   smoke is testing an artifact nobody described. Both are worth a packet, and\n   both are invisible if this step silently proceeds.\n3. **Record sibling heads** (`main`, `linux-next`, `windows-next`, `osx-next`)\n   per multi-host discipline.\n4. **ARCHIVE THE PREVIOUS RUN'S EVIDENCE, THEN create the findings log dir**\n   (order 1189-7yvu). `mkdir -p` on its own is what let a run inherit every\n   file from every previous run:\n   ```bash\n   SMOKE_EVIDENCE_DIR=target\u002Fsmoke-e2e\n   SMOKE_RUN_START=\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"\n   # MOVE ASIDE, NEVER DELETE — prior evidence is worth keeping, and a step\n   # that deletes it makes the previous run unreconstructable.\n   if [ -d \"$SMOKE_EVIDENCE_DIR\" ] && [ -n \"$(ls -A \"$SMOKE_EVIDENCE_DIR\" 2>\u002Fdev\u002Fnull)\" ]; then\n       SMOKE_ARCHIVE=\"$SMOKE_EVIDENCE_DIR\u002F_archived-$(date -u +%Y%m%dt%H%M%Sz)\"\n       mkdir -p \"$SMOKE_ARCHIVE\"\n       # Move every entry except the archive dirs themselves.\n       for _e in \"$SMOKE_EVIDENCE_DIR\"\u002F*; do\n           case \"$_e\" in *\"\u002F_archived-\"*) continue ;; esac\n           [ -e \"$_e\" ] && mv \"$_e\" \"$SMOKE_ARCHIVE\"\u002F\n       done\n       printf 'archived_to=%s\\n' \"$SMOKE_ARCHIVE\"\n   fi\n   mkdir -p \"$SMOKE_EVIDENCE_DIR\"\n   printf 'run_start=%s\\n' \"$SMOKE_RUN_START\" | tee \"$SMOKE_EVIDENCE_DIR\u002F00-run-start.txt\"\n   ```\n   **Windows runs this step in PowerShell, and it is the lane that found the\n   defect** (order 1044-na6u, esmeraldinha v56.9.4.1: after a §3 abort,\n   `03-provision-exit.txt` still held the v56.9.2.1 round's `provision_exit=0`\n   and `elapsed_seconds=117`, eighteen hours old). §1's\n   `New-Item -ItemType Directory -Force` is the PowerShell spelling of the\n   `mkdir -p` above: it keeps every file already in the directory. Run this\n   before §1:\n   ```powershell\n   $SmokeEvidenceDir = 'target\\smoke-e2e'\n   $SmokeRunStart = (Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ')\n   # MOVE ASIDE, NEVER DELETE, exactly as the bash block does.\n   $prior = @(Get-ChildItem -LiteralPath $SmokeEvidenceDir -Force -ErrorAction SilentlyContinue |\n              Where-Object { $_.Name -notlike '_archived-*' })\n   if ($prior.Count -gt 0) {\n     $SmokeArchive = Join-Path $SmokeEvidenceDir ('_archived-' + (Get-Date).ToUniversalTime().ToString('yyyyMMdd\\tHHmmss\\z'))\n     New-Item -ItemType Directory -Force $SmokeArchive | Out-Null\n     $prior | Move-Item -Destination $SmokeArchive\n     \"archived_to=$SmokeArchive\"\n   }\n   New-Item -ItemType Directory -Force $SmokeEvidenceDir | Out-Null\n   \"run_start=$SmokeRunStart\" | Tee-Object (Join-Path $SmokeEvidenceDir '00-run-start.txt')\n   ```\n   With the directory emptied at the start of the round, a step that aborts\n   before its write leaves its evidence file ABSENT. Absent is a verdict; a\n   previous round's file under the same name is a lie.\n   **WHY THIS IS NOT HOUSEKEEPING.** In-block assertions capture their status\n   in the same shell and are unaffected. Every OUT-OF-BAND read is affected:\n   the §5 report, an orchestrator polling for completion, a human scanning the\n   directory. A step that never reaches its write leaves the PREVIOUS run's\n   file under the exact name those readers open, so a stale PASS is\n   indistinguishable from a fresh one BY NAME.\n\n   MEASURED on pirria 2026-09-14: `03-init-exit.txt` containing `init_exit=0`,\n   dated 2026-09-13 01:24, was present and being read as this run's result\n   while this run's `--init` was still building the proxy image. Fourteen files\n   from the 2026-09-12\u002F13 runs were present at start and had to be archived by\n   hand.\n\n   **CHECK EVIDENCE AGAINST `run_start`, not against its existence.** Any file\n   in the directory older than `00-run-start.txt` is a leak from an incomplete\n   archive, not a result:\n   ```bash\n   find \"$SMOKE_EVIDENCE_DIR\" -maxdepth 1 -type f \\\n        ! -newer \"$SMOKE_EVIDENCE_DIR\u002F00-run-start.txt\" \\\n        ! -name 00-run-start.txt -print\n   # any output here is stale evidence that survived the archive step\n   ```\n5. **Source the timing helpers, and keep them sourced for every block below**\n   (order 1013-qv7c). Each smoke step emits ONE duration record so the\n   recurrence rung (`repeat:` \u002F `recur:` \u002F `skippable:` in\n   `scripts\u002Fcycle-metrics.sh`) can see this runbook's work:\n   ```bash\n   . \"$PWD\u002Fscripts\u002Ftiming-log.sh\" 2>\u002Fdev\u002Fnull || true\n   command -v timing_emit >\u002Fdev\u002Fnull 2>&1 || { timing_now_ms() { echo 0; }; timing_emit() { return 0; }; }\n   command -v timing_begin >\u002Fdev\u002Fnull 2>&1 || { timing_begin() { return 0; }; timing_commit() { return 0; }; timing_reap() { return 0; }; }\n   timing_reap\n   ```\n   `timing_reap` reports on the PREVIOUS run, not this one (order 1026-ps4n).\n   If a earlier smoke's supervising shell was killed mid-step, its start stamp\n   is still on disk; reaping turns it into a `\u003Cstep>-supervisor-lost` record so\n   the log says what happened instead of being silent. Run it first, before any\n   step below writes a stamp of its own.\n   **Why this and not the gate.** Every other emitter in the tree is a\n   build\u002Ftest\u002Flitmus step in `build.sh`, `scripts\u002Flocal-ci.sh` or\n   `scripts\u002Frun-litmus-test.sh`, and all of those need cargo. A floor host\n   without a toolchain therefore has *never* written a timing record —\n   measured on pirria 2026-09-04, where `repeat:`\u002F`recur:`\u002F`skippable:` all\n   read `source=absent` and `.cache\u002Fmetrics\u002F` was an empty directory the probe\n   itself created. An instrument for finding what slow hosts pay cannot be\n   downstream of the thing slow hosts cannot run. `timing_emit` is bash and\n   `jq`, needs no toolchain, and the smoke is work the floor *can* do — so the\n   records come from here.\n\n   The emits are **best-effort by construction**: `timing_emit` wraps its whole\n   body and always returns 0, and the fallback stub above keeps every call site\n   unconditional and `set -e`-safe. A metrics write can never fail a smoke step.\n\n   Records are named `phase=smoke` with these pinned `step` values, one per\n   step below: `smoke-curl-install`, `smoke-destructive-reset`,\n   `smoke-init-pristine`, `smoke-forge-lane`, `smoke-health-check`. They land\n   in `\u003Ccheckout>\u002F.cache\u002Fmetrics\u002Ftillandsias-timing.jsonl` (the same log the\n   gate steps write) and are read back by `scripts\u002Fcycle-metrics.sh`.\n\n   A sixth name appears only when something went wrong:\n   `smoke-forge-lane-supervisor-lost` (order 1026-ps4n). It means a previous\n   run's shell was killed while the lane was running, and its `duration_ms` is\n   a **lower bound** — the end was never observed. It is deliberately a\n   separate step name so it can never be averaged into `smoke-forge-lane`;\n   see §4a for what that state looks like on the host and why it is not a\n   product failure.\n\n---\n\n## 1 — Curl-install the latest release\n\nInstall the published artifact the canonical way an operator would — do NOT use a\nlocally built `target\u002F` binary; the whole point is to test the *download*.\n\n**`install.sh` is not a download test — it runs the full init (1133-kktm).**\nMeasured on v56.9.12.2: 131 lines of podman\u002Fvault output, a Vault bootstrap\nprovisioning twelve policies and AppRole roles, and a `tillandsias-vault`\ncontainer left running on 8201. Reversible, not inert, and not what\n\"curl-install and assert the tag\" describes above. The §1\u002F§2 consent line\nstill holds (§2 destroys, §1 provisions), but on an operator's workstation say\nwhat §1 actually does before running it; consent to a download check is not\nconsent to a Vault bootstrap (drill: plan\u002Fissues\u002Ffleet-restart-2026-09-12.md, §1 of the smoke is not a non-destructive binary install).\n\n**SINCE 1286-4437, `install.sh` CALLS `--reset-state` ITSELF, so on a release\ncarrying that change §1 IS A DESTRUCTIVE STEP.** Bank the pre-state BEFORE §1,\nnot before §2, or the reset contract has nothing to be measured against — and\non an operator's workstation get consent for §1 on those grounds, not §2's.\n\n**AFTER A SUCCESSFUL §1 THE ENCLAVE SHOWS ZERO RUNNING CONTAINERS, AND THAT IS\nCORRECT.** The reprovision rebuilds IMAGES synchronously; the install log ends\n`SUCCESS web`, \"Reset and reprovision complete\", exit 0, and directs the\noperator to launch the tray. Containers arrive at tray or lane launch, not at\ninstall. A reader who checks `podman ps` here and finds it empty will file a\nfailed provision against a release that installed perfectly — measured on\npirria during the v56.9.21.1 run. Check the IMAGE count against `run_start`\ninstead: on a real reprovision every image post-dates it.\n\nLinux:\n\nThe installer honors `TILLANDSIAS_RELEASE_BASE` so the smoke pins the exact\nresolved release (`$SMOKE_BASE`) instead of the hard-coded\n`\u002Freleases\u002Flatest\u002Fdownload` (which is stable-only by GitHub semantics — it\nwould ignore the daily prerelease). Real users are unaffected: with the env\nunset the installer defaults to the stable channel.\n\n```bash\n[ -n \"${BASH_VERSION:-}\" ] || { echo 'FAIL: run this block under bash — PIPESTATUS is a bash array and zsh expands it empty'; exit 2; }\n_T0=\"$(timing_now_ms)\"\nTILLANDSIAS_SMOKE_LOCK_LOG=target\u002Fsmoke-e2e\u002F00-smoke-lock.log \\\n  scripts\u002Fwith-smoke-lock.sh --name release-smoke-e2e -- \\\n  bash -c \"curl -fsSL '${SMOKE_BASE}\u002Finstall.sh' | TILLANDSIAS_RELEASE_BASE='${SMOKE_BASE}' bash\" 2>&1 \\\n  | tee target\u002Fsmoke-e2e\u002F01-install.log\nINSTALL_RC=${PIPESTATUS[0]}; printf 'install_exit=%s\\n' \"$INSTALL_RC\" | tee target\u002Fsmoke-e2e\u002F01-install-exit.txt\ntiming_emit smoke-curl-install smoke \"$_T0\" \"${INSTALL_RC:-1}\" || true\ntest -n \"$INSTALL_RC\" && test \"$INSTALL_RC\" -eq 0\nhash -r\ntillandsias --version | tee target\u002Fsmoke-e2e\u002F01-version.txt\n_rc=${PIPESTATUS[0]}; test -n \"$_rc\" && test \"$_rc\" -eq 0\n# The comment used to say \"must equal $SMOKE_TAG\". Now it is checked.\n# BOUNDED (amendment to 1133-kktm): the version scheme is a monotonic\n# counter, so an unbounded substring test would accept 56.9.12.20 as a match\n# for 56.9.12.2. (drill: plan\u002Fissues\u002Ffleet-restart-2026-09-12.md, The promotion proven on the default Windows path)\ngrep -qE \"(^|[^0-9.])${SMOKE_TAG#v}([^0-9.]|\\$)\" target\u002Fsmoke-e2e\u002F01-version.txt\n```\n\n> Three assertions replacing a pipe and a comment (order 727-kmks). The\n> installer ran through `| tee`, so a curl-install that failed outright exited 0\n> — `tee` wrote the failure into the evidence file and the smoke walked on. The\n> version line then carried `# must equal $SMOKE_TAG` as a comment, which meant\n> the clean-room test of a PUBLISHED release never once confirmed it was running\n> the release it claimed to be testing: a stale binary already on PATH would\n> answer `--version` and pass.\n\n**`install-macos.sh` is not a download test either — it launches the tray and\nprovisions a VM (1281-pgit).** The hazard above is written for `install.sh` and\nLinux; the macOS installer does the platform equivalent and had no equivalent\nwarning. MEASURED on macneo during the v56.9.19.1 and v56.9.19.2 smokes: §1 ends\nwith \"Launching Tillandsias (--init \u002F VM provisioning runs automatically on\nfirst launch)\", leaves a `tillandsias-tray` process running that §2 must then\nstop, and provisioning downloads a ~528 MB Fedora Cloud image in the background.\n\nWHY THE ASYMMETRY MATTERED, and why it is now stated on both paths: most of the\nfleet's macOS hosts are OPERATORS' WORKSTATIONS rather than dedicated smoke\nhosts, and this runbook has already recorded once that the distinction was\nmissed (1004-vsh2 — \"this section read as though every host running it were a\nsmoke host\"). A reader who has internalised \"§1 is the safe download step, §2 is\nthe destructive one\" is correct on Linux by documentation and wrong on macOS.\nSay what §1 actually does before running it on a machine whose guest holds work\nsomeone has not finished with.\n\nAND AN INTERRUPTED INSTALL USED TO COST THE EXISTING APP. Until 1281-pgit the\ninstaller removed the previous backup and moved the live app aside BEFORE\nextracting, so a kill between those steps left `\u002FApplications` with neither the\napp nor a backup — measured here when the installer was piped through `head` to\nread its first lines and died on SIGPIPE. The swap is now staged-extract,\nrename, rename, with the old backup dropped last and a trap that restores it, so\nthe destination always holds a runnable app; `litmus:installer-swap-atomicity`\npins that. A SIGKILL is still untrappable, so do not pipe the installer into\nsomething that closes early just to read its output — run it and read the log.\n\nmacOS:\n\n```bash\n[ -n \"${BASH_VERSION:-}\" ] || { echo 'FAIL: run this block under bash — PIPESTATUS is a bash array and zsh expands it empty'; exit 2; }\ncurl -fsSL \"${SMOKE_BASE}\u002Finstall-macos.sh\" | TILLANDSIAS_RELEASE_BASE=\"${SMOKE_BASE}\" bash 2>&1 \\\n  | tee target\u002Fsmoke-e2e\u002F01-install-macos.log\nINSTALL_RC=${PIPESTATUS[0]}; printf 'install_exit=%s\\n' \"$INSTALL_RC\" \\\n  | tee target\u002Fsmoke-e2e\u002F01-install-macos-exit.txt\ntest -n \"$INSTALL_RC\" && test \"$INSTALL_RC\" -eq 0\n\n# install-macos.sh extracts to \u002FApplications — but FALLS BACK to\n# ~\u002FApplications when \u002FApplications is not writable, and this runbook then\n# verifies \u002FApplications unconditionally. Assert which branch it took rather\n# than assuming: a stale ~\u002FApplications copy plus a silent fallback is the\n# live mixup of 2026-07-16, and it \"verifies\" the wrong binary.\ntest -d \"\u002FApplications\u002FTillandsias.app\"\n! grep -q \"not writable; using\" target\u002Fsmoke-e2e\u002F01-install-macos.log\n\n\"\u002FApplications\u002FTillandsias.app\u002FContents\u002FMacOS\u002Ftillandsias-tray\" --version 2>&1 \\\n  | tee target\u002Fsmoke-e2e\u002F01-version.txt\n_rc=${PIPESTATUS[0]}; test -n \"$_rc\" && test \"$_rc\" -eq 0\n# EXACT, not `>=` and not \"contains 0.4\". Assertable at all only since\n# 635-bhkb: every macOS build answered `0.1.0` before it, so this lane could\n# not confirm which release it was testing even in principle.\ngrep -qF \"tillandsias-tray ${SMOKE_TAG#v} \" target\u002Fsmoke-e2e\u002F01-version.txt\n```\n\n> The same three assertions the Linux lane got in 727-kmks, plus two the macOS\n> lane needs and Linux does not. The install ran through `| tee` with no\n> `PIPESTATUS` capture and the version check ended in `|| true` — so a\n> curl-install that failed outright, and a `--version` that failed after it,\n> both exited 0 and the smoke walked on. That is the identical defect 727-kmks\n> fixed one lane over, left standing here, in the lane that had never once been\n> run against a published release.\n>\n> The two extra assertions are the `\u002FApplications`-vs-`~\u002FApplications`\n> fallback (the installer chooses, this runbook does not, and only one of them\n> is the path verified below) and the exact-tag match, which was not expressible\n> before 635-bhkb.\n\nWindows PowerShell (daily-channel pinned — the release publishes\n`install-windows.ps1` + the x64 tray zip since v0.3.260721.1; the installer\nhonors `TILLANDSIAS_VERSION` for an exact-tag pin, so the smoke installs the\nSAME resolved daily as the Linux\u002FmacOS lanes instead of `\u002Freleases\u002Flatest`,\nwhich is stable-only by GitHub semantics):\n\n```powershell\n# $SmokeTag from pre-flight, e.g. v0.3.260721.1 (strip\u002Fkeep the leading v —\n# the installer normalizes both).\n$ErrorActionPreference = 'Stop'\n# Pre-flight step 4 must have run: without 00-run-start.txt the directory may\n# still hold the previous round's files (1044-na6u).\nif (-not (Test-Path target\\smoke-e2e\\00-run-start.txt)) { throw 'run pre-flight step 4 first: no 00-run-start.txt' }\n$env:TILLANDSIAS_VERSION = $SmokeTag\n$installExit = 0\ntry {\n  $script = irm \"https:\u002F\u002Fgithub.com\u002F8007342\u002Ftillandsias\u002Freleases\u002Fdownload\u002F$SmokeTag\u002Finstall-windows.ps1\"\n  Invoke-Expression $script *>&1 | Tee-Object target\\smoke-e2e\\01-install-windows.log\n  if ($LASTEXITCODE) { $installExit = $LASTEXITCODE }\n} catch {\n  $_ | Out-String | Tee-Object -Append target\\smoke-e2e\\01-install-windows.log\n  $installExit = 1\n}\nRemove-Item Env:TILLANDSIAS_VERSION\n\"install_exit=$installExit\" | Tee-Object target\\smoke-e2e\\01-install-exit.txt\nif ($installExit -ne 0) { throw \"install failed (exit $installExit) — file a finding and STOP\" }\n# The tray is the only installed surface on Windows; assert it resolves NOW,\n# not at §3 where a missing binary would read as a provision failure.\n#\n# MEASURED 2026-09-04 on yolanda (order 1004-vsh2): the installer does NOT put\n# its directory on PATH, so a bare `Get-Command tillandsias-tray.exe` THROWS on\n# a host where the install just succeeded — \"not recognized as a name of a\n# cmdlet\". The binary is at $env:LOCALAPPDATA\\Programs\\Tillandsias, which the\n# installer prints as its install path. Resolve PATH first (an operator may\n# have added it) and fall back to the install location; only then fail.\n$tray = (Get-Command tillandsias-tray.exe -ErrorAction SilentlyContinue |\n    Select-Object -First 1 -ExpandProperty Source)\nif (-not $tray) { $tray = \"$env:LOCALAPPDATA\\Programs\\Tillandsias\\tillandsias-tray.exe\" }\nif (-not (Test-Path $tray)) { throw \"tray not found on PATH or at $tray after a successful install\" }\n\"tray=$tray\" | Tee-Object target\\smoke-e2e\\01-tray-path.txt\n# EXACT, not \"contains\": the tray answers --version \u002F -V (windows-tray\n# main.rs), so the lane can confirm which release it is testing.\n& $tray --version 2>&1 | Tee-Object target\\smoke-e2e\\01-version.txt | Out-Null\nif ($LASTEXITCODE -ne 0) { throw \"tray --version failed (exit $LASTEXITCODE)\" }\n$installedVersion = (Get-Content target\\smoke-e2e\\01-version.txt -Raw).Trim()\n# BOUNDED (amendment to 1133-kktm): an unbounded substring match would accept\n# 56.9.12.20 as a match for 56.9.12.2 — the version scheme is a monotonic\n# counter, so the collision is reachable, not hypothetical.\nif ($installedVersion -notmatch ('(?\u003C![0-9.])' + [regex]::Escape($SmokeTag.TrimStart('v')) + '(?![0-9.])')) {\n  throw \"installed tray version '$installedVersion' does not carry release $SmokeTag\"\n}\n```\n\n> Same three assertions the Linux lane got on 727-kmks and macOS on\n> 2026-08-26, added 2026-09-04 (order 1004-fue3): the old block piped `iex`\n> into `Tee-Object` and asserted nothing, so a failed installer exited 0 and\n> the smoke walked on — the shape the Linux lane had already been fixed for.\n> The release-tag pin on this lane is the installer's `TILLANDSIAS_VERSION`\n> (an exact tag: a tag that does not exist fails the download and trips the\n> exit assertion). The tray's OWN version is asserted above from `--version` (the flag\n> exists in windows-tray main.rs); the `.version` field of `--diagnose --json`\n> is a second surface, asserted in §3 only when the build reports it.\n\nVerify the installed version matches the release tag from Step 0. If the install\nscript errors, the version mismatches, or `tillandsias` is not on `PATH`\nafterward → **file a finding (capability: `release`, `install`) and STOP**;\nthe rest of the smoke is invalid on a bad install.\n\n### 1s — Verify the SIGNATURE of the artifact this lane installed (1273-4mak)\n\nUntil this section existed the smoke verified INTEGRITY and never AUTHENTICITY.\n`install.sh` checks the asset's SHA256 against a `SHA256SUMS` fetched from the\nsame place as the asset, which is self-consistent by construction: a substituted\nasset served with a regenerated manifest passes. The `.cosign.bundle` beside\nevery asset is the only artifact in the set that answers *who produced this*,\nand nothing read one — on any lane, for any release, ever. It was declared\n\"NOT CHECKED\" in the 08-28 Linux and Windows reports and in the 09-19 macOS\nreport, three platforms, three times, and stayed open: a gap everyone declares\nand nobody closes is a missing GATE, not a missing observation.\n\n**Two facts measured on v56.9.19.2 that decide the shape of these blocks:**\n\n- **Every asset has its own `\u003Casset>.cosign.bundle`** (32 assets). That is what\n  these blocks verify.\n- **`SHA256SUMS` and `SHA256SUMS-macos` have NO bundle; only\n  `SHA256SUMS-windows` does.** So \"verify the manifest and trust it for every\n  asset it lists\" is not available on the Linux or macOS lanes. Verify the\n  ARTIFACT THIS LANE INSTALLED, against its own bundle.\n\n**The precondition is probed, never inferred from an exit code.** The release's\n`verify.sh` exits 1 both when cosign is MISSING and when a signature is BAD, and\nthose need opposite responses — one is \"this run cannot answer the question\",\nthe other is \"this artifact is not what it claims\". A block that reads rc=1 and\nreports a failure turns a floor host without cosign into a fake security\nincident; one that swallows rc=1 turns a bad signature into a pass. So each\nblock asks `command -v cosign` FIRST.\n\n**`cosign:could-not-run:\u003Creason>` IS NOT A PASS.** It is not a failure either —\n`command -v cosign` returns nothing on macneo and on yoga today, and a host\nwithout the tool has not found a bad signature, it has found nothing. It is a\nTHIRD verdict, and §5 requires it in the report's opening lines so a run that\ncould not verify cannot be filed as an unqualified PASS. That requirement is the\npart that closes this gap rather than re-declaring it.\n\nLinux — use the release's own `verify.sh`, which ships with every release:\n\n```bash\ncd \"$(mktemp -d)\" || exit 1\nASSET=tillandsias-linux-x86_64        # what install.sh actually downloads\nif ! command -v cosign >\u002Fdev\u002Fnull 2>&1; then\n  echo \"cosign:could-not-run:cosign-absent\"\nelse\n  curl -fsSL -O \"$SMOKE_BASE\u002Fverify.sh\" \\\n    && curl -fsSL -O \"$SMOKE_BASE\u002F$ASSET\" \\\n    && curl -fsSL -O \"$SMOKE_BASE\u002F$ASSET.cosign.bundle\" || {\n         echo \"cosign:could-not-run:asset-or-bundle-download-failed\"; }\n  if [ -f \"$ASSET.cosign.bundle\" ]; then\n    if bash verify.sh \"$ASSET\"; then echo \"cosign:verified:1\u002F1\"\n    else echo \"cosign:FAILED:$ASSET\"; fi\n  fi\nfi\n```\n\nmacOS — its own call, NOT an inherited Linux assumption. The lane verifies the\n**tar.gz the installer consumed**, not a binary it never touched:\n\n```bash\ncd \"$(mktemp -d)\" || exit 1\nASSET=\"tillandsias-tray-${SMOKE_VERSION}-macos-arm64.tar.gz\"\nif ! command -v cosign >\u002Fdev\u002Fnull 2>&1; then\n  echo \"cosign:could-not-run:cosign-absent (brew install cosign)\"\nelse\n  curl -fsSL -O \"$SMOKE_BASE\u002Fverify.sh\" \\\n    && curl -fsSL -O \"$SMOKE_BASE\u002F$ASSET\" \\\n    && curl -fsSL -O \"$SMOKE_BASE\u002F$ASSET.cosign.bundle\" || {\n         echo \"cosign:could-not-run:asset-or-bundle-download-failed\"; }\n  if [ -f \"$ASSET.cosign.bundle\" ]; then\n    if bash verify.sh \"$ASSET\"; then echo \"cosign:verified:1\u002F1\"\n    else echo \"cosign:FAILED:$ASSET\"; fi\n  fi\nfi\n```\n\n`verify.sh` is bash and runs under macOS's bash 3.2, which is why this lane may\ncall it — but it is called HERE, on this lane's own artifact, so a future change\nto the Linux block cannot silently redefine what macOS verified.\n\nWindows PowerShell — `verify.sh` is bash, so this lane calls cosign directly:\n\n```powershell\n$asset = \"tillandsias-windows-x64.zip\"\nif (-not (Get-Command cosign -ErrorAction SilentlyContinue)) {\n  \"cosign:could-not-run:cosign-absent (winget install sigstore.cosign)\"\n} else {\n  $tmp = New-Item -ItemType Directory -Path (Join-Path $env:TEMP ([guid]::NewGuid()))\n  Set-Location $tmp\n  curl.exe -fsSL -O \"$env:SMOKE_BASE\u002F$asset\"\n  curl.exe -fsSL -O \"$env:SMOKE_BASE\u002F$asset.cosign.bundle\"\n  if (Test-Path \"$asset.cosign.bundle\") {\n    cosign verify-blob --bundle \"$asset.cosign.bundle\" `\n      --certificate-identity-regexp 'https:\u002F\u002Fgithub\\.com\u002F8007342\u002Ftillandsias\u002F' `\n      --certificate-oidc-issuer 'https:\u002F\u002Ftoken.actions.githubusercontent.com' `\n      $asset\n    if ($LASTEXITCODE -eq 0) { \"cosign:verified:1\u002F1\" } else { \"cosign:FAILED:$asset\" }\n  } else { \"cosign:could-not-run:bundle-download-failed\" }\n}\n```\n\n**A `cosign:FAILED:` line is a STOP.** File a finding (capability: `release`,\n`security`) and do not continue: an artifact whose signature does not verify\nmust not be exercised further, and the rest of the smoke would be reporting on\nsoftware of unknown origin. This is the one check whose failure is not a bug\nreport about Tillandsias but a question about what was downloaded.\n\nCarry whichever `cosign:` line this lane emitted into §5 verbatim.\n\n\n---\n\n## 2 — Full substrate reset (DESTRUCTIVE — see warning above)\n\nIf `TILLANDSIAS_DESTRUCTIVE_RESET_OK=0`, stop here, write a plan blocker, and\npush it. Otherwise run the reset immediately; on Linux this step is mandatory.\n\n```bash\n[ -n \"${BASH_VERSION:-}\" ] || { echo 'FAIL: run this block under bash — PIPESTATUS is a bash array and zsh expands it empty'; exit 2; }\n_T0=\"$(timing_now_ms)\"\nTILLANDSIAS_SMOKE_LOCK_LOG=target\u002Fsmoke-e2e\u002F00-smoke-lock.log \\\n  scripts\u002Fwith-smoke-lock.sh --name release-smoke-e2e -- \\\n  podman system reset --force 2>&1 | tee target\u002Fsmoke-e2e\u002F02-reset.log\nRESET_RC=${PIPESTATUS[0]}; printf 'reset_exit=%s\\n' \"$RESET_RC\" | tee target\u002Fsmoke-e2e\u002F02-reset-exit.txt\n  # 900-z3kv (operator ruling 2026-09-13, landed by yoga): the reset is the baseline, and\n  # an empty podman store is not a cold room — clear the host-held Vault credentials\n  # (keychain items, ~\u002F.cache\u002Ftillandsias\u002Ffallback_*, the vault-data dir) in the SAME\n  # step, or the next --init resyncs the old share and the clean room is not one\n  # (drill: plan\u002Fissues\u002Ffleet-restart-2026-09-12.md, 900-z3kv COMPLETED).\n  scripts\u002Fclear-vault-host-credentials.sh 2>&1 | tee -a target\u002Fsmoke-e2e\u002F02-reset.log\n  CLEAR_RC=${PIPESTATUS[0]}; printf 'clear_exit=%s\\n' \"$CLEAR_RC\" | tee target\u002Fsmoke-e2e\u002F02-clear-exit.txt\n  test -n \"$CLEAR_RC\" && test \"$CLEAR_RC\" -eq 0\ntiming_emit smoke-destructive-reset smoke \"$_T0\" \"${RESET_RC:-1}\" || true\ntest -n \"$RESET_RC\" && test \"$RESET_RC\" -eq 0\n```\n\nConfirm afterward that the store is empty:\n```bash\nCONTAINERS=\"$(podman ps -aq)\"; VOLUMES=\"$(podman volume ls -q)\"; IMAGES=\"$(podman images -q)\"\nprintf '[containers]\\n%s\\n[volumes]\\n%s\\n[images]\\n%s\\n' \"$CONTAINERS\" \"$VOLUMES\" \"$IMAGES\" \\\n  | tee target\u002Fsmoke-e2e\u002F02-empty-store.txt\ntest -z \"$CONTAINERS\"; test -z \"$VOLUMES\"; test -z \"$IMAGES\"\n```\n\n**`0 volumes` is not `Vault's data is gone`, and the gap ran for ~2.5\nmonths.** Every Linux pass asserted an empty podman store while `--init`\nlogged `preserving existing data volume` — both true, about different\nthings: `vault_data_volume_exists()` tests `init_cache_dir()\u002Fvault-data`, a\nHOST DIRECTORY, not a podman volume. Assert that directory is absent too, in\nthe same block as the three `test -z` lines above:\n\n```bash\nVAULT_DATA_DIR=\"${XDG_CACHE_HOME:-$HOME\u002F.cache}\u002Ftillandsias\u002Fvault-data\"\n{ echo \"[vault-data-dir]\"; ls -la \"$VAULT_DATA_DIR\" 2>&1; } | tee target\u002Fsmoke-e2e\u002F02-vault-data-dir.txt\ntest ! -e \"$VAULT_DATA_DIR\"\n```\n\n**AFTER THE REPROVISION, CHECK THAT THE IMAGES WERE REBUILT — AND SCOPE IT TO\n`localhost\u002F`.** An empty store proves the reset destroyed; it does not prove the\nreprovision rebuilt. The natural check is \"no image predates `run_start`\", and\nwritten without a scope it is WRONG in a way that reads as a failure:\n\n```bash\n# CORRECT: locally BUILT images only.\npodman images --format '{{.CreatedAt}}\\t{{.Repository}}' \\\n  | grep 'localhost\u002F' | awk -F'\\t' -v rs=\"$RUN_START_LOCAL\" '$1 \u003C rs' \\\n  | tee target\u002Fsmoke-e2e\u002F01-images-predating.txt\ntest ! -s target\u002Fsmoke-e2e\u002F01-images-predating.txt\n```\n\nA PULLED BASE IMAGE'S `CreatedAt` IS ITS UPSTREAM BUILD DATE, not the moment\nthis host fetched it. `alpine:3.20` reports its upstream build — months old —\nhowever freshly it was pulled a minute ago, and so do `caddy`, `hashicorp\u002Fvault`\nand `fedora-minimal`. Unscoped, the check reports those as \"images predating\nrun_start\" on a perfectly healthy reprovision.\n\nMEASURED on pirria 2026-09-21: 30 `localhost\u002F` tag-rows, none predating\nrun_start, beside 5 base images every one of which predates it by construction.\nThe stable-channel report claimed \"all recreated — 0 predate run_start\" over all\n15 images while its evidence file held only the 20 `localhost\u002F` lines it had\nactually examined — a true measurement described with a scope it did not have.\nEither error is available to the next reader: count the base images and report a\nfalse failure, or omit them and claim more than you measured.\n\n`scripts\u002Fclear-vault-host-credentials.sh` removes it but only best-effort —\nit is written from inside a container under a subuid, so a rootless `rm -rf`\ncan be refused and the script still exits 0 with a `warn:` line. A\n`0-volumes` PASS beside a surviving `vault-data\u002F` is a clean-room claim the\nrun cannot support (drill: plan\u002Fissues\u002Ffleet-restart-2026-09-12.md, 900-z3kv criterion 1 DECIDED: (a)).\n\nIf the reset errors or leaves residue → file a finding (capability: `podman`,\n`runtime`).\n\n> This step was prose until 727-kmks: the reset was piped to `tee` with no\n> `PIPESTATUS` capture, so a failed reset exited 0, and \"All three should be\n> empty\" was an instruction rather than an assertion. Its sibling runbook\n> (`build-install-and-smoke-test-e2e` §2) already asserted both, which is what\n> made the gap visible — the same destruction gate was executable on one path\n> and advisory on the other, and this is the path that tests PUBLISHED releases.\n\nOn macOS, stop the tray, then destroy the VM substrate and ASSERT it is gone.\n\nThe paths are correct as written and match the source of truth\n(`status_item.rs:367`, `diagnose.rs:71`, `scripts\u002Funinstall.sh:19` — all\nlowercase `tillandsias`). What was missing is the ASSERTION: this was one prose\nsentence while the Linux branch above captures `PIPESTATUS` and then proves the\nstore is empty. That asymmetry is exactly what the 727-kmks note describes, one\nlayer down — and this is the path that tests PUBLISHED releases, so a removal\nthat silently matched nothing would let the smoke run against a pre-existing\nmulti-GiB VM image while reporting a clean-room result. A false PASS on the\ndestruction precondition is worse than a red run, because it gates promotion.\n\n```bash\nscripts\u002Fe2e-step2-macos.sh target\u002Fsmoke-e2e\ntest ! -e \"$HOME\u002FLibrary\u002FApplication Support\u002Ftillandsias\"\nMACOS_RESIDUE=\"$(cat target\u002Fsmoke-e2e\u002F02-macos-residue.txt)\"\ntest -z \"$(printf '%s' \"$MACOS_RESIDUE\" | tail -n +2)\"\n```\n\nIf residue survives → file a finding (capability: `macos`, `runtime`) and do NOT\ncontinue.\n\n> A NOTE ON WHAT DID NOT NEED FIXING, so nobody re-opens it (889-bx99,\n> retracted). This step was reported as carrying a case bug — capital-`T`\n> `Tillandsias` on disk versus lowercase in the runbook. It does not. The\n> reporting host checked by typing a capital-`T` path and watching it resolve,\n> on a case-INSENSITIVE volume where any spelling resolves; `ls` of the PARENT\n> shows the stored name is lowercase, matching the code. When testing a\n> case-sensitivity hypothesis, read the stored name — a path you typed yourself\n> proves only that the filesystem folded it.\n\nOn Windows, FIRST snapshot the builder distro's disk, so §3 can prove it\nsurvived (order 1295-b4i8):\n\n```powershell\nNew-Item -ItemType Directory -Force target\\smoke-e2e | Out-Null\n$b = Get-Item -LiteralPath \"$env:LOCALAPPDATA\\tillandsias\\wsl-build\\ext4.vhdx\" -ErrorAction SilentlyContinue\n$(if ($b) { \"$($b.Length) $($b.LastWriteTimeUtc.Ticks)\" } else { 'absent' }) |\n  Set-Content target\\smoke-e2e\\02-builder-vhdx-before.txt\n```\n\nThen stop the tray, run `wsl --terminate tillandsias` followed by\n`wsl --unregister tillandsias`, tolerating an already-absent distro.\n\n**Then purge the runtime cache BY NAME (order 1295-b4i8).** This step used to\nsay only \"cache purge\", and the obvious directory,\n`%LOCALAPPDATA%\\tillandsias`, also holds `wsl-build\\ext4.vhdx`: the BUILDER\ndistro's disk (142.9 GB on yolanda), the host's gate toolchain. Measured on\nyolanda 2026-09-20: that purge was attempted and failed only because the\nbuilder was Running and held the file open. With the builder Stopped it is\ndeleted, and §2 still reports a clean reset.\n\n- DELETE: `%USERPROFILE%\\.cache\\tillandsias` and `%APPDATA%\\tillandsias`.\n- NEVER DELETE: `%LOCALAPPDATA%\\tillandsias\\wsl-build` (the builder distro),\n  nor `%LOCALAPPDATA%\\tillandsias` as a whole. The runtime distro's own disk\n  is removed by `--unregister` above, not by a directory delete.\n- Do NOT work around this by stopping the builder first: that makes the\n  destructive case the default.\n\n```powershell\nforeach ($p in @(\"$env:USERPROFILE\\.cache\\tillandsias\", \"$env:APPDATA\\tillandsias\")) {\n  if ($p -match 'wsl-build') { throw \"refusing to purge a path that names the builder: $p\" }\n  if (Test-Path -LiteralPath $p) { Remove-Item -LiteralPath $p -Recurse -Force }\n  if (Test-Path -LiteralPath $p) { throw \"runtime cache survived the purge: $p\" }\n}\n```\n\n**Then clear the host credential store, or the run is not a clean room (order\n804-ckst).** Unregistering the distro and purging the cache leave Windows\nCredential Manager untouched, and the tray treats it as authoritative:\n\n```powershell\n# 'tillandsias-vm-uuid' is deliberately PRESERVED -- it anchors the\n# INSTALLATION, not the guest, and the in-VM Vault derives its master key\n# from it. Only the two guest-vault entries go.\n#\n# ORDER 1004-vsh2. `cmdkey \u002Flist:\u003Ctarget>` ECHOES THE TARGET IN ITS HEADER\n# even when no such credential exists, so the obvious predicate\n# `$out -match [regex]::Escape($cred)` is TRUE FOR EVERY TARGET and the\n# verifier below threw on every run. Measured on yolanda 2026-09-04:\n#\n#   \u002Flist:definitely-not-a-real-target-12345  ->  exit 0, 4 lines\n#     \"Currently stored credentials for definitely-not-a-real-target-12345:\"\n#     \"* NONE *\"\n#   \u002Flist:\u003Ca target that exists>              ->  exit 0, 7 lines\n#     \"Currently stored credentials for \u003Ctarget>:\"\n#     \"    Target: \u003Ctarget>\"   \u003C- the record, and the second echo\n#\n# THE EXIT CODE DOES NOT DISCRIMINATE: cmdkey returns 0 for both, so the\n# locale-proof status predicate is not available and was not used. Measured,\n# not assumed.\n#\n# So count the ECHOES OF THE TARGET NAME, which is the one string in that\n# output that Windows does not localize: the header echoes it once; a real\n# record echoes it again on its own `Target:` line. 1 = absent, >=2 = present.\n# Do NOT test for the absence of \"* NONE *\" or match the header text -- both\n# are LOCALIZED, and an English-text predicate trades a bug that fails on\n# every run for one that fails only on some operators' machines, which is\n# strictly worse because it fails where nobody is looking.\nfunction Test-TillandsiasCredPresent([string] $target) {\n    $out = & cmdkey.exe \"\u002Flist:$target\" 2>$null\n    (($out | Where-Object { $_ -match [regex]::Escape($target) }) | Measure-Object).Count -ge 2\n}\n\nforeach ($cred in @('vault-shamir-share-v1', 'vault-root-token-v1')) {\n    if (Test-TillandsiasCredPresent $cred) { & cmdkey.exe \"\u002Fdelete:$cred\" > $null 2>&1 }\n}\n$stillThere = @('vault-shamir-share-v1', 'vault-root-token-v1') |\n    Where-Object { Test-TillandsiasCredPresent $_ }\nif ($stillThere) { throw \"host vault credentials survived the reset: $($stillThere -join ', ')\" }\n```\n\nThis is not hygiene, it is the difference between a valid result and an\ninvalid one. The 2026-08-17 run on v0.4.260817.1 claimed a \"truly cold\" run\nbecause it purged the 34.9 GB `ext4.vhdx` AND the rootfs cache — both true,\nboth irrelevant to this store. The stale share survived, the tray delivered it\ninto the fresh guest unconditionally, and the release looked healthy in the\nsmoke and then broke for the operator forty minutes later on the first GitHub\nlogin (803-49re). A \"cold\" claim without this step is a claim the run cannot\nsupport.\n\n**Use `--terminate`, NOT `wsl --shutdown` (order 802-bajv).** `--shutdown` stops\nEVERY WSL2 distro on the host, while `--unregister` only requires the target\ndistro to be stopped. A Windows host commonly also runs `tillandsias-build` —\nthe lane that builds Linux-target artifacts, kept deliberately separate so the\nsmoke cannot wipe a toolchain mid-cycle — and a global shutdown kills it for no\ntest benefit.\n\n**This step DESTROYS the model cache, and that is not a footnote (order\n806-a4tu).** On Windows the weights live at `\u002Froot\u002F.cache\u002Ftillandsias\u002Fmodels`\nINSIDE the distro's `ext4.vhdx`, so `--unregister` deletes them along with the\ndisk. Measured on yolanda 2026-08-17: ~447 MB of `nomic-embed-text` plus\n`qwen2.5:0.5b` had to be re-pulled after the reset. Every Windows run of this\nsmoke therefore starts cold BY CONSTRUCTION. Do not describe a Windows result as\na warm-cache run, and do not treat warm-vs-cold as a variable on this lane — it\nhas exactly one value. Budget the re-pull into the run, and note that a host on a\nmetered or slow link pays it every time.\n\n---\n\n## 3 — Fresh init from a pristine state\n\n```bash\n[ -n \"${BASH_VERSION:-}\" ] || { echo 'FAIL: run this block under bash — PIPESTATUS is a bash array and zsh expands it empty'; exit 2; }\n_T0=\"$(timing_now_ms)\"\nTILLANDSIAS_SMOKE_LOCK_LOG=target\u002Fsmoke-e2e\u002F00-smoke-lock.log \\\n  scripts\u002Fwith-smoke-lock.sh --name release-smoke-e2e -- \\\n  tillandsias --debug --init 2>&1 | tee target\u002Fsmoke-e2e\u002F03-init.log\nINIT_RC=${PIPESTATUS[0]}\ntiming_emit smoke-init-pristine smoke \"$_T0\" \"${INIT_RC:-1}\" || true; printf 'init_exit=%s\\n' \"$INIT_RC\" | tee target\u002Fsmoke-e2e\u002F03-init-exit.txt\ntest -n \"$INIT_RC\" && test \"$INIT_RC\" -eq 0\n```\n\n**Observe carefully.** This is the highest-signal step — a clean-room `--init`\nrebuilds every image and brings up Vault from nothing. Scan `03-init.log` (and\n`tillandsias --diagnostics` \u002F container logs) for:\n\n- non-zero exit, panics, or `Error:` lines;\n- Vault failing to initialize\u002Funseal (connection-refused loops, HTTP 400\n  \"cipher: message authentication failed\", keychain↔volume share mismatch);\n- image build failures (proxy\u002Fgit\u002Finference\u002Fforge), short-name-mode prompts,\n  registry\u002FTLS errors;\n- the enclave network failing to come up;\n- any container that exits non-zero (e.g. proxy SIGSEGV\u002F139).\n\n**File a finding for every distinct issue** (see §5). If `--init` did not reach\na healthy state, STOP here — do not proceed to Step 4; record that the smoke\nhalted at init and why.\n\n### macOS\n\n**The block above is Linux-only and there is no `tillandsias` CLI on macOS** —\nthe installed bundle ships `tillandsias-tray`. The Host Matrix has always said\nthis lane re-provisions with `--provision` + `--diagnose --json`; the step had\nno macOS block to match, so the lane the matrix promises was unexecutable as\nwritten. Added 2026-08-26, before this lane's first run against a published\nrelease.\n\n> **A 300 s `wait_phase_ready` timeout on macOS is answered FIRST by\n> `\u002Fvar\u002Flog\u002Ftillandsias-provision-marker` inside the guest** (1055-e8ie). Read\n> it with\n> `…\u002Ftillandsias-tray --exec-guest 'cat \u002Fvar\u002Flog\u002Ftillandsias-provision-marker'`.\n> It says in one file whether the cloud-init provisioning script COMPLETED,\n> and if not, the exact line it died on plus `systemctl --failed` and\n> `systemctl status` for the headless units at that moment.\n>\n> WHY THIS IS THE FIRST THING TO READ, not the last: the guest boots fine,\n> networks, reaches a login prompt and installs its binary while failing to\n> provision — because the script is `set -euo pipefail` and cloud-init does\n> NOT surface a user-script failure, so `cloud-init status` still reports\n> `done, errors: []`. Measured 2026-09-05: the script aborted at its\n> `systemctl start` of the headless units, and the readiness-service start on\n> the VERY NEXT LINE never ran, so the guest could not report Ready. Nothing\n> anywhere said so. Four hypotheses were spent before the marker existed;\n> reading it now costs one command.\n\n```bash\n[ -n \"${BASH_VERSION:-}\" ] || { echo 'FAIL: run this block under bash — PIPESTATUS is a bash array and zsh expands it empty'; exit 2; }\nAPP=\"\u002FApplications\u002FTillandsias.app\u002FContents\u002FMacOS\u002Ftillandsias-tray\"\nIMG=\"$HOME\u002FLibrary\u002FApplication Support\u002Ftillandsias\u002Frootfs.img\"\n\n# Marker to prove the image below was built AFTER the destruction, not\n# inherited from it. `test -nt` is POSIX and needs no date arithmetic.\ntouch target\u002Fsmoke-e2e\u002F03-destruction-marker\n\n\"$APP\" --provision 2>&1 | tee target\u002Fsmoke-e2e\u002F03-provision.log\nPROVISION_RC=${PIPESTATUS[0]}\nprintf 'provision_exit=%s\\n' \"$PROVISION_RC\" | tee target\u002Fsmoke-e2e\u002F03-provision-exit.txt\ntest -n \"$PROVISION_RC\" && test \"$PROVISION_RC\" -eq 0\n\n# A fresh image, not a survivor. An exit code cannot tell these apart.\ntest -f \"$IMG\"\ntest \"$IMG\" -nt target\u002Fsmoke-e2e\u002F03-destruction-marker\n\n# LAST — after every mutating step above. If anything below this line mutates\n# the host, this report is stale and the run is unfinished (the 2026-08-10\n# incident: 4\u002F4 PASS on a health check taken before one more mutating step\n# wedged the host for 25 minutes).\n_T0=\"$(timing_now_ms)\"\n\"$APP\" --diagnose --json 2>&1 | tee target\u002Fsmoke-e2e\u002F03-diagnose.json\n_rc=${PIPESTATUS[0]}\ntiming_emit smoke-health-check smoke \"$_T0\" \"${_rc:-1}\" || true\ntest -n \"$_rc\" && test \"$_rc\" -eq 0\n\njq -e '.provisioned == true'    target\u002Fsmoke-e2e\u002F03-diagnose.json\njq -e '.rootfs_present == true' target\u002Fsmoke-e2e\u002F03-diagnose.json\n# The tray's OWN version, a second surface for the step-1 assertion. Truthful\n# only since 635-bhkb; it read the frozen crate version \"0.1.0\" before.\njq -e --arg v \"${SMOKE_TAG#v}\" '.version == $v' target\u002Fsmoke-e2e\u002F03-diagnose.json\n```\n\n> **`release_tag` is NOT the release version — it is the guest image tag**\n> (`fedora-44`). Asserting it against `$SMOKE_TAG` fails for a reason that has\n> nothing to do with the release, and reads like a real defect. Measured\n> 2026-08-26 while writing this block.\n>\n> **`guest_version` and `guest_binary_staged_matches_bundle` are `null` under a\n> plain `--diagnose`** — they need a live VM, i.e. `--with-metrics`, which\n> BOOTS. Do not assert them here; a `null == null` check would pass forever\n> without ever testing anything, which is the class this runbook has already\n> been bitten by twice. Exercise the guest\u002Ftray skew check under\n> `--with-metrics` if you want it, and note that it is a mutating step, so the\n> `--diagnose` above must then be re-run after it.\n\n### Windows\n\n> **This block is not runnable on its own.** It assumes §1 installed the tray\n> and §2 unregistered the distro. Run alone it fails twice and both failures\n> lie: `Get-Command tillandsias-tray.exe -ErrorAction Stop` throws on line 2 on\n> a host where §1 never installed it, and the destruction-marker assertion\n> reports \"a survivor, not a fresh provision\" when the truth is that nothing\n> destroyed it. The runnable unit is §1 + §2 + §3, never §1 + §3 (order\n> 1004-vsh2 — an instruction to run \"§1 and §3\" was issued and measured\n> unrunnable on yolanda before it was executed).\n\n**Neither block above runs on Windows and there is no `tillandsias` CLI there\neither** — the installed surface is `tillandsias-tray.exe`, and its\nprovisioning flag is `--provision-once`, NOT the macOS `--provision` (the two\nare not interchangeable: `tillandsias-tray.exe --help`). The Host Matrix has\npromised this lane since the Windows installer shipped; no block matched it,\nso every Windows run improvised and no two runs were comparable. Added\n2026-09-04 (order 1004-fue3) from esme-windows's improvised v56.9.2.1 run on\nesmeraldinha (cold `--provision-once` exit 0 in 117 s, warm 18 s, wire Ready).\n\n```powershell\n$ErrorActionPreference = 'Stop'\n# Same resolution as §1 — the installer does not add its directory to PATH\n# (measured 2026-09-04, order 1004-vsh2), so `Get-Command` alone throws here.\n$tray = (Get-Command tillandsias-tray.exe -ErrorAction SilentlyContinue |\n    Select-Object -First 1 -ExpandProperty Source)\nif (-not $tray) { $tray = \"$env:LOCALAPPDATA\\Programs\\Tillandsias\\tillandsias-tray.exe\" }\nif (-not (Test-Path $tray)) { throw \"tray not found on PATH or at $tray (did §1 run?)\" }\n\n# Marker to prove the distro below was registered AFTER §2's unregister, not\n# inherited from it. An exit code cannot tell these apart.\nNew-Item -ItemType File -Force target\\smoke-e2e\\03-destruction-marker | Out-Null\n\n# Cold provision from pristine. `--provision-once` provisions and EXITS; it is\n# the headless form the tray's own --help prescribes for scripted use.\n& $tray --provision-once *>&1 | Tee-Object target\\smoke-e2e\\03-provision.log\n$provisionExit = $LASTEXITCODE\n\"provision_exit=$provisionExit\" | Tee-Object target\\smoke-e2e\\03-provision-exit.txt\nif ($provisionExit -ne 0) { throw \"provision-once failed (exit $provisionExit)\" }\n\n# A fresh distro, not a survivor: it must exist, and its rootfs must postdate\n# the marker (WSL2 keeps each distro's ext4.vhdx under LOCALAPPDATA).\n$distros = (wsl.exe -l -q) -replace \"`0\", '' | ForEach-Object { $_.Trim() }\nif ($distros -notcontains 'tillandsias') { throw \"distro 'tillandsias' not registered after provision\" }\n#\n# ORDER 1295-b4i8: select the disk by the distro's REGISTERED path, never by a\n# substring of a directory name. The old selector (every ext4.vhdx under\n# LOCALAPPDATA whose path contains 'tillandsias', newest first) also matches\n# the BUILDER distro at %LOCALAPPDATA%\\tillandsias\\wsl-build, and a running\n# builder writes its vhdx constantly, so the freshness check below could pass\n# on the wrong disk.\n$vhdx = $null\n$lxss = Get-ChildItem 'HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Lxss' -ErrorAction SilentlyContinue |\n  ForEach-Object { Get-ItemProperty $_.PSPath } | Where-Object { $_.DistributionName -eq 'tillandsias' }\nif ($lxss) {\n  $vhdxPath = Join-Path ($lxss.BasePath -replace '^\\\\\\\\\\?\\\\', '') 'ext4.vhdx'\n  if (Test-Path -LiteralPath $vhdxPath) { $vhdx = Get-Item -LiteralPath $vhdxPath }\n}\nif (-not $vhdx) { throw \"no ext4.vhdx at the registered BasePath of distro 'tillandsias'\" }\nif ($vhdx.FullName -match '\\\\wsl-build\\\\') { throw \"the tillandsias distro resolves to the BUILDER's disk $($vhdx.FullName)\" }\nif ($vhdx.LastWriteTime -lt (Get-Item target\\smoke-e2e\\03-destruction-marker).LastWriteTime) {\n  throw \"rootfs $($vhdx.FullName) predates the destruction marker — a survivor, not a fresh provision\"\n}\n\n# ORDER 1295-b4i8: the builder distro SURVIVED §1+§2+§3 untouched. Compare\n# with the snapshot §2 took before it deleted anything. Size AND mtime: a\n# deleted-and-recreated disk has a new mtime even at the same size.\nif (Test-Path target\\smoke-e2e\\02-builder-vhdx-before.txt) {\n  $before = Get-Content target\\smoke-e2e\\02-builder-vhdx-before.txt -Raw\n  $b = Get-Item -LiteralPath \"$env:LOCALAPPDATA\\tillandsias\\wsl-build\\ext4.vhdx\" -ErrorAction SilentlyContinue\n  $after = if ($b) { \"$($b.Length) $($b.LastWriteTimeUtc.Ticks)\" } else { 'absent' }\n  \"$after\" | Set-Content target\\smoke-e2e\\03-builder-vhdx-after.txt\n  if ($after -eq 'absent') { throw \"the smoke DELETED the builder distro's disk (was: $($before.Trim()))\" }\n  # A RUNNING builder writes its own disk, so byte-identity is only asserted\n  # when it is stopped. Stopped is the case the old purge destroyed.\n  $builderRunning = ((wsl.exe -l -q --running) -replace \"`0\", '' | ForEach-Object { $_.Trim() }) -contains 'tillandsias-build'\n  if (-not $builderRunning -and $after -ne $before.Trim()) {\n    throw \"builder vhdx changed while the builder was STOPPED: before=$($before.Trim()) after=$after\"\n  }\n}\n\n# Wire state at provision exit, POLLED to Ready: `--status-once --json` is\n# read-only, and Ready can lag the provision exit by a few seconds; it can\n# also LAPSE later (see the note below), so the poll starts immediately and\n# gives up loudly rather than sleeping first.\n$deadline = (Get-Date).AddSeconds(60); $status = $null; $statusExit = 1\ndo {\n  & $tray --status-once --json 2>&1 | Tee-Object target\\smoke-e2e\\03-status.json | Out-Null\n  $statusExit = $LASTEXITCODE\n  if ($statusExit -eq 0) { $status = Get-Content target\\smoke-e2e\\03-status.json -Raw | ConvertFrom-Json }\n  if ($status -and $status.phase -eq 'Ready') { break }\n  Start-Sleep -Seconds 5\n} while ((Get-Date) -lt $deadline)\n\"status_exit=$statusExit phase=$($status.phase) podman_ready=$($status.podman_ready)\" | Tee-Object target\\smoke-e2e\\03-status-summary.txt\nif ($statusExit -ne 0) { throw \"status-once failed (exit $statusExit)\" }\nif ($status.phase -ne 'Ready') { throw \"phase is '$($status.phase)' after 60 s, expected Ready\" }\nif (-not $status.podman_ready) { throw \"podman_ready is false at Ready\" }\n\n# LAST — after every mutating step above. If anything below this line mutates\n# the host, this report is stale and the run is unfinished (the 2026-08-10\n# incident, same rule as the macOS block).\n& $tray --diagnose --json 2>&1 | Tee-Object target\\smoke-e2e\\03-diagnose.json\n$diagnoseExit = $LASTEXITCODE\n\"diagnose_exit=$diagnoseExit\" | Tee-Object target\\smoke-e2e\\03-diagnose-exit.txt\n# DO NOT assert `$diagnoseExit -eq 0`, and the reason is the note above.\n#\n# MEASURED 2026-09-04 on yolanda (order 1004-vsh2), inline in ONE script with\n# nothing interposed: --status-once read Ready \u002F podman_ready=true, and\n# --diagnose seconds later exited 2 with distro_running=false and\n# wire.reachable=false. The tray log shows the wire closing ~15 s after\n# \"provision-once: VM Ready\". Nothing holds the guest open, so by the time the\n# LAST step runs the wire is legitimately down and diagnose reports that\n# truthfully. Requiring exit 0 here contradicts this block's own\n# \"Ready is not durable after --provision-once\" note, one screen up.\n#\n# So assert what diagnose is FOR at this point in the lane — a well-formed\n# report carrying this tray's identity — and record the exit code as data.\n# A missing or unparseable report is still a hard failure.\nif (-not (Test-Path target\\smoke-e2e\\03-diagnose.json)) { throw \"diagnose wrote no report\" }\n$diag = Get-Content target\\smoke-e2e\\03-diagnose.json -Raw | ConvertFrom-Json\nif (-not $diag) { throw \"diagnose report is not valid JSON (exit $diagnoseExit)\" }\nif ($diag.PSObject.Properties.Name -contains 'version') {\n  if ($diag.version -ne $SmokeTag.TrimStart('v')) { throw \"tray version '$($diag.version)' != release $SmokeTag\" }\n} else {\n  \"diagnose --json carries no 'version' field on this build — the release-tag assertion for the tray is UNMET, record it as a finding\" |\n    Tee-Object -Append target\\smoke-e2e\\03-diagnose-notes.txt\n}\n```\n\n> **Ready is not durable after `--provision-once`** (esme, finding\n> `smoke-finding\u002Fwindows-ready-not-durable-after-provision-once`, order\n> 1004-* series): nothing holds the guest open once the headless provision\n> exits, so a `--status-once` taken a minute later can read exit 1 while the\n> block above, taken immediately, reads Ready. Both are true. This block\n> asserts the state AT provision exit, which is what the lane promises; do not\n> re-run `--status-once` later and file its exit 1 as a provision failure.\n>\n> **Every assertion here reads `$LASTEXITCODE` from a native call, never\n> `$?` from a pipeline** — `$?` after `... | Tee-Object` is Tee-Object's\n> status, which is how the §1 Windows install asserted nothing for a year.\n\n---\n\n## 3b — Stop the substrate and assert every container exits cleanly\n\n**Run this after §3, before §4.** It is where order `1134-u934` was found and\nit costs one stop.\n\n**Why it is its own step rather than a line in §3.** §3 asserts that a\npristine `--init` reaches a healthy state, and it did — the run that filed\n`1134-u934` was §1\u002F§2\u002F§3 all PASS with zero occurrences of every failure class\n§3 enumerates. The defect was in SHUTDOWN, so a lane that stops at \"init was\nclean\" cannot see it in principle, however carefully it reads `03-init.log`.\nIt was found only by looking at what the tray's own `Graceful shutdown\ncompleted` line actually produced: `tillandsias-vault  Exited (137)` — killed\nafter stalling the full 30 s grace — next to `tillandsias-proxy  Exited (0)`\nin the same shutdown.\n\n**Assert BOTH halves, per container.** Elapsed alone passes a container that\nexits fast for a bad reason; exit code alone passes one that burns the whole\ngrace and is then reported 0. 137 specifically means the grace expired and the\ncontainer was SIGKILLed.\n\n```bash\n# Linux. Record the grace each container declares — they differ — then stop\n# them all and read what podman recorded, container by container.\npodman ps --format '{{.Names}}' | tee target\u002Fsmoke-e2e\u002F3b-running.txt\nfor c in $(cat target\u002Fsmoke-e2e\u002F3b-running.txt); do\n  grace=\"$(podman inspect \"$c\" --format '{{.Config.StopTimeout}}')\"\n  t0=\"$(date +%s)\"\n  podman stop -t \"$grace\" \"$c\" >\u002Fdev\u002Fnull 2>&1\n  t1=\"$(date +%s)\"\n  printf '%s elapsed=%ss grace=%ss exit=%s oom=%s\\n' \"$c\" \"$((t1 - t0))\" \"$grace\" \\\n    \"$(podman inspect \"$c\" --format '{{.State.ExitCode}}')\" \\\n    \"$(podman inspect \"$c\" --format '{{.State.OOMKilled}}')\"\ndone | tee target\u002Fsmoke-e2e\u002F3b-shutdown.txt\n\n# The verdict. A non-zero exit OR an elapsed at\u002Fabove the grace is a finding\n# per container, not a run-level FAIL — the enclave is already destroyed and\n# rebuilt by this point, so §4 may still proceed on a clean §3.\nawk '{\n  split($2, e, \"=\"); split($3, g, \"=\"); split($4, x, \"=\")\n  if (x[2] != 0 || e[2] + 0 >= g[2] + 0) { print \"FINDING: \" $0; bad++ }\n} END { printf \"3b: %d container(s) did not stop cleanly\\n\", bad + 0 }' \\\n  target\u002Fsmoke-e2e\u002F3b-shutdown.txt | tee target\u002Fsmoke-e2e\u002F3b-verdict.txt\n```\n\nA container that fails here is a **`plan\u002Fissues` work packet per §5**, and the\npacket must name the process tree, not just the exit code — read it from the\nrunning container BEFORE the stop:\n\n```bash\npodman exec \u003Ccontainer> sh -c 'for p in \u002Fproc\u002F[0-9]*; do echo \"$(basename $p) $(cat $p\u002Fcomm 2>\u002Fdev\u002Fnull)\"; done'\n```\n\n`1134-u934` is why. Its entrypoint was a PID-1 shell that trapped nothing, and\nthe pid it held was `tee`'s rather than the server's, because `$!` after a\nbackgrounded PIPELINE is the LAST stage. The obvious one-line trap forwarding\nto that pid signals `tee`, leaves the 30 s and the 137 exactly as they are, and\n**looks correct**. The tree (`1 bash \u002F 10 vault \u002F 11 tee`) is what separates\nthe two, and it is not readable from the script's text.\n\n`scripts\u002Ftest-vault-shutdown-forwards-sigterm.sh` is the standing single-\ncontainer form of this step for vault, and exits 3 (`could-not-run`) rather\nthan 0 on a host with no provisioned enclave.\n\n> **macOS and Windows.** The substrate is a Virtualization.framework VM and a\n> WSL2 distro, not host podman, so the loop above runs INSIDE the guest or not\n> at all. Neither lane asserts guest-container shutdown today; that is a\n> stated gap, not a silent pass — record it rather than reporting 3b clean.\n\n## 4 — Forge continuous-enhancement run (only if Step 3 was clean)\n\n```bash\n[ -n \"${BASH_VERSION:-}\" ] || { echo 'FAIL: run this block under bash — PIPESTATUS is a bash array and zsh expands it empty'; exit 2; }\n_T0=\"$(timing_now_ms)\"\ntiming_begin smoke-forge-lane smoke\n# 1275-ngrc: the agent-death watch runs BESIDE the lane (see §4a, third state).\nrm -f target\u002Fsmoke-e2e\u002F04-agent-watch.txt\nscripts\u002Fsmoke-agent-watch.sh watch --out target\u002Fsmoke-e2e --grace 300 > target\u002Fsmoke-e2e\u002F04-agent-watch.log 2>&1 &\n_WATCH_PID=$!\n# 1941-smkp: ONE short agent turn, never the \u002Fmeta-orchestration loop. The\n# forge's model is a hosted free tier every fleet host shares; a full loop is\n# 100+ requests per smoke, and on 2026-11-01 that ended in a 429 with\n# Retry-After 78443. The prompt spells the token out so the prompt text itself\n# can never satisfy the grep below.\nSMOKE_PROMPT='Smoke check, one turn only. Run `bash scripts\u002Fcheck-credential-channel.sh` in the checkout and show its last line. Then reply with the word SMOKE-AGENT, a hyphen, and the word OK, all on one line with no spaces. Load no skill and do nothing else.'\nTILLANDSIAS_SMOKE_LOCK_LOG=target\u002Fsmoke-e2e\u002F00-smoke-lock.log \\\n  scripts\u002Fwith-smoke-lock.sh --name release-smoke-e2e -- \\\n  env TILLANDSIAS_NO_TRAY=1 tillandsias --cloud 8007342\u002Ftillandsias --opencode --prompt \"$SMOKE_PROMPT\" 2>&1 \\\n  | tee target\u002Fsmoke-e2e\u002F04-opencode.log\nLANE_RC=${PIPESTATUS[0]}; printf 'opencode_exit=%s\\n' \"$LANE_RC\" | tee target\u002Fsmoke-e2e\u002F04-opencode-exit.txt\n# The agent answered and called a tool: the token, not the exit code.\ngrep -q 'SMOKE-AGENT-OK' target\u002Fsmoke-e2e\u002F04-opencode.log \\\n  && echo 'agent_turn=answered' || echo 'agent_turn=NO-TOKEN (finding)'\nkill \"$_WATCH_PID\" 2>\u002Fdev\u002Fnull; wait \"$_WATCH_PID\" 2>\u002Fdev\u002Fnull\n# The watch's verdict, when it issued one, IS the §4 verdict: the agent died and\n# the watch stopped the forge so the lane could return.\nif [ -f target\u002Fsmoke-e2e\u002F04-agent-watch.txt ]; then\n  printf 'lane_verdict=agent-dead-process-idling\\n' | tee -a target\u002Fsmoke-e2e\u002F04-opencode-exit.txt\n  cat target\u002Fsmoke-e2e\u002F04-agent-watch.txt\nfi\ntiming_commit smoke-forge-lane smoke \"$_T0\" \"${LANE_RC:-1}\"\n```\n\n> **THIS IS THE STEP MOST LIKELY TO LOSE ITS SUPERVISOR, so it is the one that\n> stamps** (order 1026-ps4n). `timing_begin` writes the start to disk before\n> the lane runs; `timing_commit` emits the real record and clears the stamp. If\n> the shell running this block is killed, the stamp survives and the NEXT run's\n> `timing_reap` (§0) emits `smoke-forge-lane-supervisor-lost` instead of\n> nothing. The lost record is reported under a DIFFERENT step name on purpose:\n> the recurrence rung groups by step, so a lower-bound duration from a killed\n> run can never be averaged into real `smoke-forge-lane` timings.\n>\n> **RUN IT DETACHED ON A FLOOR HOST.** A detached run survived on pirria where\n> a plain backgrounded run did not, because the kill takes the process group.\n> Detaching does not make the host less short of memory — it stops the\n> supervisor being collateral.\n>\n> **THE FORM DIFFERS BY PLATFORM AND macOS HAS NO `setsid`** (macneo,\n> 2026-09-15): `setsid nohup \u003Cscript-file> \u003C \u002Fdev\u002Fnull > log 2>&1 &` on Linux,\n> `nohup \u003Cscript-file> \u003C \u002Fdev\u002Fnull > log 2>&1 & disown` on macOS. This runbook\n> named only the Linux form, which fails outright on both Macs — and this is\n> the lane most likely to be run on one, since a curl-install smoke is floor\n> work. A script FILE and a terminal `rc=` marker are required on both.\n\n**Windows: the tray must be running, and the lane runs as a `systemd-run`\nunit inside the guest** (yolanda, v56.10.15.1, 2026-10-15). There is no host\nCLI forge lane on Windows; the lane is `tillandsias-headless --cloud \u003Cowner\u002Frepo>\n--opencode` inside the `tillandsias` distro. Two attempts were lost before the\nform below worked, and neither was a product defect:\n\n- `setsid nohup \u003Cscript> &` piped through `wsl.exe -d tillandsias -u root --\n  bash -s` dies when that wsl.exe session returns, before writing a byte.\n- A `systemd-run` unit is stopped about 20 s in when nothing holds the guest\n  open. §2 stops the tray and `--provision-once` exits, so after §3 the guest\n  idles out with the lane in it.\n\nRestart the tray first, then start the lane as a transient unit and watch it:\n\n```powershell\nif (-not (Get-Process tillandsias-tray -ErrorAction SilentlyContinue)) {\n  Start-Process \"$env:LOCALAPPDATA\\Programs\\Tillandsias\\tillandsias-tray.exe\"\n}\n# \u002Froot\u002Fsmoke\u002Flane.sh: runs the lane > \u002Froot\u002Fsmoke\u002Flane.log 2>&1, then appends rc=$?\nwsl.exe -d tillandsias -u root -- systemd-run --unit=smoke-lane --collect \u002Froot\u002Fsmoke\u002Flane.sh\nwsl.exe -d tillandsias -u root -- systemctl is-active smoke-lane   # poll until inactive\n```\n\nWrite the lane script into the guest by piping a script FILE on stdin, never\nas a `bash -c` string. The unit also survived 4% free host memory, because the\nharness's memory reaper only stops host-side shells. Record host free memory\nat the start and sample it during the lane.\n\n### 4a — What a killed supervisor looks like, and what it is not\n\n**Containers alive, wrapper gone.** Measured on pirria 2026-09-04: the agent\nharness reported \"system is running low on memory\" and killed the shell running\n§4; `journalctl` showed **no kernel oom-kill**; all six enclave containers\nincluding inference were **still up and healthy 56 minutes later**. Only the\nsupervising bash died. The same lane had completed in 71m30s that morning on\nthe same host, so the condition is **marginal, not deterministic** — it fails\nintermittently, which is worse than failing reliably, because the floor's\nlargest measurement is the one least likely to be captured.\n\nRead that state correctly: **the lane did not fail.** A reader who sees the\nwrapper gone and concludes the release is broken is reading a host-resource\nevent as a product defect. The discriminating checks, in order:\n\n```bash\npodman ps --format '{{.Names}} {{.Status}}'   # lane containers still Up? -> the lane lives\njournalctl --since '1 hour ago' | grep -iE 'oom-kill|Killed process'   # empty -> not the kernel\n```\nContainers up **and** no kernel oom-kill means the supervisor was killed by the\nagent harness, not the product and not the OOM killer. The run is unfinished,\nnot red.\n\n**THREE STATES, NOT TWO (1275-ngrc).** The checks above tell a killed\nsupervisor from a live lane. They CANNOT tell a working agent from a dead one\nwhose process idles: measured on pirria 2026-09-19, the agent died at\n17:19:38Z (`AI_RetryError: Failed after 3 attempts. Last error: Rate limit\nexceeded.`), opencode idled instead of exiting, and the lane ran 2h19m more\nwith all six containers Up, no oom-kill, the supervisor alive, and even a\n60-second CPU-delta probe reading ALIVE (an idle loop plus an hourly\n`cleanup prune=7.days` timer burns about a second a minute).\n\n| state | containers | supervisor | agent log (`04-opencode-agent.log`) |\n|---|---|---|---|\n| supervisor killed | Up | gone | — (read the lane's own evidence) |\n| agent working | Up | alive | lines keep arriving |\n| **agent dead, process idling** | Up | alive | last non-housekeeping line is a terminal ERROR, nothing after it |\n\nThe third state is what `scripts\u002Fsmoke-agent-watch.sh` detects, from the\nAGENT's log and never from the clock: a terminal error (retries exhausted, a\nbad key, no such model) that stays the agent's last line for 300s. It then\ncopies the log out of the forge to `target\u002Fsmoke-e2e\u002F04-opencode-agent.log`\n(the path inside the forge is `\u002Fhome\u002Fforge\u002F.local\u002Fshare\u002Fopencode\u002Flog\u002F`, which\nthis runbook never named before), writes `04-agent-watch.txt` beginning\n`refused:smoke-forge-lane:agent-dead-process-idling` with the error line, and\nstops the forge container so the lane returns in minutes instead of never.\n**Do not replace this with a timeout.** A budget tuned to the ~70-minute\nworking figure kills long healthy lanes and still waits 70 minutes to notice a\ndeath at minute 2; any agent activity after an error resets the watch, which\nis the negative control (`scripts\u002Ftest-smoke-agent-watch.sh` arm 4).\nTo classify a lane by hand: `scripts\u002Fsmoke-agent-watch.sh classify\ntarget\u002Fsmoke-e2e\u002F04-opencode-agent.log`.\nLIMIT, by name: the watch finds the forge by `podman ps` on THIS host, so on\nmacOS and Windows (forge inside the VM) it finds nothing and the lane behaves\nas before; the log path above is still where to look.\n\n**The memory floor this step needs.** The forge lane brings up six containers\n(vault, proxy, router, git, inference, forge). Measured on **pirria, 15 GiB\ntotal, 4 cores**: the lane itself completes, and it is the *supervisor* that\ngets sacrificed under pressure — so 15 GiB is **at** the boundary, not below\nit. No host with less has been measured, and no host above 16 GiB has reported\nthis, so the honest statement is a boundary observation and not a threshold:\n**at 15 GiB the wrapper is collateral; the number at which it stops being is\nunmeasured.** Do not invent one. If a host with 8 or 32 GiB runs this step,\nrecord which side of the line it lands on and the floor gets a real threshold\ninstead of a single point.\n\n> The guard and the `LANE_RC` capture arrived with the timing wrapper\n> (1013-qv7c). This block had neither: it piped to `tee` and recorded no status\n> at all, so a forge lane that failed to launch left the same evidence as one\n> that completed. Emitting a duration without an exit code would have recorded\n> *how long the failure took* and called it a measurement, so the capture is\n> part of the record, not scope creep — the 727-kmks assertion shape, arriving\n> at the one step that never had it.\n\n### 4a-cold — `opencode_exit=0` IS NOT THE PASS CONDITION ON A POST-RESET HOST\n\n**Read this before you read `LANE_RC`.** Order 1190-swen; coordinator ruling\n2026-09-14, option (a).\n\n§2 reset the substrate, so Vault is **cold** and holds no GitHub token. The\nin-forge lane therefore reaches the Credential Channel Guard and **hard-stops\nthere, deterministically, before any committable work**. That is not a\ndegraded run. On a post-reset host it is the *only* correct outcome, and it is\nwhat §4 exercises: enclave bring-up, and the guard. Nothing past them.\n\nThe failure this replaces is a reader — human or orchestrator — seeing\n`opencode_exit=0` and concluding the forge did a cycle's worth of work. It did\nnot. It could not have.\n\n**ASSERT THE GUARD LINE, NEVER THE EXIT CODE:**\n\n```bash\n# PASS on a cold (post-§2-reset) host: the lane came up and stopped AT the guard.\nif grep -qE 'blocked:upstream-(no-credential|auth-unpublished)' target\u002Fsmoke-e2e\u002F04-opencode.log; then\n    echo \"cold-host PASS: lane reached the credential guard and stopped there\"\nelse\n    echo \"FINDING: no credential-guard stop in the lane log on a post-reset host.\"\n    echo \"  A cold Vault holds no token, so the guard MUST have refused.\"\n    echo \"  Either the guard was skipped, or this room was not clean.\"\nfi | tee target\u002Fsmoke-e2e\u002F04a-cold-host-outcome.txt\n\n# NEGATIVE CONTROL — exit 0 WITHOUT the guard line FAILS the assertion.\n# This is the whole point: the two are independent, and only the second is evidence.\ngrep -qE 'blocked:upstream-(no-credential|auth-unpublished)' target\u002Fsmoke-e2e\u002F04-opencode.log   || echo \"negative control fired: opencode_exit=${LANE_RC} is NOT a pass on its own\"\n```\n\nThen confirm the lane left nothing behind, which is the other half of \"stopped\nbefore committable work\":\n\n```bash\n{\n  echo \"git_status_empty=$([ -z \"$(git status --porcelain)\" ] && echo yes || echo no)\"\n  echo \"head_matches_origin=$([ \"$(git rev-parse HEAD)\" = \"$(git rev-parse origin\u002Flinux-next)\" ] && echo yes || echo no)\"\n  # ORDER 1190-swen, CORRECTED 2026-09-20. This greped `^MO-FULL: `\n  # GENERICALLY and was WRONG: a guard-stopped cycle is SUPPOSED to emit\n  # `MO-FULL: BLOCKED`. The meta-orchestration skill sanctions it explicitly\n  # (`MO_FULL_DISPOSITION=BLOCKED scripts\u002Fmo-full-attest.sh self`, and \"BLOCKED\n  # is exempt: a cycle saying it did not finish must still be able to say so\").\n  # MEASURED on pirria 2026-09-20: a lane that behaved exactly as designed —\n  # enclave up, `blocked:upstream-no-credential`, nothing claimed or pushed —\n  # emitted `MO-FULL: BLOCKED 7e33445f9 linux-next 7e33445f9` and this check\n  # flagged it, which would send the next reader to investigate a correct run.\n  # What must be absent is a COMPLETE marker: that is the claim a guard-stopped\n  # cycle has no right to make.\n  echo \"mo_full_complete_present=$(grep -qE '^MO-FULL: COMPLETE ' target\u002Fsmoke-e2e\u002F04-opencode.log && echo yes || echo no)\"\n  echo \"mo_full_blocked_present=$(grep -qE '^MO-FULL: BLOCKED ' target\u002Fsmoke-e2e\u002F04-opencode.log && echo yes || echo no)\"\n} | tee target\u002Fsmoke-e2e\u002F04a-cold-host-residue.txt\n```\n\nExpected on a cold host: `yes`, `yes`, **`no`** for COMPLETE, and either value\nfor BLOCKED. The absent COMPLETE marker is correct and loud — a lane that\nstopped at the guard has not completed its exit contract and must not claim it\ndid. A `BLOCKED` marker is NOT a finding: it is the cycle correctly saying it\ndid not finish, and a run that emits one has behaved better than a run that\nemits nothing, because the disposition is then on the record rather than\ninferred from silence.\n\nMEASURED on pirria 2026-09-14 (`04-opencode.log:848-862`): the guard answered\n`blocked:upstream-no-credential` (exit 1); the mirror published\n`refs\u002Ftillandsias\u002Fupstream-auth\u002Fno-credential`, fresh; the in-forge agent\nclaimed nothing, drained nothing, filed nothing, committed nothing, left\n`git status` empty and `HEAD == origin\u002Flinux-next`, and emitted no `MO-FULL:`\nmarker — correctly refusing to commit from a container about to be destroyed.\nThe HOST could push at that same moment\n(`00-credential-channel.txt` = `ok:gh-keyring-push-verified`). **The asymmetry\nis the design, not a defect**, and the in-forge handling is not what needed\nfixing — the runbook's pass condition was.\n\n**Option (b) — issue a scoped token after §3 — was DECLINED** by the\ncoordinator, and the reason generalises: it would test a different machine than\nthe one this smoke exists to prove. **A clean room that holds a credential is\nnot a clean room.**\n\nThis launches the full enclave + the OpenCode agent inside the forge, which runs\n[[forge-continuous-enhancement]] against the `tillandsias` checkout. Two streams\nof findings come out of this step:\n\n- **Forge-internal findings** — issues the in-forge agent surfaces while doing\n  continuous-enhancement work (build warnings, slow\u002Ffragile Containerfile steps,\n  failed `dnf` migrations, telemetry gaps). The forge agent should itself file\n  these as plan\u002Fissues; if it cannot push from inside the enclave, capture its\n  reported findings from `04-opencode.log` and file them on its behalf.\n- **Harness findings** — issues YOU (the agent running this skill) observe about\n  the run itself: the agent failing to launch, the prompt not being honored,\n  remote-projects not listing, git-mirror push needing interactive auth, the\n  maintenance\u002Fagent terminal stealing focus, vsock\u002Fcontrol-wire version skew\n  (e.g. `wire_version mismatch: server=N, sidecar=M`), etc.\n\nFile every distinct issue from both streams (see §5).\n\n### 4b — First-launch egress assertion (order 298 regression)\n\nWhile Step 4's forge lane is up (right after the agent terminal appears, or as\nsoon as `04-opencode.log` shows the lane container starting), assert from the\nHOST that the shared proxy survived launch — v0.3.260711.8 tore down\n`tillandsias-proxy` during first-launch bring-up, so every pristine install got\na forge whose baked proxy env resolved to nothing (`Could not resolve proxy:\nproxy`), and the fail-soft harness installer then shipped zero harnesses:\n\n```bash\npodman ps --format '{{.Names}}' | tee target\u002Fsmoke-e2e\u002F04b-containers.txt\ngrep -q '^tillandsias-proxy$' target\u002Fsmoke-e2e\u002F04b-containers.txt \\\n  && echo \"egress assertion: proxy alive alongside lane\" \\\n  || echo \"FINDING: tillandsias-proxy ABSENT while a lane container runs (order 298 regression)\"\n```\n\nIf the proxy is absent, also check `04-opencode.log` for the unconditional\nteardown trace (`no active lane containers; cleaning project + shared stack`)\nto identify the actor, and file the finding with that line as evidence.\n\n**The trace alone is NOT the finding.** A healthy run prints that same line\nWITH a `keeping application-lifetime: tillandsias-vault, tillandsias-proxy,\ntillandsias-router, tillandsias-nix-cache` clause — that is the order-298 fix\nworking, not regressing (pirria, v56.9.2.1 floor smoke, 2026-09-04: the line\nwas present, the proxy was alive, and a reader grepping the string alone would\nhave filed a false regression). The assertion is proxy LIVENESS while the lane\nis up, taken by a concurrent watcher, never a grep for the trace. Take it while\nthe lane is up, not after: lane-scoped containers are torn down on exit by\ndesign, and only the application-lifetime set must survive.\n\n### 4c — Final health check (Linux)\n\n**LAST — after every mutating step above**, the same rule the macOS and Windows\nlanes already carry (the 2026-08-10 incident: 4\u002F4 PASS on a health check taken\nbefore one more mutating step wedged the host for 25 minutes).\n\n```bash\n[ -n \"${BASH_VERSION:-}\" ] || { echo 'FAIL: run this block under bash — PIPESTATUS is a bash array and zsh expands it empty'; exit 2; }\n_T0=\"$(timing_now_ms)\"\n{\n  echo \"=== containers ===\"\n  podman ps --format '{{.Names}}\\t{{.Status}}'\n  echo \"=== vault health ===\"\n  podman exec tillandsias-vault sh -c \\\n    'curl -s --cacert \u002Frun\u002Fsecrets\u002Ftillandsias-vault-tls-ca https:\u002F\u002F127.0.0.1:8200\u002Fv1\u002Fsys\u002Fhealth?standbyok=true'\n  echo\n  echo \"=== version ===\"\n  tillandsias --version\n} 2>&1 | tee target\u002Fsmoke-e2e\u002F05-health.log\n_rc=${PIPESTATUS[0]}\ntiming_emit smoke-health-check smoke \"$_T0\" \"${_rc:-1}\" || true\ntest -n \"$_rc\" && test \"$_rc\" -eq 0\ngrep -q '\"sealed\":false' target\u002Fsmoke-e2e\u002F05-health.log\ngrep -q '^tillandsias-proxy' target\u002Fsmoke-e2e\u002F05-health.log\n```\n\nExpect the application-lifetime set (`tillandsias-vault`, `tillandsias-proxy`,\n`tillandsias-router`) up and healthy, and the lane-scoped ones\n(`tillandsias-inference`, `tillandsias-git-*`, the forge) gone — §4b's teardown\nis by design, so their ABSENCE here is the pass, not a finding.\n\n> **There was no Linux health-check block until 1013-qv7c**, though the Host\n> Matrix promises the step and the macOS\u002FWindows lanes both implement it. The\n> gap is not cosmetic: `tillandsias --diagnostics` reads like the command to\n> reach for and is NOT one — it is a MODIFIER (\"stream real-time logs from all\n> enclave containers (implies `--debug`)\"), so bare, with no subcommand, it\n> falls through to the default tray launch and starts a cloud refresh. Measured\n> on pirria 2026-09-04, which ran it as the final health check of the\n> v56.9.2.1 smoke and had to kill it: a \"health check\" that mutates is exactly\n> what the LAST rule above exists to prevent. The block above is what that run\n> used instead, after the fact.\n\n## 5 — File the findings report\n\n> **This heading did not exist until order 1189-7yvu\u002F1190-swen.** Five places\n> in this runbook say \"see §5\" or \"the §5 report\" (§0.2b, §3, §3b, §4, §4a-cold)\n> and a reader following any of them found no §5 — the section was here,\n> unnumbered, after §4c. A cross-reference to a section that cannot be located\n> is the cheapest kind of broken instrument.\n\n**The report MUST open with these three lines**, before any packet:\n\n```markdown\n- run_start: \u003Cthe `run_start=` value from target\u002Fsmoke-e2e\u002F00-run-start.txt>\n- evidence_dir: target\u002Fsmoke-e2e   (previous runs archived under _archived-\u003Cts>\u002F)\n- forge_lane_outcome: \u003Csee below — required whenever §4 ran>\n- signature_verification: \u003Cthe `cosign:` line §1s emitted, VERBATIM — required always>\n```\n\n`signature_verification` carries §1s's line unchanged: `cosign:verified:\u003Cn>\u002F\u003Cn>`,\n`cosign:could-not-run:\u003Creason>`, or `cosign:FAILED:\u003Casset>` (order 1273-4mak).\n\n**A run whose line is `cosign:could-not-run:` MUST NOT be reported as an\nunqualified PASS.** Write the verdict as `PASS (signatures unverified: \u003Creason>)`.\nThis is the requirement that closes the gap rather than re-declaring it: the\n08-28 Linux, 08-28 Windows and 09-19 macOS reports all recorded the missing\nsignature check honestly, under \"NOT CHECKED\", and the gap still shipped three\ntimes — because declaring it cost nothing and the headline still said PASS.\nA reader who sees only the verdict must not be able to miss that authenticity\nwas not established.\n\n`could-not-run` is NOT a failure. A host without cosign has not found a bad\nsignature; it has found nothing, and reporting nothing as a failure would make a\nfloor host look like a security incident. It is a third verdict, and it must be\nvisible.\n\n**The report MUST NOT cite an evidence file older than `00-run-start.txt`**\n(order 1044-na6u). Before writing any PASS, list the files that predate the\nround; each one is a leak from an earlier round, and the step it names counts\nas NOT RUN, whatever the file says:\n\n```bash\nfind target\u002Fsmoke-e2e -maxdepth 1 -type f ! -newer target\u002Fsmoke-e2e\u002F00-run-start.txt ! -name 00-run-start.txt -print\n```\n\n```powershell\n$rs = (Get-Item target\\smoke-e2e\\00-run-start.txt).LastWriteTimeUtc\nGet-ChildItem target\\smoke-e2e -File | Where-Object { $_.Name -ne '00-run-start.txt' -and $_.LastWriteTimeUtc -le $rs } | ForEach-Object FullName\n```\n\nEmpty output is the only answer that lets a file be cited. A missing\n`00-run-start.txt` means no file can be cited at all: the round has no start\nto compare against.\n\n`run_start` is what makes every other file in the evidence directory checkable\n(order 1189-7yvu). Without it a reader cannot tell this run's `03-init-exit.txt`\nfrom a previous run's, because they have the same name — and on pirria\n2026-09-14 a 2026-09-13 `init_exit=0` was read as that run's result while its\n`--init` was still building the proxy image.\n\n`forge_lane_outcome` must say, **in words a reader cannot mistake for a\ncompleted cycle** (order 1190-swen), which of these happened:\n\n- `cold-host guard stop (EXPECTED PASS)` — the lane brought the enclave up and\n  stopped at the Credential Channel Guard with\n  `blocked:upstream-no-credential`. Nothing was claimed, drained, filed or\n  committed; the tree is pristine; **no `MO-FULL:` marker was emitted, and its\n  absence is correct.** On a post-§2-reset host this is the expected outcome,\n  not a partial one. Say so explicitly — do NOT write \"forge run clean\", which\n  reads as a cycle's worth of work.\n- `completed cycle` — only legitimate if the lane got past the guard, which on\n  a properly cold host it cannot. If you are writing this after a §2 reset,\n  something held a credential and **the room was not clean** — that is a\n  finding, not a pass.\n- `supervisor lost` — see §4a; containers up and no kernel oom-kill means the\n  run is unfinished, not red.\n- `agent dead, process idling` — `04-opencode-exit.txt` carries\n  `lane_verdict=agent-dead-process-idling`; report the error line from\n  `04-agent-watch.txt` and cite `04-opencode-agent.log`. The lane ended BECAUSE\n  the agent died, so it is a verdict on the agent run (red unless the error is\n  the release's declared known red), never \"unfinished\".\n\n**Never report the forge lane from `opencode_exit` alone.** Exit 0 and a\nguard-stop are the same number.\n\nEach finding becomes a `### Work Packet:` entry so `\u002Fadvance-work-from-plan` can\nclaim and fix it. Append packets to a dated, **host-qualified** smoke report:\n\n```\nplan\u002Fissues\u002Fsmoke-e2e-findings-\u003CRELEASE_TAG>-\u003CDATE>-\u003Chost_kind>-\u003Chost_id>.md\n```\n\ne.g. `smoke-e2e-findings-v56.9.11.1-2026-09-12-macos-macbookair.md`.\n\n**THE HOST FIELDS ARE NOT DECORATION — WITHOUT THEM TWO LANES COLLIDE IN GIT.**\nThis template read `\u003CRELEASE_TAG>-\u003CDATE>` until 2026-09-12, while the convention\nin practice had always carried a host (`plan\u002Fsmoke-e2e-v0.4.260815.1-windows.md`\nin-tree; the README row for v0.4.260826.1 cites `…-macos-…-macbook.md`,\n`…-windows-…-yolanda.md`, `…-linux-…-yoga.md`). A three-platform release asks\nevery lane to smoke the same tag on the same day, so the dropped field made a\ncollision *certain*, not unlucky: on 2026-09-12 yoga's Linux report and\nmacbookair's macOS report were both written to\n`smoke-e2e-findings-v56.9.11.1-2026-09-12.md`, and\n`land-on-platform-branch.sh` refused with `refused:land:trunk-merge-conflict`\n(add\u002Fadd). Recorded on order 1004-fue3.\n\n**On such a conflict, KEEP BOTH LANES' REPORTS.** The conflict surfaces at LAND\ntime, on a host that did nothing wrong, and the obvious resolution — take one\nside — silently destroys another platform's entire smoke result, including its\nNOT CHECKED list and any findings only that platform could have seen. Give each\nside its host-qualified name; never resolve by choosing. If one side already\nsits at an unqualified path on trunk, leave it there (renaming another host's\nlanded file is that host's call) and qualify yours.\n\nPacket template (status `ready` so it is immediately claimable):\n\n```markdown\n### Work Packet: smoke-finding\u002F\u003Cshort-slug>\n\n- id: `smoke-finding\u002F\u003Cshort-slug>`\n- owner_host: linux            # or any \u002F macos \u002F windows\n- capability_tags: [rust, podman, vault, testing, release]   # intersect what's needed\n- status: ready\n- discovered_by: `\u002Fsmoke-curl-install-and-test-e2e` on release `\u003CRELEASE_TAG>`\n- evidence:\n  - `target\u002Fsmoke-e2e\u002F03-init.log:\u003Cline>` — \u003Cone-line excerpt>\n- repro:\n  - smallest command that reproduces (e.g. `tillandsias --debug --init`)\n- next_action: >\n    \u003Csmallest concrete diagnostic or fix the next worker should attempt>\n- events:\n  - type: discovered\n    ts: `\u003CISO-8601-UTC>`\n    agent_id: `\u003Cyour-agent-id>`\n    host: linux\n```\n\nRules for good findings:\n\n- **One issue per packet.** Split compound failures.\n- **Always include a repro and a log excerpt.** A finding with no evidence is\n  noise; cite `target\u002Fsmoke-e2e\u002F*.log:\u003Cline>`.\n- **Redact secrets.** Never paste tokens or unredacted push URLs into a packet.\n- **De-duplicate.** Before filing, grep `plan\u002Fissues\u002F` for an existing packet on\n  the same symptom; if found, append an `events:` note instead of a new packet.\n- **No silent passes.** If the smoke ran clean end-to-end, still write a\n  one-line PASS entry to the report (release tag + \"init clean\") so the\n  convergence record shows the release was exercised. **Do not write \"forge run\n  clean\"** — state the `forge_lane_outcome` from the top of this section\n  instead. On a post-reset host the honest line is \"init clean; forge lane\n  stopped at the credential guard as expected\", and the old wording is exactly\n  the sentence order 1190-swen exists to remove.\n- **Cite the release's ledger row and account for its claims** (order 380). The\n  report carries a short `## Ledger claims` section listing each claim from the\n  row read in §0.2b under exactly one of three headings:\n  **EXERCISED** (this lane checked it — say how),\n  **NOT APPLICABLE** (the claim is another platform's, or another lane's), or\n  **NOT CHECKED** (this lane could have and did not).\n  The third heading is the one that earns this section. A report with no\n  NOT-CHECKED list reads as though the run covered everything the release\n  claimed, and a reader has no way to tell that from a run that simply never\n  looked. Naming the gaps is what makes a PASS mean something narrower and\n  truer than \"the release works\".\n\nCommit the report (and any forge-pushed findings) to the appropriate host branch (`linux-next`, `osx-next`, or `windows-next`) and push. **DO NOT push directly to `main` or open PRs against `main`.** Update the host work-queue\nledger with a one-line outcome, exactly as `\u002Fadvance-work-from-plan` §6\nprescribes.\n\nBefore a successful exit, the PASS\u002Ffinding report must be committed and pushed.\nDo not leave a local-only release smoke result.\n\n---\n\n## Guardrails\n\n- **Never** skip Step 2 on a Tillandsias smoke host because it wipes Podman.\n  The wipe is the precondition that makes the test meaningful. The only\n  supported opt-out is `TILLANDSIAS_DESTRUCTIVE_RESET_OK=0`, which must produce\n  a pushed plan blocker.\n- **Never** substitute a local `target\u002F` build for the curl-installed binary —\n  that defeats the purpose (testing the published artifact).\n- **Never** push fixes from this skill. This skill only *installs, observes, and\n  files*. Fixes are the job of `\u002Fadvance-work-from-plan` workers claiming the\n  packets you filed.\n- **Never** paste secrets into logs or packets; redact tokens and auth URLs.\n- **Never** push directly to `main` or create PRs to `main`. Always use the appropriate host branch (`linux-next`, `osx-next`, or `windows-next`).\n- Findings are intake, not authority — durable conclusions still land in\n  `openspec\u002Fspecs\u002F`, `methodology\u002F`, or cheatsheets via the normal flow.\n\n## How orchestrators steer this skill\n\nThe canonical file lives at `skills\u002Fsmoke-curl-install-and-test-e2e\u002FSKILL.md`;\neach runtime accesses it via a symlink under its `skills\u002F` directory. An\norchestrator can set `TILLANDSIAS_DESTRUCTIVE_RESET_OK=0` for a non-smoke host,\nchange the forge prompt in Step 4, or adjust the finding capability_tags\nbetween iterations.\n","# Smoke: Curl-Install and Test End-to-End\n\nThis skill validates that a **published release** actually works for a real\noperator starting from nothing. It is the acceptance gate that catches what\n`.\u002Fbuild.sh --ci-full` cannot: problems that only appear when the signed,\ndownloadable artifact bootstraps the whole enclave from a wiped host substrate.\n\n## Authority\n\n`methodology.yaml` remains the source of truth. This skill is an executable\nrunbook; it does not redefine release, trace, or coordination policy. Findings\nbecome `plan\u002Fissues\u002F` work packets so they flow through the normal\n`\u002Fadvance-work-from-plan` worker loop.\n\n---\n\n## Host Matrix\n\n| Host | Installer | Destructive substrate | Re-provision |\n|---|---|---|---|\n| immutable Linux | `scripts\u002Finstall.sh` via release curl URL | `podman system reset --force` | `tillandsias --debug --init` |\n| mutable Linux | `scripts\u002Finstall.sh` via release curl URL | `podman system reset --force` | `tillandsias --debug --init` |\n| macOS | `scripts\u002Finstall-macos.sh` via release curl URL — **launches the tray and begins VM provisioning; not a download test (1281-pgit)** | remove Tillandsias app state\u002Fcache VM dirs | installed tray `--provision` + `--diagnose --json` |\n| Windows | `scripts\u002Finstall-windows.ps1` release path when available | `wsl --unregister tillandsias`, runtime-cache purge BY NAME (`%USERPROFILE%\\.cache\\tillandsias`, `%APPDATA%\\tillandsias`; never `%LOCALAPPDATA%\\tillandsias\\wsl-build`, the builder distro — 1295-b4i8), plus `vault-shamir-share-v1` + `vault-root-token-v1` cleared from Credential Manager (keeping `tillandsias-vm-uuid`) | installed tray provision\u002Fdiagnose — implemented by the §3 \"Windows\" block (`--provision-once`, `--status-once --json` polled to Ready, `--diagnose --json` LAST) |\n\nThis is the only e2e install skill allowed on immutable Linux.\n\n## DESTRUCTIVE — read before running\n\nOn Linux, Step 2 runs **`podman system reset --force`**, which irreversibly\ndeletes ALL Podman state for this user: every container, image, volume, network,\nand secret — including:\n\n- the `tillandsias-vault-data` volume (Vault's sealed store),\n- every project mirror volume (`tillandsias-mirror-*`),\n- all locally built enclave images (proxy\u002Fgit\u002Finference\u002Fforge) — these get\n  **rebuilt from scratch on the next `--init`, which can take many minutes**.\n\nOn a DEDICATED SMOKE HOST, wiping Podman is expected and is a required\nprecondition for the release idempotence test.\nPre-authorise the reset by prefixing the reset command with exactly `TILLANDSIAS_DESTRUCTIVE_RESET_OK=1 TILLANDSIAS_SKILL=smoke-curl-install-and-test-e2e` (1462-qvxj). The consent\nengine (1443-9f5w) and the Bash-tool bridge honour ONLY that pair, on bare\nmetal, for a SOFT reset: unset is not `1`, and a skill name alone never\nauthorises a wipe. Without both, the reset is asked, not skipped. With it set,\ndo not ask for confirmation,\ndo not pause for operator timing, and do not skip Step 2 because Podman state\nwill be destroyed. Only block the reset when the environment explicitly sets\n`TILLANDSIAS_DESTRUCTIVE_RESET_OK=0`, in which case file a plan blocker and\npush it.\n\n**That no-pause clause applies to a dedicated smoke host and to nothing else\n(order 1004-vsh2, 2026-09-04).** On an OPERATOR'S WORKSTATION — a machine whose\nguest holds work they have not finished with — Step 2 destroys their Vault\nstore, their project mirrors and their images, and this document cannot consent\non their behalf. Get the operator's authorization for THAT RUN before starting.\nAn orchestrator's or a peer agent's instruction to run this skill is not that\nauthorization: it is a request to run a procedure, not consent to destroy a\nparticular machine's state. The distinction was missed once because this\nsection read as though every host running it were a smoke host; most of the\nfleet's Windows and macOS hosts are workstations.\n\n**`TILLANDSIAS_RESET_KEEP_MODELS=1`** lets this destruction spare the model\ncache (`cache_root()\u002Fmodels`) on the operator's word — opt-in, per run, never\nthe default: the clean room stays clean unless this run asked otherwise (the\n2026-09-13 reset ruling; operator, 2026-09-14: \"let's add the keep models\nflag to our resets\"). Per platform: **Linux** — the podman reset and the\ncredential clearer never touch `~\u002F.cache\u002Ftillandsias\u002Fmodels`, so the flag is\na documented no-op and the models survive regardless. **macOS** — honoured by\n`scripts\u002Fe2e-step2-macos.sh` below, which names the spared directory in its\nresidue line. **Windows** — a no-op until 1182-2vaz moves the weights out of\nthe distro (they live at `\u002Froot\u002F.cache\u002Ftillandsias\u002Fmodels` inside the vhdx\nthat `wsl --unregister` deletes) (operator ruling 2026-09-14; 1181-bkem).\n\nA fresh `--init` re-initializes Vault and re-captures the keychain-held unseal\nshare, so the keychain↔volume resync brick (see git history `738059bc`) is part\nof what this smoke exercises — if init bricks, that is a finding, not a failure\nto hide.\n\n**On Linux this is true only because the reset now CLEARS the host-held\ncredentials (order 900-z3kv). Step 2 runs\n`scripts\u002Fclear-vault-host-credentials.sh` after emptying the store; without it\nthe paragraph above was false.** `podman system reset --force` empties the podman\nstore — containers, volumes AND images — but it does not reach the HOST\nKEYCHAIN. Vault then recovers the pre-existing Shamir share and logs `preserving\nexisting data volume (Shamir share present in keychain)`, so without the clearer the resync path\nabove is **not exercised** — which is what every Linux pass silently carried\nuntil 900-z3kv wired it. Measured independently on two Linux hosts with\ndifferently-aged shares (yoga, created 2026-06-15; lenovinha, created\n2026-07-08), which makes it a property of the Linux lane rather than one host's\ndirty state — and it means every Linux \"clean room\" pass since at least 2026-06\nsilently carried this gap.\n\nRun `scripts\u002Fprobe-credential-cold-state.sh --format=md` and paste its block\ninto the findings file, the way the Windows leg records its hashes. It reports\n`credential-cold` or `credential-warm` from **metadata only** — never\n`secret-tool search --all`, which prints the secret inline and put live tokens\ninto two transcripts on 2026-08-25 — and reports `could-not-run` when the\nquestion cannot be asked, which must never be read as cold.\n\n**Since 1149-vgn2 it checks the host keychain AND\n`~\u002F.cache\u002Ftillandsias\u002Ffallback_*`, and a cold verdict names everything it\nchecked.** It read the keychain alone until then, so pirria — no keychain\nitem, a `fallback_vault-shamir-share-v1` untouched since 2026-09-01 keeping\nevery reset warm — was certified cold, and the verdict's own text claimed the\nresync path was exercised. If the checkout running this skill predates\n1149-vgn2, its cold verdict is keychain-only: do not trust it (drill: plan\u002Fissues\u002Ffleet-restart-2026-09-12.md, 1149-vgn2 fixed: the cold probe now checks the fallback share).\n\n**DECIDED (900-z3kv, operator ruling 2026-09-13): the reset clears the\nhost-held credentials.** Not open — the platform prefers idempotency to\nlegacy support, and `podman system reset --force` is the baseline.\n`scripts\u002Fclear-vault-host-credentials.sh` clears THREE locations: the\nkeychain items `vault-shamir-share-v1` and `vault-root-token-v1`, the\n`~\u002F.cache\u002Ftillandsias\u002Ffallback_*` copies of both, and\n`~\u002F.cache\u002Ftillandsias\u002Fvault-data`. `installation-uuid-v1` is deliberately\nPRESERVED — it anchors the INSTALLATION, and clearing it makes the next vault\nunderivable rather than re-initialized. **Read the clearer's own last line,\nnot the reset's exit code:** a partial clear prints\n`warn:clear-vault-credentials:partial` and still exits 0, which is precisely\nthe state that looks cold and is not (drill: plan\u002Fissues\u002Ffleet-restart-2026-09-12.md, 900-z3kv COMPLETED).\n\n---\n\nOn macOS, the destructive substrate is the Tillandsias Virtualization.framework\nstate and cache directories. On Windows, it is the `tillandsias` WSL2 distro and\ndownload cache.\n\n## 0 — Pre-flight\n\n0. **Shell: every fenced `bash` block in this runbook runs under bash, and the\n   first line of each block asserts it.** `PIPESTATUS` is a bash array; under\n   zsh it expands EMPTY and zsh's `test \"\" -eq 0` is TRUE, so every exit-code\n   assertion below silently passes on a failed step (measured on pirria,\n   2026-09-04: the first install attempt recorded `install_exit=` and walked\n   on — the exact walk-past-a-failed-install 727-kmks wrote the assertions to\n   kill, reintroduced by shell choice; order 1004-fue3). Paste this line at the\n   top of every bash block, or run each block as `bash -c '...'`:\n   ```bash\n[ -n \"${BASH_VERSION:-}\" ] || { echo 'FAIL: run this block under bash — PIPESTATUS is a bash array and zsh expands it empty'; exit 2; }\n   [ -n \"${BASH_VERSION:-}\" ] || { echo 'FAIL: run this block under bash — PIPESTATUS is a bash array and zsh expands it empty'; exit 2; }\n   ```\n   Every assertion on a captured status also checks the capture is NON-EMPTY\n   (`test -n \"$RC\" && test \"$RC\" -eq 0`), so a void capture fails loud even if\n   the guard above is skipped. PowerShell blocks assert `$LASTEXITCODE` and\n   `$?` instead; there is no PIPESTATUS there.\n\n1. **Identify host + branch** (Linux → `linux-next`, macOS → `osx-next`,\n   Windows → `windows-next`). The `--opencode` forge lane is Linux\u002FPodman today.\n2. **Choose the channel and resolve the release under test.** Two channels\n   (plan order 305 + operator directive 2026-07-15):\n   - **`daily` (DEFAULT for routine smoke)** — the newest release *including\n     prereleases* (the latest daily). Routine curl-install smoke tracks the\n     bleeding edge because that is the next promotion candidate.\n   - **`stable` (one-shot after a promotion)** — the newest non-prerelease\n     (what `\u002Freleases\u002Flatest` and the README serve). Run this ONCE right\n     after `scripts\u002Fpromote-stable.sh` promotes a release, to prove the\n     promoted artifact installs; then routine runs go back to `daily`.\n   ```bash\n   awk -v tag=\"${SMOKE_TAG}\" '\n       # 1. An exact row for this tag.\n       $0 ~ \"^\\\\| \" tag \"( |\\\\()\" { print; found=1; next }\n       # 2. A DISTILLED SPAN covering it (order 380). Old series are collapsed\n       #    into one `first … last` row, so a tag inside that range HAS been\n       #    described — just not individually. Without this arm a distilled tag\n       #    is indistinguishable from an undescribed one, and the finding below\n       #    fires falsely on every release old enough to have been compressed.\n       \u002F^\\| v[0-9].* … v[0-9].*DISTILLED\u002F {\n           split($0, c, \"|\"); split(c[2], span, \"…\")\n           lo = span[1]; hi = span[2]\n           gsub(\u002F[^0-9A-Za-z.]\u002F, \"\", lo); gsub(\u002F .*\u002F, \"\", hi); gsub(\u002F[^0-9A-Za-z.]\u002F, \"\", hi)\n           if (tag >= lo && tag \u003C= hi) { print; found=1; distilled=1 }\n       }\n       END {\n           if (!found) print \"NO LEDGER ROW for \" tag\n           else if (distilled) print \"(row is a DISTILLED span, not a per-release row — claims are series-level)\"\n       }\n   ' README.md | tee target\u002Fsmoke-e2e\u002F00-ledger-row.txt\n   ```\n   Note the tag — every filed finding cites it so issues are attributable to a\n   specific published artifact AND channel.\n2b. **Read the release's own ledger row BEFORE testing it** (order 380).\n   `README.md` carries a RELEASE \u002F INTENDED FEATURES \u002F BUGFIXES table, and the\n   row for `$SMOKE_TAG` is the release stating **what it claims to have fixed**:\n\n   ```bash\n   awk -v tag=\"${SMOKE_TAG}\" '\n       # 1. An exact row for this tag.\n       $0 ~ \"^\\\\| \" tag \"( |\\\\()\" { print; found=1; next }\n       # 2. A DISTILLED SPAN covering it (order 380). Old series are collapsed\n       #    into one `first … last` row, so a tag inside that range HAS been\n       #    described — just not individually. Without this arm a distilled tag\n       #    is indistinguishable from an undescribed one, and the finding below\n       #    fires falsely on every release old enough to have been compressed.\n       \u002F^\\| v[0-9].*DISTILLED\u002F {\n           row = $0\n           sub(\u002F^\\| \u002F, \"\", row); split(row, parts, \" … \")\n           lo = parts[1]; hi = parts[2]; sub(\u002F .*$\u002F, \"\", hi)\n           if (tag >= lo && tag \u003C= hi) { print; found=1; distilled=1 }\n       }\n       END {\n           if (!found) print \"NO LEDGER ROW for \" tag\n           else if (distilled) print \"(DISTILLED span — claims are series-level, not per-release)\"\n       }\n   ' README.md | tee target\u002Fsmoke-e2e\u002F00-ledger-row.txt\n   ```\n\n   **Why this is a step and not a courtesy.** Without it the smoke validates a\n   generic property — it installs, it destroys, it re-provisions — against\n   *any* release, and cannot tell whether the specific thing this release says\n   it repaired actually got repaired. The row names orders; those are checkable.\n   On 2026-08-26 the macOS lane verified that `--version` reports the workspace\n   VERSION rather than `0.1.0`, which is precisely what that row claims for\n   635-bhkb — **but by coincidence, because the runbook had just been changed,\n   not because anything directed the run at the claim.**\n\n   Cite the row in the §5 report and state which of its claims this lane\n   exercised, which it could not, and which it did not look at. A claim the\n   lane cannot reach (a Windows fix on the macOS lane) is a legitimate\n   *not-applicable*; a claim it could have checked and did not is a gap in the\n   run, and only naming them separately makes that visible.\n\n   **A MISSING ROW IS A FINDING, NOT A SKIP.** `NO LEDGER ROW for \u003Ctag>` means\n   either the release skill's append step did not run for this release, or the\n   smoke is testing an artifact nobody described. Both are worth a packet, and\n   both are invisible if this step silently proceeds.\n3. **Record sibling heads** (`main`, `linux-next`, `windows-next`, `osx-next`)\n   per multi-host discipline.\n4. **ARCHIVE THE PREVIOUS RUN'S EVIDENCE, THEN create the findings log dir**\n   (order 1189-7yvu). `mkdir -p` on its own is what let a run inherit every\n   file from every previous run:\n   ```bash\n   SMOKE_EVIDENCE_DIR=target\u002Fsmoke-e2e\n   SMOKE_RUN_START=\"$(date -u +%Y-%m-%dT%H:%M:%SZ)\"\n   # MOVE ASIDE, NEVER DELETE — prior evidence is worth keeping, and a step\n   # that deletes it makes the previous run unreconstructable.\n   if [ -d \"$SMOKE_EVIDENCE_DIR\" ] && [ -n \"$(ls -A \"$SMOKE_EVIDENCE_DIR\" 2>\u002Fdev\u002Fnull)\" ]; then\n       SMOKE_ARCHIVE=\"$SMOKE_EVIDENCE_DIR\u002F_archived-$(date -u +%Y%m%dt%H%M%Sz)\"\n       mkdir -p \"$SMOKE_ARCHIVE\"\n       # Move every entry except the archive dirs themselves.\n       for _e in \"$SMOKE_EVIDENCE_DIR\"\u002F*; do\n           case \"$_e\" in *\"\u002F_archived-\"*) continue ;; esac\n           [ -e \"$_e\" ] && mv \"$_e\" \"$SMOKE_ARCHIVE\"\u002F\n       done\n       printf 'archived_to=%s\\n' \"$SMOKE_ARCHIVE\"\n   fi\n   mkdir -p \"$SMOKE_EVIDENCE_DIR\"\n   printf 'run_start=%s\\n' \"$SMOKE_RUN_START\" | tee \"$SMOKE_EVIDENCE_DIR\u002F00-run-start.txt\"\n   ```\n   **Windows runs this step in PowerShell, and it is the lane that found the\n   defect** (order 1044-na6u, esmeraldinha v56.9.4.1: after a §3 abort,\n   `03-provision-exit.txt` still held the v56.9.2.1 round's `provision_exit=0`\n   and `elapsed_seconds=117`, eighteen hours old). §1's\n   `New-Item -ItemType Directory -Force` is the PowerShell spelling of the\n   `mkdir -p` above: it keeps every file already in the directory. Run this\n   before §1:\n   ```powershell\n   $SmokeEvidenceDir = 'target\\smoke-e2e'\n   $SmokeRunStart = (Get-Date).ToUniversalTime().ToString('yyyy-MM-ddTHH:mm:ssZ')\n   # MOVE ASIDE, NEVER DELETE, exactly as the bash block does.\n   $prior = @(Get-ChildItem -LiteralPath $SmokeEvidenceDir -Force -ErrorAction SilentlyContinue |\n              Where-Object { $_.Name -notlike '_archived-*' })\n   if ($prior.Count -gt 0) {\n     $SmokeArchive = Join-Path $SmokeEvidenceDir ('_archived-' + (Get-Date).ToUniversalTime().ToString('yyyyMMdd\\tHHmmss\\z'))\n     New-Item -ItemType Directory -Force $SmokeArchive | Out-Null\n     $prior | Move-Item -Destination $SmokeArchive\n     \"archived_to=$SmokeArchive\"\n   }\n   New-Item -ItemType Directory -Force $SmokeEvidenceDir | Out-Null\n   \"run_start=$SmokeRunStart\" | Tee-Object (Join-Path $SmokeEvidenceDir '00-run-start.txt')\n   ```\n   With the directory emptied at the start of the round, a step that aborts\n   before its write leaves its evidence file ABSENT. Absent is a verdict; a\n   previous round's file under the same name is a lie.\n   **WHY THIS IS NOT HOUSEKEEPING.** In-block assertions capture their status\n   in the same shell and are unaffected. Every OUT-OF-BAND read is affected:\n   the §5 report, an orchestrator polling for completion, a human scanning the\n   directory. A step that never reaches its write leaves the PREVIOUS run's\n   file under the exact name those readers open, so a stale PASS is\n   indistinguishable from a fresh one BY NAME.\n\n   MEASURED on pirria 2026-09-14: `03-init-exit.txt` containing `init_exit=0`,\n   dated 2026-09-13 01:24, was present and being read as this run's result\n   while this run's `--init` was still building the proxy image. Fourteen files\n   from the 2026-09-12\u002F13 runs were present at start and had to be archived by\n   hand.\n\n   **CHECK EVIDENCE AGAINST `run_start`, not against its existence.** Any file\n   in the directory older than `00-run-start.txt` is a leak from an incomplete\n   archive, not a result:\n   ```bash\n   find \"$SMOKE_EVIDENCE_DIR\" -maxdepth 1 -type f \\\n        ! -newer \"$SMOKE_EVIDENCE_DIR\u002F00-run-start.txt\" \\\n        ! -name 00-run-start.txt -print\n   # any output here is stale evidence that survived the archive step\n   ```\n5. **Source the timing helpers, and keep them sourced for every block below**\n   (order 1013-qv7c). Each smoke step emits ONE duration record so the\n   recurrence rung (`repeat:` \u002F `recur:` \u002F `skippable:` in\n   `scripts\u002Fcycle-metrics.sh`) can see this runbook's work:\n   ```bash\n   . \"$PWD\u002Fscripts\u002Ftiming-log.sh\" 2>\u002Fdev\u002Fnull || true\n   command -v timing_emit >\u002Fdev\u002Fnull 2>&1 || { timing_now_ms() { echo 0; }; timing_emit() { return 0; }; }\n   command -v timing_begin >\u002Fdev\u002Fnull 2>&1 || { timing_begin() { return 0; }; timing_commit() { return 0; }; timing_reap() { return 0; }; }\n   timing_reap\n   ```\n   `timing_reap` reports on the PREVIOUS run, not this one (order 1026-ps4n).\n   If a earlier smoke's supervising shell was killed mid-step, its start stamp\n   is still on disk; reaping turns it into a `\u003Cstep>-supervisor-lost` record so\n   the log says what happened instead of being silent. Run it first, before any\n   step below writes a stamp of its own.\n   **Why this and not the gate.** Every other emitter in the tree is a\n   build\u002Ftest\u002Flitmus step in `build.sh`, `scripts\u002Flocal-ci.sh` or\n   `scripts\u002Frun-litmus-test.sh`, and all of those need cargo. A floor host\n   without a toolchain therefore has *never* written a timing record —\n   measured on pirria 2026-09-04, where `repeat:`\u002F`recur:`\u002F`skippable:` all\n   read `source=absent` and `.cache\u002Fmetrics\u002F` was an empty directory the probe\n   itself created. An instrument for finding what slow hosts pay cannot be\n   downstream of the thing slow hosts cannot run. `timing_emit` is bash and\n   `jq`, needs no toolchain, and the smoke is work the floor *can* do — so the\n   records come from here.\n\n   The emits are **best-effort by construction**: `timing_emit` wraps its whole\n   body and always returns 0, and the fallback stub above keeps every call site\n   unconditional and `set -e`-safe. A metrics write can never fail a smoke step.\n\n   Records are named `phase=smoke` with these pinned `step` values, one per\n   step below: `smoke-curl-install`, `smoke-destructive-reset`,\n   `smoke-init-pristine`, `smoke-forge-lane`, `smoke-health-check`. They land\n   in `\u003Ccheckout>\u002F.cache\u002Fmetrics\u002Ftillandsias-timing.jsonl` (the same log the\n   gate steps write) and are read back by `scripts\u002Fcycle-metrics.sh`.\n\n   A sixth name appears only when something went wrong:\n   `smoke-forge-lane-supervisor-lost` (order 1026-ps4n). It means a previous\n   run's shell was killed while the lane was running, and its `duration_ms` is\n   a **lower bound** — the end was never observed. It is deliberately a\n   separate step name so it can never be averaged into `smoke-forge-lane`;\n   see §4a for what that state looks like on the host and why it is not a\n   product failure.\n\n---\n\n## 1 — Curl-install the latest release\n\nInstall the published artifact the canonical way an operator would — do NOT use a\nlocally built `target\u002F` binary; the whole point is to test the *download*.\n\n**`install.sh` is not a download test — it runs the full init (1133-kktm).**\nMeasured on v56.9.12.2: 131 lines of podman\u002Fvault output, a Vault bootstrap\nprovisioning twelve policies and AppRole roles, and a `tillandsias-vault`\ncontainer left running on 8201. Reversible, not inert, and not what\n\"curl-install and assert the tag\" describes above. The §1\u002F§2 consent line\nstill holds (§2 destroys, §1 provisions), but on an operator's workstation say\nwhat §1 actually does before running it; consent to a download check is not\nconsent to a Vault bootstrap (drill: plan\u002Fissues\u002Ffleet-restart-2026-09-12.md, §1 of the smoke is not a non-destructive binary install).\n\n**SINCE 1286-4437, `install.sh` CALLS `--reset-state` ITSELF, so on a release\ncarrying that change §1 IS A DESTRUCTIVE STEP.** Bank the pre-state BEFORE §1,\nnot before §2, or the reset contract has nothing to be measured against — and\non an operator's workstation get consent for §1 on those grounds, not §2's.\n\n**AFTER A SUCCESSFUL §1 THE ENCLAVE SHOWS ZERO RUNNING CONTAINERS, AND THAT IS\nCORRECT.** The reprovision rebuilds IMAGES synchronously; the install log ends\n`SUCCESS web`, \"Reset and reprovision complete\", exit 0, and directs the\noperator to launch the tray. Containers arrive at tray or lane launch, not at\ninstall. A reader who checks `podman ps` here and finds it empty will file a\nfailed provision against a release that installed perfectly — measured on\npirria during the v56.9.21.1 run. Check the IMAGE count against `run_start`\ninstead: on a real reprovision every image post-dates it.\n\nLinux:\n\nThe installer honors `TILLANDSIAS_RELEASE_BASE` so the smoke pins the exact\nresolved release (`$SMOKE_BASE`) instead of the hard-coded\n`\u002Freleases\u002Flatest\u002Fdownload` (which is stable-only by GitHub semantics — it\nwould ignore the daily prerelease). Real users are unaffected: with the env\nunset the installer defaults to the stable channel.\n\n```bash\n[ -n \"${BASH_VERSION:-}\" ] || { echo 'FAIL: run this block under bash — PIPESTATUS is a bash array and zsh expands it empty'; exit 2; }\n_T0=\"$(timing_now_ms)\"\nTILLANDSIAS_SMOKE_LOCK_LOG=target\u002Fsmoke-e2e\u002F00-smoke-lock.log \\\n  scripts\u002Fwith-smoke-lock.sh --name release-smoke-e2e -- \\\n  bash -c \"curl -fsSL '${SMOKE_BASE}\u002Finstall.sh' | TILLANDSIAS_RELEASE_BASE='${SMOKE_BASE}' bash\" 2>&1 \\\n  | tee target\u002Fsmoke-e2e\u002F01-install.log\nINSTALL_RC=${PIPESTATUS[0]}; printf 'install_exit=%s\\n' \"$INSTALL_RC\" | tee target\u002Fsmoke-e2e\u002F01-install-exit.txt\ntiming_emit smoke-curl-install smoke \"$_T0\" \"${INSTALL_RC:-1}\" || true\ntest -n \"$INSTALL_RC\" && test \"$INSTALL_RC\" -eq 0\nhash -r\ntillandsias --version | tee target\u002Fsmoke-e2e\u002F01-version.txt\n_rc=${PIPESTATUS[0]}; test -n \"$_rc\" && test \"$_rc\" -eq 0\n# The comment used to say \"must equal $SMOKE_TAG\". Now it is checked.\n# BOUNDED (amendment to 1133-kktm): the version scheme is a monotonic\n# counter, so an unbounded substring test would accept 56.9.12.20 as a match\n# for 56.9.12.2. (drill: plan\u002Fissues\u002Ffleet-restart-2026-09-12.md, The promotion proven on the default Windows path)\ngrep -qE \"(^|[^0-9.])${SMOKE_TAG#v}([^0-9.]|\\$)\" target\u002Fsmoke-e2e\u002F01-version.txt\n```\n\n> Three assertions replacing a pipe and a comment (order 727-kmks). The\n> installer ran through `| tee`, so a curl-install that failed outright exited 0\n> — `tee` wrote the failure into the evidence file and the smoke walked on. The\n> version line then carried `# must equal $SMOKE_TAG` as a comment, which meant\n> the clean-room test of a PUBLISHED release never once confirmed it was running\n> the release it claimed to be testing: a stale binary already on PATH would\n> answer `--version` and pass.\n\n**`install-macos.sh` is not a download test either — it launches the tray and\nprovisions a VM (1281-pgit).** The hazard above is written for `install.sh` and\nLinux; the macOS installer does the platform equivalent and had no equivalent\nwarning. MEASURED on macneo during the v56.9.19.1 and v56.9.19.2 smokes: §1 ends\nwith \"Launching Tillandsias (--init \u002F VM provisioning runs automatically on\nfirst launch)\", leaves a `tillandsias-tray` process running that §2 must then\nstop, and provisioning downloads a ~528 MB Fedora Cloud image in the background.\n\nWHY THE ASYMMETRY MATTERED, and why it is now stated on both paths: most of the\nfleet's macOS hosts are OPERATORS' WORKSTATIONS rather than dedicated smoke\nhosts, and this runbook has already recorded once that the distinction was\nmissed (1004-vsh2 — \"this section read as though every host running it were a\nsmoke host\"). A reader who has internalised \"§1 is the safe download step, §2 is\nthe destructive one\" is correct on Linux by documentation and wrong on macOS.\nSay what §1 actually does before running it on a machine whose guest holds work\nsomeone has not finished with.\n\nAND AN INTERRUPTED INSTALL USED TO COST THE EXISTING APP. Until 1281-pgit the\ninstaller removed the previous backup and moved the live app aside BEFORE\nextracting, so a kill between those steps left `\u002FApplications` with neither the\napp nor a backup — measured here when the installer was piped through `head` to\nread its first lines and died on SIGPIPE. The swap is now staged-extract,\nrename, rename, with the old backup dropped last and a trap that restores it, so\nthe destination always holds a runnable app; `litmus:installer-swap-atomicity`\npins that. A SIGKILL is still untrappable, so do not pipe the installer into\nsomething that closes early just to read its output — run it and read the log.\n\nmacOS:\n\n```bash\n[ -n \"${BASH_VERSION:-}\" ] || { echo 'FAIL: run this block under bash — PIPESTATUS is a bash array and zsh expands it empty'; exit 2; }\ncurl -fsSL \"${SMOKE_BASE}\u002Finstall-macos.sh\" | TILLANDSIAS_RELEASE_BASE=\"${SMOKE_BASE}\" bash 2>&1 \\\n  | tee target\u002Fsmoke-e2e\u002F01-install-macos.log\nINSTALL_RC=${PIPESTATUS[0]}; printf 'install_exit=%s\\n' \"$INSTALL_RC\" \\\n  | tee target\u002Fsmoke-e2e\u002F01-install-macos-exit.txt\ntest -n \"$INSTALL_RC\" && test \"$INSTALL_RC\" -eq 0\n\n# install-macos.sh extracts to \u002FApplications — but FALLS BACK to\n# ~\u002FApplications when \u002FApplications is not writable, and this runbook then\n# verifies \u002FApplications unconditionally. Assert which branch it took rather\n# than assuming: a stale ~\u002FApplications copy plus a silent fallback is the\n# live mixup of 2026-07-16, and it \"verifies\" the wrong binary.\ntest -d \"\u002FApplications\u002FTillandsias.app\"\n! grep -q \"not writable; using\" target\u002Fsmoke-e2e\u002F01-install-macos.log\n\n\"\u002FApplications\u002FTillandsias.app\u002FContents\u002FMacOS\u002Ftillandsias-tray\" --version 2>&1 \\\n  | tee target\u002Fsmoke-e2e\u002F01-version.txt\n_rc=${PIPESTATUS[0]}; test -n \"$_rc\" && test \"$_rc\" -eq 0\n# EXACT, not `>=` and not \"contains 0.4\". Assertable at all only since\n# 635-bhkb: every macOS build answered `0.1.0` before it, so this lane could\n# not confirm which release it was testing even in principle.\ngrep -qF \"tillandsias-tray ${SMOKE_TAG#v} \" target\u002Fsmoke-e2e\u002F01-version.txt\n```\n\n> The same three assertions the Linux lane got in 727-kmks, plus two the macOS\n> lane needs and Linux does not. The install ran through `| tee` with no\n> `PIPESTATUS` capture and the version check ended in `|| true` — so a\n> curl-install that failed outright, and a `--version` that failed after it,\n> both exited 0 and the smoke walked on. That is the identical defect 727-kmks\n> fixed one lane over, left standing here, in the lane that had never once been\n> run against a published release.\n>\n> The two extra assertions are the `\u002FApplications`-vs-`~\u002FApplications`\n> fallback (the installer chooses, this runbook does not, and only one of them\n> is the path verified below) and the exact-tag match, which was not expressible\n> before 635-bhkb.\n\nWindows PowerShell (daily-channel pinned — the release publishes\n`install-windows.ps1` + the x64 tray zip since v0.3.260721.1; the installer\nhonors `TILLANDSIAS_VERSION` for an exact-tag pin, so the smoke installs the\nSAME resolved daily as the Linux\u002FmacOS lanes instead of `\u002Freleases\u002Flatest`,\nwhich is stable-only by GitHub semantics):\n\n```powershell\n# $SmokeTag from pre-flight, e.g. v0.3.260721.1 (strip\u002Fkeep the leading v —\n# the installer normalizes both).\n$ErrorActionPreference = 'Stop'\n# Pre-flight step 4 must have run: without 00-run-start.txt the directory may\n# still hold the previous round's files (1044-na6u).\nif (-not (Test-Path target\\smoke-e2e\\00-run-start.txt)) { throw 'run pre-flight step 4 first: no 00-run-start.txt' }\n$env:TILLANDSIAS_VERSION = $SmokeTag\n$installExit = 0\ntry {\n  $script = irm \"https:\u002F\u002Fgithub.com\u002F8007342\u002Ftillandsias\u002Freleases\u002Fdownload\u002F$SmokeTag\u002Finstall-windows.ps1\"\n  Invoke-Expression $script *>&1 | Tee-Object target\\smoke-e2e\\01-install-windows.log\n  if ($LASTEXITCODE) { $installExit = $LASTEXITCODE }\n} catch {\n  $_ | Out-String | Tee-Object -Append target\\smoke-e2e\\01-install-windows.log\n  $installExit = 1\n}\nRemove-Item Env:TILLANDSIAS_VERSION\n\"install_exit=$installExit\" | Tee-Object target\\smoke-e2e\\01-install-exit.txt\nif ($installExit -ne 0) { throw \"install failed (exit $installExit) — file a finding and STOP\" }\n# The tray is the only installed surface on Windows; assert it resolves NOW,\n# not at §3 where a missing binary would read as a provision failure.\n#\n# MEASURED 2026-09-04 on yolanda (order 1004-vsh2): the installer does NOT put\n# its directory on PATH, so a bare `Get-Command tillandsias-tray.exe` THROWS on\n# a host where the install just succeeded — \"not recognized as a name of a\n# cmdlet\". The binary is at $env:LOCALAPPDATA\\Programs\\Tillandsias, which the\n# installer prints as its install path. Resolve PATH first (an operator may\n# have added it) and fall back to the install location; only then fail.\n$tray = (Get-Command tillandsias-tray.exe -ErrorAction SilentlyContinue |\n    Select-Object -First 1 -ExpandProperty Source)\nif (-not $tray) { $tray = \"$env:LOCALAPPDATA\\Programs\\Tillandsias\\tillandsias-tray.exe\" }\nif (-not (Test-Path $tray)) { throw \"tray not found on PATH or at $tray after a successful install\" }\n\"tray=$tray\" | Tee-Object target\\smoke-e2e\\01-tray-path.txt\n# EXACT, not \"contains\": the tray answers --version \u002F -V (windows-tray\n# main.rs), so the lane can confirm which release it is testing.\n& $tray --version 2>&1 | Tee-Object target\\smoke-e2e\\01-version.txt | Out-Null\nif ($LASTEXITCODE -ne 0) { throw \"tray --version failed (exit $LASTEXITCODE)\" }\n$installedVersion = (Get-Content target\\smoke-e2e\\01-version.txt -Raw).Trim()\n# BOUNDED (amendment to 1133-kktm): an unbounded substring match would accept\n# 56.9.12.20 as a match for 56.9.12.2 — the version scheme is a monotonic\n# counter, so the collision is reachable, not hypothetical.\nif ($installedVersion -notmatch ('(?\u003C![0-9.])' + [regex]::Escape($SmokeTag.TrimStart('v')) + '(?![0-9.])')) {\n  throw \"installed tray version '$installedVersion' does not carry release $SmokeTag\"\n}\n```\n\n> Same three assertions the Linux lane got on 727-kmks and macOS on\n> 2026-08-26, added 2026-09-04 (order 1004-fue3): the old block piped `iex`\n> into `Tee-Object` and asserted nothing, so a failed installer exited 0 and\n> the smoke walked on — the shape the Linux lane had already been fixed for.\n> The release-tag pin on this lane is the installer's `TILLANDSIAS_VERSION`\n> (an exact tag: a tag that does not exist fails the download and trips the\n> exit assertion). The tray's OWN version is asserted above from `--version` (the flag\n> exists in windows-tray main.rs); the `.version` field of `--diagnose --json`\n> is a second surface, asserted in §3 only when the build reports it.\n\nVerify the installed version matches the release tag from Step 0. If the install\nscript errors, the version mismatches, or `tillandsias` is not on `PATH`\nafterward → **file a finding (capability: `release`, `install`) and STOP**;\nthe rest of the smoke is invalid on a bad install.\n\n### 1s — Verify the SIGNATURE of the artifact this lane installed (1273-4mak)\n\nUntil this section existed the smoke verified INTEGRITY and never AUTHENTICITY.\n`install.sh` checks the asset's SHA256 against a `SHA256SUMS` fetched from the\nsame place as the asset, which is self-consistent by construction: a substituted\nasset served with a regenerated manifest passes. The `.cosign.bundle` beside\nevery asset is the only artifact in the set that answers *who produced this*,\nand nothing read one — on any lane, for any release, ever. It was declared\n\"NOT CHECKED\" in the 08-28 Linux and Windows reports and in the 09-19 macOS\nreport, three platforms, three times, and stayed open: a gap everyone declares\nand nobody closes is a missing GATE, not a missing observation.\n\n**Two facts measured on v56.9.19.2 that decide the shape of these blocks:**\n\n- **Every asset has its own `\u003Casset>.cosign.bundle`** (32 assets). That is what\n  these blocks verify.\n- **`SHA256SUMS` and `SHA256SUMS-macos` have NO bundle; only\n  `SHA256SUMS-windows` does.** So \"verify the manifest and trust it for every\n  asset it lists\" is not available on the Linux or macOS lanes. Verify the\n  ARTIFACT THIS LANE INSTALLED, against its own bundle.\n\n**The precondition is probed, never inferred from an exit code.** The release's\n`verify.sh` exits 1 both when cosign is MISSING and when a signature is BAD, and\nthose need opposite responses — one is \"this run cannot answer the question\",\nthe other is \"this artifact is not what it claims\". A block that reads rc=1 and\nreports a failure turns a floor host without cosign into a fake security\nincident; one that swallows rc=1 turns a bad signature into a pass. So each\nblock asks `command -v cosign` FIRST.\n\n**`cosign:could-not-run:\u003Creason>` IS NOT A PASS.** It is not a failure either —\n`command -v cosign` returns nothing on macneo and on yoga today, and a host\nwithout the tool has not found a bad signature, it has found nothing. It is a\nTHIRD verdict, and §5 requires it in the report's opening lines so a run that\ncould not verify cannot be filed as an unqualified PASS. That requirement is the\npart that closes this gap rather than re-declaring it.\n\nLinux — use the release's own `verify.sh`, which ships with every release:\n\n```bash\ncd \"$(mktemp -d)\" || exit 1\nASSET=tillandsias-linux-x86_64        # what install.sh actually downloads\nif ! command -v cosign >\u002Fdev\u002Fnull 2>&1; then\n  echo \"cosign:could-not-run:cosign-absent\"\nelse\n  curl -fsSL -O \"$SMOKE_BASE\u002Fverify.sh\" \\\n    && curl -fsSL -O \"$SMOKE_BASE\u002F$ASSET\" \\\n    && curl -fsSL -O \"$SMOKE_BASE\u002F$ASSET.cosign.bundle\" || {\n         echo \"cosign:could-not-run:asset-or-bundle-download-failed\"; }\n  if [ -f \"$ASSET.cosign.bundle\" ]; then\n    if bash verify.sh \"$ASSET\"; then echo \"cosign:verified:1\u002F1\"\n    else echo \"cosign:FAILED:$ASSET\"; fi\n  fi\nfi\n```\n\nmacOS — its own call, NOT an inherited Linux assumption. The lane verifies the\n**tar.gz the installer consumed**, not a binary it never touched:\n\n```bash\ncd \"$(mktemp -d)\" || exit 1\nASSET=\"tillandsias-tray-${SMOKE_VERSION}-macos-arm64.tar.gz\"\nif ! command -v cosign >\u002Fdev\u002Fnull 2>&1; then\n  echo \"cosign:could-not-run:cosign-absent (brew install cosign)\"\nelse\n  curl -fsSL -O \"$SMOKE_BASE\u002Fverify.sh\" \\\n    && curl -fsSL -O \"$SMOKE_BASE\u002F$ASSET\" \\\n    && curl -fsSL -O \"$SMOKE_BASE\u002F$ASSET.cosign.bundle\" || {\n         echo \"cosign:could-not-run:asset-or-bundle-download-failed\"; }\n  if [ -f \"$ASSET.cosign.bundle\" ]; then\n    if bash verify.sh \"$ASSET\"; then echo \"cosign:verified:1\u002F1\"\n    else echo \"cosign:FAILED:$ASSET\"; fi\n  fi\nfi\n```\n\n`verify.sh` is bash and runs under macOS's bash 3.2, which is why this lane may\ncall it — but it is called HERE, on this lane's own artifact, so a future change\nto the Linux block cannot silently redefine what macOS verified.\n\nWindows PowerShell — `verify.sh` is bash, so this lane calls cosign directly:\n\n```powershell\n$asset = \"tillandsias-windows-x64.zip\"\nif (-not (Get-Command cosign -ErrorAction SilentlyContinue)) {\n  \"cosign:could-not-run:cosign-absent (winget install sigstore.cosign)\"\n} else {\n  $tmp = New-Item -ItemType Directory -Path (Join-Path $env:TEMP ([guid]::NewGuid()))\n  Set-Location $tmp\n  curl.exe -fsSL -O \"$env:SMOKE_BASE\u002F$asset\"\n  curl.exe -fsSL -O \"$env:SMOKE_BASE\u002F$asset.cosign.bundle\"\n  if (Test-Path \"$asset.cosign.bundle\") {\n    cosign verify-blob --bundle \"$asset.cosign.bundle\" `\n      --certificate-identity-regexp 'https:\u002F\u002Fgithub\\.com\u002F8007342\u002Ftillandsias\u002F' `\n      --certificate-oidc-issuer 'https:\u002F\u002Ftoken.actions.githubusercontent.com' `\n      $asset\n    if ($LASTEXITCODE -eq 0) { \"cosign:verified:1\u002F1\" } else { \"cosign:FAILED:$asset\" }\n  } else { \"cosign:could-not-run:bundle-download-failed\" }\n}\n```\n\n**A `cosign:FAILED:` line is a STOP.** File a finding (capability: `release`,\n`security`) and do not continue: an artifact whose signature does not verify\nmust not be exercised further, and the rest of the smoke would be reporting on\nsoftware of unknown origin. This is the one check whose failure is not a bug\nreport about Tillandsias but a question about what was downloaded.\n\nCarry whichever `cosign:` line this lane emitted into §5 verbatim.\n\n\n---\n\n## 2 — Full substrate reset (DESTRUCTIVE — see warning above)\n\nIf `TILLANDSIAS_DESTRUCTIVE_RESET_OK=0`, stop here, write a plan blocker, and\npush it. Otherwise run the reset immediately; on Linux this step is mandatory.\n\n```bash\n[ -n \"${BASH_VERSION:-}\" ] || { echo 'FAIL: run this block under bash — PIPESTATUS is a bash array and zsh expands it empty'; exit 2; }\n_T0=\"$(timing_now_ms)\"\nTILLANDSIAS_SMOKE_LOCK_LOG=target\u002Fsmoke-e2e\u002F00-smoke-lock.log \\\n  scripts\u002Fwith-smoke-lock.sh --name release-smoke-e2e -- \\\n  podman system reset --force 2>&1 | tee target\u002Fsmoke-e2e\u002F02-reset.log\nRESET_RC=${PIPESTATUS[0]}; printf 'reset_exit=%s\\n' \"$RESET_RC\" | tee target\u002Fsmoke-e2e\u002F02-reset-exit.txt\n  # 900-z3kv (operator ruling 2026-09-13, landed by yoga): the reset is the baseline, and\n  # an empty podman store is not a cold room — clear the host-held Vault credentials\n  # (keychain items, ~\u002F.cache\u002Ftillandsias\u002Ffallback_*, the vault-data dir) in the SAME\n  # step, or the next --init resyncs the old share and the clean room is not one\n  # (drill: plan\u002Fissues\u002Ffleet-restart-2026-09-12.md, 900-z3kv COMPLETED).\n  scripts\u002Fclear-vault-host-credentials.sh 2>&1 | tee -a target\u002Fsmoke-e2e\u002F02-reset.log\n  CLEAR_RC=${PIPESTATUS[0]}; printf 'clear_exit=%s\\n' \"$CLEAR_RC\" | tee target\u002Fsmoke-e2e\u002F02-clear-exit.txt\n  test -n \"$CLEAR_RC\" && test \"$CLEAR_RC\" -eq 0\ntiming_emit smoke-destructive-reset smoke \"$_T0\" \"${RESET_RC:-1}\" || true\ntest -n \"$RESET_RC\" && test \"$RESET_RC\" -eq 0\n```\n\nConfirm afterward that the store is empty:\n```bash\nCONTAINERS=\"$(podman ps -aq)\"; VOLUMES=\"$(podman volume ls -q)\"; IMAGES=\"$(podman images -q)\"\nprintf '[containers]\\n%s\\n[volumes]\\n%s\\n[images]\\n%s\\n' \"$CONTAINERS\" \"$VOLUMES\" \"$IMAGES\" \\\n  | tee target\u002Fsmoke-e2e\u002F02-empty-store.txt\ntest -z \"$CONTAINERS\"; test -z \"$VOLUMES\"; test -z \"$IMAGES\"\n```\n\n**`0 volumes` is not `Vault's data is gone`, and the gap ran for ~2.5\nmonths.** Every Linux pass asserted an empty podman store while `--init`\nlogged `preserving existing data volume` — both true, about different\nthings: `vault_data_volume_exists()` tests `init_cache_dir()\u002Fvault-data`, a\nHOST DIRECTORY, not a podman volume. Assert that directory is absent too, in\nthe same block as the three `test -z` lines above:\n\n```bash\nVAULT_DATA_DIR=\"${XDG_CACHE_HOME:-$HOME\u002F.cache}\u002Ftillandsias\u002Fvault-data\"\n{ echo \"[vault-data-dir]\"; ls -la \"$VAULT_DATA_DIR\" 2>&1; } | tee target\u002Fsmoke-e2e\u002F02-vault-data-dir.txt\ntest ! -e \"$VAULT_DATA_DIR\"\n```\n\n**AFTER THE REPROVISION, CHECK THAT THE IMAGES WERE REBUILT — AND SCOPE IT TO\n`localhost\u002F`.** An empty store proves the reset destroyed; it does not prove the\nreprovision rebuilt. The natural check is \"no image predates `run_start`\", and\nwritten without a scope it is WRONG in a way that reads as a failure:\n\n```bash\n# CORRECT: locally BUILT images only.\npodman images --format '{{.CreatedAt}}\\t{{.Repository}}' \\\n  | grep 'localhost\u002F' | awk -F'\\t' -v rs=\"$RUN_START_LOCAL\" '$1 \u003C rs' \\\n  | tee target\u002Fsmoke-e2e\u002F01-images-predating.txt\ntest ! -s target\u002Fsmoke-e2e\u002F01-images-predating.txt\n```\n\nA PULLED BASE IMAGE'S `CreatedAt` IS ITS UPSTREAM BUILD DATE, not the moment\nthis host fetched it. `alpine:3.20` reports its upstream build — months old —\nhowever freshly it was pulled a minute ago, and so do `caddy`, `hashicorp\u002Fvault`\nand `fedora-minimal`. Unscoped, the check reports those as \"images predating\nrun_start\" on a perfectly healthy reprovision.\n\nMEASURED on pirria 2026-09-21: 30 `localhost\u002F` tag-rows, none predating\nrun_start, beside 5 base images every one of which predates it by construction.\nThe stable-channel report claimed \"all recreated — 0 predate run_start\" over all\n15 images while its evidence file held only the 20 `localhost\u002F` lines it had\nactually examined — a true measurement described with a scope it did not have.\nEither error is available to the next reader: count the base images and report a\nfalse failure, or omit them and claim more than you measured.\n\n`scripts\u002Fclear-vault-host-credentials.sh` removes it but only best-effort —\nit is written from inside a container under a subuid, so a rootless `rm -rf`\ncan be refused and the script still exits 0 with a `warn:` line. A\n`0-volumes` PASS beside a surviving `vault-data\u002F` is a clean-room claim the\nrun cannot support (drill: plan\u002Fissues\u002Ffleet-restart-2026-09-12.md, 900-z3kv criterion 1 DECIDED: (a)).\n\nIf the reset errors or leaves residue → file a finding (capability: `podman`,\n`runtime`).\n\n> This step was prose until 727-kmks: the reset was piped to `tee` with no\n> `PIPESTATUS` capture, so a failed reset exited 0, and \"All three should be\n> empty\" was an instruction rather than an assertion. Its sibling runbook\n> (`build-install-and-smoke-test-e2e` §2) already asserted both, which is what\n> made the gap visible — the same destruction gate was executable on one path\n> and advisory on the other, and this is the path that tests PUBLISHED releases.\n\nOn macOS, stop the tray, then destroy the VM substrate and ASSERT it is gone.\n\nThe paths are correct as written and match the source of truth\n(`status_item.rs:367`, `diagnose.rs:71`, `scripts\u002Funinstall.sh:19` — all\nlowercase `tillandsias`). What was missing is the ASSERTION: this was one prose\nsentence while the Linux branch above captures `PIPESTATUS` and then proves the\nstore is empty. That asymmetry is exactly what the 727-kmks note describes, one\nlayer down — and this is the path that tests PUBLISHED releases, so a removal\nthat silently matched nothing would let the smoke run against a pre-existing\nmulti-GiB VM image while reporting a clean-room result. A false PASS on the\ndestruction precondition is worse than a red run, because it gates promotion.\n\n```bash\nscripts\u002Fe2e-step2-macos.sh target\u002Fsmoke-e2e\ntest ! -e \"$HOME\u002FLibrary\u002FApplication Support\u002Ftillandsias\"\nMACOS_RESIDUE=\"$(cat target\u002Fsmoke-e2e\u002F02-macos-residue.txt)\"\ntest -z \"$(printf '%s' \"$MACOS_RESIDUE\" | tail -n +2)\"\n```\n\nIf residue survives → file a finding (capability: `macos`, `runtime`) and do NOT\ncontinue.\n\n> A NOTE ON WHAT DID NOT NEED FIXING, so nobody re-opens it (889-bx99,\n> retracted). This step was reported as carrying a case bug — capital-`T`\n> `Tillandsias` on disk versus lowercase in the runbook. It does not. The\n> reporting host checked by typing a capital-`T` path and watching it resolve,\n> on a case-INSENSITIVE volume where any spelling resolves; `ls` of the PARENT\n> shows the stored name is lowercase, matching the code. When testing a\n> case-sensitivity hypothesis, read the stored name — a path you typed yourself\n> proves only that the filesystem folded it.\n\nOn Windows, FIRST snapshot the builder distro's disk, so §3 can prove it\nsurvived (order 1295-b4i8):\n\n```powershell\nNew-Item -ItemType Directory -Force target\\smoke-e2e | Out-Null\n$b = Get-Item -LiteralPath \"$env:LOCALAPPDATA\\tillandsias\\wsl-build\\ext4.vhdx\" -ErrorAction SilentlyContinue\n$(if ($b) { \"$($b.Length) $($b.LastWriteTimeUtc.Ticks)\" } else { 'absent' }) |\n  Set-Content target\\smoke-e2e\\02-builder-vhdx-before.txt\n```\n\nThen stop the tray, run `wsl --terminate tillandsias` followed by\n`wsl --unregister tillandsias`, tolerating an already-absent distro.\n\n**Then purge the runtime cache BY NAME (order 1295-b4i8).** This step used to\nsay only \"cache purge\", and the obvious directory,\n`%LOCALAPPDATA%\\tillandsias`, also holds `wsl-build\\ext4.vhdx`: the BUILDER\ndistro's disk (142.9 GB on yolanda), the host's gate toolchain. Measured on\nyolanda 2026-09-20: that purge was attempted and failed only because the\nbuilder was Running and held the file open. With the builder Stopped it is\ndeleted, and §2 still reports a clean reset.\n\n- DELETE: `%USERPROFILE%\\.cache\\tillandsias` and `%APPDATA%\\tillandsias`.\n- NEVER DELETE: `%LOCALAPPDATA%\\tillandsias\\wsl-build` (the builder distro),\n  nor `%LOCALAPPDATA%\\tillandsias` as a whole. The runtime distro's own disk\n  is removed by `--unregister` above, not by a directory delete.\n- Do NOT work around this by stopping the builder first: that makes the\n  destructive case the default.\n\n```powershell\nforeach ($p in @(\"$env:USERPROFILE\\.cache\\tillandsias\", \"$env:APPDATA\\tillandsias\")) {\n  if ($p -match 'wsl-build') { throw \"refusing to purge a path that names the builder: $p\" }\n  if (Test-Path -LiteralPath $p) { Remove-Item -LiteralPath $p -Recurse -Force }\n  if (Test-Path -LiteralPath $p) { throw \"runtime cache survived the purge: $p\" }\n}\n```\n\n**Then clear the host credential store, or the run is not a clean room (order\n804-ckst).** Unregistering the distro and purging the cache leave Windows\nCredential Manager untouched, and the tray treats it as authoritative:\n\n```powershell\n# 'tillandsias-vm-uuid' is deliberately PRESERVED -- it anchors the\n# INSTALLATION, not the guest, and the in-VM Vault derives its master key\n# from it. Only the two guest-vault entries go.\n#\n# ORDER 1004-vsh2. `cmdkey \u002Flist:\u003Ctarget>` ECHOES THE TARGET IN ITS HEADER\n# even when no such credential exists, so the obvious predicate\n# `$out -match [regex]::Escape($cred)` is TRUE FOR EVERY TARGET and the\n# verifier below threw on every run. Measured on yolanda 2026-09-04:\n#\n#   \u002Flist:definitely-not-a-real-target-12345  ->  exit 0, 4 lines\n#     \"Currently stored credentials for definitely-not-a-real-target-12345:\"\n#     \"* NONE *\"\n#   \u002Flist:\u003Ca target that exists>              ->  exit 0, 7 lines\n#     \"Currently stored credentials for \u003Ctarget>:\"\n#     \"    Target: \u003Ctarget>\"   \u003C- the record, and the second echo\n#\n# THE EXIT CODE DOES NOT DISCRIMINATE: cmdkey returns 0 for both, so the\n# locale-proof status predicate is not available and was not used. Measured,\n# not assumed.\n#\n# So count the ECHOES OF THE TARGET NAME, which is the one string in that\n# output that Windows does not localize: the header echoes it once; a real\n# record echoes it again on its own `Target:` line. 1 = absent, >=2 = present.\n# Do NOT test for the absence of \"* NONE *\" or match the header text -- both\n# are LOCALIZED, and an English-text predicate trades a bug that fails on\n# every run for one that fails only on some operators' machines, which is\n# strictly worse because it fails where nobody is looking.\nfunction Test-TillandsiasCredPresent([string] $target) {\n    $out = & cmdkey.exe \"\u002Flist:$target\" 2>$null\n    (($out | Where-Object { $_ -match [regex]::Escape($target) }) | Measure-Object).Count -ge 2\n}\n\nforeach ($cred in @('vault-shamir-share-v1', 'vault-root-token-v1')) {\n    if (Test-TillandsiasCredPresent $cred) { & cmdkey.exe \"\u002Fdelete:$cred\" > $null 2>&1 }\n}\n$stillThere = @('vault-shamir-share-v1', 'vault-root-token-v1') |\n    Where-Object { Test-TillandsiasCredPresent $_ }\nif ($stillThere) { throw \"host vault credentials survived the reset: $($stillThere -join ', ')\" }\n```\n\nThis is not hygiene, it is the difference between a valid result and an\ninvalid one. The 2026-08-17 run on v0.4.260817.1 claimed a \"truly cold\" run\nbecause it purged the 34.9 GB `ext4.vhdx` AND the rootfs cache — both true,\nboth irrelevant to this store. The stale share survived, the tray delivered it\ninto the fresh guest unconditionally, and the release looked healthy in the\nsmoke and then broke for the operator forty minutes later on the first GitHub\nlogin (803-49re). A \"cold\" claim without this step is a claim the run cannot\nsupport.\n\n**Use `--terminate`, NOT `wsl --shutdown` (order 802-bajv).** `--shutdown` stops\nEVERY WSL2 distro on the host, while `--unregister` only requires the target\ndistro to be stopped. A Windows host commonly also runs `tillandsias-build` —\nthe lane that builds Linux-target artifacts, kept deliberately separate so the\nsmoke cannot wipe a toolchain mid-cycle — and a global shutdown kills it for no\ntest benefit.\n\n**This step DESTROYS the model cache, and that is not a footnote (order\n806-a4tu).** On Windows the weights live at `\u002Froot\u002F.cache\u002Ftillandsias\u002Fmodels`\nINSIDE the distro's `ext4.vhdx`, so `--unregister` deletes them along with the\ndisk. Measured on yolanda 2026-08-17: ~447 MB of `nomic-embed-text` plus\n`qwen2.5:0.5b` had to be re-pulled after the reset. Every Windows run of this\nsmoke therefore starts cold BY CONSTRUCTION. Do not describe a Windows result as\na warm-cache run, and do not treat warm-vs-cold as a variable on this lane — it\nhas exactly one value. Budget the re-pull into the run, and note that a host on a\nmetered or slow link pays it every time.\n\n---\n\n## 3 — Fresh init from a pristine state\n\n```bash\n[ -n \"${BASH_VERSION:-}\" ] || { echo 'FAIL: run this block under bash — PIPESTATUS is a bash array and zsh expands it empty'; exit 2; }\n_T0=\"$(timing_now_ms)\"\nTILLANDSIAS_SMOKE_LOCK_LOG=target\u002Fsmoke-e2e\u002F00-smoke-lock.log \\\n  scripts\u002Fwith-smoke-lock.sh --name release-smoke-e2e -- \\\n  tillandsias --debug --init 2>&1 | tee target\u002Fsmoke-e2e\u002F03-init.log\nINIT_RC=${PIPESTATUS[0]}\ntiming_emit smoke-init-pristine smoke \"$_T0\" \"${INIT_RC:-1}\" || true; printf 'init_exit=%s\\n' \"$INIT_RC\" | tee target\u002Fsmoke-e2e\u002F03-init-exit.txt\ntest -n \"$INIT_RC\" && test \"$INIT_RC\" -eq 0\n```\n\n**Observe carefully.** This is the highest-signal step — a clean-room `--init`\nrebuilds every image and brings up Vault from nothing. Scan `03-init.log` (and\n`tillandsias --diagnostics` \u002F container logs) for:\n\n- non-zero exit, panics, or `Error:` lines;\n- Vault failing to initialize\u002Funseal (connection-refused loops, HTTP 400\n  \"cipher: message authentication failed\", keychain↔volume share mismatch);\n- image build failures (proxy\u002Fgit\u002Finference\u002Fforge), short-name-mode prompts,\n  registry\u002FTLS errors;\n- the enclave network failing to come up;\n- any container that exits non-zero (e.g. proxy SIGSEGV\u002F139).\n\n**File a finding for every distinct issue** (see §5). If `--init` did not reach\na healthy state, STOP here — do not proceed to Step 4; record that the smoke\nhalted at init and why.\n\n### macOS\n\n**The block above is Linux-only and there is no `tillandsias` CLI on macOS** —\nthe installed bundle ships `tillandsias-tray`. The Host Matrix has always said\nthis lane re-provisions with `--provision` + `--diagnose --json`; the step had\nno macOS block to match, so the lane the matrix promises was unexecutable as\nwritten. Added 2026-08-26, before this lane's first run against a published\nrelease.\n\n> **A 300 s `wait_phase_ready` timeout on macOS is answered FIRST by\n> `\u002Fvar\u002Flog\u002Ftillandsias-provision-marker` inside the guest** (1055-e8ie). Read\n> it with\n> `…\u002Ftillandsias-tray --exec-guest 'cat \u002Fvar\u002Flog\u002Ftillandsias-provision-marker'`.\n> It says in one file whether the cloud-init provisioning script COMPLETED,\n> and if not, the exact line it died on plus `systemctl --failed` and\n> `systemctl status` for the headless units at that moment.\n>\n> WHY THIS IS THE FIRST THING TO READ, not the last: the guest boots fine,\n> networks, reaches a login prompt and installs its binary while failing to\n> provision — because the script is `set -euo pipefail` and cloud-init does\n> NOT surface a user-script failure, so `cloud-init status` still reports\n> `done, errors: []`. Measured 2026-09-05: the script aborted at its\n> `systemctl start` of the headless units, and the readiness-service start on\n> the VERY NEXT LINE never ran, so the guest could not report Ready. Nothing\n> anywhere said so. Four hypotheses were spent before the marker existed;\n> reading it now costs one command.\n\n```bash\n[ -n \"${BASH_VERSION:-}\" ] || { echo 'FAIL: run this block under bash — PIPESTATUS is a bash array and zsh expands it empty'; exit 2; }\nAPP=\"\u002FApplications\u002FTillandsias.app\u002FContents\u002FMacOS\u002Ftillandsias-tray\"\nIMG=\"$HOME\u002FLibrary\u002FApplication Support\u002Ftillandsias\u002Frootfs.img\"\n\n# Marker to prove the image below was built AFTER the destruction, not\n# inherited from it. `test -nt` is POSIX and needs no date arithmetic.\ntouch target\u002Fsmoke-e2e\u002F03-destruction-marker\n\n\"$APP\" --provision 2>&1 | tee target\u002Fsmoke-e2e\u002F03-provision.log\nPROVISION_RC=${PIPESTATUS[0]}\nprintf 'provision_exit=%s\\n' \"$PROVISION_RC\" | tee target\u002Fsmoke-e2e\u002F03-provision-exit.txt\ntest -n \"$PROVISION_RC\" && test \"$PROVISION_RC\" -eq 0\n\n# A fresh image, not a survivor. An exit code cannot tell these apart.\ntest -f \"$IMG\"\ntest \"$IMG\" -nt target\u002Fsmoke-e2e\u002F03-destruction-marker\n\n# LAST — after every mutating step above. If anything below this line mutates\n# the host, this report is stale and the run is unfinished (the 2026-08-10\n# incident: 4\u002F4 PASS on a health check taken before one more mutating step\n# wedged the host for 25 minutes).\n_T0=\"$(timing_now_ms)\"\n\"$APP\" --diagnose --json 2>&1 | tee target\u002Fsmoke-e2e\u002F03-diagnose.json\n_rc=${PIPESTATUS[0]}\ntiming_emit smoke-health-check smoke \"$_T0\" \"${_rc:-1}\" || true\ntest -n \"$_rc\" && test \"$_rc\" -eq 0\n\njq -e '.provisioned == true'    target\u002Fsmoke-e2e\u002F03-diagnose.json\njq -e '.rootfs_present == true' target\u002Fsmoke-e2e\u002F03-diagnose.json\n# The tray's OWN version, a second surface for the step-1 assertion. Truthful\n# only since 635-bhkb; it read the frozen crate version \"0.1.0\" before.\njq -e --arg v \"${SMOKE_TAG#v}\" '.version == $v' target\u002Fsmoke-e2e\u002F03-diagnose.json\n```\n\n> **`release_tag` is NOT the release version — it is the guest image tag**\n> (`fedora-44`). Asserting it against `$SMOKE_TAG` fails for a reason that has\n> nothing to do with the release, and reads like a real defect. Measured\n> 2026-08-26 while writing this block.\n>\n> **`guest_version` and `guest_binary_staged_matches_bundle` are `null` under a\n> plain `--diagnose`** — they need a live VM, i.e. `--with-metrics`, which\n> BOOTS. Do not assert them here; a `null == null` check would pass forever\n> without ever testing anything, which is the class this runbook has already\n> been bitten by twice. Exercise the guest\u002Ftray skew check under\n> `--with-metrics` if you want it, and note that it is a mutating step, so the\n> `--diagnose` above must then be re-run after it.\n\n### Windows\n\n> **This block is not runnable on its own.** It assumes §1 installed the tray\n> and §2 unregistered the distro. Run alone it fails twice and both failures\n> lie: `Get-Command tillandsias-tray.exe -ErrorAction Stop` throws on line 2 on\n> a host where §1 never installed it, and the destruction-marker assertion\n> reports \"a survivor, not a fresh provision\" when the truth is that nothing\n> destroyed it. The runnable unit is §1 + §2 + §3, never §1 + §3 (order\n> 1004-vsh2 — an instruction to run \"§1 and §3\" was issued and measured\n> unrunnable on yolanda before it was executed).\n\n**Neither block above runs on Windows and there is no `tillandsias` CLI there\neither** — the installed surface is `tillandsias-tray.exe`, and its\nprovisioning flag is `--provision-once`, NOT the macOS `--provision` (the two\nare not interchangeable: `tillandsias-tray.exe --help`). The Host Matrix has\npromised this lane since the Windows installer shipped; no block matched it,\nso every Windows run improvised and no two runs were comparable. Added\n2026-09-04 (order 1004-fue3) from esme-windows's improvised v56.9.2.1 run on\nesmeraldinha (cold `--provision-once` exit 0 in 117 s, warm 18 s, wire Ready).\n\n```powershell\n$ErrorActionPreference = 'Stop'\n# Same resolution as §1 — the installer does not add its directory to PATH\n# (measured 2026-09-04, order 1004-vsh2), so `Get-Command` alone throws here.\n$tray = (Get-Command tillandsias-tray.exe -ErrorAction SilentlyContinue |\n    Select-Object -First 1 -ExpandProperty Source)\nif (-not $tray) { $tray = \"$env:LOCALAPPDATA\\Programs\\Tillandsias\\tillandsias-tray.exe\" }\nif (-not (Test-Path $tray)) { throw \"tray not found on PATH or at $tray (did §1 run?)\" }\n\n# Marker to prove the distro below was registered AFTER §2's unregister, not\n# inherited from it. An exit code cannot tell these apart.\nNew-Item -ItemType File -Force target\\smoke-e2e\\03-destruction-marker | Out-Null\n\n# Cold provision from pristine. `--provision-once` provisions and EXITS; it is\n# the headless form the tray's own --help prescribes for scripted use.\n& $tray --provision-once *>&1 | Tee-Object target\\smoke-e2e\\03-provision.log\n$provisionExit = $LASTEXITCODE\n\"provision_exit=$provisionExit\" | Tee-Object target\\smoke-e2e\\03-provision-exit.txt\nif ($provisionExit -ne 0) { throw \"provision-once failed (exit $provisionExit)\" }\n\n# A fresh distro, not a survivor: it must exist, and its rootfs must postdate\n# the marker (WSL2 keeps each distro's ext4.vhdx under LOCALAPPDATA).\n$distros = (wsl.exe -l -q) -replace \"`0\", '' | ForEach-Object { $_.Trim() }\nif ($distros -notcontains 'tillandsias') { throw \"distro 'tillandsias' not registered after provision\" }\n#\n# ORDER 1295-b4i8: select the disk by the distro's REGISTERED path, never by a\n# substring of a directory name. The old selector (every ext4.vhdx under\n# LOCALAPPDATA whose path contains 'tillandsias', newest first) also matches\n# the BUILDER distro at %LOCALAPPDATA%\\tillandsias\\wsl-build, and a running\n# builder writes its vhdx constantly, so the freshness check below could pass\n# on the wrong disk.\n$vhdx = $null\n$lxss = Get-ChildItem 'HKCU:\\Software\\Microsoft\\Windows\\CurrentVersion\\Lxss' -ErrorAction SilentlyContinue |\n  ForEach-Object { Get-ItemProperty $_.PSPath } | Where-Object { $_.DistributionName -eq 'tillandsias' }\nif ($lxss) {\n  $vhdxPath = Join-Path ($lxss.BasePath -replace '^\\\\\\\\\\?\\\\', '') 'ext4.vhdx'\n  if (Test-Path -LiteralPath $vhdxPath) { $vhdx = Get-Item -LiteralPath $vhdxPath }\n}\nif (-not $vhdx) { throw \"no ext4.vhdx at the registered BasePath of distro 'tillandsias'\" }\nif ($vhdx.FullName -match '\\\\wsl-build\\\\') { throw \"the tillandsias distro resolves to the BUILDER's disk $($vhdx.FullName)\" }\nif ($vhdx.LastWriteTime -lt (Get-Item target\\smoke-e2e\\03-destruction-marker).LastWriteTime) {\n  throw \"rootfs $($vhdx.FullName) predates the destruction marker — a survivor, not a fresh provision\"\n}\n\n# ORDER 1295-b4i8: the builder distro SURVIVED §1+§2+§3 untouched. Compare\n# with the snapshot §2 took before it deleted anything. Size AND mtime: a\n# deleted-and-recreated disk has a new mtime even at the same size.\nif (Test-Path target\\smoke-e2e\\02-builder-vhdx-before.txt) {\n  $before = Get-Content target\\smoke-e2e\\02-builder-vhdx-before.txt -Raw\n  $b = Get-Item -LiteralPath \"$env:LOCALAPPDATA\\tillandsias\\wsl-build\\ext4.vhdx\" -ErrorAction SilentlyContinue\n  $after = if ($b) { \"$($b.Length) $($b.LastWriteTimeUtc.Ticks)\" } else { 'absent' }\n  \"$after\" | Set-Content target\\smoke-e2e\\03-builder-vhdx-after.txt\n  if ($after -eq 'absent') { throw \"the smoke DELETED the builder distro's disk (was: $($before.Trim()))\" }\n  # A RUNNING builder writes its own disk, so byte-identity is only asserted\n  # when it is stopped. Stopped is the case the old purge destroyed.\n  $builderRunning = ((wsl.exe -l -q --running) -replace \"`0\", '' | ForEach-Object { $_.Trim() }) -contains 'tillandsias-build'\n  if (-not $builderRunning -and $after -ne $before.Trim()) {\n    throw \"builder vhdx changed while the builder was STOPPED: before=$($before.Trim()) after=$after\"\n  }\n}\n\n# Wire state at provision exit, POLLED to Ready: `--status-once --json` is\n# read-only, and Ready can lag the provision exit by a few seconds; it can\n# also LAPSE later (see the note below), so the poll starts immediately and\n# gives up loudly rather than sleeping first.\n$deadline = (Get-Date).AddSeconds(60); $status = $null; $statusExit = 1\ndo {\n  & $tray --status-once --json 2>&1 | Tee-Object target\\smoke-e2e\\03-status.json | Out-Null\n  $statusExit = $LASTEXITCODE\n  if ($statusExit -eq 0) { $status = Get-Content target\\smoke-e2e\\03-status.json -Raw | ConvertFrom-Json }\n  if ($status -and $status.phase -eq 'Ready') { break }\n  Start-Sleep -Seconds 5\n} while ((Get-Date) -lt $deadline)\n\"status_exit=$statusExit phase=$($status.phase) podman_ready=$($status.podman_ready)\" | Tee-Object target\\smoke-e2e\\03-status-summary.txt\nif ($statusExit -ne 0) { throw \"status-once failed (exit $statusExit)\" }\nif ($status.phase -ne 'Ready') { throw \"phase is '$($status.phase)' after 60 s, expected Ready\" }\nif (-not $status.podman_ready) { throw \"podman_ready is false at Ready\" }\n\n# LAST — after every mutating step above. If anything below this line mutates\n# the host, this report is stale and the run is unfinished (the 2026-08-10\n# incident, same rule as the macOS block).\n& $tray --diagnose --json 2>&1 | Tee-Object target\\smoke-e2e\\03-diagnose.json\n$diagnoseExit = $LASTEXITCODE\n\"diagnose_exit=$diagnoseExit\" | Tee-Object target\\smoke-e2e\\03-diagnose-exit.txt\n# DO NOT assert `$diagnoseExit -eq 0`, and the reason is the note above.\n#\n# MEASURED 2026-09-04 on yolanda (order 1004-vsh2), inline in ONE script with\n# nothing interposed: --status-once read Ready \u002F podman_ready=true, and\n# --diagnose seconds later exited 2 with distro_running=false and\n# wire.reachable=false. The tray log shows the wire closing ~15 s after\n# \"provision-once: VM Ready\". Nothing holds the guest open, so by the time the\n# LAST step runs the wire is legitimately down and diagnose reports that\n# truthfully. Requiring exit 0 here contradicts this block's own\n# \"Ready is not durable after --provision-once\" note, one screen up.\n#\n# So assert what diagnose is FOR at this point in the lane — a well-formed\n# report carrying this tray's identity — and record the exit code as data.\n# A missing or unparseable report is still a hard failure.\nif (-not (Test-Path target\\smoke-e2e\\03-diagnose.json)) { throw \"diagnose wrote no report\" }\n$diag = Get-Content target\\smoke-e2e\\03-diagnose.json -Raw | ConvertFrom-Json\nif (-not $diag) { throw \"diagnose report is not valid JSON (exit $diagnoseExit)\" }\nif ($diag.PSObject.Properties.Name -contains 'version') {\n  if ($diag.version -ne $SmokeTag.TrimStart('v')) { throw \"tray version '$($diag.version)' != release $SmokeTag\" }\n} else {\n  \"diagnose --json carries no 'version' field on this build — the release-tag assertion for the tray is UNMET, record it as a finding\" |\n    Tee-Object -Append target\\smoke-e2e\\03-diagnose-notes.txt\n}\n```\n\n> **Ready is not durable after `--provision-once`** (esme, finding\n> `smoke-finding\u002Fwindows-ready-not-durable-after-provision-once`, order\n> 1004-* series): nothing holds the guest open once the headless provision\n> exits, so a `--status-once` taken a minute later can read exit 1 while the\n> block above, taken immediately, reads Ready. Both are true. This block\n> asserts the state AT provision exit, which is what the lane promises; do not\n> re-run `--status-once` later and file its exit 1 as a provision failure.\n>\n> **Every assertion here reads `$LASTEXITCODE` from a native call, never\n> `$?` from a pipeline** — `$?` after `... | Tee-Object` is Tee-Object's\n> status, which is how the §1 Windows install asserted nothing for a year.\n\n---\n\n## 3b — Stop the substrate and assert every container exits cleanly\n\n**Run this after §3, before §4.** It is where order `1134-u934` was found and\nit costs one stop.\n\n**Why it is its own step rather than a line in §3.** §3 asserts that a\npristine `--init` reaches a healthy state, and it did — the run that filed\n`1134-u934` was §1\u002F§2\u002F§3 all PASS with zero occurrences of every failure class\n§3 enumerates. The defect was in SHUTDOWN, so a lane that stops at \"init was\nclean\" cannot see it in principle, however carefully it reads `03-init.log`.\nIt was found only by looking at what the tray's own `Graceful shutdown\ncompleted` line actually produced: `tillandsias-vault  Exited (137)` — killed\nafter stalling the full 30 s grace — next to `tillandsias-proxy  Exited (0)`\nin the same shutdown.\n\n**Assert BOTH halves, per container.** Elapsed alone passes a container that\nexits fast for a bad reason; exit code alone passes one that burns the whole\ngrace and is then reported 0. 137 specifically means the grace expired and the\ncontainer was SIGKILLed.\n\n```bash\n# Linux. Record the grace each container declares — they differ — then stop\n# them all and read what podman recorded, container by container.\npodman ps --format '{{.Names}}' | tee target\u002Fsmoke-e2e\u002F3b-running.txt\nfor c in $(cat target\u002Fsmoke-e2e\u002F3b-running.txt); do\n  grace=\"$(podman inspect \"$c\" --format '{{.Config.StopTimeout}}')\"\n  t0=\"$(date +%s)\"\n  podman stop -t \"$grace\" \"$c\" >\u002Fdev\u002Fnull 2>&1\n  t1=\"$(date +%s)\"\n  printf '%s elapsed=%ss grace=%ss exit=%s oom=%s\\n' \"$c\" \"$((t1 - t0))\" \"$grace\" \\\n    \"$(podman inspect \"$c\" --format '{{.State.ExitCode}}')\" \\\n    \"$(podman inspect \"$c\" --format '{{.State.OOMKilled}}')\"\ndone | tee target\u002Fsmoke-e2e\u002F3b-shutdown.txt\n\n# The verdict. A non-zero exit OR an elapsed at\u002Fabove the grace is a finding\n# per container, not a run-level FAIL — the enclave is already destroyed and\n# rebuilt by this point, so §4 may still proceed on a clean §3.\nawk '{\n  split($2, e, \"=\"); split($3, g, \"=\"); split($4, x, \"=\")\n  if (x[2] != 0 || e[2] + 0 >= g[2] + 0) { print \"FINDING: \" $0; bad++ }\n} END { printf \"3b: %d container(s) did not stop cleanly\\n\", bad + 0 }' \\\n  target\u002Fsmoke-e2e\u002F3b-shutdown.txt | tee target\u002Fsmoke-e2e\u002F3b-verdict.txt\n```\n\nA container that fails here is a **`plan\u002Fissues` work packet per §5**, and the\npacket must name the process tree, not just the exit code — read it from the\nrunning container BEFORE the stop:\n\n```bash\npodman exec \u003Ccontainer> sh -c 'for p in \u002Fproc\u002F[0-9]*; do echo \"$(basename $p) $(cat $p\u002Fcomm 2>\u002Fdev\u002Fnull)\"; done'\n```\n\n`1134-u934` is why. Its entrypoint was a PID-1 shell that trapped nothing, and\nthe pid it held was `tee`'s rather than the server's, because `$!` after a\nbackgrounded PIPELINE is the LAST stage. The obvious one-line trap forwarding\nto that pid signals `tee`, leaves the 30 s and the 137 exactly as they are, and\n**looks correct**. The tree (`1 bash \u002F 10 vault \u002F 11 tee`) is what separates\nthe two, and it is not readable from the script's text.\n\n`scripts\u002Ftest-vault-shutdown-forwards-sigterm.sh` is the standing single-\ncontainer form of this step for vault, and exits 3 (`could-not-run`) rather\nthan 0 on a host with no provisioned enclave.\n\n> **macOS and Windows.** The substrate is a Virtualization.framework VM and a\n> WSL2 distro, not host podman, so the loop above runs INSIDE the guest or not\n> at all. Neither lane asserts guest-container shutdown today; that is a\n> stated gap, not a silent pass — record it rather than reporting 3b clean.\n\n## 4 — Forge continuous-enhancement run (only if Step 3 was clean)\n\n```bash\n[ -n \"${BASH_VERSION:-}\" ] || { echo 'FAIL: run this block under bash — PIPESTATUS is a bash array and zsh expands it empty'; exit 2; }\n_T0=\"$(timing_now_ms)\"\ntiming_begin smoke-forge-lane smoke\n# 1275-ngrc: the agent-death watch runs BESIDE the lane (see §4a, third state).\nrm -f target\u002Fsmoke-e2e\u002F04-agent-watch.txt\nscripts\u002Fsmoke-agent-watch.sh watch --out target\u002Fsmoke-e2e --grace 300 > target\u002Fsmoke-e2e\u002F04-agent-watch.log 2>&1 &\n_WATCH_PID=$!\n# 1941-smkp: ONE short agent turn, never the \u002Fmeta-orchestration loop. The\n# forge's model is a hosted free tier every fleet host shares; a full loop is\n# 100+ requests per smoke, and on 2026-11-01 that ended in a 429 with\n# Retry-After 78443. The prompt spells the token out so the prompt text itself\n# can never satisfy the grep below.\nSMOKE_PROMPT='Smoke check, one turn only. Run `bash scripts\u002Fcheck-credential-channel.sh` in the checkout and show its last line. Then reply with the word SMOKE-AGENT, a hyphen, and the word OK, all on one line with no spaces. Load no skill and do nothing else.'\nTILLANDSIAS_SMOKE_LOCK_LOG=target\u002Fsmoke-e2e\u002F00-smoke-lock.log \\\n  scripts\u002Fwith-smoke-lock.sh --name release-smoke-e2e -- \\\n  env TILLANDSIAS_NO_TRAY=1 tillandsias --cloud 8007342\u002Ftillandsias --opencode --prompt \"$SMOKE_PROMPT\" 2>&1 \\\n  | tee target\u002Fsmoke-e2e\u002F04-opencode.log\nLANE_RC=${PIPESTATUS[0]}; printf 'opencode_exit=%s\\n' \"$LANE_RC\" | tee target\u002Fsmoke-e2e\u002F04-opencode-exit.txt\n# The agent answered and called a tool: the token, not the exit code.\ngrep -q 'SMOKE-AGENT-OK' target\u002Fsmoke-e2e\u002F04-opencode.log \\\n  && echo 'agent_turn=answered' || echo 'agent_turn=NO-TOKEN (finding)'\nkill \"$_WATCH_PID\" 2>\u002Fdev\u002Fnull; wait \"$_WATCH_PID\" 2>\u002Fdev\u002Fnull\n# The watch's verdict, when it issued one, IS the §4 verdict: the agent died and\n# the watch stopped the forge so the lane could return.\nif [ -f target\u002Fsmoke-e2e\u002F04-agent-watch.txt ]; then\n  printf 'lane_verdict=agent-dead-process-idling\\n' | tee -a target\u002Fsmoke-e2e\u002F04-opencode-exit.txt\n  cat target\u002Fsmoke-e2e\u002F04-agent-watch.txt\nfi\ntiming_commit smoke-forge-lane smoke \"$_T0\" \"${LANE_RC:-1}\"\n```\n\n> **THIS IS THE STEP MOST LIKELY TO LOSE ITS SUPERVISOR, so it is the one that\n> stamps** (order 1026-ps4n). `timing_begin` writes the start to disk before\n> the lane runs; `timing_commit` emits the real record and clears the stamp. If\n> the shell running this block is killed, the stamp survives and the NEXT run's\n> `timing_reap` (§0) emits `smoke-forge-lane-supervisor-lost` instead of\n> nothing. The lost record is reported under a DIFFERENT step name on purpose:\n> the recurrence rung groups by step, so a lower-bound duration from a killed\n> run can never be averaged into real `smoke-forge-lane` timings.\n>\n> **RUN IT DETACHED ON A FLOOR HOST.** A detached run survived on pirria where\n> a plain backgrounded run did not, because the kill takes the process group.\n> Detaching does not make the host less short of memory — it stops the\n> supervisor being collateral.\n>\n> **THE FORM DIFFERS BY PLATFORM AND macOS HAS NO `setsid`** (macneo,\n> 2026-09-15): `setsid nohup \u003Cscript-file> \u003C \u002Fdev\u002Fnull > log 2>&1 &` on Linux,\n> `nohup \u003Cscript-file> \u003C \u002Fdev\u002Fnull > log 2>&1 & disown` on macOS. This runbook\n> named only the Linux form, which fails outright on both Macs — and this is\n> the lane most likely to be run on one, since a curl-install smoke is floor\n> work. A script FILE and a terminal `rc=` marker are required on both.\n\n**Windows: the tray must be running, and the lane runs as a `systemd-run`\nunit inside the guest** (yolanda, v56.10.15.1, 2026-10-15). There is no host\nCLI forge lane on Windows; the lane is `tillandsias-headless --cloud \u003Cowner\u002Frepo>\n--opencode` inside the `tillandsias` distro. Two attempts were lost before the\nform below worked, and neither was a product defect:\n\n- `setsid nohup \u003Cscript> &` piped through `wsl.exe -d tillandsias -u root --\n  bash -s` dies when that wsl.exe session returns, before writing a byte.\n- A `systemd-run` unit is stopped about 20 s in when nothing holds the guest\n  open. §2 stops the tray and `--provision-once` exits, so after §3 the guest\n  idles out with the lane in it.\n\nRestart the tray first, then start the lane as a transient unit and watch it:\n\n```powershell\nif (-not (Get-Process tillandsias-tray -ErrorAction SilentlyContinue)) {\n  Start-Process \"$env:LOCALAPPDATA\\Programs\\Tillandsias\\tillandsias-tray.exe\"\n}\n# \u002Froot\u002Fsmoke\u002Flane.sh: runs the lane > \u002Froot\u002Fsmoke\u002Flane.log 2>&1, then appends rc=$?\nwsl.exe -d tillandsias -u root -- systemd-run --unit=smoke-lane --collect \u002Froot\u002Fsmoke\u002Flane.sh\nwsl.exe -d tillandsias -u root -- systemctl is-active smoke-lane   # poll until inactive\n```\n\nWrite the lane script into the guest by piping a script FILE on stdin, never\nas a `bash -c` string. The unit also survived 4% free host memory, because the\nharness's memory reaper only stops host-side shells. Record host free memory\nat the start and sample it during the lane.\n\n### 4a — What a killed supervisor looks like, and what it is not\n\n**Containers alive, wrapper gone.** Measured on pirria 2026-09-04: the agent\nharness reported \"system is running low on memory\" and killed the shell running\n§4; `journalctl` showed **no kernel oom-kill**; all six enclave containers\nincluding inference were **still up and healthy 56 minutes later**. Only the\nsupervising bash died. The same lane had completed in 71m30s that morning on\nthe same host, so the condition is **marginal, not deterministic** — it fails\nintermittently, which is worse than failing reliably, because the floor's\nlargest measurement is the one least likely to be captured.\n\nRead that state correctly: **the lane did not fail.** A reader who sees the\nwrapper gone and concludes the release is broken is reading a host-resource\nevent as a product defect. The discriminating checks, in order:\n\n```bash\npodman ps --format '{{.Names}} {{.Status}}'   # lane containers still Up? -> the lane lives\njournalctl --since '1 hour ago' | grep -iE 'oom-kill|Killed process'   # empty -> not the kernel\n```\nContainers up **and** no kernel oom-kill means the supervisor was killed by the\nagent harness, not the product and not the OOM killer. The run is unfinished,\nnot red.\n\n**THREE STATES, NOT TWO (1275-ngrc).** The checks above tell a killed\nsupervisor from a live lane. They CANNOT tell a working agent from a dead one\nwhose process idles: measured on pirria 2026-09-19, the agent died at\n17:19:38Z (`AI_RetryError: Failed after 3 attempts. Last error: Rate limit\nexceeded.`), opencode idled instead of exiting, and the lane ran 2h19m more\nwith all six containers Up, no oom-kill, the supervisor alive, and even a\n60-second CPU-delta probe reading ALIVE (an idle loop plus an hourly\n`cleanup prune=7.days` timer burns about a second a minute).\n\n| state | containers | supervisor | agent log (`04-opencode-agent.log`) |\n|---|---|---|---|\n| supervisor killed | Up | gone | — (read the lane's own evidence) |\n| agent working | Up | alive | lines keep arriving |\n| **agent dead, process idling** | Up | alive | last non-housekeeping line is a terminal ERROR, nothing after it |\n\nThe third state is what `scripts\u002Fsmoke-agent-watch.sh` detects, from the\nAGENT's log and never from the clock: a terminal error (retries exhausted, a\nbad key, no such model) that stays the agent's last line for 300s. It then\ncopies the log out of the forge to `target\u002Fsmoke-e2e\u002F04-opencode-agent.log`\n(the path inside the forge is `\u002Fhome\u002Fforge\u002F.local\u002Fshare\u002Fopencode\u002Flog\u002F`, which\nthis runbook never named before), writes `04-agent-watch.txt` beginning\n`refused:smoke-forge-lane:agent-dead-process-idling` with the error line, and\nstops the forge container so the lane returns in minutes instead of never.\n**Do not replace this with a timeout.** A budget tuned to the ~70-minute\nworking figure kills long healthy lanes and still waits 70 minutes to notice a\ndeath at minute 2; any agent activity after an error resets the watch, which\nis the negative control (`scripts\u002Ftest-smoke-agent-watch.sh` arm 4).\nTo classify a lane by hand: `scripts\u002Fsmoke-agent-watch.sh classify\ntarget\u002Fsmoke-e2e\u002F04-opencode-agent.log`.\nLIMIT, by name: the watch finds the forge by `podman ps` on THIS host, so on\nmacOS and Windows (forge inside the VM) it finds nothing and the lane behaves\nas before; the log path above is still where to look.\n\n**The memory floor this step needs.** The forge lane brings up six containers\n(vault, proxy, router, git, inference, forge). Measured on **pirria, 15 GiB\ntotal, 4 cores**: the lane itself completes, and it is the *supervisor* that\ngets sacrificed under pressure — so 15 GiB is **at** the boundary, not below\nit. No host with less has been measured, and no host above 16 GiB has reported\nthis, so the honest statement is a boundary observation and not a threshold:\n**at 15 GiB the wrapper is collateral; the number at which it stops being is\nunmeasured.** Do not invent one. If a host with 8 or 32 GiB runs this step,\nrecord which side of the line it lands on and the floor gets a real threshold\ninstead of a single point.\n\n> The guard and the `LANE_RC` capture arrived with the timing wrapper\n> (1013-qv7c). This block had neither: it piped to `tee` and recorded no status\n> at all, so a forge lane that failed to launch left the same evidence as one\n> that completed. Emitting a duration without an exit code would have recorded\n> *how long the failure took* and called it a measurement, so the capture is\n> part of the record, not scope creep — the 727-kmks assertion shape, arriving\n> at the one step that never had it.\n\n### 4a-cold — `opencode_exit=0` IS NOT THE PASS CONDITION ON A POST-RESET HOST\n\n**Read this before you read `LANE_RC`.** Order 1190-swen; coordinator ruling\n2026-09-14, option (a).\n\n§2 reset the substrate, so Vault is **cold** and holds no GitHub token. The\nin-forge lane therefore reaches the Credential Channel Guard and **hard-stops\nthere, deterministically, before any committable work**. That is not a\ndegraded run. On a post-reset host it is the *only* correct outcome, and it is\nwhat §4 exercises: enclave bring-up, and the guard. Nothing past them.\n\nThe failure this replaces is a reader — human or orchestrator — seeing\n`opencode_exit=0` and concluding the forge did a cycle's worth of work. It did\nnot. It could not have.\n\n**ASSERT THE GUARD LINE, NEVER THE EXIT CODE:**\n\n```bash\n# PASS on a cold (post-§2-reset) host: the lane came up and stopped AT the guard.\nif grep -qE 'blocked:upstream-(no-credential|auth-unpublished)' target\u002Fsmoke-e2e\u002F04-opencode.log; then\n    echo \"cold-host PASS: lane reached the credential guard and stopped there\"\nelse\n    echo \"FINDING: no credential-guard stop in the lane log on a post-reset host.\"\n    echo \"  A cold Vault holds no token, so the guard MUST have refused.\"\n    echo \"  Either the guard was skipped, or this room was not clean.\"\nfi | tee target\u002Fsmoke-e2e\u002F04a-cold-host-outcome.txt\n\n# NEGATIVE CONTROL — exit 0 WITHOUT the guard line FAILS the assertion.\n# This is the whole point: the two are independent, and only the second is evidence.\ngrep -qE 'blocked:upstream-(no-credential|auth-unpublished)' target\u002Fsmoke-e2e\u002F04-opencode.log   || echo \"negative control fired: opencode_exit=${LANE_RC} is NOT a pass on its own\"\n```\n\nThen confirm the lane left nothing behind, which is the other half of \"stopped\nbefore committable work\":\n\n```bash\n{\n  echo \"git_status_empty=$([ -z \"$(git status --porcelain)\" ] && echo yes || echo no)\"\n  echo \"head_matches_origin=$([ \"$(git rev-parse HEAD)\" = \"$(git rev-parse origin\u002Flinux-next)\" ] && echo yes || echo no)\"\n  # ORDER 1190-swen, CORRECTED 2026-09-20. This greped `^MO-FULL: `\n  # GENERICALLY and was WRONG: a guard-stopped cycle is SUPPOSED to emit\n  # `MO-FULL: BLOCKED`. The meta-orchestration skill sanctions it explicitly\n  # (`MO_FULL_DISPOSITION=BLOCKED scripts\u002Fmo-full-attest.sh self`, and \"BLOCKED\n  # is exempt: a cycle saying it did not finish must still be able to say so\").\n  # MEASURED on pirria 2026-09-20: a lane that behaved exactly as designed —\n  # enclave up, `blocked:upstream-no-credential`, nothing claimed or pushed —\n  # emitted `MO-FULL: BLOCKED 7e33445f9 linux-next 7e33445f9` and this check\n  # flagged it, which would send the next reader to investigate a correct run.\n  # What must be absent is a COMPLETE marker: that is the claim a guard-stopped\n  # cycle has no right to make.\n  echo \"mo_full_complete_present=$(grep -qE '^MO-FULL: COMPLETE ' target\u002Fsmoke-e2e\u002F04-opencode.log && echo yes || echo no)\"\n  echo \"mo_full_blocked_present=$(grep -qE '^MO-FULL: BLOCKED ' target\u002Fsmoke-e2e\u002F04-opencode.log && echo yes || echo no)\"\n} | tee target\u002Fsmoke-e2e\u002F04a-cold-host-residue.txt\n```\n\nExpected on a cold host: `yes`, `yes`, **`no`** for COMPLETE, and either value\nfor BLOCKED. The absent COMPLETE marker is correct and loud — a lane that\nstopped at the guard has not completed its exit contract and must not claim it\ndid. A `BLOCKED` marker is NOT a finding: it is the cycle correctly saying it\ndid not finish, and a run that emits one has behaved better than a run that\nemits nothing, because the disposition is then on the record rather than\ninferred from silence.\n\nMEASURED on pirria 2026-09-14 (`04-opencode.log:848-862`): the guard answered\n`blocked:upstream-no-credential` (exit 1); the mirror published\n`refs\u002Ftillandsias\u002Fupstream-auth\u002Fno-credential`, fresh; the in-forge agent\nclaimed nothing, drained nothing, filed nothing, committed nothing, left\n`git status` empty and `HEAD == origin\u002Flinux-next`, and emitted no `MO-FULL:`\nmarker — correctly refusing to commit from a container about to be destroyed.\nThe HOST could push at that same moment\n(`00-credential-channel.txt` = `ok:gh-keyring-push-verified`). **The asymmetry\nis the design, not a defect**, and the in-forge handling is not what needed\nfixing — the runbook's pass condition was.\n\n**Option (b) — issue a scoped token after §3 — was DECLINED** by the\ncoordinator, and the reason generalises: it would test a different machine than\nthe one this smoke exists to prove. **A clean room that holds a credential is\nnot a clean room.**\n\nThis launches the full enclave + the OpenCode agent inside the forge, which runs\n[[forge-continuous-enhancement]] against the `tillandsias` checkout. Two streams\nof findings come out of this step:\n\n- **Forge-internal findings** — issues the in-forge agent surfaces while doing\n  continuous-enhancement work (build warnings, slow\u002Ffragile Containerfile steps,\n  failed `dnf` migrations, telemetry gaps). The forge agent should itself file\n  these as plan\u002Fissues; if it cannot push from inside the enclave, capture its\n  reported findings from `04-opencode.log` and file them on its behalf.\n- **Harness findings** — issues YOU (the agent running this skill) observe about\n  the run itself: the agent failing to launch, the prompt not being honored,\n  remote-projects not listing, git-mirror push needing interactive auth, the\n  maintenance\u002Fagent terminal stealing focus, vsock\u002Fcontrol-wire version skew\n  (e.g. `wire_version mismatch: server=N, sidecar=M`), etc.\n\nFile every distinct issue from both streams (see §5).\n\n### 4b — First-launch egress assertion (order 298 regression)\n\nWhile Step 4's forge lane is up (right after the agent terminal appears, or as\nsoon as `04-opencode.log` shows the lane container starting), assert from the\nHOST that the shared proxy survived launch — v0.3.260711.8 tore down\n`tillandsias-proxy` during first-launch bring-up, so every pristine install got\na forge whose baked proxy env resolved to nothing (`Could not resolve proxy:\nproxy`), and the fail-soft harness installer then shipped zero harnesses:\n\n```bash\npodman ps --format '{{.Names}}' | tee target\u002Fsmoke-e2e\u002F04b-containers.txt\ngrep -q '^tillandsias-proxy$' target\u002Fsmoke-e2e\u002F04b-containers.txt \\\n  && echo \"egress assertion: proxy alive alongside lane\" \\\n  || echo \"FINDING: tillandsias-proxy ABSENT while a lane container runs (order 298 regression)\"\n```\n\nIf the proxy is absent, also check `04-opencode.log` for the unconditional\nteardown trace (`no active lane containers; cleaning project + shared stack`)\nto identify the actor, and file the finding with that line as evidence.\n\n**The trace alone is NOT the finding.** A healthy run prints that same line\nWITH a `keeping application-lifetime: tillandsias-vault, tillandsias-proxy,\ntillandsias-router, tillandsias-nix-cache` clause — that is the order-298 fix\nworking, not regressing (pirria, v56.9.2.1 floor smoke, 2026-09-04: the line\nwas present, the proxy was alive, and a reader grepping the string alone would\nhave filed a false regression). The assertion is proxy LIVENESS while the lane\nis up, taken by a concurrent watcher, never a grep for the trace. Take it while\nthe lane is up, not after: lane-scoped containers are torn down on exit by\ndesign, and only the application-lifetime set must survive.\n\n### 4c — Final health check (Linux)\n\n**LAST — after every mutating step above**, the same rule the macOS and Windows\nlanes already carry (the 2026-08-10 incident: 4\u002F4 PASS on a health check taken\nbefore one more mutating step wedged the host for 25 minutes).\n\n```bash\n[ -n \"${BASH_VERSION:-}\" ] || { echo 'FAIL: run this block under bash — PIPESTATUS is a bash array and zsh expands it empty'; exit 2; }\n_T0=\"$(timing_now_ms)\"\n{\n  echo \"=== containers ===\"\n  podman ps --format '{{.Names}}\\t{{.Status}}'\n  echo \"=== vault health ===\"\n  podman exec tillandsias-vault sh -c \\\n    'curl -s --cacert \u002Frun\u002Fsecrets\u002Ftillandsias-vault-tls-ca https:\u002F\u002F127.0.0.1:8200\u002Fv1\u002Fsys\u002Fhealth?standbyok=true'\n  echo\n  echo \"=== version ===\"\n  tillandsias --version\n} 2>&1 | tee target\u002Fsmoke-e2e\u002F05-health.log\n_rc=${PIPESTATUS[0]}\ntiming_emit smoke-health-check smoke \"$_T0\" \"${_rc:-1}\" || true\ntest -n \"$_rc\" && test \"$_rc\" -eq 0\ngrep -q '\"sealed\":false' target\u002Fsmoke-e2e\u002F05-health.log\ngrep -q '^tillandsias-proxy' target\u002Fsmoke-e2e\u002F05-health.log\n```\n\nExpect the application-lifetime set (`tillandsias-vault`, `tillandsias-proxy`,\n`tillandsias-router`) up and healthy, and the lane-scoped ones\n(`tillandsias-inference`, `tillandsias-git-*`, the forge) gone — §4b's teardown\nis by design, so their ABSENCE here is the pass, not a finding.\n\n> **There was no Linux health-check block until 1013-qv7c**, though the Host\n> Matrix promises the step and the macOS\u002FWindows lanes both implement it. The\n> gap is not cosmetic: `tillandsias --diagnostics` reads like the command to\n> reach for and is NOT one — it is a MODIFIER (\"stream real-time logs from all\n> enclave containers (implies `--debug`)\"), so bare, with no subcommand, it\n> falls through to the default tray launch and starts a cloud refresh. Measured\n> on pirria 2026-09-04, which ran it as the final health check of the\n> v56.9.2.1 smoke and had to kill it: a \"health check\" that mutates is exactly\n> what the LAST rule above exists to prevent. The block above is what that run\n> used instead, after the fact.\n\n## 5 — File the findings report\n\n> **This heading did not exist until order 1189-7yvu\u002F1190-swen.** Five places\n> in this runbook say \"see §5\" or \"the §5 report\" (§0.2b, §3, §3b, §4, §4a-cold)\n> and a reader following any of them found no §5 — the section was here,\n> unnumbered, after §4c. A cross-reference to a section that cannot be located\n> is the cheapest kind of broken instrument.\n\n**The report MUST open with these three lines**, before any packet:\n\n```markdown\n- run_start: \u003Cthe `run_start=` value from target\u002Fsmoke-e2e\u002F00-run-start.txt>\n- evidence_dir: target\u002Fsmoke-e2e   (previous runs archived under _archived-\u003Cts>\u002F)\n- forge_lane_outcome: \u003Csee below — required whenever §4 ran>\n- signature_verification: \u003Cthe `cosign:` line §1s emitted, VERBATIM — required always>\n```\n\n`signature_verification` carries §1s's line unchanged: `cosign:verified:\u003Cn>\u002F\u003Cn>`,\n`cosign:could-not-run:\u003Creason>`, or `cosign:FAILED:\u003Casset>` (order 1273-4mak).\n\n**A run whose line is `cosign:could-not-run:` MUST NOT be reported as an\nunqualified PASS.** Write the verdict as `PASS (signatures unverified: \u003Creason>)`.\nThis is the requirement that closes the gap rather than re-declaring it: the\n08-28 Linux, 08-28 Windows and 09-19 macOS reports all recorded the missing\nsignature check honestly, under \"NOT CHECKED\", and the gap still shipped three\ntimes — because declaring it cost nothing and the headline still said PASS.\nA reader who sees only the verdict must not be able to miss that authenticity\nwas not established.\n\n`could-not-run` is NOT a failure. A host without cosign has not found a bad\nsignature; it has found nothing, and reporting nothing as a failure would make a\nfloor host look like a security incident. It is a third verdict, and it must be\nvisible.\n\n**The report MUST NOT cite an evidence file older than `00-run-start.txt`**\n(order 1044-na6u). Before writing any PASS, list the files that predate the\nround; each one is a leak from an earlier round, and the step it names counts\nas NOT RUN, whatever the file says:\n\n```bash\nfind target\u002Fsmoke-e2e -maxdepth 1 -type f ! -newer target\u002Fsmoke-e2e\u002F00-run-start.txt ! -name 00-run-start.txt -print\n```\n\n```powershell\n$rs = (Get-Item target\\smoke-e2e\\00-run-start.txt).LastWriteTimeUtc\nGet-ChildItem target\\smoke-e2e -File | Where-Object { $_.Name -ne '00-run-start.txt' -and $_.LastWriteTimeUtc -le $rs } | ForEach-Object FullName\n```\n\nEmpty output is the only answer that lets a file be cited. A missing\n`00-run-start.txt` means no file can be cited at all: the round has no start\nto compare against.\n\n`run_start` is what makes every other file in the evidence directory checkable\n(order 1189-7yvu). Without it a reader cannot tell this run's `03-init-exit.txt`\nfrom a previous run's, because they have the same name — and on pirria\n2026-09-14 a 2026-09-13 `init_exit=0` was read as that run's result while its\n`--init` was still building the proxy image.\n\n`forge_lane_outcome` must say, **in words a reader cannot mistake for a\ncompleted cycle** (order 1190-swen), which of these happened:\n\n- `cold-host guard stop (EXPECTED PASS)` — the lane brought the enclave up and\n  stopped at the Credential Channel Guard with\n  `blocked:upstream-no-credential`. Nothing was claimed, drained, filed or\n  committed; the tree is pristine; **no `MO-FULL:` marker was emitted, and its\n  absence is correct.** On a post-§2-reset host this is the expected outcome,\n  not a partial one. Say so explicitly — do NOT write \"forge run clean\", which\n  reads as a cycle's worth of work.\n- `completed cycle` — only legitimate if the lane got past the guard, which on\n  a properly cold host it cannot. If you are writing this after a §2 reset,\n  something held a credential and **the room was not clean** — that is a\n  finding, not a pass.\n- `supervisor lost` — see §4a; containers up and no kernel oom-kill means the\n  run is unfinished, not red.\n- `agent dead, process idling` — `04-opencode-exit.txt` carries\n  `lane_verdict=agent-dead-process-idling`; report the error line from\n  `04-agent-watch.txt` and cite `04-opencode-agent.log`. The lane ended BECAUSE\n  the agent died, so it is a verdict on the agent run (red unless the error is\n  the release's declared known red), never \"unfinished\".\n\n**Never report the forge lane from `opencode_exit` alone.** Exit 0 and a\nguard-stop are the same number.\n\nEach finding becomes a `### Work Packet:` entry so `\u002Fadvance-work-from-plan` can\nclaim and fix it. Append packets to a dated, **host-qualified** smoke report:\n\n```\nplan\u002Fissues\u002Fsmoke-e2e-findings-\u003CRELEASE_TAG>-\u003CDATE>-\u003Chost_kind>-\u003Chost_id>.md\n```\n\ne.g. `smoke-e2e-findings-v56.9.11.1-2026-09-12-macos-macbookair.md`.\n\n**THE HOST FIELDS ARE NOT DECORATION — WITHOUT THEM TWO LANES COLLIDE IN GIT.**\nThis template read `\u003CRELEASE_TAG>-\u003CDATE>` until 2026-09-12, while the convention\nin practice had always carried a host (`plan\u002Fsmoke-e2e-v0.4.260815.1-windows.md`\nin-tree; the README row for v0.4.260826.1 cites `…-macos-…-macbook.md`,\n`…-windows-…-yolanda.md`, `…-linux-…-yoga.md`). A three-platform release asks\nevery lane to smoke the same tag on the same day, so the dropped field made a\ncollision *certain*, not unlucky: on 2026-09-12 yoga's Linux report and\nmacbookair's macOS report were both written to\n`smoke-e2e-findings-v56.9.11.1-2026-09-12.md`, and\n`land-on-platform-branch.sh` refused with `refused:land:trunk-merge-conflict`\n(add\u002Fadd). Recorded on order 1004-fue3.\n\n**On such a conflict, KEEP BOTH LANES' REPORTS.** The conflict surfaces at LAND\ntime, on a host that did nothing wrong, and the obvious resolution — take one\nside — silently destroys another platform's entire smoke result, including its\nNOT CHECKED list and any findings only that platform could have seen. Give each\nside its host-qualified name; never resolve by choosing. If one side already\nsits at an unqualified path on trunk, leave it there (renaming another host's\nlanded file is that host's call) and qualify yours.\n\nPacket template (status `ready` so it is immediately claimable):\n\n```markdown\n### Work Packet: smoke-finding\u002F\u003Cshort-slug>\n\n- id: `smoke-finding\u002F\u003Cshort-slug>`\n- owner_host: linux            # or any \u002F macos \u002F windows\n- capability_tags: [rust, podman, vault, testing, release]   # intersect what's needed\n- status: ready\n- discovered_by: `\u002Fsmoke-curl-install-and-test-e2e` on release `\u003CRELEASE_TAG>`\n- evidence:\n  - `target\u002Fsmoke-e2e\u002F03-init.log:\u003Cline>` — \u003Cone-line excerpt>\n- repro:\n  - smallest command that reproduces (e.g. `tillandsias --debug --init`)\n- next_action: >\n    \u003Csmallest concrete diagnostic or fix the next worker should attempt>\n- events:\n  - type: discovered\n    ts: `\u003CISO-8601-UTC>`\n    agent_id: `\u003Cyour-agent-id>`\n    host: linux\n```\n\nRules for good findings:\n\n- **One issue per packet.** Split compound failures.\n- **Always include a repro and a log excerpt.** A finding with no evidence is\n  noise; cite `target\u002Fsmoke-e2e\u002F*.log:\u003Cline>`.\n- **Redact secrets.** Never paste tokens or unredacted push URLs into a packet.\n- **De-duplicate.** Before filing, grep `plan\u002Fissues\u002F` for an existing packet on\n  the same symptom; if found, append an `events:` note instead of a new packet.\n- **No silent passes.** If the smoke ran clean end-to-end, still write a\n  one-line PASS entry to the report (release tag + \"init clean\") so the\n  convergence record shows the release was exercised. **Do not write \"forge run\n  clean\"** — state the `forge_lane_outcome` from the top of this section\n  instead. On a post-reset host the honest line is \"init clean; forge lane\n  stopped at the credential guard as expected\", and the old wording is exactly\n  the sentence order 1190-swen exists to remove.\n- **Cite the release's ledger row and account for its claims** (order 380). The\n  report carries a short `## Ledger claims` section listing each claim from the\n  row read in §0.2b under exactly one of three headings:\n  **EXERCISED** (this lane checked it — say how),\n  **NOT APPLICABLE** (the claim is another platform's, or another lane's), or\n  **NOT CHECKED** (this lane could have and did not).\n  The third heading is the one that earns this section. A report with no\n  NOT-CHECKED list reads as though the run covered everything the release\n  claimed, and a reader has no way to tell that from a run that simply never\n  looked. Naming the gaps is what makes a PASS mean something narrower and\n  truer than \"the release works\".\n\nCommit the report (and any forge-pushed findings) to the appropriate host branch (`linux-next`, `osx-next`, or `windows-next`) and push. **DO NOT push directly to `main` or open PRs against `main`.** Update the host work-queue\nledger with a one-line outcome, exactly as `\u002Fadvance-work-from-plan` §6\nprescribes.\n\nBefore a successful exit, the PASS\u002Ffinding report must be committed and pushed.\nDo not leave a local-only release smoke result.\n\n---\n\n## Guardrails\n\n- **Never** skip Step 2 on a Tillandsias smoke host because it wipes Podman.\n  The wipe is the precondition that makes the test meaningful. The only\n  supported opt-out is `TILLANDSIAS_DESTRUCTIVE_RESET_OK=0`, which must produce\n  a pushed plan blocker.\n- **Never** substitute a local `target\u002F` build for the curl-installed binary —\n  that defeats the purpose (testing the published artifact).\n- **Never** push fixes from this skill. This skill only *installs, observes, and\n  files*. Fixes are the job of `\u002Fadvance-work-from-plan` workers claiming the\n  packets you filed.\n- **Never** paste secrets into logs or packets; redact tokens and auth URLs.\n- **Never** push directly to `main` or create PRs to `main`. Always use the appropriate host branch (`linux-next`, `osx-next`, or `windows-next`).\n- Findings are intake, not authority — durable conclusions still land in\n  `openspec\u002Fspecs\u002F`, `methodology\u002F`, or cheatsheets via the normal flow.\n\n## How orchestrators steer this skill\n\nThe canonical file lives at `skills\u002Fsmoke-curl-install-and-test-e2e\u002FSKILL.md`;\neach runtime accesses it via a symlink under its `skills\u002F` directory. An\norchestrator can set `TILLANDSIAS_DESTRUCTIVE_RESET_OK=0` for a non-smoke host,\nchange the forge prompt in Step 4, or adjust the finding capability_tags\nbetween iterations.\n",{"name":5,"description":7},"main","bf1668fd1df1b3363b826d083f060234cd2e1d0c","skills\u002Fsmoke-curl-install-and-test-e2e",0,"https:\u002F\u002Fgithub.com\u002F8007342\u002Ftillandsias","https:\u002F\u002Fgithub.com\u002F8007342","https:\u002F\u002Ftlatoani.net","I used to be a software engineer.","2026-11-12 04:10:03",{"source":8,"skillName":5,"commands":62,"prompt":72,"zipAvailable":73},[63,66,69],{"tool":64,"command":65},"npx","npx skills add 8007342\u002Ftillandsias --skill smoke-curl-install-and-test-e2e",{"tool":67,"command":68},"bunx","bunx skills add 8007342\u002Ftillandsias --skill smoke-curl-install-and-test-e2e",{"tool":70,"command":71},"pnpm","pnpm dlx skills add 8007342\u002Ftillandsias --skill smoke-curl-install-and-test-e2e","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002F8007342\u002Ftillandsias\u002Fblob\u002Fmain\u002Fskills\u002Fsmoke-curl-install-and-test-e2e\u002FSKILL.md",true,[],[76,104,123,146,158,178],{"skillNo":77,"name":78,"nameZh":6,"description":79,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":80,"licenseFileUrl":6,"sourceHtmlUrl":81,"categories":82,"keywords":83,"publishedAt":47},"01M6H60M8Y949GNECQVKAYFNH3","start-a-new-project","Use when the user wants to start a new project, asks how to begin, or is in an empty or nearly empty repository (\"how do I start?\", \"I want to build an app\", \"help me set up a new project\"). Guides them, in plain language, to describe the app as specs first (spec-driven development with OpenSpec), recommends Flutter (and the Flame engine for games and graphics), and sets up specs, a plan folder for longer work, and a README. Works for any project, not only Tillandsias.","MIT","https:\u002F\u002Fgithub.com\u002F8007342\u002Ftillandsias\u002Fblob\u002Fmain\u002Fskills\u002Fstart-a-new-project\u002FSKILL.md",[],[84,85,86,87,88,89,90,91,92,93,94,95,96,97,98,99,100,101,102,103],"start","new project","project","start a new project","development","SET","flutter","README","use","only","up","openspec","do","as","app","how to","flame","games","spec-driven","for",{"skillNo":105,"name":106,"nameZh":6,"description":107,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":80,"licenseFileUrl":6,"sourceHtmlUrl":108,"categories":109,"keywords":110,"publishedAt":47},"01M6H609K8BAW74S59C68QRKC3","project-discipline","How THIS project wants its branches and pushes shaped — read its branch-discipline level (0 push to main freely; 1 integration branch + pull requests; 2 work refs into the integration branch), the drift between what it declares and what its history shows, which hooks it has installed, how to raise it, and the work format each hook refusal asks for. Every refusal that says \"use \u002Fproject-discipline for instructions\" resolves here. Works for any project in a Tillandsias forge, not only Tillandsias.","https:\u002F\u002Fgithub.com\u002F8007342\u002Ftillandsias\u002Fblob\u002Fmain\u002Fskills\u002Fproject-discipline\u002FSKILL.md",[],[111,86,112,113,114,115,34,116,37,117,92,93,118,52,119,120,99,121,122,103],"discipline","project discipline","pull requests","pull","push","history","branch","hooks","branches","drift","requests","which",{"skillNo":124,"name":125,"nameZh":6,"description":126,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":127,"categories":128,"keywords":129,"publishedAt":47},"01M6H605G5NAKPP1RE10T3716W","probe-macos-tray-on-windows","Daily cross-platform health probe — compiles the macos-tray crate from the local Windows host. Expected to succeed as a stub (the crate is fully cfg-gated for non-macOS); a build failure here means a shared module or crate broke for everyone. Files structured findings to plan\u002Fissues\u002Fprobe-macos-tray-on-windows-findings-\u003CDATE>.md.","https:\u002F\u002Fgithub.com\u002F8007342\u002Ftillandsias\u002Fblob\u002Fmain\u002Fskills\u002Fprobe-macos-tray-on-windows\u002FSKILL.md",[],[130,131,132,133,38,134,135,36,136,137,138,139,140,141,142,143,97,144,103,145],"macos","windows","probe","probe macos tray on windows","CFG","health","daily","files","build","gated","local","shared","platform","module","host","expected",{"skillNo":147,"name":148,"nameZh":6,"description":149,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":150,"categories":151,"keywords":152,"publishedAt":47},"01M6H603KPFQJNC7WWD6X5Q4AA","multihost-orchestration","Compatibility alias for the canonical coordinate-multihost-work skill.","https:\u002F\u002Fgithub.com\u002F8007342\u002Ftillandsias\u002Fblob\u002Fmain\u002Fskills\u002Fmultihost-orchestration\u002FSKILL.md",[],[46,153,37,154,155,156,157,103],"multihost orchestration","compatibility","coordinate","alias","canonical",{"skillNo":159,"name":160,"nameZh":6,"description":161,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":162,"categories":163,"keywords":166,"publishedAt":47},"01M6H5ZXRBC66CSA5N28HP2BY7","meta-orchestration","Host-aware Tillandsias recurring runtime loop: sync remote state, drain claimable plan work, run eligible e2e smoke gates, coordinate integrations on mutable Linux, release when warranted, update plan, commit, and push before exit.","https:\u002F\u002Fgithub.com\u002F8007342\u002Ftillandsias\u002Fblob\u002Fmain\u002Fskills\u002Fmeta-orchestration\u002FSKILL.md",[164,165],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},[46,33,167,168,169,170,171,172,173,115,35,36,174,37,175,29,176,155,144,177],"meta orchestration","commit","sync","run","update","release","state","integrations","recurring","exit","remote",{"skillNo":179,"name":180,"nameZh":6,"description":181,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":182,"categories":183,"keywords":184,"publishedAt":47},"01M6H5ZRW9CY3F0B95F3AD4A78","merge-to-main-and-release","Refresh linux-next, open\u002Fupdate the PR to main, merge once green, bump VERSION, tag, and trigger the workflow_dispatch release. Runs on a daily cadence so the latest linux-next work reaches a downloadable Linux release operators can smoke-test on a Fedora Silverblue host.","https:\u002F\u002Fgithub.com\u002F8007342\u002Ftillandsias\u002Fblob\u002Fmain\u002Fskills\u002Fmerge-to-main-and-release\u002FSKILL.md",[],[185,172,52,186,187,188,189,190,171,191,37,29,192,193,194,195,144,196,197,198],"merge","merge to main","merge to main and release","workflow","bump version","pr","open","bump","next","green","operators","trigger","cadence","fedora"]