[{"data":1,"prerenderedAt":-1},["ShallowReactive",2],{"skill:01M6H5ZXRBC66CSA5N28HP2BY7":3,"skill-same:01M6H5ZXRBC66CSA5N28HP2BY7":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},"01M6H5ZXRBC66CSA5N28HP2BY7","meta-orchestration",null,"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.","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\u002Fmeta-orchestration\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],"meta orchestration","Meta","orchestration","plan","remote","host","coordinate","exit","smoke","recurring","work","integrations","loop","push","state","release","update","run","sync","commit","2026-11-10 10:12:30",false,"---\nname: meta-orchestration\ndescription: \"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.\"\n---\n\n# Meta Orchestration\n\nThis is the top-level unattended loop intended for:\n\n```bash\n.\u002Frepeat --prompt \"Use the \u002Fmeta-orchestration skill\"\n```\n\nIt composes the worker, coordination, e2e, and release skills without replacing\ntheir detailed runbooks.\n\n## Invocation Modes — check FIRST, before anything else\n\nThe skill is parameterized by the invoking prompt. **Before doing any work —\nbefore host classification, before `git fetch`, before reading the plan —\ninspect the prompt that invoked this skill and pick the mode.** Full cycles\nare token-expensive; running one when a smoke pass was requested wastes a\nrate-limited provider budget (operator directive, 2026-07-11).\n\n- **Full mode** (default): the prompt is a bare \"Use the \u002Fmeta-orchestration\n  skill\". Run the complete cycle described in the rest of this document.\n- **Smoke Mode** (early break): the prompt contains the word `smoke` (e.g.\n  \"Use the \u002Fmeta-orchestration skill in smoke mode (verify-only)\"). You are\n  inside a short e2e smoke test with a hard budget of a few minutes. Do NOT\n  run a full cycle. Follow \"Smoke Mode Runbook\" below and exit.\n- **Targeted verify** (a variant of Smoke Mode): the prompt names specific\n  packets, orders, specs, or files (e.g. \"…smoke mode, verify order 283\" or\n  \"…smoke: spec git-mirror-service\"). Same rules as Smoke Mode, but the\n  verification set is the named targets' verifiable closures instead of the\n  generic checks.\n\n### Smoke Mode Runbook\n\nPurpose: give fast, cheap feedback that the forge lane and the work under\ntest are healthy — WITHOUT advancing the plan or consuming a full-cycle\ntoken budget. Hosted e2e gates (`litmus:opencode-prompt-e2e-shape`) invoke\nthis mode whenever the full cycle is rate-limited\n(`scripts\u002Fforge-e2e-rate-limit.sh`, one full cycle per 4h per host).\n\nHard rules:\n\n1. Do NOT claim ledger nodes, drain plan work, file routine findings, run\n   nested e2e gates, release, commit, or push. A smoke run leaves the repo\n   untouched. (Exception: a real defect discovered during verification may\n   be reported in your final output text — the HOST files it, not you.)\n2. Keep it small: prefer `scripts\u002Frun-litmus-test.sh --size instant\n   --phase pre-build --compact` scoped with a spec filter when targets are\n   named, plus cheap direct checks (parse `plan\u002Findex.yaml`, `git status`,\n   `git fetch --dry-run` reachability, the targets' named verifiable\n   closures). Skip anything that builds, launches containers, or exceeds\n   the budget.\n2a. **WHAT DECIDES THE VERDICT** (order 822-4vwa). Rule 2's last sentence and\n   its first are in tension INSIDE A FORGE, because a large fraction of\n   pre-build litmus needs vault, podman or vsock — none of which a forge has.\n   An agent that runs the unscoped suite there gets a near-total failure that\n   says nothing about the lane. So:\n\n   - The VERDICT is the forge SUBSTRATE: the checkout resolves and is on the\n     expected branch, the plan ledger parses, the plan\u002Fmethodology experts\n     answer, and the harness came up. If those hold, the lane is healthy.\n   - Litmus results in a forge are a **REPORT**, on the same footing as the\n     credential verdict in 3a. Quote the pass rate; do NOT convert it into\n     `MO-SMOKE: FAIL` on its own.\n   - When the invoking prompt NAMES targets, their scoped closures ARE part of\n     the verdict — that is the whole point of a targeted verify.\n\n   MEASURED on macuahuitl 2026-08-18, the same prompt on the same host 25\n   minutes apart with a verified-fresh seed, disagreeing with itself:\n   run 20260818T053811Z returned `MO-SMOKE: PASS` (post-build 11\u002F11), and run\n   20260818T063931Z returned `MO-SMOKE: FAIL litmus pre-build 0% pass rate\n   (1\u002F252); infrastructure-dependent failures expected but unconfirmed`. The\n   second agent was right to refuse to bless what it could not confirm; the\n   first agent's PASS is the one that should worry you. A gate whose result\n   depends on how much the agent chose to run is not a gate.\n3. Budget: finish well inside ~5 minutes of wall time.\n3a. The **Credential Channel Guard is a REPORT here, never a gate** (order\n   818-cgpn). That guard is a precondition for COMMITTABLE work, and rule 1\n   says a smoke run performs none — it claims nothing, commits nothing and\n   pushes nothing, so an absent or stale push credential cannot harm it.\n   Report the verdict in your output and carry on verifying; do NOT return\n   `MO-SMOKE: FAIL` for it.\n\n   MEASURED on macuahuitl 2026-08-18, twice: with the mirror's upstream-auth\n   verdict stale, the FULL lane blocked (correctly — it would have pushed) and\n   the SMOKE lane returned `MO-SMOKE: FAIL credential channel blocked\n   (upstream-auth-stale, 22880s > 900s max)`. Smoke exists precisely as the\n   cheap path for when the expensive one is unavailable; gating it on the same\n   credential leaves NO path, and takes the substrate-idempotence e2e (§2\u002F§3,\n   which never touch a credential) down with it — see 808-zrzz.\n4. Verdict grammar: your FINAL output line MUST be exactly one of\n   `MO-SMOKE: PASS` or `MO-SMOKE: FAIL \u003Cone-line reason>`. The launching\n   litmus greps for this marker; a smoke run that exits without it is a\n   failure by definition.\n\n## Sub-agent and token budget (operator directive 2026-09-11; packet 1119-6wn6)\n\nSub-agents spend the same rate-limited pool as the main loop, and that pool\nran out a week early last month. This checkout's 2026-09-06 cycle died\nmid-finalization for the same reason, with two finished fragments sitting\nuncommitted for five days. MEASURED on macuahuitl 2026-09-11: one read-only\nreconciliation Workflow of 42 agents at the main model's tier spent 4,480,590\ntokens in 21 minutes — roughly twenty times the main context of the entire\ncycle. The output was good; the price was invisible until the operator asked.\n\nThe loop has `timing:`, `recur:` and `skippable:` for CPU seconds and nothing\nfor tokens, so an expensive repeatable delegation cannot be seen the way the\nlow-end hosts made the CPU bottlenecks visible. Until the counter in\n1119-6wn6 lands and replaces these rules with numbers:\n\n- **Count.** At most 8 sub-agents per full cycle by default, at most 3 running\n  at once. A Workflow (fan-out orchestration) only when the invoking prompt\n  opts in (\"ultracode\", \"use a workflow\"), and then at most 15 agents.\n- **Tier by task class, and pass `model` and `effort` explicitly every time.**\n  Lookups, greps, \"does commit X exist \u002F touch file Y\", ancestry and existence\n  checks: haiku, effort low. Summarising a diff or a fragment, drafting event\n  prose: sonnet, effort medium. Judgment (a verdict on a packet, a review\n  finding, a design choice): opus, effort medium — high only when the error is\n  unrecoverable. The main model's tier is for the main loop, never for\n  refuters or fan-out.\n- **Refuters.** At most one per verdict, one tier below the verdict's author.\n  Prefer one agent with a schema over N parallel ones when the items are cheap.\n- **Packets carry their tier too (trims 2026-09-27, umbrella 1437-62g8).**\n  Every filed packet declares `size: S|M|L` and `implementer_tier:\n  haiku|sonnet|opus` (as scalars once 1437-khnx lands; as two lines inside\n  `notes:` until then). S = mechanical, fully specified → haiku; M = a few\n  files, clear design → sonnet; L = cross-cutting, judgment, or\n  gate-integrity-sensitive → opus. Anything that changes what the land gate\n  or the pre-push hook refuses is at least sonnet, opus if it could let a\n  red tree land. An UNTAGGED row is opus (operator 2026-09-27: \"No size\n  tags get Opus\") and the tier is a floor. A session states its tier to the\n  selector (`scripts\u002Fselect-work-batch.sh \u003Crole> --tier \u003Ct>`, 1437-vdz5)\n  and runs a cheaper packet through `scripts\u002Fclaude-delegate.sh implement\n  \u003Corder>` (1437-yjf6) or a dedicated `.\u002Frepeat --model haiku` session\n  (1437-m5yx); the host session keeps verify and commit. A host may also\n  run an all-day Haiku ORCHESTRATOR (`\u002Fhaiku-orchestrate`, 1443-hbgt) that\n  delegates by tier and accepts only a closure it measured with\n  `scripts\u002Fverify-closure.sh` (1443-qwpj) — never a delegate's \"met\".\n  Canonical: `methodology\u002Fdistributed-work.yaml` →\n  `cycle_batch_triage.model_tier_routing`.\n- **Messages to peers: budget ON HOLD** (operator question pending,\n  2026-09-27; 1437-arjg blocked). The shape in\n  `distributed-work.yaml` → `sibling_heads_up_protocol.size_budget` stays\n  written and is not enforced until the operator answers.\n- **Never delegate a read an expert answers.** `plan_status`, `plan_answer`,\n  `methodology_ask` and the project-info tools cost nothing next to an agent.\n- **Report it, and LOG it — from the instrument.** `scripts\u002Fcycle-metrics.sh\n  --emit-tokens` exists (1119-6wn6); with `--from-transcript` (1437-3pj7) it\n  reads this session's own harness transcript and fills `main_ctx`,\n  `main_ctx_cumulative`, `subagent_tokens`, `agents` and `by_model` itself,\n  or records `source=absent`. Hand-passed numbers remain accepted for a\n  harness with no transcript. The typed form was:\n\n  ```\n  scripts\u002Fcycle-metrics.sh --emit-tokens host=\u003Ch> cycle=\u003Cid> \\\n      main_ctx=\u003Cn> subagent_tokens=\u003Cn> agents=\u003Cn> \\\n      by_model=\u003Copus:3,haiku:39> label=\u003Cwhat the delegation was for>\n  ```\n\n  The handoff still carries the `tokens:` line — `scripts\u002Fcycle-metrics.sh`\n  renders it, with a rolling per-cycle average, and `source=absent` until a\n  record exists. A cycle that spawned nothing writes `subagent_tokens=0\n  agents=0` and is correctly absent from `token_recur:`.\n\n  **`label` is the field that earns the log its keep.** It names the WORK, not\n  the cycle, so the same expensive delegation recurring across days ranks as one\n  entry in `token_recur:` instead of scattering into unrelated rows. Only labels\n  seen MORE THAN ONCE are ranked: a one-off 4.5M sweep is a cost, not a\n  recurrence, and letting it top the list would bury the cheap thing paid fifty\n  times — which is the one the operator asked to find and simplify.\n\n  Only the agent can observe these numbers, so this stays an attestation (the\n  `check-mcp-surface.sh` shape); what changed is that it is now structured and\n  comparable across cycles. An unmeasured spend is the order-531 shape one level\n  up: it reads as free and is not.\n\n## Full-Mode Terminal Attestation (order 614-2gqx)\n\nSmoke mode has a machine-grepped verdict (`MO-SMOKE:`); full mode did not, so\na normal provider exit between tool calls could discard local commits while\nevery outer launcher returned zero (the `4a1410a2` breach; see\n`plan\u002Fissues\u002Fmeta-orchestration-full-mode-exit-attestation-gap-2026-08-05.md`).\n\nFull mode therefore MUST emit a typed terminal marker as its FINAL output\nline, and MAY emit it ONLY after every finalization obligation below has\npassed (boundary verification, `.\u002Fbuild.sh --check`, commit, push):\n\n```text\nMO-FULL: \u003CDISPOSITION> \u003CLOCAL_SHA> \u003CBRANCH> \u003CREMOTE_SHA>\n```\n\n- `DISPOSITION` ∈ {`COMPLETE`, `BLOCKED`} — the cycle's terminal disposition.\n- `LOCAL_SHA` = final local HEAD (`git rev-parse HEAD`) at emission time.\n- `BRANCH` = the working branch the cycle committed to.\n- `REMOTE_SHA` = the remote branch head after the push.\n\nInvariants the outer gate (`scripts\u002Fmo-full-attest.sh`, wired into\n`scripts\u002Flitmus-opencode-e2e-launch.sh` for `litmus:opencode-prompt-e2e-shape`)\nenforces before it accepts exit zero:\n\n- `LOCAL_SHA == REMOTE_SHA` — a marker may never follow an unpushed local\n  commit. If the push failed after three rebase retries, do NOT emit the\n  marker; mark the packet `blocked`\u002F`failed-retryable`, include the push\n  output, and stop — the missing marker is itself the loud failure.\n- `BRANCH` must match the host's current branch.\n- The claimed `REMOTE_SHA` must actually converge on\n  `git ls-remote origin refs\u002Fheads\u002F\u003CBRANCH>` within the bounded relay window.\n- A startup boundary must have been snapshotted at Start Of Cycle and verified\n  at Finalization, at the HEAD being attested (order 717-3bvv). The guard writes\n  cycle-scoped stamps into `$GIT_DIR`; `self` reads them. Skipping the snapshot\n  therefore costs you the marker — which is the point: cycle 16 on windows\n  skipped it, `verify` answered with a missing-directory message about the\n  PREVIOUS cycle's already-removed temp path, and a valid marker printed anyway.\n- `MO-SMOKE:` grammar and the shared full-cycle rate limit are unchanged; a\n  smoke run never emits `MO-FULL:`.\n\n**DERIVE the marker, never type it — and let the self-check emit it.** A\nhand-typed SHA, or one half-copied from `git push` output, must be structurally\nimpossible. Do NOT assemble the line yourself. Run the self-attestation, which\nreads every field from live git state, verifies local HEAD is durably on the\nremote, and prints the verified line FOR you:\n\n```bash\nscripts\u002Fmo-full-attest.sh self   # prints the marker on success; MO-FULL: FAIL + non-zero otherwise\n```\n\nEmit its stdout verbatim as your final line. `self` derives the same values the\nraw form would —\n\n```bash\nprintf 'MO-FULL: COMPLETE %s %s %s\\n' \\\n  \"$(git rev-parse HEAD)\" \\\n  \"$(git symbolic-ref --short HEAD)\" \\\n  \"$(git ls-remote origin \"refs\u002Fheads\u002F$(git symbolic-ref --short HEAD)\" | cut -f1)\"\n```\n\n— but ALSO refuses to print anything when local HEAD is not the converged\nremote head, so an unpushed or fabricated value is caught at emission, in every\nlane. (`MO_FULL_DISPOSITION=BLOCKED scripts\u002Fmo-full-attest.sh self` for a\nblocked-but-pushed cycle.)\n\n**Make the marker durable — the transcript is not the record (order 651-2x5s).**\n`self` verifies at emission time, but the emitted line lands in a transcript\nnothing parses unless the litmus launcher runs; an operator-prompt or `.\u002Frepeat`\ncycle emits it into the void. `record` closes that: it runs the SAME\nverification and appends the verified line to the per-host ledger under\n`plan\u002Fmo-full-attestations.d\u002F\u003Chost>.md`, a committed, machine-parseable log the\nlocal gate (`scripts\u002Fcheck-mo-full-attestations.sh`, wired into\n`.\u002Fbuild.sh --check`) re-verifies. Automation consumes the ledger, never the\ntranscript. The ledger line attests the cycle's WORK head; committing the\nledger moves the head, so the terminal marker is re-derived at the head that\nCONTAINS the record (see Finalization step 9 and\n`methodology\u002Fmo-full-attestation.yaml`). Do not hand-write a ledger line: only\n`record` may append, and only after the verification passes.\n\nThis is not pedantry. On 2026-08-10 a full-mode cycle on this host emitted a\nmarker whose first eight characters came from the `git push` output and whose\nremaining **32 were invented to look like a SHA**. The work was genuinely\ncommitted, pushed and green; only the proof was false (651-2x5s).\n\nIt went unnoticed because `scripts\u002Fmo-full-attest.sh check` — which would have\nrejected it instantly, since it requires `git ls-remote` to converge on the\nclaimed value — is wired into exactly one caller, the\n`litmus:opencode-prompt-e2e-shape` launcher. A cycle driven by an operator\nprompt, a `.\u002Frepeat` loop, or a cron emits the marker into a transcript nothing\nparses, so that `check` never runs. **Without a check the marker is decorative,\nand an unverified attestation is worse than none: it reads as proof and carries\nnone.** The `self` mode closes that gap by moving the same convergence\nverification to emission time: EVERY lane self-checks, because the cycle proves\nits own marker in the one command that prints it.\n\nAny full-mode run that exits without a valid, converging `MO-FULL:` marker\nhas not completed its exit contract — regardless of the process exit code.\n`scripts\u002Fmo-full-attest.sh fixture` \u002F `scripts\u002Ftest-mo-full-attest.sh`\nreproduce the breach shapes hermetically (missing marker, malformed, unpushed\nlocal commit, branch mismatch, remote-head mismatch, a well-formed but\nfabricated SHA that matches nothing on the remote, clean pass — 7\u002F7).\n\n## Non-Negotiable Exit Contract\n\nLocal state is volatile. Before a successful exit, every meaningful result must\nbe committed and pushed to the correct remote branch.\n\n- Exit cleanliness is relative to the startup worktree boundary. No\n  uncommitted change created by this cycle may remain.\n- Pre-existing tracked changes and status-visible untracked files are\n  sibling\u002Foperator work, not temporary artifacts. Every path recorded by the\n  startup boundary MUST remain byte-identical on every exit, including blocked\n  exits. Never run broad `git clean`, `git checkout --`, `git restore`, or\n  `git reset` against a worktree that was dirty at startup. Ignored trees are\n  not hashed because they may contain an arbitrarily large build cache; they\n  are not thereby cycle-owned and must not be overwritten.\n- Automated finalization must never delete or restore worktree paths. Put every\n  disposable diagnostic or scratch artifact under the unique external\n  `$boundary_dir\u002Ftmp\u002F` directory. Files created in the worktree are meaningful\n  cycle output: commit and push them, or stop with a blocker and leave them for\n  explicit operator disposition.\n- Ensure any `tillandsias` background binaries or test processes are fully terminated.\n- No local-only commits.\n- No completed work without a `plan\u002F` event or finding.\n- No e2e pass\u002Ffail without a dated plan report.\n- No blocked state without a blocker, owner if known, and smallest next action.\n- Explicitly log things that make you slower (e.g., repeated steps, invalidated caches, uncoordinated scripts) into `plan\u002Fissues\u002F`.\n\n**SALVAGE BEFORE YOU REFUSE (order 872-c9nd). This is not optional and it comes\nFIRST — before the handoff, before the blocker, before anything else.**\n\n```bash\nscripts\u002Fsalvage-dirty-worktree.sh \u003Cslug>   # -> ok:salvaged:\u003Cref>:\u003Csha>\n```\n\nThe script handles a DIRTY tree OR a CLEAN tree whose HEAD is on no origin\nref (order 1146-8j7i). For a dirty tree, it pushes a COPY — tracked\nmodifications, deletions and untracked files — to\n`salvage\u002F\u003Chost>\u002F\u003Cyyyymmdd>-\u003Cslug>` on origin, and it CANNOT touch the\nworktree: it builds the commit through a temporary `GIT_INDEX_FILE` and\nplumbing (`write-tree` \u002F `commit-tree`), never a stash, an add against the\nreal index, or a checkout. Verified: worktree status and `.git\u002Findex` are\nbyte-identical afterwards, and `git show \u003Csha>:\u003Cpath>` returns an untracked\nfile's full content.\n\nTHE SAME SCRIPT ALSO COVERS A CLEAN TREE THAT IS NOT A SAFE ONE (order\n1146-8j7i): if `git status` is empty but HEAD itself is not reachable from any\norigin ref — a finished, gate-passing commit stranded when a later trunk merge\nreds the gate and every push is then refused — it pushes HEAD to the same\nsalvage ref and answers `ok:salvaged-commits:\u003Cref>:\u003Csha>` instead of\n`ok:salvage-not-needed`. A host whose gate just went red on an otherwise-clean\ntree should run this script, not open a fresh `work\u002F\u003Corder>` ref that the same\nred gate will refuse for the same reason the commit is stranded.\n\n**A tool whose name describes its original case will not be found by someone\nin its extended case: `salvage-dirty-worktree.sh` is also the hand-off lane\nfor a host that cannot gate (1177-k4jq); the `work\u002F` lane is the GATED\nhand-off and demands the stamp.** A host whose own gate cannot complete —\nmemory-ceilinged, credential-dead, or otherwise unable to produce a green —\ncannot use `work\u002F\u003Corder>` at all: the relay-ref lane still requires the full\ngate on first push, which is exactly what such a host cannot supply. Salvage\nthe finished commit to `salvage\u002F\u003Chost>\u002F\u003Cyyyymmdd>-\u003Corder>` instead and name it\nexplicitly as an UNGATED hand-off in the report; the host or orchestrator that\nrelays it gates it there, next pass (drill: the lenovinha entries of 2026-09-14).\n\nWHY THIS RULE EXISTS, and it is the most expensive lesson in this file. On\n2026-08-23 a host wedged with 16 modified paths and one untracked litmus file\nbelonging to two claimed packets. Three consecutive cycles refused the dirty\ntree, verified all 17 paths byte-identical to their boundary snapshots, and\nwrote increasingly detailed prose about the diff. On 2026-08-24T06:09Z the\ncheckout was replaced by a fresh clone. Four hours of finished work are\nunrecoverable; the untracked file's name appears in no commit on any branch.\n\n**The boundary guard did its job perfectly and protected a directory that\nsomeone then deleted wholesale.** A guard that forbids the AGENT from touching\nthe work does not forbid anything else from touching it, and a prose description\nof a diff is not a copy of it. The refusal path was a place work could sit\nindefinitely; it is now a place work passes THROUGH on its way to origin.\n\nA dirty-start preflight refusal is not a work cycle and is the sole exception\nto in-checkout blocker filing: touching `plan\u002F` would itself violate the\nstartup boundary. Report `blocked: dirty-start-worktree`, owner, the exact\nstatus paths, **the salvage ref and sha**, and the smallest next action in the\nfinal handoff so the clean host\u002Forchestrator can file it durably. Do not create\nthen delete a blocker file inside either the shared checkout or `$boundary_dir`.\n\nIf the salvage itself fails, say so loudly and do NOT soften the refusal: an\nunsalvaged dirty tree is the exact state that cost four hours, and the operator\nneeds to know the copy does not exist before deciding what to do with the\ndirectory.\n\n**AN OPERATOR LICENCE CAN GO STALE, AND A CLEAN TREE IS HOW YOU KNOW.** When a\nprompt authorises you to land dirt — order 833-fpe7's `resumable:` verdict\nor an operator sentence naming specific work to review\nand land — CHECK THAT THE DIRT IS STILL THERE before acting on it. If\n`git status --porcelain --untracked-files=all` is empty, the premise of the\nlicence is gone: answer **\"the premise is gone\"**, say what the licence expected\nto find, and stop. Do NOT reconstruct what you think it referred to and land\nthat instead. This is how 872-c9nd was discovered: an operator relaunched a host\nwith a verbatim unblock prompt hours after the checkout had been re-cloned, and\nthe honest answer was that there was nothing left to land.\n\nIf a push fails after three fetch\u002Frebase retries, mark the active plan item\n`blocked` or `failed-retryable`, include the failed push output, and stop.\n\n## Host Classification\n\nDetect host at the start of every cycle:\n\n- `forge`: Inside the Tillandsias developer forge container (typically detected by checking if `TILLANDSIAS_HOST_KIND` is set to `forge`).\n- `linux_immutable`: Linux with `\u002Frun\u002Fostree-booted` present or `rpm-ostree` on PATH.\n- `linux_mutable`: Linux without the immutable marker (and not inside the forge container).\n- `macos`: Darwin.\n- `windows`: Windows, MSYS, MINGW, or PowerShell host.\n\nCanonical branches:\n\n- Linux shared\u002Fintegration: `linux-next`\n- macOS code: `osx-next`\n- Windows code: `windows-next`\n- Release: `main` through PR only\n\nAll `plan\u002F`, `methodology\u002F`, `openspec\u002F`, and `cheatsheets\u002F` files consider `linux-next` their canonical home. However, agents working on platform branches (`windows-next`, `osx-next`) MUST commit and push all edits (including plan updates) directly to their active platform branch. The Linux coordinator will merge these branches back into `linux-next` during the `\u002Fmultihost-orchestration` pass.\n\n## Start Of Day \u002F Post-Restart Gate (run FIRST, once per day; methodology `development_environment_lifecycle`)\n\nEvery host restarts with the prompt \"Use the .\u002Fskills\u002Fmeta-orchestration skill\",\nso THIS gate is how a restart or a new day gets its maintenance and verification.\nIt is idempotent and cheap when already done today, and the marker that makes it\nso is now REAL and CHECKABLE (order 801-qasc) — run the check, do not eyeball it:\n\n```bash\nscripts\u002Fcheck-daily-maintenance.sh check     # exit 0 = today's gate ran; skip the body\n```\n\nRead the push guards too, every time, even when the day's gate is current\n(see \"Push Guards Armed\" below): `tillandsias-plan script run scripts\u002Flua\u002Fcheck-hooks-armed.lua`.\n\nIt prints exactly one line matching\n`^(ok:daily-maintenance-(current|stamped):[0-9]{4}-[0-9]{2}-[0-9]{2}|skip:forge-exempt|due:(no-marker|unreadable-marker|stale:[0-9]{4}-[0-9]{2}-[0-9]{2}))$`\nand exits 0 only when today's gate is recorded. **`due:*` means run the body**;\na corrupt or missing marker is `due:`, never a pass. From 2026-08-13 to\n2026-08-17 the marker this section names existed only as prose — nothing wrote\nit, nothing read it — so \"did today's gate run\" had no answer at all, one cycle\ninherited a false \"already stamped\" premise from its brief and skipped the body,\nand the next found nothing to confirm. An unobservable gate is indistinguishable\nfrom one that never runs, and the cheapest way to satisfy it is to skip it.\n\nOn a durable bare-metal DEVELOPMENT host (not an ephemeral forge):\n\n1. **Post-restart verification** (only when the stack looks freshly booted — MCP\n   experts just rebuilt, images\u002Fbinary possibly toolchain-bumped): run the durable\n   checklist `plan\u002Fissues\u002Ffleet-restart-post-restart-checklist-2026-08-13.md`\n   (order 718-nuvm). Do NOT trust `plan_answer`\u002F`project_answer` until the MCP\n   experts serve `source_commit == git rev-parse HEAD`; verify clock\u002FNTP sync\n   (a skewed clock breaks SSH-CA cert TTLs + freshness stamps); rebuild forge\n   images at the installed VERSION before launching any forge (version-skew DOA);\n   reinstall per-checkout git hooks; ensure the router sidecar is staged as a\n   build artifact (710-w9kc).\n2. **Daily maintenance** (methodology `development_environment_lifecycle.start_of_day_maintenance`):\n   build-cache GC per `build_cache_hygiene` (cargo clean when bloated\u002Fstale),\n   `scripts\u002Fnix-toolbox.sh gc` — never a bare `nix store gc`, which would\n   delete the whole persistent cache rather than prune it\n   (`build_cache_hygiene.nix_store_policy`) — `podman image prune` of\n   superseded versioned images,\n   the nix-lane guards on hosts with nix (`scripts\u002Ftest-nix-toolbox.sh`,\n   `scripts\u002Fcheck-nix-deps-stability.sh` — daily, not per-commit: each is a\n   flake evaluation), the enclave nix binary cache on Linux hosts with a\n   running enclave (`scripts\u002Fnix-cache-service.sh ensure` then\n   `scripts\u002Ftest-nix-cache-service.sh` — order 801-kqme; serves the persistent\n   795-h8er store to the enclave so a disposable forge lands warm without any\n   host path being mounted into it), reap defunct delegate handles\n   (`delegate-outcome.sh sweep`), verify the\n   dev-environment expert containers are up + fresh (`dev_environment_experts` —\n   the same ephemeral RAG experts + commit-hook RAG retraining the forge runs),\n   and confirm this host is visible in the capability matrix (order 850-bif2):\n   ```bash\n   scripts\u002Fcheck-capability-row.sh   # ok:capability-row-current:\u003Chost> | due:no-capability-row:\u003Chost>\n                                     # | stale:capability-row-drifted:\u003Chost>:row-only=…,probe-only=…\n                                     # | stale:capability-row-expired:\u003Chost>:age=\u003Cn>s\n   ```\n   On Linux, confirm this host is not carrying the orphaned enclave proxy\n   block (order 923-rmtw):\n   ```bash\n   scripts\u002Fcheck-containers-conf-proxy-env.sh   # ok:… | drift:… | unavailable:…\n   ```\n   `[engine] env` in containers.conf is injected into EVERY container on every\n   network, and `proxy` resolves only inside the enclave. Init used to write\n   that block and could never converge it, so hosts provisioned before\n   801-kqme kept a no_proxy list without `nix-cache` — that was four days of\n   phantom 883-ncrs \"cache RSTs\" and one broken nix e2e, hand-repaired on\n   macuahuitl and lenovinha. On `drift:containers-conf-proxy-env-present`, run\n   `tillandsias --init`: it now REMOVES the block, and containers get proxy env\n   per-container. A commented-out block still counts as drift — that is how\n   yoga ended up with no proxy env at all while init reported success.\n\n   Report scratchpad headroom in the same breath (order 915-wkm2) — one line,\n   ADVISORY, exits 0 on every path:\n   ```bash\n   tillandsias-plan script run scripts\u002Flua\u002Fcheck-scratchpad-headroom.lua   # ok:\u002Fdegraded:scratchpad-headroom-low:\u002Fskip:\n   ```\n   The agent scratchpad is tmpfs; systemd sizes \u002Ftmp at 50% of RAM but a\n   usrquota can sit far below that, so `df` reports gigabytes free while every\n   write returns EDQUOT — the host stays healthy and only the agent's tooling\n   dies. That wedged macuahuitl for several cycles: it presents as \"my shell is\n   broken\", not \"I filled a disk\". On `degraded:` do NOT build in the scratchpad;\n   build in the checkout. The threshold is absolute (one cold Rust `target\u002F`,\n   2.6-4.4 GB) rather than a percentage, because the fleet's quotas span 4.6x —\n   lenovinha warns at 29% used while macuahuitl is fine at 62%, so any\n   \"warn above N%\" rule passes the host that will wedge and warns the one that\n   will not.\n\n   On `due:`, publish the row THIS cycle — the matrix was silent for 5 of 7\n   hosts because nothing ever asked, and capability routing (847-wgy4) cannot\n   route to hardware it cannot see:\n   ```bash\n   bash scripts\u002Fhost-capability-probe.sh --fragment \\\n     > \"plan\u002Findex.d\u002F$(date -u +%Y%m%dt%H%M%Sz)-capability-row-$(hostname -s | tr 'A-Z' 'a-z').yaml\"\n   ```\n   then commit it with the cycle's plan changes. Never hand-assemble a row\n   (the unquoted-heredoc incident on 850-bif2 is why the generator exists).\n3. Stamp the marker, NAMING what actually ran — the stamp is refused without\n   `--steps`, because a stamp that records \"something happened\" without\n   recording what restores the same unfalsifiability one level up:\n\n   ```bash\n   scripts\u002Fcheck-daily-maintenance.sh stamp --host \u003Chost> \\\n     --steps 'delegate-sweep:\u003Cresult>,podman-prune:\u003Cresult>,nix-gc:\u003Cresult>,cargo-gc:\u003Cresult>'\n   ```\n\n   Record `skipped-absent` \u002F `deferred-\u003Creason>` honestly for steps this host\n   cannot or did not run; a partial pass that says so is worth more than a\n   green that says nothing. `scripts\u002Fcheck-daily-maintenance.sh show` prints the\n   last claim. Ephemeral forges skip this whole gate (they discard their\n   substrate on teardown) and read `skip:forge-exempt`.\n\nThen favor the expert system for the cycle's work-pull\u002Ftriage\u002Fdebug\u002Fresearch\n(methodology `expert_first_work`): ask the experts first; on a gap, fall back\nwith a loud warning naming the gap, never silently.\n\n## How to invoke the gate (read this before your first `.\u002Fbuild.sh`)\n\nTwo environment variables are not optional and neither is discoverable by\nreading `build.sh`. They were carried in operator prompt text for ten cycles\nbefore anyone noticed the skill never mentioned them — which meant the\nbootstrap contract (\"Use the .\u002Fskills\u002Fmeta-orchestration skill.\" and nothing\nelse) was quietly false for any fresh host.\n\n```bash\nTILLANDSIAS_SKIP_VERSION_BUMP=1 .\u002Fbuild.sh --check                  # every time\nTILLANDSIAS_SKIP_VERSION_BUMP=1 TILLANDSIAS_FORCE_CHECK=1 .\u002Fbuild.sh --check   # to VERIFY\n```\n\n- **`TILLANDSIAS_SKIP_VERSION_BUMP=1` — always.** Without it the gate bumps\n  VERSION as a side effect and the pre-push hook then refuses YOUR OWN push,\n  because VERSION may not change on a platform branch (643-64bx). The blast\n  radius is six files — VERSION, Cargo.lock and four crate Cargo.tomls — so a\n  remedy that reverts only VERSION leaves the tree dirty and the push still\n  refused. Measured live on linux-next 2026-08-20.\n- **`TILLANDSIAS_FORCE_CHECK=1` whenever the green matters.** Since 765-tkq2 a\n  plain `--check` MEMOISES: on an unchanged tree it prints `ok:gate-fresh` and\n  re-runs nothing, in 0.4s instead of 10s. That is correct for the inner loop\n  and useless as evidence. A green you did not force proves only that the tree\n  has not changed since some earlier green.\n\n**Killing the gate does not kill the gate (1132-r4mt).** `.\u002Fbuild.sh --check`\nre-execs inside the `tillandsias-builder` toolbox via `podman exec`, so\nkilling the host-side wrapper reaps only the wrapper: measured on pirria, the\ncontainer-side `build.sh` kept running 12 minutes after it was \"stopped\",\nconcurrently with the gate started after it — and two gates racing one\ncheckout is the leading mechanism for the archiver-fixture flake that cost\ntwo full gates in a night (reproduced independently on yoga). SIGTERM to the\nwrapper is inert; only SIGKILL to the container-side pid and its child ends\nit. **The discriminator is NOT conmon parentage** — every container-side\n`build.sh` under toolbox dispatch has parent `conmon` while its launcher\nchain (`toolbox run` → `podman exec`) is alive, so that reading would record\nevery healthy gate as a stray. A stray is a container-side pid whose\nHOST-SIDE `podman exec` no longer exists (measured by yoga on 2026-09-13 on a\nhealthy running gate). Before relaunching any gate or land you stopped — or\nthat a harness reaped — check for a survivor by that test, and force the\nrelaunch: a stamped `ok:gate-fresh` no-op proves nothing about strays. Match\n`ps` output by NAME, never by field index — an index match once wrote an\nempty file and read as \"no stray processes\" (drill: plan\u002Fissues\u002Ffleet-restart-2026-09-12.md, yoga: 1132-r4mt advanced at 191d606db (MO-FULL 90dcbbe07), claim released, criteria 2 and 3 open).\n\n## Where standing direction lives\n\nAsk, do not guess:\n\n```bash\ntillandsias-plan answer \"what is the current Direction?\"\ntillandsias-plan next \u003Crole>\n```\n\nThe Direction section is operator-owned and is the one place a theme is\ndeclared. Per-row carry-forward lives in each row's `next_action`, which\n`next` prints beside the row it belongs to.\n\n**A caveat learned the hard way, 2026-08-22.** Cross-cutting direction parked in\nthe `next_action` of a CLAIMED row is invisible: claiming removes the row from\nselection, so `next` never shows it and a fresh host cannot find it. That is\nR1 working as designed, and it means a claimed row is the wrong home for\nanything a future host must read. Standing direction belongs in the Direction\nsection or in this skill; `next_action` is for the row's own next step.\n\n## Joining the fleet (read this if you are not macuahuitl)\n\nAs of 2026-08-23 the fleet is FIVE working hosts, not one: macuahuitl\n(`linux_mutable`, coordinator), lenovinha and yoga (Silverblue, `linux-next`),\ntlatoanis-macbook-air (`osx-next`), and yolanda (Windows 11, `windows-next`).\nAll five have completed attested cycles. The staged rejoin this section used to\ndescribe is DONE; the three mechanisms it was gating on — claiming, the\nfirst-attestation lane, and capability rows — all landed on 2026-08-22\u002F23.\n\nNOT EVERY HOST IS A DRAIN HOST. Machines with roughly four cores are the\nfleet's deliberate LOWER BOUND and take profiling and characterization work in\ntheir own tier, never the general queue (operator mandate 2026-08-16 for\nesmeraldinha, extended 2026-08-23 to its Silverblue cousin). A slow host in the\ngeneral queue produces slow duplicates of work a faster host already claimed.\nThe SELECTOR now enforces this (847-wgy4): it probes physical cores locally,\nroutes a \u003C=4-core host to `low-end`-tagged work only, refuses loudly\n(`refused:no-tier-work`) rather than falling back to the general queue, and\nsubtracts that tier from everyone else's pool — a fast host running the\nfloor's profiling work would measure the wrong machine. Override with\nTILLANDSIAS_HOST_TIER when the probe misreads a host. Separation between\ngeneral hosts is ordinal: your rank in the capability-matrix roster picks\nyour epic (route=rank:\u003Cr>\u002F\u003Cn> in the batch header), so publishing your row\n(850-bif2, above) is what buys you a collision-free lane; a rowless host\nfalls back to the seeded pick and R1 claiming.\n\nThe criteria that gated the original rejoin, kept because they are still what\n\"working\" means:\n\n- **Claiming is live.** `expire-claims` reports a non-zero `in_progress`, and a\n  claimed row is genuinely hidden from `next \u003Crole>`. Verified on a real claim,\n  both halves. What one host CANNOT prove is the cross-host half — a row\n  claimed HERE being skipped THERE. That is the second host's first job, and it\n  is worth doing deliberately before it drains anything.\n- **The selector separates hosts.** `select-work-batch.sh \u003Crole> --seed \u003Chost>`\n  returns disjoint batches for different seeds — different epic, different\n  packets, and `urgent=` no longer forces every host to one head. This FAILED\n  on 2026-08-19 (three seeds, one byte-identical batch) and the `--seed` flag\n  did not exist then. **Pass your hostname as `--seed`.** The default is\n  `${TILLANDSIAS_HOST_KIND:-host}-$(date -u +%Y%m%d)`\n  (`scripts\u002Fselect-work-batch.sh:232`), which varies by host KIND and date — not\n  by host. Two Linux boxes therefore derive the same seed every day whether or\n  not that variable is set, so separation is available but NOT automatic: a\n  second host that forgets the flag collides exactly as the fleet did before.\n\nThe third is a fleet property no single host can close: the queue must stop\ngrowing faster than it drains. One host currently measures well inside the\nbound, but that reading says nothing about what a second host does to it —\nwhich is precisely why hosts rejoin one at a time and the number is re-measured\nafter each.\n\n**On immutable Linux, run the update-skew probe at cycle start and carry its\nverdict into the handoff** (order 1165-g6wx):\n\n```bash\nscripts\u002Fprobe-silverblue-update-skew.sh   # -> skew: | ok:no-skew | could-not-run:\n```\n\nRead-only: it runs no `rpm-ostree` command that can mutate a deployment, and it\nexists so a cycle SAYS \"skew\" instead of a host guessing. A `skew:` verdict means\nthis host cannot apply the offered update at all — `akmods` is layered, the base\nkernel has outrun the repo's `kernel-devel-matched`, depsolve fails and nothing\nstages, while `--check` and GNOME Software keep reporting \"ready, requires\nrestart\". **Do not treat it as a cycle failure and do not act on it**: the three\nremedies all change what is installed on someone's workstation and are the\noperator's decision. Report the verdict and carry on. `could-not-run:` is not a\nclean verdict either — it means the question could not be asked.\nSee `cheatsheets\u002Fruntime\u002Fsilverblue-updates.md`.\n\n**If you are on immutable Linux (Silverblue\u002FKinoite), two things differ.**\nFirst, `.\u002Fbuild.sh` transparently re-execs inside the `tillandsias-builder`\ntoolbox (`scripts\u002Fwith-tillandsias-builder.sh`), creating it with\n`toolbox create --assumeyes` on first use. So unlike a mutable host, your gate\nNEEDS a working podman — a Silverblue box with podman broken cannot run\n`--check` at all, where a mutable box happily would. The first `--check` of a\nfresh checkout spends its opening minutes building the toolbox — measured on\nyoga (Silverblue, Ryzen AI 5 340, ~250 Mbit\u002Fs registry link, 2026-08-23; filed\nas an event on 850-bif2): image pull 11.5s (355 MiB compressed), `toolbox\ncreate` 0.1s, then 131.9s for the first forced `--check` (dnf 17s, rustup 14s,\ngate ~100s), with a warm `~\u002F.cargo` — a truly pristine home also pays crates.io\ndownloads on top. That is the toolbox being built, not a hang. (The previous\n\"minutes\" figure here was an unmeasured inference written on a mutable host\nthat never executes this path — b629bb379.)\nSecond, `scripts\u002Fe2e-preflight.sh` carries NO immutability logic and will report\n`eligible` to you. Do not believe it: the skill's E2E table routes immutable\nLinux to `\u002Fsmoke-curl-install-and-test-e2e` (test a PUBLISHED release), never to\n`\u002Fbuild-install-and-smoke-test-e2e` (test a LOCAL build). The preflight is\nanswering a narrower question than the one you are asking it.\n\n**If you are on macOS (Darwin), most defaults hold — these are the parts that\ndo not** (851-gpb5, learned by the first Mac to join). Your branch is\n`osx-next`: commit and push everything there, and before EVERY push merge\n`origin\u002Flinux-next` into it — methodology's pre-push gate\n(`pull_merge_cadence.pre_push_gate`; Finalization step 6). Run\n`scripts\u002Finstall-hooks.sh` once so the v5 pre-push hook actually enforces that\nmerge on your checkout. `.\u002Fbuild.sh --check`\u002F`--test` work natively, but **run\n`scripts\u002Fcheck-host-tools.sh` FIRST — it prints every missing host tool with its\n`brew install` line** (order 989-ykks). That replaces the list of host tools this\nparagraph used to carry, and the replacement is not tidying: the list was wrong\nin two ways in one week (it omitted `coreutils`, a hard requirement of the\ncredential gate per 988-7kxf, and `pkg-config`, without which `--check` cannot\nstart), and a list is only ever written by someone whose machine already works.\nThe host that HAS a tool cannot detect that it is undocumented; it reports `ok:`\nand lands all night while the host that lacks it debugs an unrelated failure\nhours later. A probe cannot drift that way. `--install` is REFUSED by design\n(723-whrx): the macOS build path is `scripts\u002Fbuild-macos-tray.sh` — wrapped by\n`\u002Fbuild-macos-tray`, which also files findings to\n`plan\u002Fissues\u002Fmacos-build-findings-\u003CDATE>.md` — and local-build e2e\n(`\u002Fbuild-install-and-smoke-test-e2e`) destroys and re-provisions the\nVirtualization.framework VM directory, not a podman store. The system shell is\nbash 3.2 with BSD userland: no GNU-only flags in anything a Mac must run (no\n`xargs -r`, no suffix-less `sed -i`), and `sha256sum` only exists on macOS\n13+ — use the `sha256sum`-or-`shasum -a 256` dispatch\n(`scripts\u002Fbuild-sidecar.sh`, `scripts\u002Fgate-stamp.sh`). Expect the MCP experts\nto be DOWN on first boot (`down:forge-plan`, `degraded(not-built)`):\n`scripts\u002Fcycle-preflight.sh` builds `.\u002Ftarget\u002Frelease\u002Ftillandsias-plan`, the\nsame binary the MCP wrapper serves — work through it by path and record the\noutage, per `mcp_first_read_path`. And like every joining host, pass your\nhostname as `--seed` to `select-work-batch.sh`.\n\n**Publish your capability row before you drain anything** (order 850-bif2).\n`scripts\u002Fcheck-capability-row.sh` answers whether the matrix can see you AND\nwhether what it sees is still true (order 889-ewvt); on `due:`, `stale:…drifted`\nor `stale:…expired` generate and commit a row with\n`scripts\u002Fhost-capability-probe.sh --fragment` (Linux\u002FmacOS\u002Fforge loci; the\nwindows-host locus keeps its own generator). `drifted` is the urgent one: the\ncommitted row disagrees with a live probe, and routing that consumes it will\nsend work to hardware this host does not have — that is how the release gate\nwas routed to yoga for a `gpu\u002Fcontainer\u002Follama` engine yoga never had. A joining host that drains work\nwhile publishing nothing is how the matrix went silent for 5 of 7 hosts —\nand capability-aware routing (847-wgy4) cannot route to hardware the matrix\ncannot see.\n\n**Expect to be offered other hosts' abandoned work.** Claims expire on a 24h\nlease, and expired rows return to the pool with their history intact — a row\nyou are offered may have been started elsewhere and dropped. Read the row's\nevents before assuming it is fresh.\n\nThe bootstrap prompt is `Use the .\u002Fskills\u002Fmeta-orchestration skill.` and nothing\nelse. If you needed something said to you beyond that sentence, the thing you\nneeded was missing from this skill or the ledger, and THAT is the defect worth\nfiling — not the prompt.\n\n## Start Of Cycle\n\n0. **Rebuild the instrument before using it** (operator directive 2026-08-13):\n\n   ```bash\n   scripts\u002Fcycle-preflight.sh   # -> ok:cycle-preflight:\u003Cplan>:\u003Cinference>\n   ```\n\n   The project believes in idempotency and ephemerality — everything should be\n   safe to destroy and relaunch at any moment, Erlang style — so a cycle never\n   inherits a component from the previous one and hopes it is current. This\n   rebuilds `tillandsias-plan` (the binary every expert call, the batch\n   selector, every ledger write and every closure check goes through) and\n   re-establishes the dev inference endpoint. Both are idempotent; the common\n   path costs a no-op `cargo build` and one HTTP round trip, measured at ~2.8s.\n\n   **The `\u003Cplan>` segment names WHICH instrument the cycle is running on, and\n   `existing` is a legitimate verdict** (order 1004-ws5q):\n\n   | verdict | meaning |\n   |---|---|\n   | `rebuilt` | cargo was present and the instrument was built or confirmed current |\n   | `existing` | **no cargo on this host, but a runnable binary resolved** — the cycle proceeds on it |\n   | `skipped` | the build step was skipped by `CYCLE_PREFLIGHT_SKIP_BUILD=1` |\n   | `blocked:preflight:plan:cargo-absent` | no cargo AND no runnable binary — no instrument, and the cycle must not start |\n\n   `existing` exists because the old order of checks was backwards: preflight\n   declared the COMPILER absent before ever looking for a BINARY, so a host\n   doing compile-free work lost its whole slot with a healthy instrument on\n   disk. Measured on pirria 2026-09-04, where a floor-tier release smoke —\n   which compiles nothing — was refused a 4h slot.\n\n   **`CYCLE_PREFLIGHT_SKIP_BUILD=1` is for compile-free work on a host that\n   cannot compile, and nothing else.** It is NOT a way past a red build on a\n   host that can compile: that is a broken instrument, and selecting work with\n   one is the failure this whole step exists to prevent. Since 1004-ws5q a host\n   with no cargo but a working binary no longer needs the variable at all —\n   preflight answers `existing` on its own — so reaching for it should now be\n   rare enough to be worth a second thought.\n\n   It rebuilds the INSTRUMENT, not the product: `.\u002Fbuild.sh --check` already\n   compiles what it validates, and rebuilding everything on a schedule is a\n   heavier decision than this step is making.\n\n   Confirm the rebuilt instrument is CURRENT before minting or writing, and\n   again after any merge that touches crates\u002Ftillandsias-plan\u002Fsrc (a relay of\n   a plan-binary change makes the binary you built an hour ago stale; the\n   next `next-order` then refuses with `stale-plan-binary`) (1513-pppk):\n\n   ```bash\n   bash scripts\u002Fcheck-plan-binary-current.sh\n   # -> ends ok:plan-binary-current; any stale:* or blocked:* line is a stop:\n   #    cargo build --release -p tillandsias-plan, then re-run\n   ```\n\n   A `blocked:preflight:*` verdict means do not start the cycle — selecting work\n   with an unverified instrument is the one failure the loop cannot reason its\n   way out of, because the tool it would reason WITH is the stale thing. That is\n   not hypothetical: a selector change on 2026-08-13 added a subcommand every\n   host's binary predated, and this checkout went on refusing until someone\n   rebuilt by hand. Inference is a REPORT inside that verdict, never a gate —\n   the deterministic expert tiers work without it, and a host with no network is\n   degraded, not broken. When inference cannot be established, the report\n   segment reads `degraded:\u003Creason>` (never `blocked:*` — the gate word is\n   reserved for `blocked:preflight:*`); continue the cycle.\n\n0b. **Name yourself before the first ledger write** (orders 756-hn3a, 885-zvzu):\n\n   ```bash\n   agent_id=\"$(scripts\u002Fagent-identity.sh id \u003Cbackend>)\" || exit 1   # claude|codex|opencode|gemini\n   ```\n\n   Every `append-event`, `set-field` reason and loop-status entry this cycle\n   writes carries an `agent_id`, and the plan binary REFUSES a non-canonical\n   one (874-idnt): `\u003Cplatform>-\u003Cworkstation>-\u003Cbackend>-\u003Cutc-timestamp>`,\n   sanitised to `[a-z0-9-]`. Never hand-compose it. The helper resolves it\n   from stable sources and itself refuses\n   (`refused:agent-identity:empty-\u003Ccomponent>`, empty stdout) rather than mint\n   an incomplete id; on that refusal append, claim and push nothing.\n\n   WHY IT IS HERE: this skill is the whole bootstrap contract, and it never\n   named the helper. Measured on macuahuitl 2026-08-25: the first\n   `append-event` of a cycle driven by the documented prompt hand-wrote an id\n   and was refused, and the cycle recovered only by reading the error text.\n   Same class as the two gate variables in \"How to invoke the gate\", which\n   lived in operator prompt text for ten cycles.\n\n1. Record UTC time, host kind, current branch, worktree path, and sibling heads.\n   Report this host's scheduler posture in the same breath — it is one line and\n   it answers the question an operator otherwise has to read a transcript for:\n\n   ```bash\n   tillandsias-plan script run scripts\u002Flua\u002Fcheck-cycle-scheduler.lua   # armed? last fire? next due?\n   ```\n\n   ADVISORY, NEVER A GATE (order 856-s56y exit criterion 5, wired 865-j3kd).\n   `blocked:cycle-scheduler:not-installed` (exit 1; `due:not-installed` before\n   the 1624-bv73 Lua port) is a true and acceptable answer: macuahuitl is driven by\n   an external hourly loop rather than a systemd timer, and a host with no\n   durable timer is differently-scheduled, not broken. What the line buys is\n   that \"no scheduler is armed here\" becomes a stated fact rather than something\n   nobody discovers until a host has been quietly not-cycling for a day — which\n   is the 856-s56y failure, and the same shape as a wedged host reading as\n   silent (864-t4nq).\n\n   It is wired here because the guard shipped invoked by nothing and\n   audit-guard-activation therefore failed `.\u002Fbuild.sh --ci-full`, one of three\n   checks that left the trunk unreleasable for a week (865-n8vq). The auditor\n   greps for the guard's NAME, so a mention would have cleared the verdict while\n   leaving the guard as dead as it was; an orphaned guard is fixed by invoking\n   it. Arming an actual scheduler is 856-s56y's own work and remains yoga's.\n\n2. `git fetch origin --prune`, then run the Credential Channel Guard and the\n   Committable Branch Guard below before any committable work. Run the MCP\n   Expert Health Probe here too — it is advisory and never blocks, but it must\n   run BEFORE the cycle's first expert read, or an outage during that read has\n   no recorded baseline to be visible against.\n2b. **Acquire the checkout lock — EVERY lane, before the boundary snapshot**\n   (order 873-zcim):\n\n   ```bash\n   TILLANDSIAS_CYCLE_HOLDER_PID=$PPID scripts\u002Fcycle-checkout-lock.sh acquire \\\n       --lane \u003Chow-this-cycle-was-launched> --source \"\u003Cprompt source, one line>\"\n   ```\n\n   The no-stacking lock used to be taken only by the driver lane\n   (tillandsias-cycle-driver.sh), so a cycle launched by an operator prompt, a\n   \u002Floop cron, or a cloud schedule acquired nothing and STACKED on a running\n   driver in the same worktree — measured on yoga 2026-08-24, 21 minutes into\n   a driver cycle, duplicating its claims. The lock guarded the driver lane;\n   the thing two agents contend for is the CHECKOUT.\n\n   On `skip:overlap-lock-held:\u003Cholder>` DO NOT PROCEED: the verdict names who\n   holds the checkout (lane, pid, start, source). Report it as the cycle's\n   final output and exit — this is the designed outcome, not a failure, and\n   the refusal is recorded durably OUTSIDE the checkout in\n   `~\u002F.cache\u002Ftillandsias\u002Foverlap-refusals.jsonl`, so a refused-for-overlap\n   cycle is distinguishable in the record from a cycle that ran and found\n   nothing (873-zcim criterion 3). Do not retry in a loop; the next scheduled\n   fire retries on its own clock.\n\n   `TILLANDSIAS_CYCLE_HOLDER_PID=$PPID` must be evaluated in YOUR shell — it\n   anchors liveness to the agent-harness process that spans the whole cycle.\n   The script's own default is one shell too deep and dies with the tool call.\n\n   DECIDED (873-zcim criterion 4): a second agent NEVER works in a locked\n   checkout. It WAITS for the lock: concurrent work on one host is serialized,\n   never moved to a sibling git worktree or a temp clone (operator direction\n   2026-10-11, methodology multi-host-development.yaml\n   single_checkout_branching; order 1620-67ji). The worktree\u002Fclone technique\n   yoga once used here is retired: every sibling checkout sits outside the\n   session's workspace and puts its cleanup in front of the operator.\n   Release at Finalization (step 9b) with\n   `TILLANDSIAS_CYCLE_HOLDER_PID=$PPID scripts\u002Fcycle-checkout-lock.sh release`.\n\n   **IF YOU RELOCATE, TAKE THE BOUNDARY IN THE WORKTREE YOU RELOCATE TO**\n   (order 983-xha6). This is one line and its absence cost the fleet visibility\n   three separate times on 2026-09-03:\n\n   ```bash\n   cd \u003Cthe clone or worktree you will actually work in>\n   boundary_dir=\"$(mktemp -d \"${TMPDIR:-\u002Ftmp}\u002Fmeta-orchestration-boundary.XXXXXX\")\"\n   scripts\u002Fmeta-orchestration-worktree-guard.sh snapshot \"$boundary_dir\"\n   ```\n\n   The guard's stamps live in `$(git rev-parse --git-dir)`, so they are ALREADY\n   per-checkout and a relocated worktree can hold its own boundary — verified in\n   a fresh clone: snapshot, commit, `verify` -> `ok: startup worktree boundary\n   preserved`. Nothing needed building. What was missing was anyone saying to do\n   it, so step 3 below snapshotted the checkout the cycle then correctly stopped\n   using, the clone never got a boundary, and `mo-full-attest` refused at\n   Finalization with `no verified startup boundary for this cycle` — AFTER a\n   green gate with every commit pushed.\n\n   The consequence is not a missing line of output. `MO-FULL:` is how automation\n   learns a cycle finished, so a lawfully relocated cycle is INDISTINGUISHABLE\n   FROM ONE THAT DIED: the trunk carries its commits while the fleet record says\n   the host never reported. A forge hits this by default — its checkout is a\n   clone, it is often seeded from `main` (965-rb3v), and `main` is refused by\n   `check-committable-branch.sh` — so relocating is the NORMAL forge path, not an\n   exception.\n\n   Snapshotting a fresh clone is not a formality and not vacuous: the clone\n   starts clean, so the boundary proves the cycle left nothing uncommitted behind\n   it. What IS vacuous — and must never be done to obtain a marker — is\n   snapshotting AFTER the work and verifying immediately: that compares a tree\n   against itself and emits a valid-looking proof of nothing (651-2x5s). If you\n   reach Finalization having never snapshotted, the honest outcome is a BLOCKED\n   exit with no marker; do not manufacture one.\n\n3. Snapshot the startup boundary before classifying or changing any path:\n   ```bash\n   boundary_dir=\"$(mktemp -d \"${TMPDIR:-\u002Ftmp}\u002Fmeta-orchestration-boundary.XXXXXX\")\"\n   scripts\u002Fmeta-orchestration-worktree-guard.sh snapshot \"$boundary_dir\"\n   ```\n   The guard records `git status --porcelain=v1 -z --untracked-files=all`\n   plus content hashes for every status-visible dirty path. If the worktree is\n   dirty, treat every recorded path as immutable sibling\u002Foperator work unless\n   the operator explicitly identifies it as disposable in the current prompt.\n   Refuse the cycle and do not begin committable work. Report the dirty-start\n   blocker through the final handoff as defined above. Do not commit, discard,\n   restore, reset, or clean unknown startup dirt.\n\n   **Before that refusal, run `scripts\u002Fsalvage-dirty-worktree.sh \u003Cslug>`**\n   (order 872-c9nd, full rationale in the Exit Contract above). Refusing\n   protects the work from YOU; it does not protect it from a fresh clone, and on\n   2026-08-24 a fresh clone is exactly what took it. The salvage cannot touch\n   the worktree — temporary index and plumbing only — so it is safe to run on\n   dirt you have just been forbidden to alter, and it must run BEFORE the two\n   detectors below: whether the dirt turns out to be `resumable:` changes what\n   you may LAND, never whether a copy should exist.\n4. **Launch-generated opsx dirt is a refusal (deterministic, order 1440-w8g8)**:\n   before refusing on startup dirt, name WHICH dirt it is:\n   ```bash\n   scripts\u002Fcheck-opsx-generated-dirt.sh\n   ```\n   It prints exactly one line matching\n   `^(ok:clean-tree|launch-dirt:opsx-only|non-opsx:.*)$`. `launch-dirt:opsx-only`\n   (exit 5) means every dirty path is the opsx\u002Fopenspec command\u002Fskill set the\n   openspec CLI generates — a forge launch rewrote tracked files, which\n   1422-w3p8 made impossible. That is a REGRESSION to report, not content to\n   land: refuse the cycle exactly as for any dirty start (salvage first, as\n   above), name 1422-w3p8 and the verdict line in the handoff, and do not\n   commit, discard, restore or clean the dirt. Order 540 (2026-07-31) used to\n   commit it as a `chore(opsx)` sync; the operator reversed that on\n   2026-09-27 (the dirt \"should not exist\"), and 64cceb25d is what the old\n   step produced. Moving the generated set to a new openspec version is a\n   deliberate `openspec update` + commit under its own packet, never a cycle's\n   reaction to dirt. `non-opsx:` (exit 3) is real sibling\u002Foperator dirt: fall\n   through to 4b, then to the dirty-start refusal. `ok:clean-tree` (exit 4)\n   means there is nothing to name. The checker is a falsifiable machine\n   decision; do not substitute prose judgment for it.\n4b. **Resumable claim dirt (deterministic, order 833-fpe7)**: when the dirt is\n   `non-opsx:`, run the second detector before refusing:\n   ```bash\n   scripts\u002Fcheck-resumable-claim-dirt.sh\n   ```\n   It prints exactly one line matching\n   `^(resumable:\u003Corder>(,\u003Corder>)*|ok:clean-tree|unattributable:.*)$` and exits\n   `0` only when EVERY dirty path is tracked, the folded ledger names a live\n   claim OWNED BY THIS HOST (`tillandsias-plan expire-claims --list-live`:\n   claim-convention event host, both claim and activity inside the TTL), and\n   every dirty path's mtime postdates the oldest such claim. That is the\n   signature of this host's OWN previous cycle interrupted between implement\n   and commit — the dirt the refusal would otherwise deadlock on until\n   expire-claims launders finished work into lost work (the 833-fpe7 shape;\n   814-iyu7 arriving by a second route).\n\n   `resumable:` is a licence to REVIEW AND LAND, never to auto-commit: read\n   the diff against each named order's packet, land what implements it as its\n   own commit(s) citing the orders, then re-anchor with the guard's\n   `re-snapshot` (scripts\u002Fmeta-orchestration-worktree-guard.sh). Whether an edit\n   IMPLEMENTS the packet beside it is the agent's judgment; the detector only\n   removes the deadlock. Any `unattributable:` verdict falls through to the\n   dirty-start refusal exactly as written. Pinned by\n   `litmus:resumable-claim-dirt-shape`.\n5. Update the active local branch from remote with fast-forward or an explicit\n   merge from `origin\u002Flinux-next` into the platform branch when appropriate.\n\n5a. **NOW check for sibling overlap** (methodology `sibling_heads_up_protocol`).\n   Hosts can message each other directly — `ListAgents` to see who is live,\n   `SendMessage` to reach them. **The capability is new and you will not\n   discover it on your own**; the fleet coordinated exclusively through the\n   ledger and the trunk for months before anyone noticed it existed.\n\n   ```bash\n   tillandsias-plan query --status in_progress   # who is holding what, right now\n   ```\n\n   **AFTER THE MERGE, NOT BEFORE, AND THIS ORDERING IS THE WHOLE STEP.** This\n   check first shipped as step 2a — before the branch update — and was MEASURED\n   BROKEN on the next cycle by its own author:\n\n   ```\n   before the merge:  831-ezea only            \u003C- the other host's claim INVISIBLE\n   after the merge:   642-fedr + 831-ezea      \u003C- yoga's fragments.rs claim\n   ```\n\n   `git fetch` at step 2 updates remote-tracking refs; it does NOT update the\n   worktree ledger that `tillandsias-plan` reads. So a check placed before the\n   merge answers about the claims as of your LAST merge, not as of now.\n\n   **THE STALENESS IS NOT ONE-DIRECTIONAL, and the earlier wording here said it\n   was.** This passage used to end \"a stale ledger always shows FEWER claims,\n   never more.\" Measured on yoga 2026-08-26T07:26Z, one cycle after that\n   sentence landed, running the same query either side of the merge:\n\n   ```\n   before the merge:  799-tb7q + 831-ezea    \u003C- 799-tb7q was a PHANTOM\n   after  the merge:  831-ezea only          \u003C- another host had released it\n   ```\n\n   `799-tb7q` was `in_progress` in the stale ledger and `ready` at the new head:\n   a sibling finished a slice and released it in commits this host had fetched\n   but not merged. So a pre-merge check can show a claim that no longer exists\n   as easily as it can hide one that does — **fewer claims when siblings have\n   been claiming, more when they have been releasing.**\n\n   Both directions are harmful and they fail differently. Missing a live claim\n   fails toward \"no overlap\", which is the safe-LOOKING answer and the one that\n   costs a union. Seeing a released claim fails toward a needless heads-up, or\n   toward skipping a packet that is free — cheaper, but it teaches the reader\n   that the step produces noise, which is how a step stops being run.\n\n   `expire-claims --list-live` is the tool again as of 905-wjfj: it now prints\n   one row per in_progress packet and a `rows:` accounting line whose total must\n   equal the summary's `in_progress=N`. Before that fix it printed the count and\n   no rows — two hosts hit it on the same day — and the workaround here was\n   `query --status in_progress`, which still works and is a fine cross-check.\n\n   **READ THE ROW TYPE, because the two mean opposite things.**\n\n   - `live-claim \u003Corder> \u003Cpid> \u003Chost> \u003Cclaimed-at> \u003Clast>` — a sibling holds\n     this. If it touches your surface, message that host.\n   - `unclaimed-in-progress \u003Corder> \u003Cpid> - - \u003Clast>` — in_progress, recent\n     enough that no reaper will touch it, and **nobody to send a heads-up to**.\n     The dashes are the actionable part. This row is not the quiet case; it is\n     the one where the protocol has no addressee, so if it touches your surface\n     you inspect the diff yourself rather than assuming silence means free.\n   - `attention:list-live-partition-mismatch` — a packet is in no bucket or in\n     two. The enumeration is under-reporting; do not trust a `no overlap`\n     verdict derived from it.\n\n   MEASURED 2026-08-26: `831-ezea` sat in the unclaimed row for at least a day —\n   in_progress, with a gate step wired into `.\u002Fbuild.sh --check`, last activity\n   18h old and therefore inside the 24h TTL, so neither the reaper nor the\n   live-claim list would ever surface it. Exactly the row an overlap check\n   exists to show you, and the only one it could not.\n\n   If a live claim touches the SAME SURFACE your batch touches — a wire type, a\n   shared struct, a script another lane runs, a schema, a guard wired into\n   `--check` — send one HEADS UP before implementing: what you are touching, the\n   shape of the change, any sibling call sites you know of, and the ask. They\n   reply ACK plus comments. Two short messages.\n\n   **WHY, structurally: THE UNION IS A STATE NO SINGLE BRANCH'S GATE OBSERVES.**\n   Every branch can be green alone and the merge still broken, because no\n   branch's `--check` compiles the other's configuration. Care cannot close\n   that; only a second lane looking can. MEASURED 2026-08-26: macbook's\n   731-eupn was green on both branches and `E0063 + E0308` in the union — a red\n   gate and ~30 minutes of coordinator cycle.\n\n   **Prefer the message to the resolve-to-be-careful: a heads-up is a\n   falsifiable act, care is not.** \"I considered the siblings\" cannot be checked\n   by anyone, including you an hour later.\n\n   DO NOT broadcast routine drain. Most work touches only your own lane, and a\n   channel that carries everything is one nobody reads — the recipient is\n   mid-cycle, holding a checkout lock, with expensive context. The heads-up is\n   for what the ledger cannot carry in time: **intent, before the fact.**\n\n## Credential Channel Guard\n\nRun immediately after `git fetch` and before any worker drain or committable\nwork.\n\n**Close the interactive escape hatches around EVERY push** (order 860-g798,\nexit criterion 3):\n\n```bash\nexport GIT_TERMINAL_PROMPT=0 GCM_INTERACTIVE=never\n```\n\nA credential problem must fail FAST AND LOUDLY, not hang. Measured on\nesmeraldinha: the guard reported green (`gh auth status` held a token), the\ncycle entered committable work, and the first push sat >10 minutes behind Git\nCredential Manager's interactive prompt — a hang with no output, presenting as\na slow build on the host least able to afford the misdiagnosis. With the\nprompts closed the same failure surfaces in seconds as an auth error the guard\nnow names (`blocked:interactive-credential-helper`, remedy printed). The guard\nitself verifies the PUSH path since 860-g798 — `ok:gh-keyring-push-verified`\nmeans a bounded non-interactive dry-run push actually authenticated, not\nmerely that a token exists somewhere. In SMOKE mode it is a REPORT, not a gate — a smoke run\nperforms no committable work, so a stale push credential cannot harm it (order\n818-cgpn; see Smoke Mode Runbook rule 3a). The Cowork scheduled-task runtime can inherit dangling session sockets\n(`DBUS_SESSION_BUS_ADDRESS`, `SSH_AUTH_SOCK` pointing into a non-existent\n`\u002Frun\u002Fuser\u002F\u003Cuid>`) so anonymous reads succeed while every `git push` silently\nfails for lack of a credential. See\n`plan\u002Fissues\u002Fcowork-headless-credential-isolation-2026-06-20.md`.\n\nRun the executable guard instead of re-deriving the check in prose. \n*(On Windows: ensure you run this via Git Bash, e.g. `& \"C:\\Program Files\\Git\\bin\\bash.exe\" scripts\u002Fcheck-credential-channel.sh`. PowerShell's `bash` alias defaults to an isolated WSL session that lacks host credentials).*\n\n```bash\nscripts\u002Fcheck-credential-channel.sh\n```\n\nIt prints exactly one line matching the falsifiable grammar\n`^(ok:[a-z0-9-]+|blocked:[a-z0-9-]+|missing:no-credential-channel)$` and exits\n`0` when a usable git-push credential channel is present, non-zero when it is\nabsent or blocked. A usable channel is present when ANY of these holds (the\nscript checks them in order):\n\n- `\u003Ccommon-git-dir>\u002F.gh-credentials` (absolute `git rev-parse --path-format=absolute --git-common-dir`, so every linked worktree shares it; 1409-65d5) exists and is non-empty (repo-local store helper), or\n- `GH_TOKEN` or `GITHUB_TOKEN` is set in the environment, or\n- `gh auth status` succeeds (reachable, unlocked keyring), or\n- `TILLANDSIAS_HOST_KIND=forge` is set AND the enclave git mirror is reachable\n  for `origin` AND the mirror's published upstream write-authorization verdict\n  (`refs\u002Ftillandsias\u002Fupstream-auth\u002F\u003Cstate>\u002F\u003Cepoch>`, refreshed non-mutatingly by\n  `images\u002Fgit\u002Fprobe-upstream-auth.sh`) is fresh and `authorized` (or\n  `local-only`). Order 756-2jnj: reachability alone said `ok` on 2026-08-15\n  while GitHub 403'd the mirror's credential, and a forge lost two commits it\n  discovered only at first push. `ok:forge-git-mirror` now means BOTH halves —\n  forge→mirror reachable AND mirror→upstream currently write-authorized.\n\nPinned by `litmus:credential-channel-check-shape` and\n`litmus:forge-upstream-auth-gate`. A non-zero exit (verdict\n`missing:no-credential-channel`, or any `blocked:*` verdict — e.g.\n`blocked:upstream-push-unauthorized` for the 403 state,\n`blocked:upstream-no-credential`, `blocked:upstream-auth-stale`,\n`blocked:upstream-auth-unpublished`) fails the cycle on its own; do NOT proceed\ninto worker drain or any committable work. Instead\nfail loud: file or update a blocker in `plan\u002Fissues\u002F` recording the exact\nverdict, the owner (operator), and the smallest next\naction (re-seed `.git\u002F.gh-credentials` via the gh token, inject `GH_TOKEN`\ninto the task environment, or — for `blocked:*` — repair the mirror's Vault\nGitHub token \u002F its repo push permission), then stop. Accreting local-only\ncommits that cannot be pushed violates the Non-Negotiable Exit Contract and is\nthe precise velocity-killer this guard prevents.\n\nReads (`git fetch`\u002F`git ls-remote`) succeeding is NOT evidence of a credential\nchannel — public-repo reads are anonymous. Verify write capability explicitly.\n\n**Bound every `git push` with a timeout; an empty push log is a refusal, not\nslowness (macneo, two land stalls of 3000 s each).** `land: attempt 1 — push`\nwas the last line written, the push log was ZERO bytes, and a stack sample\nshowed `git-credential-osxkeychain` blocked in `CSSM_DecryptDataFinal` — an\nACL confirmation dialog no non-GUI session can answer. The guard's\n`GIT_TERMINAL_PROMPT=0`\u002F`GCM_INTERACTIVE=never` above close git's own\nprompts, not an OS helper below them; macbookair pushed six times on the same\nhelper and repo from inside a GUI session, so the variable is the session,\nnot the config. A genuine credential fault refuses WITH output; a keychain\nhang produces none. Wrap the push (`timeout \u003Cn> git push …`), `stat` the log\ntwice before calling anything slow, and report\n`blocked:credential-helper-hung` with the probe (drill: plan\u002Fissues\u002Ffleet-restart-2026-09-12.md, A push with no timeout emits nothing).\n\n## Committable Branch Guard\n\nRun alongside the Credential Channel Guard, before any committable work.\nDirect commits\u002Fpushes to `main` are forbidden — `main` advances only through\nPR merges. Breach record: 34e60965, an antigravity forge cycle running ON\n`main` that pushed a ~42k-line `plan\u002Findex.yaml` reserialization straight to\n`origin\u002Fmain` (reverted via PR #81; see\n`plan\u002Fissues\u002Fmain-branch-direct-push-guard-2026-07-24.md`).\n\nRun the executable guard instead of re-deriving the check in prose:\n\n```bash\nscripts\u002Fcheck-committable-branch.sh\n```\n\nIt prints exactly one line matching the falsifiable grammar\n`^(ok:branch-[A-Za-z0-9._\u002F-]+|blocked:(committable-cycle-on-main|detached-head|not-a-git-repo))$`\nand exits `0` when HEAD is on a committable branch (any named branch except\n`main`), non-zero when the checkout is on `main`, detached, or not a git\nrepository (fail closed). On any `blocked:*` verdict do NOT proceed into\nworker drain or any committable work: switch to the host's canonical branch\n(`linux-next`, `windows-next`, `osx-next`) or run the cycle read-only.\nRead-only\u002Finspection cycles on a `main` checkout remain allowed — the guard\ngates committable cycles only. Pinned by\n`litmus:committable-branch-guard-shape`.\n\n## Forge Expert Base Guard\n\nRun before launching a forge from this checkout. Run the executable guard\ninstead of re-deriving the check in prose:\n\n```bash\ntillandsias-plan script run scripts\u002Flua\u002Fcheck-forge-expert-base.lua\n```\n\nIt prints exactly one line matching\n`^(ok:(expert-base-ready|no-plan-crate)|blocked:(expert-sources-absent|not-a-git-repo))$`\nand exits `0` when a forge seeded from this checkout can build a working plan\nexpert, non-zero when it cannot.\n\nWhy this is a separate guard from the branch guard above: the launcher seeds a\nforge's branch from **this checkout's current branch**\n(`read_host_project_current_branch` → `TILLANDSIAS_FORGE_SEED_BRANCH`), so\nwhatever branch you are parked on becomes the next forge's base. `main` carries\nno `crates\u002Ftillandsias-plan\u002Fsrc\u002Fanswer.rs`, so a forge seeded from it builds a\n**pre-expert binary** and then reports `experts: ready` truthfully while every\n`plan_answer` \u002F `methodology_path` returns `confidence=unsupported`. Truthful\nstate, wrong artifact. Breach record: 2026-07-30, an in-forge session found both\nexperts refusing the milestone's own exemplar question; two earlier cycles had\nabsorbed the same condition by noticing and hand-rebasing\n(`plan\u002Floop_status.md:203`, `:243`). Order 531.\n\nThe test is **source presence, not a branch name** — deliberately. The names\n`linux-next`\u002F`windows-next`\u002F`osx-next`\u002F`main` are Tillandsias's own conventions\nand are explicitly *not* a runtime convention of the product\n(`methodology\u002Fmulti-host-development.yaml:21-27`), so a forge on an end user's\nproject must not assume them. Source presence is a fact about the checkout, and\nit also catches the case a branch-name test cannot: when the seed and the actual\nbranch agree because this checkout was itself parked on a pre-expert base,\nnothing looks wrong.\n\nOn `blocked:expert-sources-absent`, do NOT launch a forge expecting expert\nanswers. Switch this checkout to a branch carrying the expert sources first. On\n`ok:no-plan-crate` the target project simply has no plan expert, which is normal\noff-Tillandsias.\n\n## Push Guards Armed (read-only; Start Of Day and Start Of Cycle, order 1255-s4im)\n\n```bash\ntillandsias-plan script run scripts\u002Flua\u002Fcheck-hooks-armed.lua   # ok:hooks-armed:\u003Cmarker>\n```\n\nIt answers whether THIS checkout's pre-push hook carries the current\n`tillandsias-pre-push-v*` marker, and it installs nothing:\n`ok:hooks-armed:\u003Cmarker>` (exit 0), `degraded:hooks:absent` or\n`degraded:hooks:stale:\u003Chave>->\u003Cwant>` (exit 1), `refused:hooks:foreign-pre-push:*`\nor `refused:hooks:\u003Cscope>-hooks-path:*` (exit 3). **On `degraded:` run\n`bash scripts\u002Fensure-hooks.sh` before any push**: until then a push from here\nruns none of the push guards, the release freeze among them. The plan-lane\nscripts arm the hooks on their own (`ensure-hooks.sh --prelude`), but a host\nwhose first push is a WORK REF never runs one of them, which is why this is\nread at the start of the day and of every cycle.\n\n## MCP Expert Health Probe (advisory — record, never block)\n\nRun at Start-Of-Cycle, alongside the guards above:\n\n```bash\nscripts\u002Fcheck-mcp-expert-health.sh\n```\n\nIt speaks the MCP `initialize` handshake to each expected expert and prints\nexactly one line matching\n`^(ok:experts-healthy|down:[a-z0-9-]+(,[a-z0-9-]+)*|absent:not-registered|skip:[a-z0-9-]+)$`,\nappending one JSONL record per server to `$TILLANDSIAS_EXPERT_HEALTH_LOG`\n(default `\u002Ftmp\u002Fforge-expert-health.jsonl`). ~40ms when healthy.\n\n**This is the concrete referent for `mcp_first_read_path`'s \"fall back and keep\ngoing, THEN RECORD IT\".** That rule named no destination, and on 2026-08-14 two\nhosts skipped the recording half on the same day: windows lost all 28 MCP tools\nmid-session and fell back to `tillandsias-plan.exe` silently; linux ran an entire\ncycle whose session had never loaded the servers at all. Both outages were\ninvisible in the ledger and would have stayed invisible (order 737-zcj5).\n\nUnlike the guards above, a non-zero exit here **does not fail the cycle** — an\nunavailable expert is a degraded read path, never a blocked one. Record and\ncontinue:\n\n- `down:\u003Ccsv>` \u002F `absent:not-registered` — keep working through\n  `.\u002Ftarget\u002Frelease\u002Ftillandsias-plan` (the same binary the MCP wrapper wraps) and\n  let the `mcp_outage:` line carry it into the handoff. Name the fallback reason,\n  as the rule has always required.\n- `ok:experts-healthy` — say nothing further. The probe is silent by design when\n  healthy; a signal that fires every cycle is one nobody reads.\n\n### The handshake is not the surface (order 801-m9tk)\n\n`ok:experts-healthy` means the registered servers answered when the PROBE\nlaunched them. It does not mean the tools reached YOUR session. For three\nconsecutive windows cycles the probe printed `ok:experts-healthy` while not one\n`mcp__forge-plan__*` \u002F `mcp__project-info__*` tool was bound to the agent, so\nevery read silently fell back to `.\u002Ftarget\u002Frelease\u002Ftillandsias-plan`. A server\nthat is up but not exposed is exactly the outage worth catching, and the\nhandshake probe calls it healthy — the order-531 shape again.\n\nA script cannot see your tool surface; nothing in this repo can. **You** are the\nonly observer of that fact, so the surface half is **attested, not measured** —\nand an unattested cycle reads `unattested:no-surface-claim`, never `ok:`.\nImmediately after the health probe, look at your own tool surface and say so:\n\n```bash\nscripts\u002Fcheck-mcp-surface.sh attest exposed      # mcp__* tools resolved this session\nscripts\u002Fcheck-mcp-surface.sh attest unexposed    # they did not — every read is a fallback\nscripts\u002Fcheck-mcp-surface.sh check               # the joined verdict\n```\n\n`check` joins the measured handshake with the attested surface and prints\n`ok:surface-exposed` \u002F `unexposed:handshake-ok` \u002F `down:\u003Ccsv>` \u002F\n`absent:not-registered` \u002F `unattested:*` \u002F `skip:no-health-log`. Advisory, never\na gate — like the probe it extends. `cycle-metrics.sh` folds a fresh `unexposed`\nattestation into `mcp: health=ok-unexposed` and fires the `mcp_outage:` line, so\nthe degraded read path reaches the ledger without anyone choosing to write it\ndown. An `exposed` attestation leaves `health=ok` unchanged, and a claim older\nthan the freshness window labels nothing: a previous cycle's marker never\nvouches for this one.\n\n**And the third question: is the server you reach running current code?**\n(order 823-u3k9). The handshake probe launches its OWN instance from the\nregistration, so it validates the FILE. It cannot see that your session's\nlong-lived MCP process was started before a fix landed and is still serving the\nold text — measured on macuahuitl 2026-08-18, where 799-j4xd's fix was in the\nfile, the index was fine, L0 was fine, and the expert answered with prose the\nfix had deleted while every signal read green. A fix in a file does not reach a\nprocess that already read it.\n\nLike the surface, only **you** can observe this, and for the same reason: a\nsubprocess cannot reach your server, and launching one is the defect. Call the\nlive tool, read the build line out of its answer, attest it:\n\n```bash\n# 1. mcp__forge-plan__expert_capability   (through YOUR tool surface, not a shell)\n# 2. read its `server_build: forge-plan=\u003Cid> source=\u003Cpath>` line\nscripts\u002Fcheck-mcp-live-build.sh attest forge-plan=\u003Cid> --source \u003Cpath>\n# 3. mcp__project-info__project_info     (1414-mjdw: the other long-lived server)\n# 4. read its JSON \"server_build\": \"project-info=\u003Cid> source=\u003Cpath>\" field\nscripts\u002Fcheck-mcp-live-build.sh attest project-info=\u003Cid> --source \u003Cpath>\nscripts\u002Fcheck-mcp-live-build.sh check            # the WORST attested server\nscripts\u002Fcheck-mcp-live-build.sh check project-info   # one server by name\n```\n\nEach server keeps its own attestation line, so a current forge-plan never\nvouches for a stale project-info. A project-info answer with no\n`server_build` field predates 1414-mjdw: attest `project-info=unreported`.\n\nIf the answer carries **no** `server_build:` line, that is the finding, not a\nreason to skip: the running server predates the emitter. Attest\n`forge-plan=unreported` and it reads `stale:live-server-build-unreported:…`.\n`check` prints `ok:live-build-current:\u003Cserver>` \u002F\n`stale:live-server-build:\u003Cserver>:\u003Cattested>!=\u003Condisk>` \u002F\n`stale:live-server-build-unreported:\u003Cserver>` \u002F `unattested:*` \u002F\n`unavailable:*`. Advisory, never a gate. On any `stale:`, relaunch the forge (or\nthe session's MCP servers) before trusting an expert answer — and record the\nfallback, per `mcp_first_read_path`.\n\nDo NOT substitute `test -x` or a registration-file check for the handshake. A\nserver that exists but wedges on startup is precisely the outage worth catching,\nand a file-existence test calls it healthy. (The first draft of the probe read\n`.command` while dropping `.args`, launched a bare `bash`, and reported both\nhealthy experts as `down` — a false outage is as bad as a missed one.)\n\n## Local Expert System Probe (advisory — at cycle start, before work drain)\n\nRun at Start-Of-Cycle, AFTER the MCP Expert Health Probe and BEFORE worker\ndrain — and ONLY on hosts with `TILLANDSIAS_HOST_EXPERTS` set, the same gate\nthe commit hooks use for host-expert work. On every other host skip this\nsection entirely rather than paying a connection timeout probing an ollama\nthat was never provisioned:\n\n```bash\n[ -n \"${TILLANDSIAS_HOST_EXPERTS:-}\" ] && \"$(. scripts\u002Fplan-binary-probe.sh && resolve_plan_binary)\" script run scripts\u002Flua\u002Fcheck-local-expert-health.lua\n```\n\nIt pings the local Ollama inference endpoint and prints exactly one line matching\n`^(ok:local-experts-healthy|degraded:local-experts[^;]*|down:local-experts[^;]*|skip:not-applicable)$`.\n\nOn `ok:local-experts-healthy` you MAY ask the local pipeline for a triage hint:\n\n```bash\nTILLANDSIAS_EXPERT_DOMAIN=methodology \\\n  .\u002Ftarget\u002Frelease\u002Ftillandsias-plan pipeline \"what is pending and neglected in the plan?\" \\\n    --domain methodology 2>\u002Fdev\u002Fnull | jq -r '.responses[0].answer \u002F\u002F empty'\n```\n\nThe pipeline emits `{tier, domain, rag_freshness, rag_source_commit,\nresponses}`, and each `responses[].answer` is RAW local-model text: no\nretrieval, no validation, no grounding (that wiring is packet\nwire-local-experts-mode-through-grounded-pipeline). Treat the output as an\nungrounded hunch, never a directive — anything it claims about specific\npackets must be re-checked against `tillandsias-plan next \u003Crole>` and the\nplan ledger before acting.\n\nWith the gate unset, or on `down:*` \u002F `degraded:*`, skip the query and\ncontinue the cycle. The local expert system is a convenience, not a gate —\nthe deterministic expert tiers and MCP experts work without it.\n\n## Reduction Engine\n\nThe loop is a reduction engine, not just a worker. Its job is the project's core\nprinciple — **Monotonic Reduction of Uncertainty Under Verifiable Constraints**\n(`methodology\u002Fphilosophy.yaml`). Every cycle must move the system toward a\nverifiable implementation of the spec by *reducing* open uncertainty, and must\nnever let an observed problem evaporate.\n\n### Capture: nothing gets lost\n\nAny time a worker notices \"welp, this isn't great\" — an inefficiency, a rough\nedge, a fragile assumption, an advisory-only guard, a repeated manual step, a\nlog warning, a deprecation notice — it MUST be filed before the cycle exits.\n\nEvery capture is a ledger write, so it carries the `agent_id` from Start Of\nCycle step 0b (`scripts\u002Fagent-identity.sh id \u003Cbackend>`), never a hand-typed one.\n\n**CAPTURE IS MANDATORY. A NEW ROW IS NOT.** These are different acts and\nconflating them is what grew the ready queue to 410 rows against a service rate\nof ~19\u002Fday. Route every capture:\n\n- **A new ROW** only if INDEPENDENTLY SCHEDULABLE — it names owned files no open\n  row already owns, OR a different `pickup_role` can claim it than every open\n  row covering that scope.\n- **Otherwise an EVENT on the row it belongs to**, or a `next_action` clause on\n  that row. The finding is recorded in full either way; only its *selectability*\n  differs.\n\n**When a row's events show a confirmed pattern — several independent\nobservations, ideally from different hosts or cycles, converging on one defect\nor one missing capability — that row has OVERFLOWED and is a promotion\ncandidate. NOTE it; do NOT promote it. Promotion is Tlatoāni-gated** (operator\nruling, 2026-08-19): what counts as a confirmed pattern is not yet expressible\nas a threshold, and an agent promoting on its own judgment restores unbounded\narrival by a longer path.\n\nWhy this is safe, and why it is not a throughput cut: with arrivals\nλ = a + b·μ, the queue moves at `dL\u002Fdt = a + (b−1)·μ`. Above b = 1 every extra\nhost and every shortened cycle fills the queue FASTER; below b = 1 the same\nvelocity drains it. Measured b is 1.80. So curation at the acceptance boundary\nis the *precondition* for velocity paying off at all — see\n`methodology\u002Fdistributed-work.yaml` → `why_velocity_is_the_other_lever`.\n\n### Standing FRESHNESS audit class (order 372, methodology `component_freshness`)\nEach cycle, after worker drain, treat the top component the `freshness-advisory`\nCI phase flagged as a claimable audit source. Re-validate ONE component against\nthe audit question — *last properly looked at and confirmed still meaningful,\nuseful, efficient, sound, and complete?* — and end in exactly one disposition:\n**refreshed** (re-validated, update its `# freshness:` stamp), **updated**\n(fixed\u002Ftuned, update stamp), or **obsoleted** (delete\u002Ftombstone with same-commit\nremoval of dependents). Apply the **discard-over-repair bias**: discard a stale\ncomponent rather than repair it when a fresh implementation would be better.\n`scripts\u002Ffreshness-inventory.sh` emits the coverage report + top stale\ncomponents each `.\u002Fbuild.sh --ci` run; the report grammar is pinned by\n`litmus:freshness-inventory-shape`. A freshness audit is a valid reduction step\non its own and counts toward burndown.\nThis is mandatory, not optional (`methodology.yaml` →\n`cooperative_work_discipline`; Non-Negotiable Exit Contract → \"Explicitly log\nthings that make you slower\"). File it as a dated issue in `plan\u002Fissues\u002F`,\nclassified as one of: `research\u002F`, `exploration\u002F`, `enhancement\u002F`, or\n`optimization\u002F`. An unfiled finding is a lost finding and a contract violation.\n\n### Ledger compaction (check each cycle; act only when eligible)\n\n```bash\ntillandsias-plan fragments     # -> compaction: eligible=\u003Cbool> fragments=N bytes=N malformed=N reason=\u003Cname>\ntillandsias-plan compact       # only when eligible=true\n```\n\n`plan\u002Findex.yaml` is a compacted BASE; `plan\u002Findex.d\u002F*.yaml` are append-only\nfragments that concurrent hosts write freely. Reads fold them transparently, so\n**an uncompacted ledger is slower, never wrong** — compaction is garbage\ncollection, not a correctness step. Never let it block filing work.\n\nTwo rules, both easy to get wrong:\n\n- **Compaction deletes only the fragments it folded, by name.** Never\n  `rm plan\u002Findex.d\u002F*`. A fragment another host wrote while you were compacting\n  has not been folded, and removing it silently destroys their work.\n- **Compaction is TEXT-LEVEL and never re-serializes the base.** It ran on the\n  real ledger for the first time on 2026-08-03 (order 582-4wdi, commit 81e12b65):\n  28 fragments folded, 120 comment lines preserved exactly, 535 packets\n  preserved, and the `plan\u002Findex.yaml` diff was 1021 added lines and zero removed\n  lines. **Do not read that zero as the invariant** — it was a true measurement of\n  a fold that could only APPEND, taken before `set-field` fragments existed, and\n  it has been unreachable since. A fragment that reassigns a field must remove the\n  superseded line; a fold carrying nine status transitions removes nine `status:`\n  lines and that is the fold working.\n\n  THE PROPERTY TO PROTECT, stated so a healthy compaction cannot fail it: no line\n  is removed EXCEPT one whose field a fragment explicitly reassigned. Comment\n  lines, packet count (minus none, plus the new ones), and the four-space item\n  prefix `append-event` locates by all survive unchanged. Check THOSE, in one\n  command, rather than eyeballing the removal count:\n\n  ```bash\n  git diff --numstat plan\u002Findex.yaml                  # removals are expected\n  git diff plan\u002Findex.yaml | grep '^-' | grep -v '^---' | head -40   # READ them\n  ```\n\n  **Read the removed LINES, not a histogram of their keys.** This recipe used to\n  end with `cut -d: -f1 | sort | uniq -c` and the question \"ONLY field keys?\".\n  That works only while every reassigned field has a SCALAR value. A fragment\n  that replaces a STRUCTURED value removes all of its lines, including list\n  items that are not field keys at all — measured on yoga 2026-08-25, a fold\n  whose 14 removals included `- container`, `- cpu`, `- gpu`, `engines`,\n  `lanes` and `supported_device_classes`, because a stale capability row's\n  `engines: [{name: ollama, ...}]` block was superseded by `engines: []`. The\n  fold was correct; the histogram made it look like structure loss, which is\n  the same stop-and-investigate 865-ng6r removed for the scalar case. The\n  question is not \"are these field keys\" but \"does each removed line belong to\n  a field some fragment reassigned\" — and the cheapest way to answer it is to\n  look at the lines.\n\n  MEASURED TWICE, on two hosts, each of which stopped its cycle to investigate:\n  lenovinha 2026-08-23 (+888\u002F-17 — five `status`, one multi-line `next_action`)\n  and yoga 2026-08-25 (+556\u002F-12 — nine `status`, two `next_action`, one\n  `next_action_ts`; 37 comments and all 526 packet prefixes intact). Both folds\n  were correct. The prose is what cost the time, which is why it is corrected\n  here rather than merely noted (865-ng6r).\n\n  It refused for months before that, correctly: a `serde_yaml` round-trip drops\n  comments and re-indents items to column 0, after which `append-event` silently\n  stops finding packets. If compaction ever regresses to round-tripping YAML,\n  restore the refusal rather than accepting a lossy fold. The candidate base must\n  still PARSE and pass the integrity gate before it may replace the base.\n\nIf `malformed=N` is non-zero, a fragment did not parse and was SKIPPED — its\ncontents are absent from every answer. Treat that as a finding, not noise.\n\n### De-slop sweep clock (consult each cycle; act only when due)\n\n```bash\nscripts\u002Fcheck-deslop-due.sh check    # exit 0 = NOT due; exit 1 = due; exit 2 = cannot compute\n```\n\n**Read the exit polarity before wiring anything to it.** The file is named\n`check-deslop-due.sh` and exits **0 when the sweep is NOT due** — same\nconvention as `check-daily-maintenance.sh`, where the actionable state is the\nnon-zero one and the healthy steady state stays at 0 for callers under `set -e`.\nThe idiom is `if ! scripts\u002Fcheck-deslop-due.sh; then run_the_sweep; fi`, or\nbranch on the verdict token (`deslop-due` \u002F `deslop-not-due`), which cannot be\ninverted by a copy-paste.\n\nIt prints exactly one line carrying the numbers it decided on, e.g.\n`ok:deslop-not-due:order=844 last=834 delta=10 hours=44 reason=under-threshold`.\nThe rule is **event-counted only**: due when\n`(current_order - order_at_last_sweep) >= 200`, with a 48h floor so a filing\nburst cannot fire two sweeps in a day, and **no calendar ceiling** — a ceiling\nwould fire low-yield sweeps over a quiet fortnight and\n`red:two-sweeps-zero-confirmed` would then retire the reconciler for doing\nnothing wrong. Time-decaying properties already have their own TTLs\n(`expire-claims` 24h, `component_freshness`). This is **not** a build gate and\nnothing in `.\u002Fbuild.sh` runs it; it is a scheduler input for this section.\n\nAfter running a sweep, record it — the marker is committed, not host-local, so\nthe whole fleet shares one clock:\n\n```bash\nscripts\u002Fcheck-deslop-due.sh record --examined \u003Crows-looked-at> --confirmed \u003Cn> \\\n  [--retracted \u003Cn>] [--filed \u003Cn>] [--net-lines \u003C±n>]\n```\n\n`--examined` and `--confirmed` are mandatory. The sweep's kill rule counts only\nsweeps that **examined new rows**, and this is why: the first real sweep\nretracted 51 of 410 rows (12.4%) against a modelled ~50%, and that pass drained\naccumulated stock. Steady-state yield will be far lower, so **two consecutive\nnear-zero sweeps is a normal outcome for a healthy queue**, not evidence the\nreconciler is broken. A sweep that confirms the queue is clean has done its job.\n\n### Filing a packet: mint its order, never pick one\n\n```bash\ntillandsias-plan next-order          # -> 581-k3f9\n```\n\n**Write the packet to a FRAGMENT, not to `plan\u002Findex.yaml`.** Create\n`plan\u002Findex.d\u002F\u003Cutc>-\u003Csuffix>-\u003Chost>.yaml` with a top-level `packets:` list. Only\nyou can have produced that filename, so git never conflicts and no host waits on\nanother. Reads fold it in automatically — the packet is queryable immediately.\nFragments are IMMUTABLE: to change something, write a new fragment, never edit an\nexisting one (that is what makes the fold order-independent).\n\n### Prose NEVER passes through argv (order 971-7muc)\n\n```bash\ntillandsias-plan append-event \u003Cref> \u003Ctype> --summary-file NOTE.md --host \u003Chost>\ntillandsias-plan append-event \u003Cref> \u003Ctype> --summary-file -  --host \u003Chost> \u003C\u003C'EOF'\n...prose...\nEOF\n```\n\n**Note the QUOTED heredoc delimiter — `\u003C\u003C'EOF'`, never `\u003C\u003CEOF`.** An unquoted\ndelimiter expands backticks and `$(...)` inside the body, which is one of the two\nways this defect actually happened.\n\nWHY, and it is worth the four lines because every instrument we have says the\nwrite succeeded. Prose passed as a shell argument is rewritten by the shell\n*before* `tillandsias-plan` starts, and the damage is unrecoverable by then:\n\n```text\n\"the `accel_mem_budget_gb` field\"   ->   argv receives:   \"the  field\"\n```\n\nBoth backticks and the word between them are gone. Two hosts lost the SUBJECT of\na sentence to this on one evening (964-r98h, 970-7fqk), and `validate-yaml`,\n`tillandsias-plan check`, the fragment-keys guard and `.\u002Fbuild.sh --check` all\npassed the result — because valid YAML carrying plausible prose is exactly what\nthe corruption produces. It bites hardest on the most valuable writes: prose that\nquotes an identifier is prose explaining *why* something is named what it is, and\nbackticks are how anyone writes that.\n\n`--summary-file` is read by the process itself, so no shell ever sees the bytes.\nThe argv path still exists and now REFUSES text carrying expansion residue (an\nunbalanced backtick, a literal `$(`) — but understand what that can and cannot\ndo: a *balanced* substitution leaves no trace at all, so the refusal is a\nbackstop, not a guarantee. The file is the guarantee.\n\nPinned by `scripts\u002Ftest-ledger-prose-roundtrip.sh`, which asserts byte-identity\nfor text containing backticks, `$(...)` and `$VAR`.\n\n### Multi-line `perl -0pi` edits are FORBIDDEN on this tree (hard rule, 2026-09-04)\n\nThree source corruptions in one day, all the same shape: a multi-line\n`perl -0pi -e 's|...|...|'` edit landed its replacement inside a file's\nHEADER COMMENT (accel_probe.rs twice, a fixture header once) instead of at\nthe intended site, the line count stayed plausible, and only the compiler or\na read of the diff's DELETIONS caught it. The author had filed the warning for\nthe fleet at 11:49Z and hit it twice more in the same afternoon.\n\nEdit by exact-match, single-string replacement only: the Edit tool, a\n`python3` script that asserts the anchor occurs exactly once before writing,\nor `sed` on ONE addressed line. After any scripted edit, read the diff's\nremoved lines before committing, not the count of them. A tool whose failure\nmode is \"plausible file, wrong place\" is not a tool for a tree whose gates\ngrep for shapes.\n\n**Never compute \"the next free order\" yourself.** That number comes from a\nledger snapshot which is stale the moment another host commits, so two hosts\nfiling in the same window pick the SAME number deterministically. It happened\ntwice on 2026-07-31 (560–562, then 568–570), and six collisions sit at HEAD.\n\nThe minted token is **permanent**. Do not renumber it later, and do not ask a\ncoordinator to \"normalize\" it — order tokens leak into code comments, `@trace\norder:` headers, and commit messages, and a pushed commit message can never be\ncorrected. Two hosts landing on prefix `575` produce `575-k3f9` and `575-m2p1`:\nboth correct, both permanent, nothing to reconcile. A shared prefix is normal.\n\nCite `packet_id` in anything durable — depends_on, specs, methodology, commit\nmessages. It is the identity and is unique by construction; the order token is a\nhuman convenience. Canonical: `methodology\u002Fdistributed-work.yaml` →\n`order_id_allocation`.\n\n### Reduce: smaller, simpler, verifiable packets\n\nFiling is only the intake half. Each recurring cycle then *reduces* open\nfindings:\n\n1. Pick the highest-value open finding that fits this host's capability.\n2. Split it into the smallest packet that closes a slice of it under a\n   **verifiable constraint** — a litmus test, an executable check returning a\n   pass\u002Ffail exit code, or a parser\u002Fvalidator — never prose intent alone. A\n   guard only an attentive agent honors is a suggestion, not a constraint;\n   reduce it to something that fails loud on its own.\n3. Promote that packet into `plan\u002Findex.yaml` as a `ready` node with a named\n   verifiable closure, then drain it when a capable host can produce evidence.\n4. When the verifiable check passes, the slice is retired; re-derive the\n   remaining residual and repeat.\n\nReduction is monotonic: each step must lower residual uncertainty or preserve it\nwhile increasing verification level (`convergence.yaml` → `drift_control`). A\n\"reduction\" that adds ambiguity or removes a validated invariant is drift and\nmust be rejected. Shaping a finding into a well-formed `ready` packet *is* a\nvalid reduction step when the current host cannot yet implement it.\n\n### Raising the bar is Tlatoāni-gated (do not self-escalate)\n\nThe scan bar is a fixed, declared depth. Reducing all open findings to zero **at\nthe current bar is a legitimate, clear convergence point** — a fixed point of\nthe refinement operator — not premature convergence. The loop MUST NOT raise the\nbar on its own. Autonomous bar-raising would make the convergence point\nundefined (the loop could never report \"done\"), which is exactly the failure\nthis rule prevents. See `methodology\u002Fconvergence.yaml` → `bar_raise_governance`.\n\nWhat the loop does as it approaches zero residual at the current bar:\n\n1. Keep reducing open findings at the current bar until none remain.\n2. Then *propose* bar-raise candidates — file them as `research\u002F` or\n   `exploration\u002F` issues describing the deeper scan that could be enabled (e.g.\n   treat build\u002Ftest\u002Fruntime warnings, non-fatal errors, deprecation notices,\n   flaky-test signals, slow steps, or stale caches as findings). A proposal is a\n   candidate, not an enabled scan.\n3. STOP there. Enabling any bar-raise — actually treating a deeper signal class\n   as findings — is an explicit, one-off decision that **The Tlatoāni must\n   approve every time.** Record the approval (who\u002Fwhen\u002Fscope) before the deeper\n   scan becomes part of the loop's contract.\n\nRationale: much of the system is \"build what works, then improve from there,\" so\neach bar-raise is a deliberate scope expansion the operator owns, not an\nemergent behavior. Automatable approval of *some* low-risk bar-raises may come\nlater; until The Tlatoāni declares such a policy, every bar-raise is manual.\nReaching zero at the current bar and filing bar-raise candidates is a complete,\nsuccessful cycle — not an excuse to escalate unprompted.\n\nSee `plan\u002Fissues\u002Fmeta-orch-enhancement-opportunities-2026-06-20.md` for a worked\nexample of capture → reduce → promote.\n\n## When the Gate Fails, Read check-logs.jsonl FIRST\n\n`.cache\u002Fconvergence\u002Fcheck-logs.jsonl` holds a per-run verdict for every check,\ngoing back weeks. It is the authoritative record of what failed and when.\n`scripts\u002Fconvergence-log-path.sh` prints its path and honours\n`TILLANDSIAS_CHECK_LOG_INDEX`. It lived at `target\u002Fconvergence\u002Fcheck-logs.jsonl`\nuntil order 888-vgs8: Finalization 9c's `cargo clean` removes `target\u002F`\nwholesale, so the sweep this skill mandates was erasing the history this\nsection mandates reading, and the sweep's verdict never said so. The first\nresolve after the move adopts a legacy `target\u002F` index once, by copy.\n\nDo NOT diagnose from terminal scrollback. The next run overwrites the per-check\nlogs under `target\u002Fconvergence\u002Fcheck-logs\u002F` (those still go with a sweep), and\nre-running to \"get a better look\" is what destroys the evidence — the re-run\nmay pass, and then the failure is gone.\n\n```bash\njq -r 'select(.status != \"pass\") | \"\\(.ci_run_id)\\t\\(.check_id)\\t\\(.status)\"' \\\n  \"$(scripts\u002Fconvergence-log-path.sh)\" | tail -20\n```\n\n`scripts\u002Flocal-ci.sh` also prints a `Failed checks:` block naming each failure.\nIf you pipe the gate through `tail -N` or a grep filter, you will cut that block\noff and lose the names — this host did exactly that twice on 2026-08-09, spent\ntwo cycles calling an intermittent failure \"unexplained\", and filed a packet on\nthe false premise that the names were unrecoverable (637-df4z, closed\nmis-diagnosed). The answer had been on disk the whole time: `rust-tests` and\n`tray-contract`, two parallel tests racing on `$HOME` and a shared fixture\ndirectory (638-ehzi).\n\nAn intermittent failure is a defect with a schedule, not noise. Treating it as\nnoise is how it survives.\n\n## Reads Go Through MCP First\n\nBefore draining anything: **do not read whole ledgers.** `plan\u002Findex.yaml` is\n31,678 lines and `plan\u002Floop_status.md` is 7,875; pulling either in full to learn\none fact is the largest single consumer of orchestrator context in this loop, and\nit is paid again by every agent on every host every cycle.\n\nAsk `forge-plan` \u002F `project-plan` (`plan_answer`, `plan_next`, `plan_query`,\n`plan_status`, `plan_blocked_by`, `methodology_ask`, `spec_answer`) and\n`project-info` (`search_code`, `grep_code`, `find_files`, `read_file`). Answers\nare cited — keep the citations. For a conversational\u002Fsynthesis status question,\nuse the Local Experts mode (`expert-serve`) — same citations-or-typed-refusal\ncontract as `spec_answer`.\n\nDrop to the filesystem for exactly three reasons, and name the one that applies:\n**unavailable** (MCP down or `confidence=unsupported` — fall back and keep going,\nthen record it so a systematically-refusing expert stays visible);\n**verification** (before any irreversible act, read the CITED SPAN, not the\nfile); **not exposed** (no tool covers it — and if the loop needs it repeatedly,\nthat is a missing tool, so file a packet).\n\nCanonical: `methodology\u002Fdistributed-work.yaml` → `mcp_first_read_path`.\n\n## Worker Drain\n\n#### Writing a validation packet: demand the post-condition AFTER the last MUTATING step\n\nAny packet that asks a host to install, launch, switch channels, or otherwise\nmutate its runtime must require the health check at the **end of everything the\nhost actually does** — not after the last step that felt like the test.\n\nEarned 2026-08-10. A sibling's smoke reported 4\u002F4 PASS on a `HEALTHY --diagnose`\ntaken at 04:32:20, then ran one more mutating step (a downgrade-to-stable \u002F\nrestore-to-unstable round trip), which wedged the control wire at 04:33:27 and\nleft the host in a failed provisioning state for ~25 minutes until the operator\nfound it. Every per-step result was true; the verdict was still incomplete about\nthe host's end state, and a stable promotion was made on it.\n\nTheir own words are the rule worth copying: *\"a post-condition check belongs\nafter the last MUTATING step, not after the last interesting one.\"*\n\nSo a validation packet this loop writes should say, explicitly:\n\n> Final step, after everything above: re-run the health check. If any step after\n> your last health check mutated the host, that check is stale and the run is\n> not finished.\n\n## Stranded-claim sweep (coordinator, every cycle)\n\n```bash\nscripts\u002Fcheck-stranded-in-progress.sh\nscripts\u002Fcheck-landed-but-open.sh\nscripts\u002Farchive-plan-packets.sh\n```\n\n`check-landed-but-open.sh` (1367-emjg) is the other half of the same leak: it\nlists every order a CODE landing on trunk cites in its subject (default window\nten days) whose row is still ready, pending, in_progress or implemented. On\n2026-09-23 that was 21 of 177 landed orders; on 2026-09-28 it found 920-tqhs a\nmonth after its relay landed. Plan-only commits are not landings; `--cite\nmessage` also reads commit bodies, which cite orders as context and triples the\nlist. Report its `summary:landed-but-open:` line beside the stranded one.\n\nA packet in `in_progress` is invisible in BOTH directions: `ready` queries skip\nit so nobody claims it, and burndown does not count it so nobody notices it is\nunfinished. 21 packets were in that state on 2026-08-09 — ~9% of the live\nledger, oldest at order 153 — every one with no progress event ever recorded\n(641-e2qa).\n\nReport the `summary:` line in the handoff. If the count is rising cycle over\ncycle, claims are outliving their cycles and that is the thing to fix, not the\nindividual packets.\n\nAdvisory, never a gate: a packet legitimately in flight right now is\nindistinguishable from one abandoned an hour ago. **Do not bulk-close what it\nreports.** Closing a packet requires checking its exit criteria against the\ntree; guessing marks unfinished work done, which is strictly worse than leaving\nit stranded.\n\n### Cycle batch triage — decide the batch BEFORE draining\n\n```bash\nscripts\u002Fselect-work-batch.sh \u003Clinux|macos|windows|any>\n```\n\nRun this once, at the top of the drain, and take the batch it prints. It selects\nONE epic (`release_target`) and at most `budget` packets from it, so a cycle\ndrains a coherent slice instead of five unrelated subsystems — the scatter that\nmade small packets cost more in orientation than in work.\n\n**THE BATCH IS A STORY, AND THE STORY IS THE UNIT OF WORK — not the packet.**\nTake the whole batch, implement it as one coherent change, and pay the cycle's\nfixed costs ONCE: one build\u002Fverify pass, one loop-status entry, one attestation.\nDo not run `.\u002Fbuild.sh --check` per packet, and do not attest per packet.\n\nWhy this is the rule and not a preference — measured on the fleet 2026-08-16..19:\n\n| commits, 3 days | count |\n| --------------- | ----- |\n| `record(mo-full)` (attestation only) | 155 |\n| `chore(plan)` (ledger bookkeeping)   |  88 |\n| every category of actual product work | single digits each |\n\nOver 5 days that is 127 product-code commits against 457 plan-only, 149\nattestation-only and 219 merge commits. **Every cycle pays the same exit cost\nwhether it carried one packet or eight** — loop-status, attestation record,\nattestation self-check at the new HEAD, and the merges each of those provokes.\nA one-packet cycle spends most of itself on the exit contract. Bundling does not\nmake the overhead smaller; it amortizes it across more delivered work, which is\nthe only lever available without weakening the contract itself.\n\nBudgets, which the selector already implements — do not restate a different\nnumber here, and if this text and `scripts\u002Fselect-work-batch.sh` ever disagree,\nthe SCRIPT is right and this paragraph is stale:\n\n- non-forge hosts: adaptive **6 → 10** (order 682-yiz7, evidence-backed tuning)\n- autonomous \u002F pairing forge cycles: adaptive **4**, or `TILLANDSIAS_CYCLE_BUDGET`\n- unattended litmus runs: 1 (order 707-3x9d)\n\nThis paragraph used to end \"Budget is 1 on forge (order 264) and 3 elsewhere\"\nwhile its own opening sentence said 4 and 6, and the script said 6 → 10. Three\nnumbers for one budget, in one paragraph plus its tool. Agents read the smallest\none, which is how a fleet tuned to 10 spent its nights draining one packet at a\ntime.\n\nIt is minimax-ranked (largest residual first, per `convergence.yaml` →\n`minimax_convergence_strategy`), with score-weighted entropy over the top-3.\nThe seed is printed; record it in the loop-status entry so the cycle can be\nreplayed. Budgets are stated ONCE, above — never restate them here.\n\n**THE SEED DOES NOT SEPARATE CONCURRENT HOSTS. Do not rely on it to.** This\nparagraph used to end \"...so coverage spreads over time and two concurrent hosts\ndo not collide on one epic\". The second half is false and was never measured.\nMeasured 2026-08-19 on macuahuitl against the live ledger: three distinct seeds\n(`macuahuitl-`, `yoga-`, `esmeraldinha-20260819`) produced a byte-identical\nbatch — same `epic=socket-audit-master`, same `pick=2\u002F3`, same score, same head\npacket. Two independent reasons, and neither is fixable by reseeding:\n\n- The default seed is `${TILLANDSIAS_HOST_KIND:-host}-\u003Cdate>`\n  (select-work-batch.sh:232). `TILLANDSIAS_HOST_KIND` is set only inside the\n  forge, so every bare-metal host falls back to the literal `host` and they all\n  seed identically. Even when set it is host KIND, so three Linux boxes collide\n  with each other regardless.\n- The `urgent=\u003Cpacket>` override puts one globally-urgent packet at the head of\n  the batch. Urgency is a property of the PACKET, so it is host-independent by\n  construction and preempts the epic pick on every host at once.\n\n**SEPARATION COMES FROM CLAIMING, which is the mechanism that already exists and\nis sitting at zero.** `next`\u002F`select-work-batch` filter to `unleased`, and\n\"leased\" means `status: in_progress`. `expire-claims` (order 672-bz7u) reaps\nclaims older than 24h so a dead host cannot strand work permanently. As of\n2026-08-19 `expire-claims` reports `in_progress=0` — nothing has been claimed at\nall, so every host is offered every packet, and on 2026-08-18 two hosts\nimplemented 798-tk7b six minutes apart (order 814-iyu7, ~4h duplicated).\n\nSo, before you implement anything from the batch — and before a coordinator\nROUTES a row to another host — ask whether a sibling branch already holds it\n(order 1513-pppk):\n\n```bash\nscripts\u002Fcheck-claims-across-branches.sh --batch \u003Corder>...\n# -> claimed-elsewhere:\u003Corder>:\u003Cbranch> per held row, then ok:cross-branch-claims:\u003Cn>\n#    blocked:* means the fold could not be read: do not treat it as \"free\"\n```\n\nA trunk-only read cannot see a claim that sits on osx-next or windows-next\nuntil the relay, and on 2026-09-29 the coordinator nearly re-assigned a row\nanother host had claimed that morning. Then claim:\n\n```bash\ntillandsias-plan set-field \u003Corder> status in_progress \\\n    --host \"$(hostname -s)\" --reason \"claimed for cycle \u003CUTC ts>\"\ngit add plan\u002Findex.d && git commit -m \"claim(\u003Corder>): \u003Chost>\" && git push\nscripts\u002Fcheck-claim-confirmed.sh \u003Corder>\n# -> ok:claim-confirmed:\u003Corder> | refused:claim-not-on-origin | refused:claim-lost:\u003Corder>\n#    | unknown:claim-origin-unreachable (never a pass)\n```\n\nPush the claim BEFORE the work, not with it — an unpushed claim separates\nnobody, and a push that failed quietly (a locked keyring, 2026-09-29) looks\nexactly like one that landed until `check-claim-confirmed` asks origin\n(1493-d93i). Then:\n\n- **Losing the race is normal and cheap.** The ledger is a CRDT; two hosts can\n  claim in the same window. On your next fetch, if another host's claim event\n  for that order carries an EARLIER timestamp (ties broken by lexicographically\n  smaller hostname), you lost: release yours back to `ready` and take the next\n  batch item. Do not both continue — that is exactly 814-iyu7.\n- **Release on exit, always.** Completed work moves to its terminal status.\n  Work you did NOT finish goes back to `ready` in the same cycle you abandon it.\n  Leaving it `in_progress` hides it from `ready` AND from burndown until the 24h\n  reaper runs — 21 packets were stranded that way on 2026-08-09 (641-e2qa).\n  Claiming is only safe because releasing is unconditional.\n\nThe `triage:` line reports `ungrouped=N` — eligible packets with no\n`release_target`. That number is the health of the epic tier itself: when it is\nlarge, selection is degrading toward flat priority order regardless of what this\nscript does. Surface it in the handoff.\n\nCanonical: `methodology\u002Fdistributed-work.yaml` → `cycle_batch_triage`.\n\nWhen choosing the builder role, run `\u002Fadvance-work-from-plan` repeatedly in a `.\u002Fplan` friendly way in fresh cycles until one of these is true:\n\n- no eligible ready work remains for this host;\n- every eligible item is blocked;\n- a terminal failure was filed;\n- the current cycle has already produced a coherent commit and the next packet\n  would exceed the recurring-loop budget.\n\nForge-hosted cycles (`TILLANDSIAS_HOST_KIND=forge`) are the OPPOSITE of\ngreedy — decided by The Tlatoāni 2026-07-10 (order 264), replacing the earlier\n\"drain as many as possible\" exception:\n\n- Drain **as much of the batch as fits the envelope, as ONE story** — bounded by\n  TIME, not by a count. Superseded 2026-08-19 by The Tlatoāni, who set order 264\n  in the first place: *\"that's also why I was asking for bundles of related\n  packets in stories and epics, rather than the 'take a single packet' baked\n  into the .\u002Fmethodology that I've been fighting you to lift.\"*\n\n  Order 264's REASONING survives intact and is the reason this is a time bound\n  rather than a licence: a litmus-launched forge cycle lives inside\n  `litmus:opencode-prompt-e2e-shape` STEP 3's 600s budget, and a cycle that\n  overruns it dies mid-work with nothing pushed. What does NOT survive is the\n  count. \"One packet\" was a proxy for \"fits in 600s\", and it is a bad proxy in\n  both directions: three one-line ledger closures fit easily, and one large\n  packet does not fit at all.\n\n  So the forge asks the envelope question about the STORY, not the packet, and\n  the selector's adaptive budget (4, or `TILLANDSIAS_CYCLE_BUDGET`) is the\n  starting size.\n- Before implementing, estimate whether implement+verify+commit+push for the\n  whole story fits the launch envelope.\n- If it does not fit, do NOT start implementing: **split** the packet into\n  smaller ready child packets (`split_into` pattern), record the shaping\n  events, commit and push. The shaping commit IS that cycle's completed work —\n  a split that lowers residual ambiguity is a valid reduction step.\n- Canonical statement: `methodology\u002Fdistributed-work.yaml`\n  `worker_agent_protocol.forge_cycle_budget`. Interim reliance on step\n  timeouts is tracked by order 265 (forge heartbeat\u002Fliveness signals).\n\nEach worker cycle must obey the non-negotiable exit contract above.\n\n### Node-Closure Claim (avoid duplicated ledger-hygiene work)\n\nBefore re-deriving and closing or hygiene-editing a `plan\u002Findex.yaml` node,\nclaim it so a concurrent cycle does not independently produce the identical edit\n(the idempotent-but-wasteful collision recorded in\n`plan\u002Fissues\u002Fagent-concurrency-collisions-2026-06-20.md`). Run the executable\nclaim instead of eyeballing the ledger:\n\n```bash\nscripts\u002Fclaim-ledger-node.sh claim \u003Cnode-id>   # e.g. release-nix-cache-ref-scoping\u002Fchoose-approach\n```\n\nIt emits exactly one line matching\n`^(claimed|reclaimed|in-flight|released|free):[a-z0-9._\u002F-]+$` and exits `0` when\nthis cycle owns the node (`claimed:`\u002F`reclaimed:`) or non-zero (`in-flight:`)\nwhen a live lease is held elsewhere — in which case skip that node and pick the\nnext eligible one. The lease is an advisory, CRDT-friendly reservation, not a\nmutex on the file: it respects the stable-ID + idempotent-merge preconditions in\n`methodology\u002Fbetween-commits-work-discipline.yaml`, so a missed or expired lease\nnever corrupts state (at worst two cycles converge on the same safe edit).\nRelease with `scripts\u002Fclaim-ledger-node.sh release \u003Cnode-id>` after the closure\nis committed; expired leases (default TTL 4h) are auto-reclaimed. Pinned by\n`litmus:ledger-node-claim-shape`.\n\n### Release-Targeted and Milestone Packets\n\nWorker selection prefers packets carrying `release_target:\n\u003Cmilestone-packet-id>` before the general backlog; a host with no eligible\ntargeted work falls back normally (never idle). `kind: milestone` packets\nare criteria holders — never claim one for implementation; claim children\nand record burndown as progress events on the milestone. Large ambitious\ngoals follow `methodology\u002Fdistributed-work.yaml` →\n`ambitious_milestone_reduction` (fat-agent research → operator-signed\ndecision record → smallest demonstrable rungs → verification): the\ncoordinator mirrors the milestone's burndown in `plan\u002Floop_status.md` each\ncycle.\n\n### Long-Running (multi_cycle) Packets\n\nPackets marked `multi_cycle: true` in `plan\u002Findex.yaml` follow\n`methodology\u002Fdistributed-work.yaml` → `long_running_packets` (plan order 251):\n\n- Claims are **cycle-scoped**; the packet returns to `ready` after each\n  cycle's commit. A `ready` multi_cycle packet with prior progress events is\n  normal, not stalled.\n- Do NOT mark one `done` — even with all exit criteria implemented — until\n  its `verification_required.completion_gate` is satisfied by `verified-by`\n  events from every named agent. Implementation-complete means\n  `phase: verification`, not `completed`.\n- Treat a packet sitting at `phase: verification` as a dispatch item for the\n  named verifier agents and surface it during coordination.\n- The active set is mirrored in `plan\u002Flong-running.md`; keep that view in\n  sync in the same commit as any phase\u002Fstatus\u002Fverification change.\n\n## E2E Gates\n\nRun eligible e2e gates after worker drain:\n\n| Host kind | Local-build e2e | Curl-install e2e |\n|---|---:|---:|\n| linux_immutable | no | yes |\n| linux_mutable | yes | yes |\n| macos | yes | yes |\n| windows | yes | yes |\n\nBefore running any local-build e2e gate, consult the structured host-eligibility\nverdict instead of re-deriving the skip reason in prose: run\n`scripts\u002Fe2e-preflight.sh eligibility`, which prints exactly one line matching\n`^(eligible|skip:[a-z0-9-]+)$`. Proceed with the local-build gate only on\n`eligible`; on any `skip:\u003Creason>` (e.g. `skip:no-podman-user-session` in the\nCowork sandbox, which has no `\u002Frun\u002Fuser\u002F\u003Cuid>`, or `skip:smoke-lock-held` when a\nparent\u002Flocal sibling smoke already owns the host lock) record the verdict once\nand skip the local-build gate without re-litigating it. Pinned by\n`litmus:e2e-eligibility-probe-shape`.\n\nRules:\n\n- Local-build e2e uses `\u002Fbuild-install-and-smoke-test-e2e`.\n- On macOS the local build that gate exercises is\n  `scripts\u002Fbuild-macos-tray.sh` (the `\u002Fbuild-macos-tray` skill wraps it and\n  files findings to `plan\u002Fissues\u002Fmacos-build-findings-\u003CDATE>.md`);\n  `.\u002Fbuild.sh --install` is refused on Darwin by design (723-whrx), so there\n  is no build.sh install path to look for.\n- Published-release e2e uses `\u002Fsmoke-curl-install-and-test-e2e`.\n- Destructive substrate reset is expected setup on Tillandsias smoke hosts.\n  `podman system reset --force` is a precondition for Linux idempotence tests,\n  not a blocker. Do not pause, ask for confirmation, or skip the e2e gate for\n  fear of wiping Podman when `TILLANDSIAS_DESTRUCTIVE_RESET_OK` is unset or `1`.\n  Only treat reset as blocked when the environment explicitly sets\n  `TILLANDSIAS_DESTRUCTIVE_RESET_OK=0`.\n- If the plan records a latest tested release older than the current GitHub\n  release, prioritize curl-install e2e.\n- File every finding as a plan packet; write a PASS report for clean runs.\n- **Host-qualify any report filename another host could produce the same\n  day (1004-fue3).** The smoke runbook once templated its report path from\n  release and UTC date with no host field; two platforms smoking one release\n  on one day collided add\u002Fadd at land time, and the naive resolution — \"take\n  one side\" — silently deleted a platform's result. Name each report or\n  per-host finding with the host baked in (`\u003Chost_kind>-\u003Chost_id>`, or the\n  hostname), never a bare subject-and-date. The smoke template carries the\n  field now; a hand-written findings path (`…-findings-\u003CDATE>.md`, the shape\n  named above for `\u002Fbuild-macos-tray`) still does not, so add it yourself\n  (drill: plan\u002Fissues\u002Ffleet-restart-2026-09-12.md, Two lanes, one report filename).\n\n## Mutable Linux Coordinator Duties\n\nOnly `linux_mutable` performs global coordination:\n\n1. Run `\u002Fmultihost-orchestration` after worker drain or when sibling branches\n   advanced.\n2. Merge eligible `origin\u002Fwindows-next` and `origin\u002Fosx-next` work into\n   `linux-next`, with explicit conflict mediation if needed.\n3. Run more frequent local-build e2e gates than other hosts.\n4. Run `\u002Fmerge-to-main-and-release` only when `linux-next` is green, plan\n   evidence is current, and no release is already in flight.\n   Read the `cloud.usage` MCP tool first (order 1966-47vt): Cloudflare at\n   ≥ 2,700 of 3,000 build minutes this month means no merge to main unless\n   the fix is urgent.\n5. After a release succeeds, ensure the plan records the new latest release so\n   immutable Linux hosts know to run curl-install e2e.\n6. **Move the project's openspec CLI forward deliberately (order 1441-myz3)**.\n   `openspec\u002Fcli-version` is the project's ONE openspec version. Forges install\n   exactly it (`ensure_openspec_pinned`, lib-common.sh) and never refresh it to\n   @latest, so a fresh forge's \u002Fopsx sets match the committed ones and launch\n   leaves the checkout clean. Keeping the pin current is the coordinator's\n   job, once per cycle and cheap when nothing is due. Run it on a CLEAN tree\n   based on `origin\u002Flinux-next` (a `work\u002F\u003Corder>` ref or the coordinator's\n   own checkout), with npm on PATH (host or `tillandsias-builder`):\n   ```bash\n   scripts\u002Fopenspec-pin.sh check    # ok:openspec-pin-current:\u003Cv> | due:openspec-bump:\u003Cpin>->\u003Clatest> | unknown:…\n   scripts\u002Fopenspec-pin.sh bump     # only on due: (or `bump --to \u003Cv>` to re-level at the current pin)\n   scripts\u002Fopenspec-pin.sh drift    # must print ok:openspec-generated-matches-pin before committing\n   ```\n   `bump` installs the new version into a version-keyed cache, runs\n   `openspec update --force` with an ISOLATED openspec config (the profile is\n   derived from the committed workflows, never from the machine running it),\n   writes the pin, and never commits. On `bumped:openspec:\u003Cold>->\u003Cnew>:\u003Cn>-paths`,\n   commit everything it changed as ONE change, subject\n   `chore(openspec): bump CLI \u003Cold> -> \u003Cnew>`, and land it like any work ref.\n   On `review:openspec-bump:…`, stop and read stderr. It names either\n   generated files that still disagree with the pin, or a superseded copy the\n   CLI left behind instead of overwriting (1.13.2: \"Left 11 files in .codex\u002F\n   that differ from the copy in .agents\u002F\"). Remove only the copy the CLI names\n   as superseded, re-run `drift` to ok, and commit that removal in the SAME\n   change. Paths outside the generated surface mean something unexpected\n   happened: do not commit, and file a packet. `unknown:` (registry\n   unreachable) waits for the next cycle. Changing the workflow profile is a\n   separate decision; it is never a side effect of a bump. This is the only\n   sanctioned way the generated \u002Fopsx sets move. Launch-generated dirt is\n   refused (step 4 of Start Of Cycle), never committed.\n\n## Cycle Metrics (report before the handoff)\n\nRun `scripts\u002Fcycle-metrics.sh --cycle-start \u003CStart-Of-Cycle UTC> [\u003Csince-ref>]`\nand include its output verbatim in the final handoff. It emits one `key=value`\nline per block — branch on those, never on prose. `--cycle-start` is the UTC\nyou recorded at Start-Of-Cycle (e.g. `2026-09-04T06:00:00Z`); without it the\n`repeat:` line measures the last three hours, not this cycle.\n\nEvery handoff MUST carry these lines; the two questions they answer are\ndistinct — measure before you optimize:\n\n- **`mcp:`** — \"are the servers used?\" Per-server call volume (`servers=`,\n  `plan-expert-calls=`). Today only the plan expert is instrumented; the other\n  servers are named `uninstrumented-see-682-m8ek`, not faked as zero.\n  Also carries **`health=`** (order 737-zcj5) — `ok` \u002F `down:\u003Ccsv>` \u002F `absent` \u002F\n  `unprobed` — sourced from the health probe, NOT from usage. Call volume cannot\n  see an outage: a server that is down writes no usage rows, and neither does one\n  nobody called, so both render as absence in every count on this line.\n  `health=unprobed` is deliberately not `health=ok`; reporting an unmeasured\n  expert as healthy is the order-531 shape.\n\n- **`mcp_outage:`** — emitted ONLY when a probe recorded a non-up state\n  (`records=`, `health=`, `log=`). Its absence on a healthy cycle is the\n  negative control, not an omission. When present, it is the ledger trace of the\n  outage: the handoff pastes these metrics verbatim and the loop-status entry is\n  built from the handoff, so the outage reaches `plan\u002Floop_status.d\u002F` without any\n  agent choosing to write it down.\n- **`expert_accuracy:`** — \"are the experts RIGHT?\" The groundtruth pass-rate\n  (`pass=\u002Ftotal=\u002Frate=`), graded against the committed rung-1 query set. Distinct\n  from `answer_rate`: an expert can answer every question yet cite spans that do\n  not support the answer. Accuracy is pass\u002Ftotal of graded cases, never call\n  volume. It reads `deferred source=litmus:expert-groundtruth-harness` when no\n  binary can grade in-cycle (then the quick-tier gate carries it).\n\n- **`flow:`** — \"does work-done-per-cycle outrun the fixed per-cycle overhead as\n  batches grow?\" The ROLLING packets-per-cycle view (`cycles=`,\n  `avg_completed_per_cycle=`, `avg_commits_per_cycle=`, `overhead_ratio=`) over a\n  per-host append log. `overhead_ratio` is total commits per total completed\n  packet — the fixed per-cycle cost amortized across the work it produced — and\n  is the number the greedier-batching decision (682-yiz7) consumes: if larger\n  batches amortize overhead, this ratio FALLS as batch size rises. It reads\n  `source=absent` until this host has appended at least one flow record.\n\n  Each cycle MUST append its flow record so the rolling view stays live. Emit it\n  here, right after running `scripts\u002Fcycle-metrics.sh` for the handoff and before\n  Finalization commits — best-effort, the emit never fails the cycle:\n  ```bash\n  scripts\u002Fcycle-metrics.sh --emit-flow \\\n    host=\u003Cthis-host> \\\n    batch_epic=\u003Cfrom select-work-batch `batch: epic=`> \\\n    batch_seed=\u003Cfrom `batch: seed=`> \\\n    batch_size=\u003Cfrom `batch: size=`> \\\n    budget=\u003Cfrom `batch: budget=`> \\\n    claimed=\u003Cpackets this cycle claimed> \\\n    completed=\u003Cpackets this cycle completed> \\\n    filed=\u003Cnew packets\u002Fissues this cycle filed> \\\n    commits=\u003Cfrom cycle-metrics `repo: commits_this_cycle=`> \\\n    plan_open=\u003Copen packet count> plan_total=\u003Ctotal packet count>\n  ```\n\n- **`timing:`** — \"where does the cycle's wall-clock go?\" The ROLLING view over a\n  per-host duration log (`steps=`, `build_check_ms_avg=`, `litmus_ms_avg=`,\n  `slowest=\u003Cstep>:\u003Cms>`). \"Time spent building, testing\" is the most likely\n  bottleneck and was invisible until the build\u002Ftest\u002Flitmus entry points began\n  appending one duration record per heavy step (packet 682-emvg). `build.sh\n  --check` (the local gate), each `scripts\u002Flocal-ci.sh` litmus phase, and each\n  `scripts\u002Frun-litmus-test.sh` suite now self-instrument — best-effort, the\n  timing write never changes the wrapped step's exit code or output. It reads\n  `source=absent` until this host has run one instrumented step. `slowest` names\n  the single step to attack first.\n\n- **`repeat:`** — \"which steps were paid REPEATEDLY inside THIS cycle?\" The\n  within-cycle count view over the same timing log (`window=`, `steps=`,\n  `top3=\u003Cstep>=\u003Ccount>,...`), order 1001-q3zf. Count, not duration: a gate\n  re-run after every rebase costs its duration TIMES the rounds, and only the\n  product is actionable. Pass `--cycle-start \u003Cyour Start-Of-Cycle UTC>` (or\n  export `TILLANDSIAS_CYCLE_START_TS`) so the window is this cycle and not the\n  default last three hours: `scripts\u002Fcycle-metrics.sh --cycle-start\n  2026-09-04T06:00:00Z`. Reads `source=absent` when the timing log is missing.\n\n- **`recur:`** — \"which steps are paid on EVERY cycle, and what do they cost\n  cumulatively?\" The cross-cycle view over the last 7 days (`window=`, `runs=`,\n  `steps=`, `top3=\u003Cstep>:runs=\u003Cn>:total_ms=\u003Ct>:avg_ms=\u003Ca>:fail_pct=\u003Cp>,...`),\n  ranked by total_ms — a cheap step paid three hundred times outranks an\n  expensive one paid twice. Step names contain colons (`step:...`,\n  `check:litmus-pre-build`), so parse an entry FROM THE RIGHT: the trailing\n  `:key=value` fields never contain a colon; the step is everything before the\n  first `:runs=`.\n\n- **`skippable:`** — \"which expensive, repeated, outcome-invariant steps could\n  be memoised or skipped?\" This is the operator's instrument for \"repeated work\n  that wastes every cycle \u002F expensive work that may be cached or skipped\"\n  (2026-09-03). A candidate ran at least `min_runs=` times, averaged at least\n  `floor_ms=`, and NEVER changed outcome in the window, so every run after the\n  first bought no information. Entries are\n  `\u003Cstep>:runs=\u003Cn>:avg_ms=\u003Ca>:fail_pct=\u003Cp>:saved_ms_upper=\u003Cs>`, parsed from the\n  right like `recur:`. **`saved_ms_upper` is a BOUND, not a saving** —\n  total_ms minus one run; the log carries no input identity, so nothing here\n  can say a run WOULD have hit a cache. Paste it as a bound. Do not file a\n  skip-or-memoise packet from one host's reading: the coordinator's cross-host\n  recurrence audit (coordinate-multihost-work) acts only when the same step\n  tops `skippable:` on two or more hosts.\n\nThe two lines worth reading first:\n\n- **`answer_rate`** — the experts' USEFULNESS. Not call count. An expert called\n  two hundred times that refuses two hundred times is heavily used and\n  completely useless, and a call counter reports that as healthy adoption. That\n  is not hypothetical: order 531 had every `plan_answer` returning\n  `confidence=unsupported` (the forge was seeded from a pre-expert branch) while\n  launch state truthfully reported `experts: ready`.\n- **`verdict`** — the single fact to look at first. `attention:` is not a\n  failure; it is the cycle naming its own weakest point.\n  `attention:expert-answered-nothing-check-base-branch` is the order-531\n  signature and means the ARTIFACT is wrong, not that the questions were hard.\n\nTwo rules about these numbers:\n\n- **Never report a metric the tooling did not produce.** `experts_substitution`\n  reads `unknown` because it needs the agent harness's tool log, which is not in\n  this repo. Leave it unknown. An estimated number makes an unmeasured thing\n  look measured, which is worse than reporting nothing.\n- **Never propose making expert metrics reward activity.** `answered` is\n  reachable only via citations the compiled expert emits when it resolved a real\n  packet or path, so calling tools more cannot raise the rate. A change that\n  lets `answered` be reached without citations converts a quality signal into a\n  volume signal and must be refused on that ground.\n\n## Finalization\n\nBefore exit:\n\n1. Reduction-engine capture check: confirm every \"this isn't great\" observation\n   from this cycle is filed in `plan\u002Fissues\u002F` (classified `research\u002F`,\n   `exploration\u002F`, `enhancement\u002F`, or `optimization\u002F`) and, where reduced,\n   promoted to a `plan\u002Findex.yaml` packet. An unfiled finding blocks exit. A\n   dirty-start preflight refusal performs no reduction cycle; it uses the final\n   handoff exception above and exits without touching the checkout.\n2. Refresh `plan\u002Findex.yaml` if this cycle changed active work, blockers,\n   tested release, or host assignments. Record THIS cycle's status as a NEW\n   `## Cycle` fragment in `plan\u002Floop_status.d\u002F` via\n   `tillandsias-plan loop-status-append --host \u003Chost> --ts \u003CUTC-ISO> --file fragment.md`\n   (`\u003C fragment.md` and a bare path also work; order 1004-8vkv) — never\n   edit the shared `plan\u002Floop_status.md` directly, or a concurrent host's\n   status write conflicts for the same reason the old monolithic ledger did\n   (packet 582-nqw5). The folded view (`tillandsias-plan loop-status`) is the\n   status every host sees; `loop-status-compact` folds fragments into the base\n   when drift makes it eligible.\n\n   **A long cycle's `--ts` legitimately predates its write, and `--backfill` is\n   the sanctioned path for it (order 801-w4pn).** `--ts` must agree with the\n   host clock within 900s or the write is refused; a cycle that read the clock\n   at Start Of Cycle and appends at Finalization two hours later trips that by\n   construction. Do not widen the window and do not invent a fresh timestamp —\n   the limit is what catches a fabricated hour, and re-reading the clock would\n   silently relabel when the work happened. Pass `--backfill` with the real\n   timestamp, or omit `--ts` entirely when \"now\" is genuinely the right stamp:\n\n   ```bash\n   tillandsias-plan loop-status-append --host \u003Chost> --ts \u003Ccycle-start-UTC> --backfill --file fragment.md\n   ```\n\n   THE FRAGMENT MUST BE SUPPLIED EXPLICITLY. `--file \u003Cpath>`, `\u003C path` and a\n   bare path argument all work. Before order 1004-8vkv a bare path was silently\n   dropped and the command fell through to stdin, which on an inherited socket\n   (a forge agent's stdin, by construction) blocked for 26 minutes at 0.0%% CPU.\n   It is now refused in 5s naming the explicit forms, but supplying the input\n   explicitly is still the invocation to type.\n\n   `--backfill` only reaches BACKWARD (a future `--ts` is still refused), so it\n   waives nothing the limit exists to protect, and the refusal already names it.\n2b. **Ask which litmus specs cover the files you touched** (order 748-tkjx),\n   BEFORE the gate rather than after the next host finds the red:\n\n   ```bash\n   scripts\u002Flitmus-covering-specs.sh --run --changed      # the specs to re-run\n   scripts\u002Flitmus-covering-specs.sh \u003Cpath>...            # one file, with detail\n   ```\n\n   `.\u002Fbuild.sh --check` runs NO litmus (deliberate — the suite is minutes, and\n   a gate that slow gets bypassed with `--no-verify`), so a green gate plus the\n   spec you happened to be working in can both pass over another spec's broken\n   pin. That is measured, twice: on 2026-08-15 an edit to\n   `images\u002Fdefault\u002Flib-common.sh` left `litmus:startup-context-addendum-shape`\n   red through a green `--check` and a passing 7\u002F7 run of the agent's own spec;\n   on 2026-08-28 three tests were found red back to `af745f3fd` only because a\n   full suite happened to run (921-vtf4). `lib-common.sh` alone is covered by\n   twelve specs across four lanes.\n\n   ADVISORY and cheap (~90ms over the whole corpus, no build). It answers from\n   committed data — each test's declared `workspace contains` artifacts plus its\n   commands — so there is no second list to drift. `match:declared` is an\n   authored coverage claim, `match:command` is coverage the preconditions never\n   declared; `binding:unbound` means no spec binds that test, so it executes in\n   no suite (885-92iu) and is excluded from the count and from `--run`. A path\n   no litmus references answers `ok:litmus-coverage:0-spec(s)` and nothing\n   else — an editor of an uncovered file is not nagged.\n\n2c. **Report split parents still competing with their own children**\n   (order 750-zrt4):\n\n   ```bash\n   tillandsias-plan split-parents   # parent\u003CTAB>status\u003CTAB>child:status,...\n   ```\n\n   A packet whose work has been split keeps `ready` and gains a `split_into`\n   list, and only `ready` is claimable — so a fully-delegated parent stays in\n   the pool forever. Measured 2026-08-14\u002F15: `select-work-batch.sh linux`\n   reported `urgent=mirror-identity-lane-sidecar-and-sshd` on four consecutive\n   cycles and no host claimed it (eleven design rungs behind a 3-hour\n   estimate), while one level up 606-bvnp ranked #1 claimable with all four\n   slices already spoken for. Both were fixed by hand, which depended on an\n   agent noticing a four-cycle stall.\n\n   REPORTS ONLY — it names the children and their statuses so you can see where\n   the work went, and changes nothing. Resolve one by setting the parent\n   `blocked` with an event naming the children (accurate: it cannot progress\n   without them), or, if it genuinely retains work of its own, declare\n   `retains_direct_work: true`. **Never `obsoleted`** — that status satisfies\n   dependents and would falsely unblock work that is still waiting on the\n   rungs.\n\n3. Validate touched YAML with a parser, using the one that EXISTS where you are:\n   `tillandsias-policy validate-yaml \u003Cfiles>` where built, else\n   `yq . \u003Cfile> >\u002Fdev\u002Fnull`, else `ruby -ryaml -e \"YAML.load_file('\u003Cfile>')\"`.\n   **`ruby` is NOT in the forge image; `yq` is** — a skill that names only ruby\n   sends a forge agent to a tool that does not exist, and the tool sitting next\n   to it is `python3`, which is FORBIDDEN for committed automation (see\n   `plan\u002Fissues\u002Fmeta-orch-enhancement-opportunities-2026-06-20.md` order 63).\n   Its presence on PATH is not permission. The forge startup context lists what\n   is actually available.\n3b. **Re-verify the credential BEFORE the gate** (order 892-aw9p):\n\n   ```bash\n   scripts\u002Fcheck-credential-channel.sh reverify\n   ```\n\n   The Start-Of-Cycle guard runs once and cannot see a credential that dies\n   afterwards. MEASURED on calmecacpilli 2026-08-25: it returned\n   `ok:gh-keyring-push-verified`, two pushes succeeded on that credential, and\n   ~50 minutes later the third failed with `remote: Invalid username or token`.\n   Nothing the guard measured was wrong — the verdict was true when issued. Its\n   RESULT simply outlived the thing it checked, which is the same shape as a\n   stale gate stamp (887-bz88).\n\n   Run it HERE, immediately before `.\u002Fbuild.sh --check`, because that is the\n   last point where the remaining cost is still worth saving: a dead credential\n   then costs the gate's wall-clock (40s here, 276s on the slowest host) instead\n   of being discovered after it, with the work done and the exit contract\n   forbidding an unpushed exit. Not per push — the healthy path must not pay a\n   round trip for every git operation, and a guard slow enough to notice is a\n   guard that gets bypassed.\n\n   On `blocked:credential-expired-mid-cycle` the credential WORKED and then\n   stopped; that is distinct from never having had one, and the printed remedy\n   is the OPERATOR re-seeding the token (`tillandsias --github-login`), not\n   seeding a store. An agent never runs `gh auth refresh` or `gh auth login`\n   itself (1025-a896: a re-auth on one host evicts the token on every other;\n   1497-ahmd corrected the guard, which used to print it). Do NOT discard the\n   cycle's work to get unstuck — salvage first (872-c9nd) and report blocked\n   with the salvage ref.\n\n3c. **EVERY LEDGER WRITE HAPPENS BEFORE THE GATE, NOT AFTER IT** (yolanda,\n   2026-09-02). The gate stamp hashes the CONTENT of every tracked and\n   untracked file in the worktree, so a ledger write after a green gate\n   creates a new `plan\u002Findex.d\u002F` or `plan\u002Floop_status.d\u002F` file, moves the\n   digest, and the pre-push hook then refuses a tree whose CODE the gate\n   validated perfectly. Order your Finalization so that `append-event`,\n   `set-field`, `loop-status-append` and any issue file all land FIRST,\n   then gate once, then commit and push.\n\n   MEASURED: three extra full gates in one cycle on windows, about 25\n   minutes, plus a fourth on this host the same day. Both agents\n   rediscovered the ordering by trial; it was written down nowhere, which\n   is why it is here now rather than in a message that scrolls away.\n\n   The one exception is the attestation ledger, which CANNOT precede the\n   gate — `record` attests the head that finalization produces. That is\n   why step 9 re-verifies and re-derives; it is not a second chance at\n   the gate.\n\n   DO NOT diagnose this from the refusal message: it lists paths whose\n   MTIME is newer than the stamp, while the decision is made on CONTENT.\n   A merge or a regeneration that rewrites bytes identically appears in\n   that list without being the cause, and the file that actually moved\n   the digest may not appear at all. `scripts\u002Fgate-stamp.sh verify` is the\n   authority.\n\n\n   **USE THE ONE COMMAND THAT DOES 4-6 IN THE RIGHT ORDER** (order 859-4jny,\n   discoverability gap found 2026-09-03):\n\n   ```bash\n   scripts\u002Fland-on-platform-branch.sh [branch] [attempts]   # -> ok:land:\u003Csha>:attempt-N\n   ```\n\n   It fetches, rebases, GATES, pushes, and then PROVES the commit landed by\n   asking the remote (`git merge-base --is-ancestor HEAD origin\u002F\u003Cbranch>`) —\n   because neither a zero exit status nor a `\u003Cbranch> -> \u003Cbranch>` line in the\n   output is sufficient evidence, and both have reported LANDED for a refused\n   push. It refuses non-retryable failures at once with their remedy (auth) and\n   retries only a lost race.\n\n   **Never read a land or gate verdict through a pipe (1137-da83).** Three\n   false claims in one hour on two hosts: `scripts\u002Fland-on-platform-branch.sh\n   … | tail -25` read as exit 0 when the land had exited 3 and named its gate\n   log — the tool was nearly filed against for the defect its header exists\n   to prevent — and `tasklist … | head -2; echo rc=$?` reported `head`'s\n   status, published to a peer as a two-host difference that did not exist.\n   Capture the command's own status (`out=\"$(cmd 2>&1)\"; rc=$?`) or `set -o\n   pipefail`. If you use PIPESTATUS, snapshot the array as the very next\n   command (`ps=(\"${PIPESTATUS[@]}\")`); any intervening command resets it,\n   and the one everyone writes — `a=$?; b=\"${PIPESTATUS[0]}\"` — yields 0 and\n   0. On Windows, `$?` through `wsl.exe -d \u003Cdistro> -- bash -lc` from Git\n   Bash is always 0 (1155-jurn): canary `false; echo \"$?\"` before trusting\n   any status through it (drill: plan\u002Fissues\u002Ffleet-restart-2026-09-12.md, What the pipe-verdict fixture found — extends the coordinator's rule entry below, which named this fixture as its follow-up).\n\n   WHY THIS IS NAMED HERE AND NOT LEFT TO BE DISCOVERED. Steps 4, 5 and 6 are\n   three manual acts whose ORDER is the whole contract, and a host that\n   hand-rolls them can invert them. That is not hypothetical: on 2026-09-03 a\n   forge inverted gate-and-push TWICE in one session — once under real urgency\n   (an ephemeral container, work not yet durable) and once with no urgency at\n   all — while spending that same session filing defects about instruments that\n   report success without measuring anything. Its improvised loop\n   (`fetch && rebase && push`) had NO GATE IN IT BY CONSTRUCTION.\n\n   The tool that cannot make that mistake had existed since 859-4jny and this\n   skill named it ZERO times, so every host was taught the hand-rolled ritual\n   and none were taught the safe one. Documentation was not the gap and neither\n   was discipline: the host had run `salvage-dirty-worktree.sh` earlier in the\n   same cycle, so it was not unaware of its tooling. **Push is what \"I am done\n   with this\" feels like**, and the action that feels like finishing must be the\n   action that is correct — so the finishing command is named here, first,\n   before the three steps it replaces.\n\n   Fall through to 4-6 by hand only when this refuses for a reason it names.\n4. Run the local gate: `.\u002Fbuild.sh --check` and fix what it reports.\n   An unparseable or unformatted push poisons every downstream clone. Push CI\n   no longer exists on any working branch — only the manually-dispatched\n   release workflow remains (litmus:github-actions-budget) — so this gate is\n   the ONLY trunk protection. Do not push past a red gate (evidence case:\n   `plan\u002Fissues\u002Flocal-gate-evidence-query-packets-clippy-2026-08-09.md`).\n\n   Terminology (851-gpb5): this skill called this step \"the pre-push gate\"\n   for months while methodology used the SAME name for a different rule —\n   the step-6 merge below — and the collision kept that rule invisible.\n   Here \"local gate\" always means `.\u002Fbuild.sh --check`; \"pre-push gate\" is\n   reserved for methodology's `pull_merge_cadence.pre_push_gate`.\n5. Commit targeted files only.\n6. Satisfy methodology's pre-push gate (`pull_merge_cadence.pre_push_gate`,\n   `methodology\u002Fmulti-host-development.yaml`), then push the relevant branch.\n   On a non-`linux-next` branch (`osx-next`, `windows-next`, any shared\n   non-trunk branch; `agent\u002F*` and `salvage\u002F*` are exempt) that gate\n   requires, before EVERY push — not just at cycle start:\n\n   ```bash\n   git fetch origin && git merge origin\u002Flinux-next   # resolve conflicts locally\n   ```\n\n   The v5 pre-push hook enforces the merge half on the two platform branches\n   (`scripts\u002Fhooks\u002Fpre-push-linux-next-merged.sh`, installed by\n   `scripts\u002Finstall-hooks.sh`); the fetch half stays yours — the hook can\n   only compare against the `origin\u002Flinux-next` your last fetch recorded. If\n   the hook refuses, merge and push again; never `--no-verify` past it.\n7. If a startup boundary was recorded, run the guard's `verify` mode. A guard\n   failure is a blocker: do not attempt destructive Git cleanup. Finalization\n   never deletes, restores, or resets a worktree path.\n\n   **Do NOT remove `$boundary_dir` here** (order 725-bu54). Retirement belongs\n   to the NEXT cycle's `snapshot`, which retires the previous boundary before\n   taking its own. Removing it here treats this Finalization as THE end of the\n   cycle — but an operator-driven loop has no single exit, and a cycle that\n   continues after a completed Finalization then finds its own boundary gone\n   and cannot attest. That happened twice in one night and cost a valid marker.\n\n   Re-running `verify` after further commits is correct and expected: it still\n   compares against the boundary taken BEFORE any work, and re-stamps the head\n   it observed so the marker matches what was actually pushed.\n8. Confirm there are no uncommitted changes created by this cycle and the\n   branch is not ahead of upstream. Pre-existing dirty paths may remain only\n   when the boundary guard verifies they are byte-identical to startup.\n\n   Then prove the cycle's FINDINGS survive it (order 741-3y48):\n\n   ```bash\n   scripts\u002Fcheck-forge-findings-persisted.sh\n   ```\n\n   A GATE, not advisory — non-zero means work already done is about to be thrown\n   away. It covers `plan\u002Findex.d\u002F`, `plan\u002Floop_status.d\u002F`, `plan\u002Fissues\u002F` and\n   `plan\u002Fmo-full-attestations.d\u002F`, and it catches what `git status` cannot: a\n   COMMITTED fragment that was never pushed presents as a clean tree and is one\n   teardown from gone. That is not hypothetical — on 2026-08-15 an in-forge\n   review filed three valid fragments, `tillandsias-plan check` accepted them,\n   and the container took all three with it; they survived only because a human\n   happened to be reading stdout. A cycle that files nothing prints\n   `ok:no-findings` and is silent, so a clean run stays quiet.\n\n   This matters most inside a forge, where the checkout is a clone that dies with\n   the container — but it is correct everywhere, and an unattended host that\n   commits without pushing loses the same work to the next `git reset`.\n9. Record the verified marker durably, then emit the terminal marker (orders\n   614-2gqx + 651-2x5s) as your FINAL output line. `record` derives-and-verifies\n   the marker exactly as `self` does and appends the verified line to the\n   per-host ledger (`plan\u002Fmo-full-attestations.d\u002F\u003Chost>.md`) so automation can\n   consume a real, reachable hash without parsing a transcript. The ledger\n   line attests the WORK head; committing it advances the head, so re-run the\n   guard `verify` (permitted: further commits are expected, step 7) and\n   re-derive ONCE more — the terminal marker must name the head that CONTAINS\n   the ledger record:\n   ```bash\n   # RUN `record` ONLY AFTER THE WORK PUSH HAS ACTUALLY SUCCEEDED, and check\n   # that it wrote. MEASURED on lenovinha 2026-09-03: `record` ran while HEAD\n   # was still unpushed and CORRECTLY REFUSED; a push-retry loop then landed\n   # the work WITHOUT re-running `record`; and the terminal `self` printed\n   # COMPLETE, because by then local and remote agreed. So the emitted marker\n   # was VALID and the durable ledger line — the thing automation actually\n   # consumes — was never written. A green marker is not evidence the ledger\n   # was appended.\n   #\n   # THE TRAP IS THE RETRY LOOP, not the ordering as written here: step 6\n   # already pushed, so this recipe is correct on the happy path. Insert a\n   # fetch\u002Frebase\u002Fretry between the push and `record` — which every host does\n   # on a busy trunk — and `record` is silently skipped on any iteration that\n   # refused. Re-run `record` after the LAST successful push, not the first\n   # attempt.\n   #\n   # THIS IS NOW ENFORCED, NOT ONLY ADVISED (order 974-uk95). `self` refuses a\n   # COMPLETE marker unless THIS cycle wrote a durable record: `record` stamps\n   # the head it recorded, the boundary guard's `snapshot` clears that stamp at\n   # Start Of Cycle, and a marker whose HEAD does not descend from a recorded\n   # head is refused. So the skipped-record case now fails LOUDLY — no marker,\n   # which every outer launcher already treats as failure — instead of printing\n   # a valid marker beside an empty ledger. BLOCKED is exempt: a cycle saying it\n   # did not finish must still be able to say so.\n   #\n   # The ordering is still yours to get right. The guard catches a skipped\n   # record; it cannot make a retry loop call `record` for you.\n   #\n   # AUDIT IT THE WAY THEY CAUGHT IT: grep the ledger for this cycle's head\n   # rather than trusting the marker.\n   #   grep -c \"$(git rev-parse HEAD)\" plan\u002Fmo-full-attestations.d\u002F\u003Chost>.md\n   # Expect the WORK head to appear, not the record commit's own head — the\n   # ledger line attests the work and committing it moves HEAD, which is why\n   # the terminal marker is re-derived one commit later.\n   scripts\u002Fmo-full-attest.sh record                                  # verify + append + print the marker\n   git add plan\u002Fmo-full-attestations.d\u002F && git commit -m \"record(mo-full): attest \u003Cbranch> cycle\"\n   git push\n   scripts\u002Fmeta-orchestration-worktree-guard.sh verify \"$boundary_dir\"   # re-stamp the new head\n   scripts\u002Fmo-full-attest.sh self                                   # terminal marker at the head containing the record\n   ```\n   Emit the FINAL `self` line verbatim as your final line — do not retype or\n   edit it. If any step prints `MO-FULL: FAIL …` and exits non-zero, do NOT\n   emit a marker — treat it as a blocker (a missing marker is itself the loud\n   failure). The ledger line and the emitted line differ by exactly the\n   bookkeeping commit; both are real commits the local gate\n   (`scripts\u002Fcheck-mo-full-attestations.sh`) verifies exist and are reachable.\n   This gives EVERY full-mode lane the same convergence verification the\n   litmus launcher's `check` applies to its one lane, and leaves a durable\n   record that outlives the transcript. The marker is the machine attestation\n   that finalization steps 1-8 all passed; the outer launcher rejects exit\n   zero without it. See \"Full-Mode Terminal Attestation\" above for the grammar\n   and invariants.\n\n9b. Release the checkout lock (order 873-zcim) — AFTER the terminal marker is\n   derived, as the cycle's last mutation:\n   ```bash\n   TILLANDSIAS_CYCLE_HOLDER_PID=$PPID scripts\u002Fcycle-checkout-lock.sh release\n   ```\n   The stale-reclaim bound (dead holder, or 3h) covers a cycle that dies\n   before reaching this line, so a crashed cycle cannot silence the cadence —\n   but do not lean on it: an explicitly released lock frees the checkout NOW,\n   a reclaimed one frees it up to three hours later, and on a 30-minute\n   cadence that is six skipped fires.\n\n9c. Reclaim the build cache when it is genuinely due (order 709-in2f,\n   methodology `build_cache_hygiene`) — LAST, after the lock is released, so a\n   full rebuild's cost is paid in the idle gap rather than inside the cycle:\n\n   ```bash\n   scripts\u002Fcheck-build-cache-sweep.sh   # exit 0 = NOT due; skip the body\n   ```\n\n   **Read the exit polarity before wiring anything to it.** It exits **0 when\n   the sweep is NOT due**, the same convention as `check-deslop-due.sh` and\n   `check-daily-maintenance.sh`: the actionable state is the non-zero one, so a\n   healthy steady state stays quiet under `set -e`. Branch on the verdict token\n   (`build-cache-sweep-not-due` \u002F `build-cache-sweep`), which a copy-paste\n   cannot invert.\n\n   Due when `target\u002F` exceeds 40 GiB, OR the marker is older than 14 days, OR\n   the marker is absent\u002Funreadable. On `due:`, run `cargo clean` (plus\n   `scripts\u002Fnix-toolbox.sh gc` where nix is present — never a bare\n   `nix store gc`, which would delete the whole persistent cache rather than\n   prune it), then stamp what actually ran:\n\n   ```bash\n   scripts\u002Fcheck-build-cache-sweep.sh stamp --host \u003Chost> \\\n       --action 'cargo-clean:\u003Cresult>,nix-gc:\u003Cresult>'\n   ```\n\n   `--action` is REQUIRED, for the same reason `check-daily-maintenance.sh`\n   requires `--steps`: a stamp recording that \"something happened\" without\n   recording what moves the unfalsifiability up a level instead of removing it.\n   Record `skipped-absent` \u002F `deferred-\u003Creason>` honestly.\n\n   The convergence check log — the file \"When the Gate Fails\" above orders\n   you to read FIRST — is NOT in `target\u002F` since order 888-vgs8: it lives at\n   `.cache\u002Fconvergence\u002Fcheck-logs.jsonl`, resolved by\n   `scripts\u002Fconvergence-log-path.sh`, so this sweep no longer erases the\n   failure history. The per-check logs under `target\u002Fconvergence\u002Fcheck-logs\u002F`\n   do go with it, as they always did; they are overwritten every run anyway.\n\n   BEST-EFFORT, NEVER A GATE: a failed sweep must not fail the cycle, and the\n   sweep must not run before the work. Ephemeral forges read `skip:forge-exempt`\n   and never sweep — their `target\u002F` dies with the container.\n","# Meta Orchestration\n\nThis is the top-level unattended loop intended for:\n\n```bash\n.\u002Frepeat --prompt \"Use the \u002Fmeta-orchestration skill\"\n```\n\nIt composes the worker, coordination, e2e, and release skills without replacing\ntheir detailed runbooks.\n\n## Invocation Modes — check FIRST, before anything else\n\nThe skill is parameterized by the invoking prompt. **Before doing any work —\nbefore host classification, before `git fetch`, before reading the plan —\ninspect the prompt that invoked this skill and pick the mode.** Full cycles\nare token-expensive; running one when a smoke pass was requested wastes a\nrate-limited provider budget (operator directive, 2026-07-11).\n\n- **Full mode** (default): the prompt is a bare \"Use the \u002Fmeta-orchestration\n  skill\". Run the complete cycle described in the rest of this document.\n- **Smoke Mode** (early break): the prompt contains the word `smoke` (e.g.\n  \"Use the \u002Fmeta-orchestration skill in smoke mode (verify-only)\"). You are\n  inside a short e2e smoke test with a hard budget of a few minutes. Do NOT\n  run a full cycle. Follow \"Smoke Mode Runbook\" below and exit.\n- **Targeted verify** (a variant of Smoke Mode): the prompt names specific\n  packets, orders, specs, or files (e.g. \"…smoke mode, verify order 283\" or\n  \"…smoke: spec git-mirror-service\"). Same rules as Smoke Mode, but the\n  verification set is the named targets' verifiable closures instead of the\n  generic checks.\n\n### Smoke Mode Runbook\n\nPurpose: give fast, cheap feedback that the forge lane and the work under\ntest are healthy — WITHOUT advancing the plan or consuming a full-cycle\ntoken budget. Hosted e2e gates (`litmus:opencode-prompt-e2e-shape`) invoke\nthis mode whenever the full cycle is rate-limited\n(`scripts\u002Fforge-e2e-rate-limit.sh`, one full cycle per 4h per host).\n\nHard rules:\n\n1. Do NOT claim ledger nodes, drain plan work, file routine findings, run\n   nested e2e gates, release, commit, or push. A smoke run leaves the repo\n   untouched. (Exception: a real defect discovered during verification may\n   be reported in your final output text — the HOST files it, not you.)\n2. Keep it small: prefer `scripts\u002Frun-litmus-test.sh --size instant\n   --phase pre-build --compact` scoped with a spec filter when targets are\n   named, plus cheap direct checks (parse `plan\u002Findex.yaml`, `git status`,\n   `git fetch --dry-run` reachability, the targets' named verifiable\n   closures). Skip anything that builds, launches containers, or exceeds\n   the budget.\n2a. **WHAT DECIDES THE VERDICT** (order 822-4vwa). Rule 2's last sentence and\n   its first are in tension INSIDE A FORGE, because a large fraction of\n   pre-build litmus needs vault, podman or vsock — none of which a forge has.\n   An agent that runs the unscoped suite there gets a near-total failure that\n   says nothing about the lane. So:\n\n   - The VERDICT is the forge SUBSTRATE: the checkout resolves and is on the\n     expected branch, the plan ledger parses, the plan\u002Fmethodology experts\n     answer, and the harness came up. If those hold, the lane is healthy.\n   - Litmus results in a forge are a **REPORT**, on the same footing as the\n     credential verdict in 3a. Quote the pass rate; do NOT convert it into\n     `MO-SMOKE: FAIL` on its own.\n   - When the invoking prompt NAMES targets, their scoped closures ARE part of\n     the verdict — that is the whole point of a targeted verify.\n\n   MEASURED on macuahuitl 2026-08-18, the same prompt on the same host 25\n   minutes apart with a verified-fresh seed, disagreeing with itself:\n   run 20260818T053811Z returned `MO-SMOKE: PASS` (post-build 11\u002F11), and run\n   20260818T063931Z returned `MO-SMOKE: FAIL litmus pre-build 0% pass rate\n   (1\u002F252); infrastructure-dependent failures expected but unconfirmed`. The\n   second agent was right to refuse to bless what it could not confirm; the\n   first agent's PASS is the one that should worry you. A gate whose result\n   depends on how much the agent chose to run is not a gate.\n3. Budget: finish well inside ~5 minutes of wall time.\n3a. The **Credential Channel Guard is a REPORT here, never a gate** (order\n   818-cgpn). That guard is a precondition for COMMITTABLE work, and rule 1\n   says a smoke run performs none — it claims nothing, commits nothing and\n   pushes nothing, so an absent or stale push credential cannot harm it.\n   Report the verdict in your output and carry on verifying; do NOT return\n   `MO-SMOKE: FAIL` for it.\n\n   MEASURED on macuahuitl 2026-08-18, twice: with the mirror's upstream-auth\n   verdict stale, the FULL lane blocked (correctly — it would have pushed) and\n   the SMOKE lane returned `MO-SMOKE: FAIL credential channel blocked\n   (upstream-auth-stale, 22880s > 900s max)`. Smoke exists precisely as the\n   cheap path for when the expensive one is unavailable; gating it on the same\n   credential leaves NO path, and takes the substrate-idempotence e2e (§2\u002F§3,\n   which never touch a credential) down with it — see 808-zrzz.\n4. Verdict grammar: your FINAL output line MUST be exactly one of\n   `MO-SMOKE: PASS` or `MO-SMOKE: FAIL \u003Cone-line reason>`. The launching\n   litmus greps for this marker; a smoke run that exits without it is a\n   failure by definition.\n\n## Sub-agent and token budget (operator directive 2026-09-11; packet 1119-6wn6)\n\nSub-agents spend the same rate-limited pool as the main loop, and that pool\nran out a week early last month. This checkout's 2026-09-06 cycle died\nmid-finalization for the same reason, with two finished fragments sitting\nuncommitted for five days. MEASURED on macuahuitl 2026-09-11: one read-only\nreconciliation Workflow of 42 agents at the main model's tier spent 4,480,590\ntokens in 21 minutes — roughly twenty times the main context of the entire\ncycle. The output was good; the price was invisible until the operator asked.\n\nThe loop has `timing:`, `recur:` and `skippable:` for CPU seconds and nothing\nfor tokens, so an expensive repeatable delegation cannot be seen the way the\nlow-end hosts made the CPU bottlenecks visible. Until the counter in\n1119-6wn6 lands and replaces these rules with numbers:\n\n- **Count.** At most 8 sub-agents per full cycle by default, at most 3 running\n  at once. A Workflow (fan-out orchestration) only when the invoking prompt\n  opts in (\"ultracode\", \"use a workflow\"), and then at most 15 agents.\n- **Tier by task class, and pass `model` and `effort` explicitly every time.**\n  Lookups, greps, \"does commit X exist \u002F touch file Y\", ancestry and existence\n  checks: haiku, effort low. Summarising a diff or a fragment, drafting event\n  prose: sonnet, effort medium. Judgment (a verdict on a packet, a review\n  finding, a design choice): opus, effort medium — high only when the error is\n  unrecoverable. The main model's tier is for the main loop, never for\n  refuters or fan-out.\n- **Refuters.** At most one per verdict, one tier below the verdict's author.\n  Prefer one agent with a schema over N parallel ones when the items are cheap.\n- **Packets carry their tier too (trims 2026-09-27, umbrella 1437-62g8).**\n  Every filed packet declares `size: S|M|L` and `implementer_tier:\n  haiku|sonnet|opus` (as scalars once 1437-khnx lands; as two lines inside\n  `notes:` until then). S = mechanical, fully specified → haiku; M = a few\n  files, clear design → sonnet; L = cross-cutting, judgment, or\n  gate-integrity-sensitive → opus. Anything that changes what the land gate\n  or the pre-push hook refuses is at least sonnet, opus if it could let a\n  red tree land. An UNTAGGED row is opus (operator 2026-09-27: \"No size\n  tags get Opus\") and the tier is a floor. A session states its tier to the\n  selector (`scripts\u002Fselect-work-batch.sh \u003Crole> --tier \u003Ct>`, 1437-vdz5)\n  and runs a cheaper packet through `scripts\u002Fclaude-delegate.sh implement\n  \u003Corder>` (1437-yjf6) or a dedicated `.\u002Frepeat --model haiku` session\n  (1437-m5yx); the host session keeps verify and commit. A host may also\n  run an all-day Haiku ORCHESTRATOR (`\u002Fhaiku-orchestrate`, 1443-hbgt) that\n  delegates by tier and accepts only a closure it measured with\n  `scripts\u002Fverify-closure.sh` (1443-qwpj) — never a delegate's \"met\".\n  Canonical: `methodology\u002Fdistributed-work.yaml` →\n  `cycle_batch_triage.model_tier_routing`.\n- **Messages to peers: budget ON HOLD** (operator question pending,\n  2026-09-27; 1437-arjg blocked). The shape in\n  `distributed-work.yaml` → `sibling_heads_up_protocol.size_budget` stays\n  written and is not enforced until the operator answers.\n- **Never delegate a read an expert answers.** `plan_status`, `plan_answer`,\n  `methodology_ask` and the project-info tools cost nothing next to an agent.\n- **Report it, and LOG it — from the instrument.** `scripts\u002Fcycle-metrics.sh\n  --emit-tokens` exists (1119-6wn6); with `--from-transcript` (1437-3pj7) it\n  reads this session's own harness transcript and fills `main_ctx`,\n  `main_ctx_cumulative`, `subagent_tokens`, `agents` and `by_model` itself,\n  or records `source=absent`. Hand-passed numbers remain accepted for a\n  harness with no transcript. The typed form was:\n\n  ```\n  scripts\u002Fcycle-metrics.sh --emit-tokens host=\u003Ch> cycle=\u003Cid> \\\n      main_ctx=\u003Cn> subagent_tokens=\u003Cn> agents=\u003Cn> \\\n      by_model=\u003Copus:3,haiku:39> label=\u003Cwhat the delegation was for>\n  ```\n\n  The handoff still carries the `tokens:` line — `scripts\u002Fcycle-metrics.sh`\n  renders it, with a rolling per-cycle average, and `source=absent` until a\n  record exists. A cycle that spawned nothing writes `subagent_tokens=0\n  agents=0` and is correctly absent from `token_recur:`.\n\n  **`label` is the field that earns the log its keep.** It names the WORK, not\n  the cycle, so the same expensive delegation recurring across days ranks as one\n  entry in `token_recur:` instead of scattering into unrelated rows. Only labels\n  seen MORE THAN ONCE are ranked: a one-off 4.5M sweep is a cost, not a\n  recurrence, and letting it top the list would bury the cheap thing paid fifty\n  times — which is the one the operator asked to find and simplify.\n\n  Only the agent can observe these numbers, so this stays an attestation (the\n  `check-mcp-surface.sh` shape); what changed is that it is now structured and\n  comparable across cycles. An unmeasured spend is the order-531 shape one level\n  up: it reads as free and is not.\n\n## Full-Mode Terminal Attestation (order 614-2gqx)\n\nSmoke mode has a machine-grepped verdict (`MO-SMOKE:`); full mode did not, so\na normal provider exit between tool calls could discard local commits while\nevery outer launcher returned zero (the `4a1410a2` breach; see\n`plan\u002Fissues\u002Fmeta-orchestration-full-mode-exit-attestation-gap-2026-08-05.md`).\n\nFull mode therefore MUST emit a typed terminal marker as its FINAL output\nline, and MAY emit it ONLY after every finalization obligation below has\npassed (boundary verification, `.\u002Fbuild.sh --check`, commit, push):\n\n```text\nMO-FULL: \u003CDISPOSITION> \u003CLOCAL_SHA> \u003CBRANCH> \u003CREMOTE_SHA>\n```\n\n- `DISPOSITION` ∈ {`COMPLETE`, `BLOCKED`} — the cycle's terminal disposition.\n- `LOCAL_SHA` = final local HEAD (`git rev-parse HEAD`) at emission time.\n- `BRANCH` = the working branch the cycle committed to.\n- `REMOTE_SHA` = the remote branch head after the push.\n\nInvariants the outer gate (`scripts\u002Fmo-full-attest.sh`, wired into\n`scripts\u002Flitmus-opencode-e2e-launch.sh` for `litmus:opencode-prompt-e2e-shape`)\nenforces before it accepts exit zero:\n\n- `LOCAL_SHA == REMOTE_SHA` — a marker may never follow an unpushed local\n  commit. If the push failed after three rebase retries, do NOT emit the\n  marker; mark the packet `blocked`\u002F`failed-retryable`, include the push\n  output, and stop — the missing marker is itself the loud failure.\n- `BRANCH` must match the host's current branch.\n- The claimed `REMOTE_SHA` must actually converge on\n  `git ls-remote origin refs\u002Fheads\u002F\u003CBRANCH>` within the bounded relay window.\n- A startup boundary must have been snapshotted at Start Of Cycle and verified\n  at Finalization, at the HEAD being attested (order 717-3bvv). The guard writes\n  cycle-scoped stamps into `$GIT_DIR`; `self` reads them. Skipping the snapshot\n  therefore costs you the marker — which is the point: cycle 16 on windows\n  skipped it, `verify` answered with a missing-directory message about the\n  PREVIOUS cycle's already-removed temp path, and a valid marker printed anyway.\n- `MO-SMOKE:` grammar and the shared full-cycle rate limit are unchanged; a\n  smoke run never emits `MO-FULL:`.\n\n**DERIVE the marker, never type it — and let the self-check emit it.** A\nhand-typed SHA, or one half-copied from `git push` output, must be structurally\nimpossible. Do NOT assemble the line yourself. Run the self-attestation, which\nreads every field from live git state, verifies local HEAD is durably on the\nremote, and prints the verified line FOR you:\n\n```bash\nscripts\u002Fmo-full-attest.sh self   # prints the marker on success; MO-FULL: FAIL + non-zero otherwise\n```\n\nEmit its stdout verbatim as your final line. `self` derives the same values the\nraw form would —\n\n```bash\nprintf 'MO-FULL: COMPLETE %s %s %s\\n' \\\n  \"$(git rev-parse HEAD)\" \\\n  \"$(git symbolic-ref --short HEAD)\" \\\n  \"$(git ls-remote origin \"refs\u002Fheads\u002F$(git symbolic-ref --short HEAD)\" | cut -f1)\"\n```\n\n— but ALSO refuses to print anything when local HEAD is not the converged\nremote head, so an unpushed or fabricated value is caught at emission, in every\nlane. (`MO_FULL_DISPOSITION=BLOCKED scripts\u002Fmo-full-attest.sh self` for a\nblocked-but-pushed cycle.)\n\n**Make the marker durable — the transcript is not the record (order 651-2x5s).**\n`self` verifies at emission time, but the emitted line lands in a transcript\nnothing parses unless the litmus launcher runs; an operator-prompt or `.\u002Frepeat`\ncycle emits it into the void. `record` closes that: it runs the SAME\nverification and appends the verified line to the per-host ledger under\n`plan\u002Fmo-full-attestations.d\u002F\u003Chost>.md`, a committed, machine-parseable log the\nlocal gate (`scripts\u002Fcheck-mo-full-attestations.sh`, wired into\n`.\u002Fbuild.sh --check`) re-verifies. Automation consumes the ledger, never the\ntranscript. The ledger line attests the cycle's WORK head; committing the\nledger moves the head, so the terminal marker is re-derived at the head that\nCONTAINS the record (see Finalization step 9 and\n`methodology\u002Fmo-full-attestation.yaml`). Do not hand-write a ledger line: only\n`record` may append, and only after the verification passes.\n\nThis is not pedantry. On 2026-08-10 a full-mode cycle on this host emitted a\nmarker whose first eight characters came from the `git push` output and whose\nremaining **32 were invented to look like a SHA**. The work was genuinely\ncommitted, pushed and green; only the proof was false (651-2x5s).\n\nIt went unnoticed because `scripts\u002Fmo-full-attest.sh check` — which would have\nrejected it instantly, since it requires `git ls-remote` to converge on the\nclaimed value — is wired into exactly one caller, the\n`litmus:opencode-prompt-e2e-shape` launcher. A cycle driven by an operator\nprompt, a `.\u002Frepeat` loop, or a cron emits the marker into a transcript nothing\nparses, so that `check` never runs. **Without a check the marker is decorative,\nand an unverified attestation is worse than none: it reads as proof and carries\nnone.** The `self` mode closes that gap by moving the same convergence\nverification to emission time: EVERY lane self-checks, because the cycle proves\nits own marker in the one command that prints it.\n\nAny full-mode run that exits without a valid, converging `MO-FULL:` marker\nhas not completed its exit contract — regardless of the process exit code.\n`scripts\u002Fmo-full-attest.sh fixture` \u002F `scripts\u002Ftest-mo-full-attest.sh`\nreproduce the breach shapes hermetically (missing marker, malformed, unpushed\nlocal commit, branch mismatch, remote-head mismatch, a well-formed but\nfabricated SHA that matches nothing on the remote, clean pass — 7\u002F7).\n\n## Non-Negotiable Exit Contract\n\nLocal state is volatile. Before a successful exit, every meaningful result must\nbe committed and pushed to the correct remote branch.\n\n- Exit cleanliness is relative to the startup worktree boundary. No\n  uncommitted change created by this cycle may remain.\n- Pre-existing tracked changes and status-visible untracked files are\n  sibling\u002Foperator work, not temporary artifacts. Every path recorded by the\n  startup boundary MUST remain byte-identical on every exit, including blocked\n  exits. Never run broad `git clean`, `git checkout --`, `git restore`, or\n  `git reset` against a worktree that was dirty at startup. Ignored trees are\n  not hashed because they may contain an arbitrarily large build cache; they\n  are not thereby cycle-owned and must not be overwritten.\n- Automated finalization must never delete or restore worktree paths. Put every\n  disposable diagnostic or scratch artifact under the unique external\n  `$boundary_dir\u002Ftmp\u002F` directory. Files created in the worktree are meaningful\n  cycle output: commit and push them, or stop with a blocker and leave them for\n  explicit operator disposition.\n- Ensure any `tillandsias` background binaries or test processes are fully terminated.\n- No local-only commits.\n- No completed work without a `plan\u002F` event or finding.\n- No e2e pass\u002Ffail without a dated plan report.\n- No blocked state without a blocker, owner if known, and smallest next action.\n- Explicitly log things that make you slower (e.g., repeated steps, invalidated caches, uncoordinated scripts) into `plan\u002Fissues\u002F`.\n\n**SALVAGE BEFORE YOU REFUSE (order 872-c9nd). This is not optional and it comes\nFIRST — before the handoff, before the blocker, before anything else.**\n\n```bash\nscripts\u002Fsalvage-dirty-worktree.sh \u003Cslug>   # -> ok:salvaged:\u003Cref>:\u003Csha>\n```\n\nThe script handles a DIRTY tree OR a CLEAN tree whose HEAD is on no origin\nref (order 1146-8j7i). For a dirty tree, it pushes a COPY — tracked\nmodifications, deletions and untracked files — to\n`salvage\u002F\u003Chost>\u002F\u003Cyyyymmdd>-\u003Cslug>` on origin, and it CANNOT touch the\nworktree: it builds the commit through a temporary `GIT_INDEX_FILE` and\nplumbing (`write-tree` \u002F `commit-tree`), never a stash, an add against the\nreal index, or a checkout. Verified: worktree status and `.git\u002Findex` are\nbyte-identical afterwards, and `git show \u003Csha>:\u003Cpath>` returns an untracked\nfile's full content.\n\nTHE SAME SCRIPT ALSO COVERS A CLEAN TREE THAT IS NOT A SAFE ONE (order\n1146-8j7i): if `git status` is empty but HEAD itself is not reachable from any\norigin ref — a finished, gate-passing commit stranded when a later trunk merge\nreds the gate and every push is then refused — it pushes HEAD to the same\nsalvage ref and answers `ok:salvaged-commits:\u003Cref>:\u003Csha>` instead of\n`ok:salvage-not-needed`. A host whose gate just went red on an otherwise-clean\ntree should run this script, not open a fresh `work\u002F\u003Corder>` ref that the same\nred gate will refuse for the same reason the commit is stranded.\n\n**A tool whose name describes its original case will not be found by someone\nin its extended case: `salvage-dirty-worktree.sh` is also the hand-off lane\nfor a host that cannot gate (1177-k4jq); the `work\u002F` lane is the GATED\nhand-off and demands the stamp.** A host whose own gate cannot complete —\nmemory-ceilinged, credential-dead, or otherwise unable to produce a green —\ncannot use `work\u002F\u003Corder>` at all: the relay-ref lane still requires the full\ngate on first push, which is exactly what such a host cannot supply. Salvage\nthe finished commit to `salvage\u002F\u003Chost>\u002F\u003Cyyyymmdd>-\u003Corder>` instead and name it\nexplicitly as an UNGATED hand-off in the report; the host or orchestrator that\nrelays it gates it there, next pass (drill: the lenovinha entries of 2026-09-14).\n\nWHY THIS RULE EXISTS, and it is the most expensive lesson in this file. On\n2026-08-23 a host wedged with 16 modified paths and one untracked litmus file\nbelonging to two claimed packets. Three consecutive cycles refused the dirty\ntree, verified all 17 paths byte-identical to their boundary snapshots, and\nwrote increasingly detailed prose about the diff. On 2026-08-24T06:09Z the\ncheckout was replaced by a fresh clone. Four hours of finished work are\nunrecoverable; the untracked file's name appears in no commit on any branch.\n\n**The boundary guard did its job perfectly and protected a directory that\nsomeone then deleted wholesale.** A guard that forbids the AGENT from touching\nthe work does not forbid anything else from touching it, and a prose description\nof a diff is not a copy of it. The refusal path was a place work could sit\nindefinitely; it is now a place work passes THROUGH on its way to origin.\n\nA dirty-start preflight refusal is not a work cycle and is the sole exception\nto in-checkout blocker filing: touching `plan\u002F` would itself violate the\nstartup boundary. Report `blocked: dirty-start-worktree`, owner, the exact\nstatus paths, **the salvage ref and sha**, and the smallest next action in the\nfinal handoff so the clean host\u002Forchestrator can file it durably. Do not create\nthen delete a blocker file inside either the shared checkout or `$boundary_dir`.\n\nIf the salvage itself fails, say so loudly and do NOT soften the refusal: an\nunsalvaged dirty tree is the exact state that cost four hours, and the operator\nneeds to know the copy does not exist before deciding what to do with the\ndirectory.\n\n**AN OPERATOR LICENCE CAN GO STALE, AND A CLEAN TREE IS HOW YOU KNOW.** When a\nprompt authorises you to land dirt — order 833-fpe7's `resumable:` verdict\nor an operator sentence naming specific work to review\nand land — CHECK THAT THE DIRT IS STILL THERE before acting on it. If\n`git status --porcelain --untracked-files=all` is empty, the premise of the\nlicence is gone: answer **\"the premise is gone\"**, say what the licence expected\nto find, and stop. Do NOT reconstruct what you think it referred to and land\nthat instead. This is how 872-c9nd was discovered: an operator relaunched a host\nwith a verbatim unblock prompt hours after the checkout had been re-cloned, and\nthe honest answer was that there was nothing left to land.\n\nIf a push fails after three fetch\u002Frebase retries, mark the active plan item\n`blocked` or `failed-retryable`, include the failed push output, and stop.\n\n## Host Classification\n\nDetect host at the start of every cycle:\n\n- `forge`: Inside the Tillandsias developer forge container (typically detected by checking if `TILLANDSIAS_HOST_KIND` is set to `forge`).\n- `linux_immutable`: Linux with `\u002Frun\u002Fostree-booted` present or `rpm-ostree` on PATH.\n- `linux_mutable`: Linux without the immutable marker (and not inside the forge container).\n- `macos`: Darwin.\n- `windows`: Windows, MSYS, MINGW, or PowerShell host.\n\nCanonical branches:\n\n- Linux shared\u002Fintegration: `linux-next`\n- macOS code: `osx-next`\n- Windows code: `windows-next`\n- Release: `main` through PR only\n\nAll `plan\u002F`, `methodology\u002F`, `openspec\u002F`, and `cheatsheets\u002F` files consider `linux-next` their canonical home. However, agents working on platform branches (`windows-next`, `osx-next`) MUST commit and push all edits (including plan updates) directly to their active platform branch. The Linux coordinator will merge these branches back into `linux-next` during the `\u002Fmultihost-orchestration` pass.\n\n## Start Of Day \u002F Post-Restart Gate (run FIRST, once per day; methodology `development_environment_lifecycle`)\n\nEvery host restarts with the prompt \"Use the .\u002Fskills\u002Fmeta-orchestration skill\",\nso THIS gate is how a restart or a new day gets its maintenance and verification.\nIt is idempotent and cheap when already done today, and the marker that makes it\nso is now REAL and CHECKABLE (order 801-qasc) — run the check, do not eyeball it:\n\n```bash\nscripts\u002Fcheck-daily-maintenance.sh check     # exit 0 = today's gate ran; skip the body\n```\n\nRead the push guards too, every time, even when the day's gate is current\n(see \"Push Guards Armed\" below): `tillandsias-plan script run scripts\u002Flua\u002Fcheck-hooks-armed.lua`.\n\nIt prints exactly one line matching\n`^(ok:daily-maintenance-(current|stamped):[0-9]{4}-[0-9]{2}-[0-9]{2}|skip:forge-exempt|due:(no-marker|unreadable-marker|stale:[0-9]{4}-[0-9]{2}-[0-9]{2}))$`\nand exits 0 only when today's gate is recorded. **`due:*` means run the body**;\na corrupt or missing marker is `due:`, never a pass. From 2026-08-13 to\n2026-08-17 the marker this section names existed only as prose — nothing wrote\nit, nothing read it — so \"did today's gate run\" had no answer at all, one cycle\ninherited a false \"already stamped\" premise from its brief and skipped the body,\nand the next found nothing to confirm. An unobservable gate is indistinguishable\nfrom one that never runs, and the cheapest way to satisfy it is to skip it.\n\nOn a durable bare-metal DEVELOPMENT host (not an ephemeral forge):\n\n1. **Post-restart verification** (only when the stack looks freshly booted — MCP\n   experts just rebuilt, images\u002Fbinary possibly toolchain-bumped): run the durable\n   checklist `plan\u002Fissues\u002Ffleet-restart-post-restart-checklist-2026-08-13.md`\n   (order 718-nuvm). Do NOT trust `plan_answer`\u002F`project_answer` until the MCP\n   experts serve `source_commit == git rev-parse HEAD`; verify clock\u002FNTP sync\n   (a skewed clock breaks SSH-CA cert TTLs + freshness stamps); rebuild forge\n   images at the installed VERSION before launching any forge (version-skew DOA);\n   reinstall per-checkout git hooks; ensure the router sidecar is staged as a\n   build artifact (710-w9kc).\n2. **Daily maintenance** (methodology `development_environment_lifecycle.start_of_day_maintenance`):\n   build-cache GC per `build_cache_hygiene` (cargo clean when bloated\u002Fstale),\n   `scripts\u002Fnix-toolbox.sh gc` — never a bare `nix store gc`, which would\n   delete the whole persistent cache rather than prune it\n   (`build_cache_hygiene.nix_store_policy`) — `podman image prune` of\n   superseded versioned images,\n   the nix-lane guards on hosts with nix (`scripts\u002Ftest-nix-toolbox.sh`,\n   `scripts\u002Fcheck-nix-deps-stability.sh` — daily, not per-commit: each is a\n   flake evaluation), the enclave nix binary cache on Linux hosts with a\n   running enclave (`scripts\u002Fnix-cache-service.sh ensure` then\n   `scripts\u002Ftest-nix-cache-service.sh` — order 801-kqme; serves the persistent\n   795-h8er store to the enclave so a disposable forge lands warm without any\n   host path being mounted into it), reap defunct delegate handles\n   (`delegate-outcome.sh sweep`), verify the\n   dev-environment expert containers are up + fresh (`dev_environment_experts` —\n   the same ephemeral RAG experts + commit-hook RAG retraining the forge runs),\n   and confirm this host is visible in the capability matrix (order 850-bif2):\n   ```bash\n   scripts\u002Fcheck-capability-row.sh   # ok:capability-row-current:\u003Chost> | due:no-capability-row:\u003Chost>\n                                     # | stale:capability-row-drifted:\u003Chost>:row-only=…,probe-only=…\n                                     # | stale:capability-row-expired:\u003Chost>:age=\u003Cn>s\n   ```\n   On Linux, confirm this host is not carrying the orphaned enclave proxy\n   block (order 923-rmtw):\n   ```bash\n   scripts\u002Fcheck-containers-conf-proxy-env.sh   # ok:… | drift:… | unavailable:…\n   ```\n   `[engine] env` in containers.conf is injected into EVERY container on every\n   network, and `proxy` resolves only inside the enclave. Init used to write\n   that block and could never converge it, so hosts provisioned before\n   801-kqme kept a no_proxy list without `nix-cache` — that was four days of\n   phantom 883-ncrs \"cache RSTs\" and one broken nix e2e, hand-repaired on\n   macuahuitl and lenovinha. On `drift:containers-conf-proxy-env-present`, run\n   `tillandsias --init`: it now REMOVES the block, and containers get proxy env\n   per-container. A commented-out block still counts as drift — that is how\n   yoga ended up with no proxy env at all while init reported success.\n\n   Report scratchpad headroom in the same breath (order 915-wkm2) — one line,\n   ADVISORY, exits 0 on every path:\n   ```bash\n   tillandsias-plan script run scripts\u002Flua\u002Fcheck-scratchpad-headroom.lua   # ok:\u002Fdegraded:scratchpad-headroom-low:\u002Fskip:\n   ```\n   The agent scratchpad is tmpfs; systemd sizes \u002Ftmp at 50% of RAM but a\n   usrquota can sit far below that, so `df` reports gigabytes free while every\n   write returns EDQUOT — the host stays healthy and only the agent's tooling\n   dies. That wedged macuahuitl for several cycles: it presents as \"my shell is\n   broken\", not \"I filled a disk\". On `degraded:` do NOT build in the scratchpad;\n   build in the checkout. The threshold is absolute (one cold Rust `target\u002F`,\n   2.6-4.4 GB) rather than a percentage, because the fleet's quotas span 4.6x —\n   lenovinha warns at 29% used while macuahuitl is fine at 62%, so any\n   \"warn above N%\" rule passes the host that will wedge and warns the one that\n   will not.\n\n   On `due:`, publish the row THIS cycle — the matrix was silent for 5 of 7\n   hosts because nothing ever asked, and capability routing (847-wgy4) cannot\n   route to hardware it cannot see:\n   ```bash\n   bash scripts\u002Fhost-capability-probe.sh --fragment \\\n     > \"plan\u002Findex.d\u002F$(date -u +%Y%m%dt%H%M%Sz)-capability-row-$(hostname -s | tr 'A-Z' 'a-z').yaml\"\n   ```\n   then commit it with the cycle's plan changes. Never hand-assemble a row\n   (the unquoted-heredoc incident on 850-bif2 is why the generator exists).\n3. Stamp the marker, NAMING what actually ran — the stamp is refused without\n   `--steps`, because a stamp that records \"something happened\" without\n   recording what restores the same unfalsifiability one level up:\n\n   ```bash\n   scripts\u002Fcheck-daily-maintenance.sh stamp --host \u003Chost> \\\n     --steps 'delegate-sweep:\u003Cresult>,podman-prune:\u003Cresult>,nix-gc:\u003Cresult>,cargo-gc:\u003Cresult>'\n   ```\n\n   Record `skipped-absent` \u002F `deferred-\u003Creason>` honestly for steps this host\n   cannot or did not run; a partial pass that says so is worth more than a\n   green that says nothing. `scripts\u002Fcheck-daily-maintenance.sh show` prints the\n   last claim. Ephemeral forges skip this whole gate (they discard their\n   substrate on teardown) and read `skip:forge-exempt`.\n\nThen favor the expert system for the cycle's work-pull\u002Ftriage\u002Fdebug\u002Fresearch\n(methodology `expert_first_work`): ask the experts first; on a gap, fall back\nwith a loud warning naming the gap, never silently.\n\n## How to invoke the gate (read this before your first `.\u002Fbuild.sh`)\n\nTwo environment variables are not optional and neither is discoverable by\nreading `build.sh`. They were carried in operator prompt text for ten cycles\nbefore anyone noticed the skill never mentioned them — which meant the\nbootstrap contract (\"Use the .\u002Fskills\u002Fmeta-orchestration skill.\" and nothing\nelse) was quietly false for any fresh host.\n\n```bash\nTILLANDSIAS_SKIP_VERSION_BUMP=1 .\u002Fbuild.sh --check                  # every time\nTILLANDSIAS_SKIP_VERSION_BUMP=1 TILLANDSIAS_FORCE_CHECK=1 .\u002Fbuild.sh --check   # to VERIFY\n```\n\n- **`TILLANDSIAS_SKIP_VERSION_BUMP=1` — always.** Without it the gate bumps\n  VERSION as a side effect and the pre-push hook then refuses YOUR OWN push,\n  because VERSION may not change on a platform branch (643-64bx). The blast\n  radius is six files — VERSION, Cargo.lock and four crate Cargo.tomls — so a\n  remedy that reverts only VERSION leaves the tree dirty and the push still\n  refused. Measured live on linux-next 2026-08-20.\n- **`TILLANDSIAS_FORCE_CHECK=1` whenever the green matters.** Since 765-tkq2 a\n  plain `--check` MEMOISES: on an unchanged tree it prints `ok:gate-fresh` and\n  re-runs nothing, in 0.4s instead of 10s. That is correct for the inner loop\n  and useless as evidence. A green you did not force proves only that the tree\n  has not changed since some earlier green.\n\n**Killing the gate does not kill the gate (1132-r4mt).** `.\u002Fbuild.sh --check`\nre-execs inside the `tillandsias-builder` toolbox via `podman exec`, so\nkilling the host-side wrapper reaps only the wrapper: measured on pirria, the\ncontainer-side `build.sh` kept running 12 minutes after it was \"stopped\",\nconcurrently with the gate started after it — and two gates racing one\ncheckout is the leading mechanism for the archiver-fixture flake that cost\ntwo full gates in a night (reproduced independently on yoga). SIGTERM to the\nwrapper is inert; only SIGKILL to the container-side pid and its child ends\nit. **The discriminator is NOT conmon parentage** — every container-side\n`build.sh` under toolbox dispatch has parent `conmon` while its launcher\nchain (`toolbox run` → `podman exec`) is alive, so that reading would record\nevery healthy gate as a stray. A stray is a container-side pid whose\nHOST-SIDE `podman exec` no longer exists (measured by yoga on 2026-09-13 on a\nhealthy running gate). Before relaunching any gate or land you stopped — or\nthat a harness reaped — check for a survivor by that test, and force the\nrelaunch: a stamped `ok:gate-fresh` no-op proves nothing about strays. Match\n`ps` output by NAME, never by field index — an index match once wrote an\nempty file and read as \"no stray processes\" (drill: plan\u002Fissues\u002Ffleet-restart-2026-09-12.md, yoga: 1132-r4mt advanced at 191d606db (MO-FULL 90dcbbe07), claim released, criteria 2 and 3 open).\n\n## Where standing direction lives\n\nAsk, do not guess:\n\n```bash\ntillandsias-plan answer \"what is the current Direction?\"\ntillandsias-plan next \u003Crole>\n```\n\nThe Direction section is operator-owned and is the one place a theme is\ndeclared. Per-row carry-forward lives in each row's `next_action`, which\n`next` prints beside the row it belongs to.\n\n**A caveat learned the hard way, 2026-08-22.** Cross-cutting direction parked in\nthe `next_action` of a CLAIMED row is invisible: claiming removes the row from\nselection, so `next` never shows it and a fresh host cannot find it. That is\nR1 working as designed, and it means a claimed row is the wrong home for\nanything a future host must read. Standing direction belongs in the Direction\nsection or in this skill; `next_action` is for the row's own next step.\n\n## Joining the fleet (read this if you are not macuahuitl)\n\nAs of 2026-08-23 the fleet is FIVE working hosts, not one: macuahuitl\n(`linux_mutable`, coordinator), lenovinha and yoga (Silverblue, `linux-next`),\ntlatoanis-macbook-air (`osx-next`), and yolanda (Windows 11, `windows-next`).\nAll five have completed attested cycles. The staged rejoin this section used to\ndescribe is DONE; the three mechanisms it was gating on — claiming, the\nfirst-attestation lane, and capability rows — all landed on 2026-08-22\u002F23.\n\nNOT EVERY HOST IS A DRAIN HOST. Machines with roughly four cores are the\nfleet's deliberate LOWER BOUND and take profiling and characterization work in\ntheir own tier, never the general queue (operator mandate 2026-08-16 for\nesmeraldinha, extended 2026-08-23 to its Silverblue cousin). A slow host in the\ngeneral queue produces slow duplicates of work a faster host already claimed.\nThe SELECTOR now enforces this (847-wgy4): it probes physical cores locally,\nroutes a \u003C=4-core host to `low-end`-tagged work only, refuses loudly\n(`refused:no-tier-work`) rather than falling back to the general queue, and\nsubtracts that tier from everyone else's pool — a fast host running the\nfloor's profiling work would measure the wrong machine. Override with\nTILLANDSIAS_HOST_TIER when the probe misreads a host. Separation between\ngeneral hosts is ordinal: your rank in the capability-matrix roster picks\nyour epic (route=rank:\u003Cr>\u002F\u003Cn> in the batch header), so publishing your row\n(850-bif2, above) is what buys you a collision-free lane; a rowless host\nfalls back to the seeded pick and R1 claiming.\n\nThe criteria that gated the original rejoin, kept because they are still what\n\"working\" means:\n\n- **Claiming is live.** `expire-claims` reports a non-zero `in_progress`, and a\n  claimed row is genuinely hidden from `next \u003Crole>`. Verified on a real claim,\n  both halves. What one host CANNOT prove is the cross-host half — a row\n  claimed HERE being skipped THERE. That is the second host's first job, and it\n  is worth doing deliberately before it drains anything.\n- **The selector separates hosts.** `select-work-batch.sh \u003Crole> --seed \u003Chost>`\n  returns disjoint batches for different seeds — different epic, different\n  packets, and `urgent=` no longer forces every host to one head. This FAILED\n  on 2026-08-19 (three seeds, one byte-identical batch) and the `--seed` flag\n  did not exist then. **Pass your hostname as `--seed`.** The default is\n  `${TILLANDSIAS_HOST_KIND:-host}-$(date -u +%Y%m%d)`\n  (`scripts\u002Fselect-work-batch.sh:232`), which varies by host KIND and date — not\n  by host. Two Linux boxes therefore derive the same seed every day whether or\n  not that variable is set, so separation is available but NOT automatic: a\n  second host that forgets the flag collides exactly as the fleet did before.\n\nThe third is a fleet property no single host can close: the queue must stop\ngrowing faster than it drains. One host currently measures well inside the\nbound, but that reading says nothing about what a second host does to it —\nwhich is precisely why hosts rejoin one at a time and the number is re-measured\nafter each.\n\n**On immutable Linux, run the update-skew probe at cycle start and carry its\nverdict into the handoff** (order 1165-g6wx):\n\n```bash\nscripts\u002Fprobe-silverblue-update-skew.sh   # -> skew: | ok:no-skew | could-not-run:\n```\n\nRead-only: it runs no `rpm-ostree` command that can mutate a deployment, and it\nexists so a cycle SAYS \"skew\" instead of a host guessing. A `skew:` verdict means\nthis host cannot apply the offered update at all — `akmods` is layered, the base\nkernel has outrun the repo's `kernel-devel-matched`, depsolve fails and nothing\nstages, while `--check` and GNOME Software keep reporting \"ready, requires\nrestart\". **Do not treat it as a cycle failure and do not act on it**: the three\nremedies all change what is installed on someone's workstation and are the\noperator's decision. Report the verdict and carry on. `could-not-run:` is not a\nclean verdict either — it means the question could not be asked.\nSee `cheatsheets\u002Fruntime\u002Fsilverblue-updates.md`.\n\n**If you are on immutable Linux (Silverblue\u002FKinoite), two things differ.**\nFirst, `.\u002Fbuild.sh` transparently re-execs inside the `tillandsias-builder`\ntoolbox (`scripts\u002Fwith-tillandsias-builder.sh`), creating it with\n`toolbox create --assumeyes` on first use. So unlike a mutable host, your gate\nNEEDS a working podman — a Silverblue box with podman broken cannot run\n`--check` at all, where a mutable box happily would. The first `--check` of a\nfresh checkout spends its opening minutes building the toolbox — measured on\nyoga (Silverblue, Ryzen AI 5 340, ~250 Mbit\u002Fs registry link, 2026-08-23; filed\nas an event on 850-bif2): image pull 11.5s (355 MiB compressed), `toolbox\ncreate` 0.1s, then 131.9s for the first forced `--check` (dnf 17s, rustup 14s,\ngate ~100s), with a warm `~\u002F.cargo` — a truly pristine home also pays crates.io\ndownloads on top. That is the toolbox being built, not a hang. (The previous\n\"minutes\" figure here was an unmeasured inference written on a mutable host\nthat never executes this path — b629bb379.)\nSecond, `scripts\u002Fe2e-preflight.sh` carries NO immutability logic and will report\n`eligible` to you. Do not believe it: the skill's E2E table routes immutable\nLinux to `\u002Fsmoke-curl-install-and-test-e2e` (test a PUBLISHED release), never to\n`\u002Fbuild-install-and-smoke-test-e2e` (test a LOCAL build). The preflight is\nanswering a narrower question than the one you are asking it.\n\n**If you are on macOS (Darwin), most defaults hold — these are the parts that\ndo not** (851-gpb5, learned by the first Mac to join). Your branch is\n`osx-next`: commit and push everything there, and before EVERY push merge\n`origin\u002Flinux-next` into it — methodology's pre-push gate\n(`pull_merge_cadence.pre_push_gate`; Finalization step 6). Run\n`scripts\u002Finstall-hooks.sh` once so the v5 pre-push hook actually enforces that\nmerge on your checkout. `.\u002Fbuild.sh --check`\u002F`--test` work natively, but **run\n`scripts\u002Fcheck-host-tools.sh` FIRST — it prints every missing host tool with its\n`brew install` line** (order 989-ykks). That replaces the list of host tools this\nparagraph used to carry, and the replacement is not tidying: the list was wrong\nin two ways in one week (it omitted `coreutils`, a hard requirement of the\ncredential gate per 988-7kxf, and `pkg-config`, without which `--check` cannot\nstart), and a list is only ever written by someone whose machine already works.\nThe host that HAS a tool cannot detect that it is undocumented; it reports `ok:`\nand lands all night while the host that lacks it debugs an unrelated failure\nhours later. A probe cannot drift that way. `--install` is REFUSED by design\n(723-whrx): the macOS build path is `scripts\u002Fbuild-macos-tray.sh` — wrapped by\n`\u002Fbuild-macos-tray`, which also files findings to\n`plan\u002Fissues\u002Fmacos-build-findings-\u003CDATE>.md` — and local-build e2e\n(`\u002Fbuild-install-and-smoke-test-e2e`) destroys and re-provisions the\nVirtualization.framework VM directory, not a podman store. The system shell is\nbash 3.2 with BSD userland: no GNU-only flags in anything a Mac must run (no\n`xargs -r`, no suffix-less `sed -i`), and `sha256sum` only exists on macOS\n13+ — use the `sha256sum`-or-`shasum -a 256` dispatch\n(`scripts\u002Fbuild-sidecar.sh`, `scripts\u002Fgate-stamp.sh`). Expect the MCP experts\nto be DOWN on first boot (`down:forge-plan`, `degraded(not-built)`):\n`scripts\u002Fcycle-preflight.sh` builds `.\u002Ftarget\u002Frelease\u002Ftillandsias-plan`, the\nsame binary the MCP wrapper serves — work through it by path and record the\noutage, per `mcp_first_read_path`. And like every joining host, pass your\nhostname as `--seed` to `select-work-batch.sh`.\n\n**Publish your capability row before you drain anything** (order 850-bif2).\n`scripts\u002Fcheck-capability-row.sh` answers whether the matrix can see you AND\nwhether what it sees is still true (order 889-ewvt); on `due:`, `stale:…drifted`\nor `stale:…expired` generate and commit a row with\n`scripts\u002Fhost-capability-probe.sh --fragment` (Linux\u002FmacOS\u002Fforge loci; the\nwindows-host locus keeps its own generator). `drifted` is the urgent one: the\ncommitted row disagrees with a live probe, and routing that consumes it will\nsend work to hardware this host does not have — that is how the release gate\nwas routed to yoga for a `gpu\u002Fcontainer\u002Follama` engine yoga never had. A joining host that drains work\nwhile publishing nothing is how the matrix went silent for 5 of 7 hosts —\nand capability-aware routing (847-wgy4) cannot route to hardware the matrix\ncannot see.\n\n**Expect to be offered other hosts' abandoned work.** Claims expire on a 24h\nlease, and expired rows return to the pool with their history intact — a row\nyou are offered may have been started elsewhere and dropped. Read the row's\nevents before assuming it is fresh.\n\nThe bootstrap prompt is `Use the .\u002Fskills\u002Fmeta-orchestration skill.` and nothing\nelse. If you needed something said to you beyond that sentence, the thing you\nneeded was missing from this skill or the ledger, and THAT is the defect worth\nfiling — not the prompt.\n\n## Start Of Cycle\n\n0. **Rebuild the instrument before using it** (operator directive 2026-08-13):\n\n   ```bash\n   scripts\u002Fcycle-preflight.sh   # -> ok:cycle-preflight:\u003Cplan>:\u003Cinference>\n   ```\n\n   The project believes in idempotency and ephemerality — everything should be\n   safe to destroy and relaunch at any moment, Erlang style — so a cycle never\n   inherits a component from the previous one and hopes it is current. This\n   rebuilds `tillandsias-plan` (the binary every expert call, the batch\n   selector, every ledger write and every closure check goes through) and\n   re-establishes the dev inference endpoint. Both are idempotent; the common\n   path costs a no-op `cargo build` and one HTTP round trip, measured at ~2.8s.\n\n   **The `\u003Cplan>` segment names WHICH instrument the cycle is running on, and\n   `existing` is a legitimate verdict** (order 1004-ws5q):\n\n   | verdict | meaning |\n   |---|---|\n   | `rebuilt` | cargo was present and the instrument was built or confirmed current |\n   | `existing` | **no cargo on this host, but a runnable binary resolved** — the cycle proceeds on it |\n   | `skipped` | the build step was skipped by `CYCLE_PREFLIGHT_SKIP_BUILD=1` |\n   | `blocked:preflight:plan:cargo-absent` | no cargo AND no runnable binary — no instrument, and the cycle must not start |\n\n   `existing` exists because the old order of checks was backwards: preflight\n   declared the COMPILER absent before ever looking for a BINARY, so a host\n   doing compile-free work lost its whole slot with a healthy instrument on\n   disk. Measured on pirria 2026-09-04, where a floor-tier release smoke —\n   which compiles nothing — was refused a 4h slot.\n\n   **`CYCLE_PREFLIGHT_SKIP_BUILD=1` is for compile-free work on a host that\n   cannot compile, and nothing else.** It is NOT a way past a red build on a\n   host that can compile: that is a broken instrument, and selecting work with\n   one is the failure this whole step exists to prevent. Since 1004-ws5q a host\n   with no cargo but a working binary no longer needs the variable at all —\n   preflight answers `existing` on its own — so reaching for it should now be\n   rare enough to be worth a second thought.\n\n   It rebuilds the INSTRUMENT, not the product: `.\u002Fbuild.sh --check` already\n   compiles what it validates, and rebuilding everything on a schedule is a\n   heavier decision than this step is making.\n\n   Confirm the rebuilt instrument is CURRENT before minting or writing, and\n   again after any merge that touches crates\u002Ftillandsias-plan\u002Fsrc (a relay of\n   a plan-binary change makes the binary you built an hour ago stale; the\n   next `next-order` then refuses with `stale-plan-binary`) (1513-pppk):\n\n   ```bash\n   bash scripts\u002Fcheck-plan-binary-current.sh\n   # -> ends ok:plan-binary-current; any stale:* or blocked:* line is a stop:\n   #    cargo build --release -p tillandsias-plan, then re-run\n   ```\n\n   A `blocked:preflight:*` verdict means do not start the cycle — selecting work\n   with an unverified instrument is the one failure the loop cannot reason its\n   way out of, because the tool it would reason WITH is the stale thing. That is\n   not hypothetical: a selector change on 2026-08-13 added a subcommand every\n   host's binary predated, and this checkout went on refusing until someone\n   rebuilt by hand. Inference is a REPORT inside that verdict, never a gate —\n   the deterministic expert tiers work without it, and a host with no network is\n   degraded, not broken. When inference cannot be established, the report\n   segment reads `degraded:\u003Creason>` (never `blocked:*` — the gate word is\n   reserved for `blocked:preflight:*`); continue the cycle.\n\n0b. **Name yourself before the first ledger write** (orders 756-hn3a, 885-zvzu):\n\n   ```bash\n   agent_id=\"$(scripts\u002Fagent-identity.sh id \u003Cbackend>)\" || exit 1   # claude|codex|opencode|gemini\n   ```\n\n   Every `append-event`, `set-field` reason and loop-status entry this cycle\n   writes carries an `agent_id`, and the plan binary REFUSES a non-canonical\n   one (874-idnt): `\u003Cplatform>-\u003Cworkstation>-\u003Cbackend>-\u003Cutc-timestamp>`,\n   sanitised to `[a-z0-9-]`. Never hand-compose it. The helper resolves it\n   from stable sources and itself refuses\n   (`refused:agent-identity:empty-\u003Ccomponent>`, empty stdout) rather than mint\n   an incomplete id; on that refusal append, claim and push nothing.\n\n   WHY IT IS HERE: this skill is the whole bootstrap contract, and it never\n   named the helper. Measured on macuahuitl 2026-08-25: the first\n   `append-event` of a cycle driven by the documented prompt hand-wrote an id\n   and was refused, and the cycle recovered only by reading the error text.\n   Same class as the two gate variables in \"How to invoke the gate\", which\n   lived in operator prompt text for ten cycles.\n\n1. Record UTC time, host kind, current branch, worktree path, and sibling heads.\n   Report this host's scheduler posture in the same breath — it is one line and\n   it answers the question an operator otherwise has to read a transcript for:\n\n   ```bash\n   tillandsias-plan script run scripts\u002Flua\u002Fcheck-cycle-scheduler.lua   # armed? last fire? next due?\n   ```\n\n   ADVISORY, NEVER A GATE (order 856-s56y exit criterion 5, wired 865-j3kd).\n   `blocked:cycle-scheduler:not-installed` (exit 1; `due:not-installed` before\n   the 1624-bv73 Lua port) is a true and acceptable answer: macuahuitl is driven by\n   an external hourly loop rather than a systemd timer, and a host with no\n   durable timer is differently-scheduled, not broken. What the line buys is\n   that \"no scheduler is armed here\" becomes a stated fact rather than something\n   nobody discovers until a host has been quietly not-cycling for a day — which\n   is the 856-s56y failure, and the same shape as a wedged host reading as\n   silent (864-t4nq).\n\n   It is wired here because the guard shipped invoked by nothing and\n   audit-guard-activation therefore failed `.\u002Fbuild.sh --ci-full`, one of three\n   checks that left the trunk unreleasable for a week (865-n8vq). The auditor\n   greps for the guard's NAME, so a mention would have cleared the verdict while\n   leaving the guard as dead as it was; an orphaned guard is fixed by invoking\n   it. Arming an actual scheduler is 856-s56y's own work and remains yoga's.\n\n2. `git fetch origin --prune`, then run the Credential Channel Guard and the\n   Committable Branch Guard below before any committable work. Run the MCP\n   Expert Health Probe here too — it is advisory and never blocks, but it must\n   run BEFORE the cycle's first expert read, or an outage during that read has\n   no recorded baseline to be visible against.\n2b. **Acquire the checkout lock — EVERY lane, before the boundary snapshot**\n   (order 873-zcim):\n\n   ```bash\n   TILLANDSIAS_CYCLE_HOLDER_PID=$PPID scripts\u002Fcycle-checkout-lock.sh acquire \\\n       --lane \u003Chow-this-cycle-was-launched> --source \"\u003Cprompt source, one line>\"\n   ```\n\n   The no-stacking lock used to be taken only by the driver lane\n   (tillandsias-cycle-driver.sh), so a cycle launched by an operator prompt, a\n   \u002Floop cron, or a cloud schedule acquired nothing and STACKED on a running\n   driver in the same worktree — measured on yoga 2026-08-24, 21 minutes into\n   a driver cycle, duplicating its claims. The lock guarded the driver lane;\n   the thing two agents contend for is the CHECKOUT.\n\n   On `skip:overlap-lock-held:\u003Cholder>` DO NOT PROCEED: the verdict names who\n   holds the checkout (lane, pid, start, source). Report it as the cycle's\n   final output and exit — this is the designed outcome, not a failure, and\n   the refusal is recorded durably OUTSIDE the checkout in\n   `~\u002F.cache\u002Ftillandsias\u002Foverlap-refusals.jsonl`, so a refused-for-overlap\n   cycle is distinguishable in the record from a cycle that ran and found\n   nothing (873-zcim criterion 3). Do not retry in a loop; the next scheduled\n   fire retries on its own clock.\n\n   `TILLANDSIAS_CYCLE_HOLDER_PID=$PPID` must be evaluated in YOUR shell — it\n   anchors liveness to the agent-harness process that spans the whole cycle.\n   The script's own default is one shell too deep and dies with the tool call.\n\n   DECIDED (873-zcim criterion 4): a second agent NEVER works in a locked\n   checkout. It WAITS for the lock: concurrent work on one host is serialized,\n   never moved to a sibling git worktree or a temp clone (operator direction\n   2026-10-11, methodology multi-host-development.yaml\n   single_checkout_branching; order 1620-67ji). The worktree\u002Fclone technique\n   yoga once used here is retired: every sibling checkout sits outside the\n   session's workspace and puts its cleanup in front of the operator.\n   Release at Finalization (step 9b) with\n   `TILLANDSIAS_CYCLE_HOLDER_PID=$PPID scripts\u002Fcycle-checkout-lock.sh release`.\n\n   **IF YOU RELOCATE, TAKE THE BOUNDARY IN THE WORKTREE YOU RELOCATE TO**\n   (order 983-xha6). This is one line and its absence cost the fleet visibility\n   three separate times on 2026-09-03:\n\n   ```bash\n   cd \u003Cthe clone or worktree you will actually work in>\n   boundary_dir=\"$(mktemp -d \"${TMPDIR:-\u002Ftmp}\u002Fmeta-orchestration-boundary.XXXXXX\")\"\n   scripts\u002Fmeta-orchestration-worktree-guard.sh snapshot \"$boundary_dir\"\n   ```\n\n   The guard's stamps live in `$(git rev-parse --git-dir)`, so they are ALREADY\n   per-checkout and a relocated worktree can hold its own boundary — verified in\n   a fresh clone: snapshot, commit, `verify` -> `ok: startup worktree boundary\n   preserved`. Nothing needed building. What was missing was anyone saying to do\n   it, so step 3 below snapshotted the checkout the cycle then correctly stopped\n   using, the clone never got a boundary, and `mo-full-attest` refused at\n   Finalization with `no verified startup boundary for this cycle` — AFTER a\n   green gate with every commit pushed.\n\n   The consequence is not a missing line of output. `MO-FULL:` is how automation\n   learns a cycle finished, so a lawfully relocated cycle is INDISTINGUISHABLE\n   FROM ONE THAT DIED: the trunk carries its commits while the fleet record says\n   the host never reported. A forge hits this by default — its checkout is a\n   clone, it is often seeded from `main` (965-rb3v), and `main` is refused by\n   `check-committable-branch.sh` — so relocating is the NORMAL forge path, not an\n   exception.\n\n   Snapshotting a fresh clone is not a formality and not vacuous: the clone\n   starts clean, so the boundary proves the cycle left nothing uncommitted behind\n   it. What IS vacuous — and must never be done to obtain a marker — is\n   snapshotting AFTER the work and verifying immediately: that compares a tree\n   against itself and emits a valid-looking proof of nothing (651-2x5s). If you\n   reach Finalization having never snapshotted, the honest outcome is a BLOCKED\n   exit with no marker; do not manufacture one.\n\n3. Snapshot the startup boundary before classifying or changing any path:\n   ```bash\n   boundary_dir=\"$(mktemp -d \"${TMPDIR:-\u002Ftmp}\u002Fmeta-orchestration-boundary.XXXXXX\")\"\n   scripts\u002Fmeta-orchestration-worktree-guard.sh snapshot \"$boundary_dir\"\n   ```\n   The guard records `git status --porcelain=v1 -z --untracked-files=all`\n   plus content hashes for every status-visible dirty path. If the worktree is\n   dirty, treat every recorded path as immutable sibling\u002Foperator work unless\n   the operator explicitly identifies it as disposable in the current prompt.\n   Refuse the cycle and do not begin committable work. Report the dirty-start\n   blocker through the final handoff as defined above. Do not commit, discard,\n   restore, reset, or clean unknown startup dirt.\n\n   **Before that refusal, run `scripts\u002Fsalvage-dirty-worktree.sh \u003Cslug>`**\n   (order 872-c9nd, full rationale in the Exit Contract above). Refusing\n   protects the work from YOU; it does not protect it from a fresh clone, and on\n   2026-08-24 a fresh clone is exactly what took it. The salvage cannot touch\n   the worktree — temporary index and plumbing only — so it is safe to run on\n   dirt you have just been forbidden to alter, and it must run BEFORE the two\n   detectors below: whether the dirt turns out to be `resumable:` changes what\n   you may LAND, never whether a copy should exist.\n4. **Launch-generated opsx dirt is a refusal (deterministic, order 1440-w8g8)**:\n   before refusing on startup dirt, name WHICH dirt it is:\n   ```bash\n   scripts\u002Fcheck-opsx-generated-dirt.sh\n   ```\n   It prints exactly one line matching\n   `^(ok:clean-tree|launch-dirt:opsx-only|non-opsx:.*)$`. `launch-dirt:opsx-only`\n   (exit 5) means every dirty path is the opsx\u002Fopenspec command\u002Fskill set the\n   openspec CLI generates — a forge launch rewrote tracked files, which\n   1422-w3p8 made impossible. That is a REGRESSION to report, not content to\n   land: refuse the cycle exactly as for any dirty start (salvage first, as\n   above), name 1422-w3p8 and the verdict line in the handoff, and do not\n   commit, discard, restore or clean the dirt. Order 540 (2026-07-31) used to\n   commit it as a `chore(opsx)` sync; the operator reversed that on\n   2026-09-27 (the dirt \"should not exist\"), and 64cceb25d is what the old\n   step produced. Moving the generated set to a new openspec version is a\n   deliberate `openspec update` + commit under its own packet, never a cycle's\n   reaction to dirt. `non-opsx:` (exit 3) is real sibling\u002Foperator dirt: fall\n   through to 4b, then to the dirty-start refusal. `ok:clean-tree` (exit 4)\n   means there is nothing to name. The checker is a falsifiable machine\n   decision; do not substitute prose judgment for it.\n4b. **Resumable claim dirt (deterministic, order 833-fpe7)**: when the dirt is\n   `non-opsx:`, run the second detector before refusing:\n   ```bash\n   scripts\u002Fcheck-resumable-claim-dirt.sh\n   ```\n   It prints exactly one line matching\n   `^(resumable:\u003Corder>(,\u003Corder>)*|ok:clean-tree|unattributable:.*)$` and exits\n   `0` only when EVERY dirty path is tracked, the folded ledger names a live\n   claim OWNED BY THIS HOST (`tillandsias-plan expire-claims --list-live`:\n   claim-convention event host, both claim and activity inside the TTL), and\n   every dirty path's mtime postdates the oldest such claim. That is the\n   signature of this host's OWN previous cycle interrupted between implement\n   and commit — the dirt the refusal would otherwise deadlock on until\n   expire-claims launders finished work into lost work (the 833-fpe7 shape;\n   814-iyu7 arriving by a second route).\n\n   `resumable:` is a licence to REVIEW AND LAND, never to auto-commit: read\n   the diff against each named order's packet, land what implements it as its\n   own commit(s) citing the orders, then re-anchor with the guard's\n   `re-snapshot` (scripts\u002Fmeta-orchestration-worktree-guard.sh). Whether an edit\n   IMPLEMENTS the packet beside it is the agent's judgment; the detector only\n   removes the deadlock. Any `unattributable:` verdict falls through to the\n   dirty-start refusal exactly as written. Pinned by\n   `litmus:resumable-claim-dirt-shape`.\n5. Update the active local branch from remote with fast-forward or an explicit\n   merge from `origin\u002Flinux-next` into the platform branch when appropriate.\n\n5a. **NOW check for sibling overlap** (methodology `sibling_heads_up_protocol`).\n   Hosts can message each other directly — `ListAgents` to see who is live,\n   `SendMessage` to reach them. **The capability is new and you will not\n   discover it on your own**; the fleet coordinated exclusively through the\n   ledger and the trunk for months before anyone noticed it existed.\n\n   ```bash\n   tillandsias-plan query --status in_progress   # who is holding what, right now\n   ```\n\n   **AFTER THE MERGE, NOT BEFORE, AND THIS ORDERING IS THE WHOLE STEP.** This\n   check first shipped as step 2a — before the branch update — and was MEASURED\n   BROKEN on the next cycle by its own author:\n\n   ```\n   before the merge:  831-ezea only            \u003C- the other host's claim INVISIBLE\n   after the merge:   642-fedr + 831-ezea      \u003C- yoga's fragments.rs claim\n   ```\n\n   `git fetch` at step 2 updates remote-tracking refs; it does NOT update the\n   worktree ledger that `tillandsias-plan` reads. So a check placed before the\n   merge answers about the claims as of your LAST merge, not as of now.\n\n   **THE STALENESS IS NOT ONE-DIRECTIONAL, and the earlier wording here said it\n   was.** This passage used to end \"a stale ledger always shows FEWER claims,\n   never more.\" Measured on yoga 2026-08-26T07:26Z, one cycle after that\n   sentence landed, running the same query either side of the merge:\n\n   ```\n   before the merge:  799-tb7q + 831-ezea    \u003C- 799-tb7q was a PHANTOM\n   after  the merge:  831-ezea only          \u003C- another host had released it\n   ```\n\n   `799-tb7q` was `in_progress` in the stale ledger and `ready` at the new head:\n   a sibling finished a slice and released it in commits this host had fetched\n   but not merged. So a pre-merge check can show a claim that no longer exists\n   as easily as it can hide one that does — **fewer claims when siblings have\n   been claiming, more when they have been releasing.**\n\n   Both directions are harmful and they fail differently. Missing a live claim\n   fails toward \"no overlap\", which is the safe-LOOKING answer and the one that\n   costs a union. Seeing a released claim fails toward a needless heads-up, or\n   toward skipping a packet that is free — cheaper, but it teaches the reader\n   that the step produces noise, which is how a step stops being run.\n\n   `expire-claims --list-live` is the tool again as of 905-wjfj: it now prints\n   one row per in_progress packet and a `rows:` accounting line whose total must\n   equal the summary's `in_progress=N`. Before that fix it printed the count and\n   no rows — two hosts hit it on the same day — and the workaround here was\n   `query --status in_progress`, which still works and is a fine cross-check.\n\n   **READ THE ROW TYPE, because the two mean opposite things.**\n\n   - `live-claim \u003Corder> \u003Cpid> \u003Chost> \u003Cclaimed-at> \u003Clast>` — a sibling holds\n     this. If it touches your surface, message that host.\n   - `unclaimed-in-progress \u003Corder> \u003Cpid> - - \u003Clast>` — in_progress, recent\n     enough that no reaper will touch it, and **nobody to send a heads-up to**.\n     The dashes are the actionable part. This row is not the quiet case; it is\n     the one where the protocol has no addressee, so if it touches your surface\n     you inspect the diff yourself rather than assuming silence means free.\n   - `attention:list-live-partition-mismatch` — a packet is in no bucket or in\n     two. The enumeration is under-reporting; do not trust a `no overlap`\n     verdict derived from it.\n\n   MEASURED 2026-08-26: `831-ezea` sat in the unclaimed row for at least a day —\n   in_progress, with a gate step wired into `.\u002Fbuild.sh --check`, last activity\n   18h old and therefore inside the 24h TTL, so neither the reaper nor the\n   live-claim list would ever surface it. Exactly the row an overlap check\n   exists to show you, and the only one it could not.\n\n   If a live claim touches the SAME SURFACE your batch touches — a wire type, a\n   shared struct, a script another lane runs, a schema, a guard wired into\n   `--check` — send one HEADS UP before implementing: what you are touching, the\n   shape of the change, any sibling call sites you know of, and the ask. They\n   reply ACK plus comments. Two short messages.\n\n   **WHY, structurally: THE UNION IS A STATE NO SINGLE BRANCH'S GATE OBSERVES.**\n   Every branch can be green alone and the merge still broken, because no\n   branch's `--check` compiles the other's configuration. Care cannot close\n   that; only a second lane looking can. MEASURED 2026-08-26: macbook's\n   731-eupn was green on both branches and `E0063 + E0308` in the union — a red\n   gate and ~30 minutes of coordinator cycle.\n\n   **Prefer the message to the resolve-to-be-careful: a heads-up is a\n   falsifiable act, care is not.** \"I considered the siblings\" cannot be checked\n   by anyone, including you an hour later.\n\n   DO NOT broadcast routine drain. Most work touches only your own lane, and a\n   channel that carries everything is one nobody reads — the recipient is\n   mid-cycle, holding a checkout lock, with expensive context. The heads-up is\n   for what the ledger cannot carry in time: **intent, before the fact.**\n\n## Credential Channel Guard\n\nRun immediately after `git fetch` and before any worker drain or committable\nwork.\n\n**Close the interactive escape hatches around EVERY push** (order 860-g798,\nexit criterion 3):\n\n```bash\nexport GIT_TERMINAL_PROMPT=0 GCM_INTERACTIVE=never\n```\n\nA credential problem must fail FAST AND LOUDLY, not hang. Measured on\nesmeraldinha: the guard reported green (`gh auth status` held a token), the\ncycle entered committable work, and the first push sat >10 minutes behind Git\nCredential Manager's interactive prompt — a hang with no output, presenting as\na slow build on the host least able to afford the misdiagnosis. With the\nprompts closed the same failure surfaces in seconds as an auth error the guard\nnow names (`blocked:interactive-credential-helper`, remedy printed). The guard\nitself verifies the PUSH path since 860-g798 — `ok:gh-keyring-push-verified`\nmeans a bounded non-interactive dry-run push actually authenticated, not\nmerely that a token exists somewhere. In SMOKE mode it is a REPORT, not a gate — a smoke run\nperforms no committable work, so a stale push credential cannot harm it (order\n818-cgpn; see Smoke Mode Runbook rule 3a). The Cowork scheduled-task runtime can inherit dangling session sockets\n(`DBUS_SESSION_BUS_ADDRESS`, `SSH_AUTH_SOCK` pointing into a non-existent\n`\u002Frun\u002Fuser\u002F\u003Cuid>`) so anonymous reads succeed while every `git push` silently\nfails for lack of a credential. See\n`plan\u002Fissues\u002Fcowork-headless-credential-isolation-2026-06-20.md`.\n\nRun the executable guard instead of re-deriving the check in prose. \n*(On Windows: ensure you run this via Git Bash, e.g. `& \"C:\\Program Files\\Git\\bin\\bash.exe\" scripts\u002Fcheck-credential-channel.sh`. PowerShell's `bash` alias defaults to an isolated WSL session that lacks host credentials).*\n\n```bash\nscripts\u002Fcheck-credential-channel.sh\n```\n\nIt prints exactly one line matching the falsifiable grammar\n`^(ok:[a-z0-9-]+|blocked:[a-z0-9-]+|missing:no-credential-channel)$` and exits\n`0` when a usable git-push credential channel is present, non-zero when it is\nabsent or blocked. A usable channel is present when ANY of these holds (the\nscript checks them in order):\n\n- `\u003Ccommon-git-dir>\u002F.gh-credentials` (absolute `git rev-parse --path-format=absolute --git-common-dir`, so every linked worktree shares it; 1409-65d5) exists and is non-empty (repo-local store helper), or\n- `GH_TOKEN` or `GITHUB_TOKEN` is set in the environment, or\n- `gh auth status` succeeds (reachable, unlocked keyring), or\n- `TILLANDSIAS_HOST_KIND=forge` is set AND the enclave git mirror is reachable\n  for `origin` AND the mirror's published upstream write-authorization verdict\n  (`refs\u002Ftillandsias\u002Fupstream-auth\u002F\u003Cstate>\u002F\u003Cepoch>`, refreshed non-mutatingly by\n  `images\u002Fgit\u002Fprobe-upstream-auth.sh`) is fresh and `authorized` (or\n  `local-only`). Order 756-2jnj: reachability alone said `ok` on 2026-08-15\n  while GitHub 403'd the mirror's credential, and a forge lost two commits it\n  discovered only at first push. `ok:forge-git-mirror` now means BOTH halves —\n  forge→mirror reachable AND mirror→upstream currently write-authorized.\n\nPinned by `litmus:credential-channel-check-shape` and\n`litmus:forge-upstream-auth-gate`. A non-zero exit (verdict\n`missing:no-credential-channel`, or any `blocked:*` verdict — e.g.\n`blocked:upstream-push-unauthorized` for the 403 state,\n`blocked:upstream-no-credential`, `blocked:upstream-auth-stale`,\n`blocked:upstream-auth-unpublished`) fails the cycle on its own; do NOT proceed\ninto worker drain or any committable work. Instead\nfail loud: file or update a blocker in `plan\u002Fissues\u002F` recording the exact\nverdict, the owner (operator), and the smallest next\naction (re-seed `.git\u002F.gh-credentials` via the gh token, inject `GH_TOKEN`\ninto the task environment, or — for `blocked:*` — repair the mirror's Vault\nGitHub token \u002F its repo push permission), then stop. Accreting local-only\ncommits that cannot be pushed violates the Non-Negotiable Exit Contract and is\nthe precise velocity-killer this guard prevents.\n\nReads (`git fetch`\u002F`git ls-remote`) succeeding is NOT evidence of a credential\nchannel — public-repo reads are anonymous. Verify write capability explicitly.\n\n**Bound every `git push` with a timeout; an empty push log is a refusal, not\nslowness (macneo, two land stalls of 3000 s each).** `land: attempt 1 — push`\nwas the last line written, the push log was ZERO bytes, and a stack sample\nshowed `git-credential-osxkeychain` blocked in `CSSM_DecryptDataFinal` — an\nACL confirmation dialog no non-GUI session can answer. The guard's\n`GIT_TERMINAL_PROMPT=0`\u002F`GCM_INTERACTIVE=never` above close git's own\nprompts, not an OS helper below them; macbookair pushed six times on the same\nhelper and repo from inside a GUI session, so the variable is the session,\nnot the config. A genuine credential fault refuses WITH output; a keychain\nhang produces none. Wrap the push (`timeout \u003Cn> git push …`), `stat` the log\ntwice before calling anything slow, and report\n`blocked:credential-helper-hung` with the probe (drill: plan\u002Fissues\u002Ffleet-restart-2026-09-12.md, A push with no timeout emits nothing).\n\n## Committable Branch Guard\n\nRun alongside the Credential Channel Guard, before any committable work.\nDirect commits\u002Fpushes to `main` are forbidden — `main` advances only through\nPR merges. Breach record: 34e60965, an antigravity forge cycle running ON\n`main` that pushed a ~42k-line `plan\u002Findex.yaml` reserialization straight to\n`origin\u002Fmain` (reverted via PR #81; see\n`plan\u002Fissues\u002Fmain-branch-direct-push-guard-2026-07-24.md`).\n\nRun the executable guard instead of re-deriving the check in prose:\n\n```bash\nscripts\u002Fcheck-committable-branch.sh\n```\n\nIt prints exactly one line matching the falsifiable grammar\n`^(ok:branch-[A-Za-z0-9._\u002F-]+|blocked:(committable-cycle-on-main|detached-head|not-a-git-repo))$`\nand exits `0` when HEAD is on a committable branch (any named branch except\n`main`), non-zero when the checkout is on `main`, detached, or not a git\nrepository (fail closed). On any `blocked:*` verdict do NOT proceed into\nworker drain or any committable work: switch to the host's canonical branch\n(`linux-next`, `windows-next`, `osx-next`) or run the cycle read-only.\nRead-only\u002Finspection cycles on a `main` checkout remain allowed — the guard\ngates committable cycles only. Pinned by\n`litmus:committable-branch-guard-shape`.\n\n## Forge Expert Base Guard\n\nRun before launching a forge from this checkout. Run the executable guard\ninstead of re-deriving the check in prose:\n\n```bash\ntillandsias-plan script run scripts\u002Flua\u002Fcheck-forge-expert-base.lua\n```\n\nIt prints exactly one line matching\n`^(ok:(expert-base-ready|no-plan-crate)|blocked:(expert-sources-absent|not-a-git-repo))$`\nand exits `0` when a forge seeded from this checkout can build a working plan\nexpert, non-zero when it cannot.\n\nWhy this is a separate guard from the branch guard above: the launcher seeds a\nforge's branch from **this checkout's current branch**\n(`read_host_project_current_branch` → `TILLANDSIAS_FORGE_SEED_BRANCH`), so\nwhatever branch you are parked on becomes the next forge's base. `main` carries\nno `crates\u002Ftillandsias-plan\u002Fsrc\u002Fanswer.rs`, so a forge seeded from it builds a\n**pre-expert binary** and then reports `experts: ready` truthfully while every\n`plan_answer` \u002F `methodology_path` returns `confidence=unsupported`. Truthful\nstate, wrong artifact. Breach record: 2026-07-30, an in-forge session found both\nexperts refusing the milestone's own exemplar question; two earlier cycles had\nabsorbed the same condition by noticing and hand-rebasing\n(`plan\u002Floop_status.md:203`, `:243`). Order 531.\n\nThe test is **source presence, not a branch name** — deliberately. The names\n`linux-next`\u002F`windows-next`\u002F`osx-next`\u002F`main` are Tillandsias's own conventions\nand are explicitly *not* a runtime convention of the product\n(`methodology\u002Fmulti-host-development.yaml:21-27`), so a forge on an end user's\nproject must not assume them. Source presence is a fact about the checkout, and\nit also catches the case a branch-name test cannot: when the seed and the actual\nbranch agree because this checkout was itself parked on a pre-expert base,\nnothing looks wrong.\n\nOn `blocked:expert-sources-absent`, do NOT launch a forge expecting expert\nanswers. Switch this checkout to a branch carrying the expert sources first. On\n`ok:no-plan-crate` the target project simply has no plan expert, which is normal\noff-Tillandsias.\n\n## Push Guards Armed (read-only; Start Of Day and Start Of Cycle, order 1255-s4im)\n\n```bash\ntillandsias-plan script run scripts\u002Flua\u002Fcheck-hooks-armed.lua   # ok:hooks-armed:\u003Cmarker>\n```\n\nIt answers whether THIS checkout's pre-push hook carries the current\n`tillandsias-pre-push-v*` marker, and it installs nothing:\n`ok:hooks-armed:\u003Cmarker>` (exit 0), `degraded:hooks:absent` or\n`degraded:hooks:stale:\u003Chave>->\u003Cwant>` (exit 1), `refused:hooks:foreign-pre-push:*`\nor `refused:hooks:\u003Cscope>-hooks-path:*` (exit 3). **On `degraded:` run\n`bash scripts\u002Fensure-hooks.sh` before any push**: until then a push from here\nruns none of the push guards, the release freeze among them. The plan-lane\nscripts arm the hooks on their own (`ensure-hooks.sh --prelude`), but a host\nwhose first push is a WORK REF never runs one of them, which is why this is\nread at the start of the day and of every cycle.\n\n## MCP Expert Health Probe (advisory — record, never block)\n\nRun at Start-Of-Cycle, alongside the guards above:\n\n```bash\nscripts\u002Fcheck-mcp-expert-health.sh\n```\n\nIt speaks the MCP `initialize` handshake to each expected expert and prints\nexactly one line matching\n`^(ok:experts-healthy|down:[a-z0-9-]+(,[a-z0-9-]+)*|absent:not-registered|skip:[a-z0-9-]+)$`,\nappending one JSONL record per server to `$TILLANDSIAS_EXPERT_HEALTH_LOG`\n(default `\u002Ftmp\u002Fforge-expert-health.jsonl`). ~40ms when healthy.\n\n**This is the concrete referent for `mcp_first_read_path`'s \"fall back and keep\ngoing, THEN RECORD IT\".** That rule named no destination, and on 2026-08-14 two\nhosts skipped the recording half on the same day: windows lost all 28 MCP tools\nmid-session and fell back to `tillandsias-plan.exe` silently; linux ran an entire\ncycle whose session had never loaded the servers at all. Both outages were\ninvisible in the ledger and would have stayed invisible (order 737-zcj5).\n\nUnlike the guards above, a non-zero exit here **does not fail the cycle** — an\nunavailable expert is a degraded read path, never a blocked one. Record and\ncontinue:\n\n- `down:\u003Ccsv>` \u002F `absent:not-registered` — keep working through\n  `.\u002Ftarget\u002Frelease\u002Ftillandsias-plan` (the same binary the MCP wrapper wraps) and\n  let the `mcp_outage:` line carry it into the handoff. Name the fallback reason,\n  as the rule has always required.\n- `ok:experts-healthy` — say nothing further. The probe is silent by design when\n  healthy; a signal that fires every cycle is one nobody reads.\n\n### The handshake is not the surface (order 801-m9tk)\n\n`ok:experts-healthy` means the registered servers answered when the PROBE\nlaunched them. It does not mean the tools reached YOUR session. For three\nconsecutive windows cycles the probe printed `ok:experts-healthy` while not one\n`mcp__forge-plan__*` \u002F `mcp__project-info__*` tool was bound to the agent, so\nevery read silently fell back to `.\u002Ftarget\u002Frelease\u002Ftillandsias-plan`. A server\nthat is up but not exposed is exactly the outage worth catching, and the\nhandshake probe calls it healthy — the order-531 shape again.\n\nA script cannot see your tool surface; nothing in this repo can. **You** are the\nonly observer of that fact, so the surface half is **attested, not measured** —\nand an unattested cycle reads `unattested:no-surface-claim`, never `ok:`.\nImmediately after the health probe, look at your own tool surface and say so:\n\n```bash\nscripts\u002Fcheck-mcp-surface.sh attest exposed      # mcp__* tools resolved this session\nscripts\u002Fcheck-mcp-surface.sh attest unexposed    # they did not — every read is a fallback\nscripts\u002Fcheck-mcp-surface.sh check               # the joined verdict\n```\n\n`check` joins the measured handshake with the attested surface and prints\n`ok:surface-exposed` \u002F `unexposed:handshake-ok` \u002F `down:\u003Ccsv>` \u002F\n`absent:not-registered` \u002F `unattested:*` \u002F `skip:no-health-log`. Advisory, never\na gate — like the probe it extends. `cycle-metrics.sh` folds a fresh `unexposed`\nattestation into `mcp: health=ok-unexposed` and fires the `mcp_outage:` line, so\nthe degraded read path reaches the ledger without anyone choosing to write it\ndown. An `exposed` attestation leaves `health=ok` unchanged, and a claim older\nthan the freshness window labels nothing: a previous cycle's marker never\nvouches for this one.\n\n**And the third question: is the server you reach running current code?**\n(order 823-u3k9). The handshake probe launches its OWN instance from the\nregistration, so it validates the FILE. It cannot see that your session's\nlong-lived MCP process was started before a fix landed and is still serving the\nold text — measured on macuahuitl 2026-08-18, where 799-j4xd's fix was in the\nfile, the index was fine, L0 was fine, and the expert answered with prose the\nfix had deleted while every signal read green. A fix in a file does not reach a\nprocess that already read it.\n\nLike the surface, only **you** can observe this, and for the same reason: a\nsubprocess cannot reach your server, and launching one is the defect. Call the\nlive tool, read the build line out of its answer, attest it:\n\n```bash\n# 1. mcp__forge-plan__expert_capability   (through YOUR tool surface, not a shell)\n# 2. read its `server_build: forge-plan=\u003Cid> source=\u003Cpath>` line\nscripts\u002Fcheck-mcp-live-build.sh attest forge-plan=\u003Cid> --source \u003Cpath>\n# 3. mcp__project-info__project_info     (1414-mjdw: the other long-lived server)\n# 4. read its JSON \"server_build\": \"project-info=\u003Cid> source=\u003Cpath>\" field\nscripts\u002Fcheck-mcp-live-build.sh attest project-info=\u003Cid> --source \u003Cpath>\nscripts\u002Fcheck-mcp-live-build.sh check            # the WORST attested server\nscripts\u002Fcheck-mcp-live-build.sh check project-info   # one server by name\n```\n\nEach server keeps its own attestation line, so a current forge-plan never\nvouches for a stale project-info. A project-info answer with no\n`server_build` field predates 1414-mjdw: attest `project-info=unreported`.\n\nIf the answer carries **no** `server_build:` line, that is the finding, not a\nreason to skip: the running server predates the emitter. Attest\n`forge-plan=unreported` and it reads `stale:live-server-build-unreported:…`.\n`check` prints `ok:live-build-current:\u003Cserver>` \u002F\n`stale:live-server-build:\u003Cserver>:\u003Cattested>!=\u003Condisk>` \u002F\n`stale:live-server-build-unreported:\u003Cserver>` \u002F `unattested:*` \u002F\n`unavailable:*`. Advisory, never a gate. On any `stale:`, relaunch the forge (or\nthe session's MCP servers) before trusting an expert answer — and record the\nfallback, per `mcp_first_read_path`.\n\nDo NOT substitute `test -x` or a registration-file check for the handshake. A\nserver that exists but wedges on startup is precisely the outage worth catching,\nand a file-existence test calls it healthy. (The first draft of the probe read\n`.command` while dropping `.args`, launched a bare `bash`, and reported both\nhealthy experts as `down` — a false outage is as bad as a missed one.)\n\n## Local Expert System Probe (advisory — at cycle start, before work drain)\n\nRun at Start-Of-Cycle, AFTER the MCP Expert Health Probe and BEFORE worker\ndrain — and ONLY on hosts with `TILLANDSIAS_HOST_EXPERTS` set, the same gate\nthe commit hooks use for host-expert work. On every other host skip this\nsection entirely rather than paying a connection timeout probing an ollama\nthat was never provisioned:\n\n```bash\n[ -n \"${TILLANDSIAS_HOST_EXPERTS:-}\" ] && \"$(. scripts\u002Fplan-binary-probe.sh && resolve_plan_binary)\" script run scripts\u002Flua\u002Fcheck-local-expert-health.lua\n```\n\nIt pings the local Ollama inference endpoint and prints exactly one line matching\n`^(ok:local-experts-healthy|degraded:local-experts[^;]*|down:local-experts[^;]*|skip:not-applicable)$`.\n\nOn `ok:local-experts-healthy` you MAY ask the local pipeline for a triage hint:\n\n```bash\nTILLANDSIAS_EXPERT_DOMAIN=methodology \\\n  .\u002Ftarget\u002Frelease\u002Ftillandsias-plan pipeline \"what is pending and neglected in the plan?\" \\\n    --domain methodology 2>\u002Fdev\u002Fnull | jq -r '.responses[0].answer \u002F\u002F empty'\n```\n\nThe pipeline emits `{tier, domain, rag_freshness, rag_source_commit,\nresponses}`, and each `responses[].answer` is RAW local-model text: no\nretrieval, no validation, no grounding (that wiring is packet\nwire-local-experts-mode-through-grounded-pipeline). Treat the output as an\nungrounded hunch, never a directive — anything it claims about specific\npackets must be re-checked against `tillandsias-plan next \u003Crole>` and the\nplan ledger before acting.\n\nWith the gate unset, or on `down:*` \u002F `degraded:*`, skip the query and\ncontinue the cycle. The local expert system is a convenience, not a gate —\nthe deterministic expert tiers and MCP experts work without it.\n\n## Reduction Engine\n\nThe loop is a reduction engine, not just a worker. Its job is the project's core\nprinciple — **Monotonic Reduction of Uncertainty Under Verifiable Constraints**\n(`methodology\u002Fphilosophy.yaml`). Every cycle must move the system toward a\nverifiable implementation of the spec by *reducing* open uncertainty, and must\nnever let an observed problem evaporate.\n\n### Capture: nothing gets lost\n\nAny time a worker notices \"welp, this isn't great\" — an inefficiency, a rough\nedge, a fragile assumption, an advisory-only guard, a repeated manual step, a\nlog warning, a deprecation notice — it MUST be filed before the cycle exits.\n\nEvery capture is a ledger write, so it carries the `agent_id` from Start Of\nCycle step 0b (`scripts\u002Fagent-identity.sh id \u003Cbackend>`), never a hand-typed one.\n\n**CAPTURE IS MANDATORY. A NEW ROW IS NOT.** These are different acts and\nconflating them is what grew the ready queue to 410 rows against a service rate\nof ~19\u002Fday. Route every capture:\n\n- **A new ROW** only if INDEPENDENTLY SCHEDULABLE — it names owned files no open\n  row already owns, OR a different `pickup_role` can claim it than every open\n  row covering that scope.\n- **Otherwise an EVENT on the row it belongs to**, or a `next_action` clause on\n  that row. The finding is recorded in full either way; only its *selectability*\n  differs.\n\n**When a row's events show a confirmed pattern — several independent\nobservations, ideally from different hosts or cycles, converging on one defect\nor one missing capability — that row has OVERFLOWED and is a promotion\ncandidate. NOTE it; do NOT promote it. Promotion is Tlatoāni-gated** (operator\nruling, 2026-08-19): what counts as a confirmed pattern is not yet expressible\nas a threshold, and an agent promoting on its own judgment restores unbounded\narrival by a longer path.\n\nWhy this is safe, and why it is not a throughput cut: with arrivals\nλ = a + b·μ, the queue moves at `dL\u002Fdt = a + (b−1)·μ`. Above b = 1 every extra\nhost and every shortened cycle fills the queue FASTER; below b = 1 the same\nvelocity drains it. Measured b is 1.80. So curation at the acceptance boundary\nis the *precondition* for velocity paying off at all — see\n`methodology\u002Fdistributed-work.yaml` → `why_velocity_is_the_other_lever`.\n\n### Standing FRESHNESS audit class (order 372, methodology `component_freshness`)\nEach cycle, after worker drain, treat the top component the `freshness-advisory`\nCI phase flagged as a claimable audit source. Re-validate ONE component against\nthe audit question — *last properly looked at and confirmed still meaningful,\nuseful, efficient, sound, and complete?* — and end in exactly one disposition:\n**refreshed** (re-validated, update its `# freshness:` stamp), **updated**\n(fixed\u002Ftuned, update stamp), or **obsoleted** (delete\u002Ftombstone with same-commit\nremoval of dependents). Apply the **discard-over-repair bias**: discard a stale\ncomponent rather than repair it when a fresh implementation would be better.\n`scripts\u002Ffreshness-inventory.sh` emits the coverage report + top stale\ncomponents each `.\u002Fbuild.sh --ci` run; the report grammar is pinned by\n`litmus:freshness-inventory-shape`. A freshness audit is a valid reduction step\non its own and counts toward burndown.\nThis is mandatory, not optional (`methodology.yaml` →\n`cooperative_work_discipline`; Non-Negotiable Exit Contract → \"Explicitly log\nthings that make you slower\"). File it as a dated issue in `plan\u002Fissues\u002F`,\nclassified as one of: `research\u002F`, `exploration\u002F`, `enhancement\u002F`, or\n`optimization\u002F`. An unfiled finding is a lost finding and a contract violation.\n\n### Ledger compaction (check each cycle; act only when eligible)\n\n```bash\ntillandsias-plan fragments     # -> compaction: eligible=\u003Cbool> fragments=N bytes=N malformed=N reason=\u003Cname>\ntillandsias-plan compact       # only when eligible=true\n```\n\n`plan\u002Findex.yaml` is a compacted BASE; `plan\u002Findex.d\u002F*.yaml` are append-only\nfragments that concurrent hosts write freely. Reads fold them transparently, so\n**an uncompacted ledger is slower, never wrong** — compaction is garbage\ncollection, not a correctness step. Never let it block filing work.\n\nTwo rules, both easy to get wrong:\n\n- **Compaction deletes only the fragments it folded, by name.** Never\n  `rm plan\u002Findex.d\u002F*`. A fragment another host wrote while you were compacting\n  has not been folded, and removing it silently destroys their work.\n- **Compaction is TEXT-LEVEL and never re-serializes the base.** It ran on the\n  real ledger for the first time on 2026-08-03 (order 582-4wdi, commit 81e12b65):\n  28 fragments folded, 120 comment lines preserved exactly, 535 packets\n  preserved, and the `plan\u002Findex.yaml` diff was 1021 added lines and zero removed\n  lines. **Do not read that zero as the invariant** — it was a true measurement of\n  a fold that could only APPEND, taken before `set-field` fragments existed, and\n  it has been unreachable since. A fragment that reassigns a field must remove the\n  superseded line; a fold carrying nine status transitions removes nine `status:`\n  lines and that is the fold working.\n\n  THE PROPERTY TO PROTECT, stated so a healthy compaction cannot fail it: no line\n  is removed EXCEPT one whose field a fragment explicitly reassigned. Comment\n  lines, packet count (minus none, plus the new ones), and the four-space item\n  prefix `append-event` locates by all survive unchanged. Check THOSE, in one\n  command, rather than eyeballing the removal count:\n\n  ```bash\n  git diff --numstat plan\u002Findex.yaml                  # removals are expected\n  git diff plan\u002Findex.yaml | grep '^-' | grep -v '^---' | head -40   # READ them\n  ```\n\n  **Read the removed LINES, not a histogram of their keys.** This recipe used to\n  end with `cut -d: -f1 | sort | uniq -c` and the question \"ONLY field keys?\".\n  That works only while every reassigned field has a SCALAR value. A fragment\n  that replaces a STRUCTURED value removes all of its lines, including list\n  items that are not field keys at all — measured on yoga 2026-08-25, a fold\n  whose 14 removals included `- container`, `- cpu`, `- gpu`, `engines`,\n  `lanes` and `supported_device_classes`, because a stale capability row's\n  `engines: [{name: ollama, ...}]` block was superseded by `engines: []`. The\n  fold was correct; the histogram made it look like structure loss, which is\n  the same stop-and-investigate 865-ng6r removed for the scalar case. The\n  question is not \"are these field keys\" but \"does each removed line belong to\n  a field some fragment reassigned\" — and the cheapest way to answer it is to\n  look at the lines.\n\n  MEASURED TWICE, on two hosts, each of which stopped its cycle to investigate:\n  lenovinha 2026-08-23 (+888\u002F-17 — five `status`, one multi-line `next_action`)\n  and yoga 2026-08-25 (+556\u002F-12 — nine `status`, two `next_action`, one\n  `next_action_ts`; 37 comments and all 526 packet prefixes intact). Both folds\n  were correct. The prose is what cost the time, which is why it is corrected\n  here rather than merely noted (865-ng6r).\n\n  It refused for months before that, correctly: a `serde_yaml` round-trip drops\n  comments and re-indents items to column 0, after which `append-event` silently\n  stops finding packets. If compaction ever regresses to round-tripping YAML,\n  restore the refusal rather than accepting a lossy fold. The candidate base must\n  still PARSE and pass the integrity gate before it may replace the base.\n\nIf `malformed=N` is non-zero, a fragment did not parse and was SKIPPED — its\ncontents are absent from every answer. Treat that as a finding, not noise.\n\n### De-slop sweep clock (consult each cycle; act only when due)\n\n```bash\nscripts\u002Fcheck-deslop-due.sh check    # exit 0 = NOT due; exit 1 = due; exit 2 = cannot compute\n```\n\n**Read the exit polarity before wiring anything to it.** The file is named\n`check-deslop-due.sh` and exits **0 when the sweep is NOT due** — same\nconvention as `check-daily-maintenance.sh`, where the actionable state is the\nnon-zero one and the healthy steady state stays at 0 for callers under `set -e`.\nThe idiom is `if ! scripts\u002Fcheck-deslop-due.sh; then run_the_sweep; fi`, or\nbranch on the verdict token (`deslop-due` \u002F `deslop-not-due`), which cannot be\ninverted by a copy-paste.\n\nIt prints exactly one line carrying the numbers it decided on, e.g.\n`ok:deslop-not-due:order=844 last=834 delta=10 hours=44 reason=under-threshold`.\nThe rule is **event-counted only**: due when\n`(current_order - order_at_last_sweep) >= 200`, with a 48h floor so a filing\nburst cannot fire two sweeps in a day, and **no calendar ceiling** — a ceiling\nwould fire low-yield sweeps over a quiet fortnight and\n`red:two-sweeps-zero-confirmed` would then retire the reconciler for doing\nnothing wrong. Time-decaying properties already have their own TTLs\n(`expire-claims` 24h, `component_freshness`). This is **not** a build gate and\nnothing in `.\u002Fbuild.sh` runs it; it is a scheduler input for this section.\n\nAfter running a sweep, record it — the marker is committed, not host-local, so\nthe whole fleet shares one clock:\n\n```bash\nscripts\u002Fcheck-deslop-due.sh record --examined \u003Crows-looked-at> --confirmed \u003Cn> \\\n  [--retracted \u003Cn>] [--filed \u003Cn>] [--net-lines \u003C±n>]\n```\n\n`--examined` and `--confirmed` are mandatory. The sweep's kill rule counts only\nsweeps that **examined new rows**, and this is why: the first real sweep\nretracted 51 of 410 rows (12.4%) against a modelled ~50%, and that pass drained\naccumulated stock. Steady-state yield will be far lower, so **two consecutive\nnear-zero sweeps is a normal outcome for a healthy queue**, not evidence the\nreconciler is broken. A sweep that confirms the queue is clean has done its job.\n\n### Filing a packet: mint its order, never pick one\n\n```bash\ntillandsias-plan next-order          # -> 581-k3f9\n```\n\n**Write the packet to a FRAGMENT, not to `plan\u002Findex.yaml`.** Create\n`plan\u002Findex.d\u002F\u003Cutc>-\u003Csuffix>-\u003Chost>.yaml` with a top-level `packets:` list. Only\nyou can have produced that filename, so git never conflicts and no host waits on\nanother. Reads fold it in automatically — the packet is queryable immediately.\nFragments are IMMUTABLE: to change something, write a new fragment, never edit an\nexisting one (that is what makes the fold order-independent).\n\n### Prose NEVER passes through argv (order 971-7muc)\n\n```bash\ntillandsias-plan append-event \u003Cref> \u003Ctype> --summary-file NOTE.md --host \u003Chost>\ntillandsias-plan append-event \u003Cref> \u003Ctype> --summary-file -  --host \u003Chost> \u003C\u003C'EOF'\n...prose...\nEOF\n```\n\n**Note the QUOTED heredoc delimiter — `\u003C\u003C'EOF'`, never `\u003C\u003CEOF`.** An unquoted\ndelimiter expands backticks and `$(...)` inside the body, which is one of the two\nways this defect actually happened.\n\nWHY, and it is worth the four lines because every instrument we have says the\nwrite succeeded. Prose passed as a shell argument is rewritten by the shell\n*before* `tillandsias-plan` starts, and the damage is unrecoverable by then:\n\n```text\n\"the `accel_mem_budget_gb` field\"   ->   argv receives:   \"the  field\"\n```\n\nBoth backticks and the word between them are gone. Two hosts lost the SUBJECT of\na sentence to this on one evening (964-r98h, 970-7fqk), and `validate-yaml`,\n`tillandsias-plan check`, the fragment-keys guard and `.\u002Fbuild.sh --check` all\npassed the result — because valid YAML carrying plausible prose is exactly what\nthe corruption produces. It bites hardest on the most valuable writes: prose that\nquotes an identifier is prose explaining *why* something is named what it is, and\nbackticks are how anyone writes that.\n\n`--summary-file` is read by the process itself, so no shell ever sees the bytes.\nThe argv path still exists and now REFUSES text carrying expansion residue (an\nunbalanced backtick, a literal `$(`) — but understand what that can and cannot\ndo: a *balanced* substitution leaves no trace at all, so the refusal is a\nbackstop, not a guarantee. The file is the guarantee.\n\nPinned by `scripts\u002Ftest-ledger-prose-roundtrip.sh`, which asserts byte-identity\nfor text containing backticks, `$(...)` and `$VAR`.\n\n### Multi-line `perl -0pi` edits are FORBIDDEN on this tree (hard rule, 2026-09-04)\n\nThree source corruptions in one day, all the same shape: a multi-line\n`perl -0pi -e 's|...|...|'` edit landed its replacement inside a file's\nHEADER COMMENT (accel_probe.rs twice, a fixture header once) instead of at\nthe intended site, the line count stayed plausible, and only the compiler or\na read of the diff's DELETIONS caught it. The author had filed the warning for\nthe fleet at 11:49Z and hit it twice more in the same afternoon.\n\nEdit by exact-match, single-string replacement only: the Edit tool, a\n`python3` script that asserts the anchor occurs exactly once before writing,\nor `sed` on ONE addressed line. After any scripted edit, read the diff's\nremoved lines before committing, not the count of them. A tool whose failure\nmode is \"plausible file, wrong place\" is not a tool for a tree whose gates\ngrep for shapes.\n\n**Never compute \"the next free order\" yourself.** That number comes from a\nledger snapshot which is stale the moment another host commits, so two hosts\nfiling in the same window pick the SAME number deterministically. It happened\ntwice on 2026-07-31 (560–562, then 568–570), and six collisions sit at HEAD.\n\nThe minted token is **permanent**. Do not renumber it later, and do not ask a\ncoordinator to \"normalize\" it — order tokens leak into code comments, `@trace\norder:` headers, and commit messages, and a pushed commit message can never be\ncorrected. Two hosts landing on prefix `575` produce `575-k3f9` and `575-m2p1`:\nboth correct, both permanent, nothing to reconcile. A shared prefix is normal.\n\nCite `packet_id` in anything durable — depends_on, specs, methodology, commit\nmessages. It is the identity and is unique by construction; the order token is a\nhuman convenience. Canonical: `methodology\u002Fdistributed-work.yaml` →\n`order_id_allocation`.\n\n### Reduce: smaller, simpler, verifiable packets\n\nFiling is only the intake half. Each recurring cycle then *reduces* open\nfindings:\n\n1. Pick the highest-value open finding that fits this host's capability.\n2. Split it into the smallest packet that closes a slice of it under a\n   **verifiable constraint** — a litmus test, an executable check returning a\n   pass\u002Ffail exit code, or a parser\u002Fvalidator — never prose intent alone. A\n   guard only an attentive agent honors is a suggestion, not a constraint;\n   reduce it to something that fails loud on its own.\n3. Promote that packet into `plan\u002Findex.yaml` as a `ready` node with a named\n   verifiable closure, then drain it when a capable host can produce evidence.\n4. When the verifiable check passes, the slice is retired; re-derive the\n   remaining residual and repeat.\n\nReduction is monotonic: each step must lower residual uncertainty or preserve it\nwhile increasing verification level (`convergence.yaml` → `drift_control`). A\n\"reduction\" that adds ambiguity or removes a validated invariant is drift and\nmust be rejected. Shaping a finding into a well-formed `ready` packet *is* a\nvalid reduction step when the current host cannot yet implement it.\n\n### Raising the bar is Tlatoāni-gated (do not self-escalate)\n\nThe scan bar is a fixed, declared depth. Reducing all open findings to zero **at\nthe current bar is a legitimate, clear convergence point** — a fixed point of\nthe refinement operator — not premature convergence. The loop MUST NOT raise the\nbar on its own. Autonomous bar-raising would make the convergence point\nundefined (the loop could never report \"done\"), which is exactly the failure\nthis rule prevents. See `methodology\u002Fconvergence.yaml` → `bar_raise_governance`.\n\nWhat the loop does as it approaches zero residual at the current bar:\n\n1. Keep reducing open findings at the current bar until none remain.\n2. Then *propose* bar-raise candidates — file them as `research\u002F` or\n   `exploration\u002F` issues describing the deeper scan that could be enabled (e.g.\n   treat build\u002Ftest\u002Fruntime warnings, non-fatal errors, deprecation notices,\n   flaky-test signals, slow steps, or stale caches as findings). A proposal is a\n   candidate, not an enabled scan.\n3. STOP there. Enabling any bar-raise — actually treating a deeper signal class\n   as findings — is an explicit, one-off decision that **The Tlatoāni must\n   approve every time.** Record the approval (who\u002Fwhen\u002Fscope) before the deeper\n   scan becomes part of the loop's contract.\n\nRationale: much of the system is \"build what works, then improve from there,\" so\neach bar-raise is a deliberate scope expansion the operator owns, not an\nemergent behavior. Automatable approval of *some* low-risk bar-raises may come\nlater; until The Tlatoāni declares such a policy, every bar-raise is manual.\nReaching zero at the current bar and filing bar-raise candidates is a complete,\nsuccessful cycle — not an excuse to escalate unprompted.\n\nSee `plan\u002Fissues\u002Fmeta-orch-enhancement-opportunities-2026-06-20.md` for a worked\nexample of capture → reduce → promote.\n\n## When the Gate Fails, Read check-logs.jsonl FIRST\n\n`.cache\u002Fconvergence\u002Fcheck-logs.jsonl` holds a per-run verdict for every check,\ngoing back weeks. It is the authoritative record of what failed and when.\n`scripts\u002Fconvergence-log-path.sh` prints its path and honours\n`TILLANDSIAS_CHECK_LOG_INDEX`. It lived at `target\u002Fconvergence\u002Fcheck-logs.jsonl`\nuntil order 888-vgs8: Finalization 9c's `cargo clean` removes `target\u002F`\nwholesale, so the sweep this skill mandates was erasing the history this\nsection mandates reading, and the sweep's verdict never said so. The first\nresolve after the move adopts a legacy `target\u002F` index once, by copy.\n\nDo NOT diagnose from terminal scrollback. The next run overwrites the per-check\nlogs under `target\u002Fconvergence\u002Fcheck-logs\u002F` (those still go with a sweep), and\nre-running to \"get a better look\" is what destroys the evidence — the re-run\nmay pass, and then the failure is gone.\n\n```bash\njq -r 'select(.status != \"pass\") | \"\\(.ci_run_id)\\t\\(.check_id)\\t\\(.status)\"' \\\n  \"$(scripts\u002Fconvergence-log-path.sh)\" | tail -20\n```\n\n`scripts\u002Flocal-ci.sh` also prints a `Failed checks:` block naming each failure.\nIf you pipe the gate through `tail -N` or a grep filter, you will cut that block\noff and lose the names — this host did exactly that twice on 2026-08-09, spent\ntwo cycles calling an intermittent failure \"unexplained\", and filed a packet on\nthe false premise that the names were unrecoverable (637-df4z, closed\nmis-diagnosed). The answer had been on disk the whole time: `rust-tests` and\n`tray-contract`, two parallel tests racing on `$HOME` and a shared fixture\ndirectory (638-ehzi).\n\nAn intermittent failure is a defect with a schedule, not noise. Treating it as\nnoise is how it survives.\n\n## Reads Go Through MCP First\n\nBefore draining anything: **do not read whole ledgers.** `plan\u002Findex.yaml` is\n31,678 lines and `plan\u002Floop_status.md` is 7,875; pulling either in full to learn\none fact is the largest single consumer of orchestrator context in this loop, and\nit is paid again by every agent on every host every cycle.\n\nAsk `forge-plan` \u002F `project-plan` (`plan_answer`, `plan_next`, `plan_query`,\n`plan_status`, `plan_blocked_by`, `methodology_ask`, `spec_answer`) and\n`project-info` (`search_code`, `grep_code`, `find_files`, `read_file`). Answers\nare cited — keep the citations. For a conversational\u002Fsynthesis status question,\nuse the Local Experts mode (`expert-serve`) — same citations-or-typed-refusal\ncontract as `spec_answer`.\n\nDrop to the filesystem for exactly three reasons, and name the one that applies:\n**unavailable** (MCP down or `confidence=unsupported` — fall back and keep going,\nthen record it so a systematically-refusing expert stays visible);\n**verification** (before any irreversible act, read the CITED SPAN, not the\nfile); **not exposed** (no tool covers it — and if the loop needs it repeatedly,\nthat is a missing tool, so file a packet).\n\nCanonical: `methodology\u002Fdistributed-work.yaml` → `mcp_first_read_path`.\n\n## Worker Drain\n\n#### Writing a validation packet: demand the post-condition AFTER the last MUTATING step\n\nAny packet that asks a host to install, launch, switch channels, or otherwise\nmutate its runtime must require the health check at the **end of everything the\nhost actually does** — not after the last step that felt like the test.\n\nEarned 2026-08-10. A sibling's smoke reported 4\u002F4 PASS on a `HEALTHY --diagnose`\ntaken at 04:32:20, then ran one more mutating step (a downgrade-to-stable \u002F\nrestore-to-unstable round trip), which wedged the control wire at 04:33:27 and\nleft the host in a failed provisioning state for ~25 minutes until the operator\nfound it. Every per-step result was true; the verdict was still incomplete about\nthe host's end state, and a stable promotion was made on it.\n\nTheir own words are the rule worth copying: *\"a post-condition check belongs\nafter the last MUTATING step, not after the last interesting one.\"*\n\nSo a validation packet this loop writes should say, explicitly:\n\n> Final step, after everything above: re-run the health check. If any step after\n> your last health check mutated the host, that check is stale and the run is\n> not finished.\n\n## Stranded-claim sweep (coordinator, every cycle)\n\n```bash\nscripts\u002Fcheck-stranded-in-progress.sh\nscripts\u002Fcheck-landed-but-open.sh\nscripts\u002Farchive-plan-packets.sh\n```\n\n`check-landed-but-open.sh` (1367-emjg) is the other half of the same leak: it\nlists every order a CODE landing on trunk cites in its subject (default window\nten days) whose row is still ready, pending, in_progress or implemented. On\n2026-09-23 that was 21 of 177 landed orders; on 2026-09-28 it found 920-tqhs a\nmonth after its relay landed. Plan-only commits are not landings; `--cite\nmessage` also reads commit bodies, which cite orders as context and triples the\nlist. Report its `summary:landed-but-open:` line beside the stranded one.\n\nA packet in `in_progress` is invisible in BOTH directions: `ready` queries skip\nit so nobody claims it, and burndown does not count it so nobody notices it is\nunfinished. 21 packets were in that state on 2026-08-09 — ~9% of the live\nledger, oldest at order 153 — every one with no progress event ever recorded\n(641-e2qa).\n\nReport the `summary:` line in the handoff. If the count is rising cycle over\ncycle, claims are outliving their cycles and that is the thing to fix, not the\nindividual packets.\n\nAdvisory, never a gate: a packet legitimately in flight right now is\nindistinguishable from one abandoned an hour ago. **Do not bulk-close what it\nreports.** Closing a packet requires checking its exit criteria against the\ntree; guessing marks unfinished work done, which is strictly worse than leaving\nit stranded.\n\n### Cycle batch triage — decide the batch BEFORE draining\n\n```bash\nscripts\u002Fselect-work-batch.sh \u003Clinux|macos|windows|any>\n```\n\nRun this once, at the top of the drain, and take the batch it prints. It selects\nONE epic (`release_target`) and at most `budget` packets from it, so a cycle\ndrains a coherent slice instead of five unrelated subsystems — the scatter that\nmade small packets cost more in orientation than in work.\n\n**THE BATCH IS A STORY, AND THE STORY IS THE UNIT OF WORK — not the packet.**\nTake the whole batch, implement it as one coherent change, and pay the cycle's\nfixed costs ONCE: one build\u002Fverify pass, one loop-status entry, one attestation.\nDo not run `.\u002Fbuild.sh --check` per packet, and do not attest per packet.\n\nWhy this is the rule and not a preference — measured on the fleet 2026-08-16..19:\n\n| commits, 3 days | count |\n| --------------- | ----- |\n| `record(mo-full)` (attestation only) | 155 |\n| `chore(plan)` (ledger bookkeeping)   |  88 |\n| every category of actual product work | single digits each |\n\nOver 5 days that is 127 product-code commits against 457 plan-only, 149\nattestation-only and 219 merge commits. **Every cycle pays the same exit cost\nwhether it carried one packet or eight** — loop-status, attestation record,\nattestation self-check at the new HEAD, and the merges each of those provokes.\nA one-packet cycle spends most of itself on the exit contract. Bundling does not\nmake the overhead smaller; it amortizes it across more delivered work, which is\nthe only lever available without weakening the contract itself.\n\nBudgets, which the selector already implements — do not restate a different\nnumber here, and if this text and `scripts\u002Fselect-work-batch.sh` ever disagree,\nthe SCRIPT is right and this paragraph is stale:\n\n- non-forge hosts: adaptive **6 → 10** (order 682-yiz7, evidence-backed tuning)\n- autonomous \u002F pairing forge cycles: adaptive **4**, or `TILLANDSIAS_CYCLE_BUDGET`\n- unattended litmus runs: 1 (order 707-3x9d)\n\nThis paragraph used to end \"Budget is 1 on forge (order 264) and 3 elsewhere\"\nwhile its own opening sentence said 4 and 6, and the script said 6 → 10. Three\nnumbers for one budget, in one paragraph plus its tool. Agents read the smallest\none, which is how a fleet tuned to 10 spent its nights draining one packet at a\ntime.\n\nIt is minimax-ranked (largest residual first, per `convergence.yaml` →\n`minimax_convergence_strategy`), with score-weighted entropy over the top-3.\nThe seed is printed; record it in the loop-status entry so the cycle can be\nreplayed. Budgets are stated ONCE, above — never restate them here.\n\n**THE SEED DOES NOT SEPARATE CONCURRENT HOSTS. Do not rely on it to.** This\nparagraph used to end \"...so coverage spreads over time and two concurrent hosts\ndo not collide on one epic\". The second half is false and was never measured.\nMeasured 2026-08-19 on macuahuitl against the live ledger: three distinct seeds\n(`macuahuitl-`, `yoga-`, `esmeraldinha-20260819`) produced a byte-identical\nbatch — same `epic=socket-audit-master`, same `pick=2\u002F3`, same score, same head\npacket. Two independent reasons, and neither is fixable by reseeding:\n\n- The default seed is `${TILLANDSIAS_HOST_KIND:-host}-\u003Cdate>`\n  (select-work-batch.sh:232). `TILLANDSIAS_HOST_KIND` is set only inside the\n  forge, so every bare-metal host falls back to the literal `host` and they all\n  seed identically. Even when set it is host KIND, so three Linux boxes collide\n  with each other regardless.\n- The `urgent=\u003Cpacket>` override puts one globally-urgent packet at the head of\n  the batch. Urgency is a property of the PACKET, so it is host-independent by\n  construction and preempts the epic pick on every host at once.\n\n**SEPARATION COMES FROM CLAIMING, which is the mechanism that already exists and\nis sitting at zero.** `next`\u002F`select-work-batch` filter to `unleased`, and\n\"leased\" means `status: in_progress`. `expire-claims` (order 672-bz7u) reaps\nclaims older than 24h so a dead host cannot strand work permanently. As of\n2026-08-19 `expire-claims` reports `in_progress=0` — nothing has been claimed at\nall, so every host is offered every packet, and on 2026-08-18 two hosts\nimplemented 798-tk7b six minutes apart (order 814-iyu7, ~4h duplicated).\n\nSo, before you implement anything from the batch — and before a coordinator\nROUTES a row to another host — ask whether a sibling branch already holds it\n(order 1513-pppk):\n\n```bash\nscripts\u002Fcheck-claims-across-branches.sh --batch \u003Corder>...\n# -> claimed-elsewhere:\u003Corder>:\u003Cbranch> per held row, then ok:cross-branch-claims:\u003Cn>\n#    blocked:* means the fold could not be read: do not treat it as \"free\"\n```\n\nA trunk-only read cannot see a claim that sits on osx-next or windows-next\nuntil the relay, and on 2026-09-29 the coordinator nearly re-assigned a row\nanother host had claimed that morning. Then claim:\n\n```bash\ntillandsias-plan set-field \u003Corder> status in_progress \\\n    --host \"$(hostname -s)\" --reason \"claimed for cycle \u003CUTC ts>\"\ngit add plan\u002Findex.d && git commit -m \"claim(\u003Corder>): \u003Chost>\" && git push\nscripts\u002Fcheck-claim-confirmed.sh \u003Corder>\n# -> ok:claim-confirmed:\u003Corder> | refused:claim-not-on-origin | refused:claim-lost:\u003Corder>\n#    | unknown:claim-origin-unreachable (never a pass)\n```\n\nPush the claim BEFORE the work, not with it — an unpushed claim separates\nnobody, and a push that failed quietly (a locked keyring, 2026-09-29) looks\nexactly like one that landed until `check-claim-confirmed` asks origin\n(1493-d93i). Then:\n\n- **Losing the race is normal and cheap.** The ledger is a CRDT; two hosts can\n  claim in the same window. On your next fetch, if another host's claim event\n  for that order carries an EARLIER timestamp (ties broken by lexicographically\n  smaller hostname), you lost: release yours back to `ready` and take the next\n  batch item. Do not both continue — that is exactly 814-iyu7.\n- **Release on exit, always.** Completed work moves to its terminal status.\n  Work you did NOT finish goes back to `ready` in the same cycle you abandon it.\n  Leaving it `in_progress` hides it from `ready` AND from burndown until the 24h\n  reaper runs — 21 packets were stranded that way on 2026-08-09 (641-e2qa).\n  Claiming is only safe because releasing is unconditional.\n\nThe `triage:` line reports `ungrouped=N` — eligible packets with no\n`release_target`. That number is the health of the epic tier itself: when it is\nlarge, selection is degrading toward flat priority order regardless of what this\nscript does. Surface it in the handoff.\n\nCanonical: `methodology\u002Fdistributed-work.yaml` → `cycle_batch_triage`.\n\nWhen choosing the builder role, run `\u002Fadvance-work-from-plan` repeatedly in a `.\u002Fplan` friendly way in fresh cycles until one of these is true:\n\n- no eligible ready work remains for this host;\n- every eligible item is blocked;\n- a terminal failure was filed;\n- the current cycle has already produced a coherent commit and the next packet\n  would exceed the recurring-loop budget.\n\nForge-hosted cycles (`TILLANDSIAS_HOST_KIND=forge`) are the OPPOSITE of\ngreedy — decided by The Tlatoāni 2026-07-10 (order 264), replacing the earlier\n\"drain as many as possible\" exception:\n\n- Drain **as much of the batch as fits the envelope, as ONE story** — bounded by\n  TIME, not by a count. Superseded 2026-08-19 by The Tlatoāni, who set order 264\n  in the first place: *\"that's also why I was asking for bundles of related\n  packets in stories and epics, rather than the 'take a single packet' baked\n  into the .\u002Fmethodology that I've been fighting you to lift.\"*\n\n  Order 264's REASONING survives intact and is the reason this is a time bound\n  rather than a licence: a litmus-launched forge cycle lives inside\n  `litmus:opencode-prompt-e2e-shape` STEP 3's 600s budget, and a cycle that\n  overruns it dies mid-work with nothing pushed. What does NOT survive is the\n  count. \"One packet\" was a proxy for \"fits in 600s\", and it is a bad proxy in\n  both directions: three one-line ledger closures fit easily, and one large\n  packet does not fit at all.\n\n  So the forge asks the envelope question about the STORY, not the packet, and\n  the selector's adaptive budget (4, or `TILLANDSIAS_CYCLE_BUDGET`) is the\n  starting size.\n- Before implementing, estimate whether implement+verify+commit+push for the\n  whole story fits the launch envelope.\n- If it does not fit, do NOT start implementing: **split** the packet into\n  smaller ready child packets (`split_into` pattern), record the shaping\n  events, commit and push. The shaping commit IS that cycle's completed work —\n  a split that lowers residual ambiguity is a valid reduction step.\n- Canonical statement: `methodology\u002Fdistributed-work.yaml`\n  `worker_agent_protocol.forge_cycle_budget`. Interim reliance on step\n  timeouts is tracked by order 265 (forge heartbeat\u002Fliveness signals).\n\nEach worker cycle must obey the non-negotiable exit contract above.\n\n### Node-Closure Claim (avoid duplicated ledger-hygiene work)\n\nBefore re-deriving and closing or hygiene-editing a `plan\u002Findex.yaml` node,\nclaim it so a concurrent cycle does not independently produce the identical edit\n(the idempotent-but-wasteful collision recorded in\n`plan\u002Fissues\u002Fagent-concurrency-collisions-2026-06-20.md`). Run the executable\nclaim instead of eyeballing the ledger:\n\n```bash\nscripts\u002Fclaim-ledger-node.sh claim \u003Cnode-id>   # e.g. release-nix-cache-ref-scoping\u002Fchoose-approach\n```\n\nIt emits exactly one line matching\n`^(claimed|reclaimed|in-flight|released|free):[a-z0-9._\u002F-]+$` and exits `0` when\nthis cycle owns the node (`claimed:`\u002F`reclaimed:`) or non-zero (`in-flight:`)\nwhen a live lease is held elsewhere — in which case skip that node and pick the\nnext eligible one. The lease is an advisory, CRDT-friendly reservation, not a\nmutex on the file: it respects the stable-ID + idempotent-merge preconditions in\n`methodology\u002Fbetween-commits-work-discipline.yaml`, so a missed or expired lease\nnever corrupts state (at worst two cycles converge on the same safe edit).\nRelease with `scripts\u002Fclaim-ledger-node.sh release \u003Cnode-id>` after the closure\nis committed; expired leases (default TTL 4h) are auto-reclaimed. Pinned by\n`litmus:ledger-node-claim-shape`.\n\n### Release-Targeted and Milestone Packets\n\nWorker selection prefers packets carrying `release_target:\n\u003Cmilestone-packet-id>` before the general backlog; a host with no eligible\ntargeted work falls back normally (never idle). `kind: milestone` packets\nare criteria holders — never claim one for implementation; claim children\nand record burndown as progress events on the milestone. Large ambitious\ngoals follow `methodology\u002Fdistributed-work.yaml` →\n`ambitious_milestone_reduction` (fat-agent research → operator-signed\ndecision record → smallest demonstrable rungs → verification): the\ncoordinator mirrors the milestone's burndown in `plan\u002Floop_status.md` each\ncycle.\n\n### Long-Running (multi_cycle) Packets\n\nPackets marked `multi_cycle: true` in `plan\u002Findex.yaml` follow\n`methodology\u002Fdistributed-work.yaml` → `long_running_packets` (plan order 251):\n\n- Claims are **cycle-scoped**; the packet returns to `ready` after each\n  cycle's commit. A `ready` multi_cycle packet with prior progress events is\n  normal, not stalled.\n- Do NOT mark one `done` — even with all exit criteria implemented — until\n  its `verification_required.completion_gate` is satisfied by `verified-by`\n  events from every named agent. Implementation-complete means\n  `phase: verification`, not `completed`.\n- Treat a packet sitting at `phase: verification` as a dispatch item for the\n  named verifier agents and surface it during coordination.\n- The active set is mirrored in `plan\u002Flong-running.md`; keep that view in\n  sync in the same commit as any phase\u002Fstatus\u002Fverification change.\n\n## E2E Gates\n\nRun eligible e2e gates after worker drain:\n\n| Host kind | Local-build e2e | Curl-install e2e |\n|---|---:|---:|\n| linux_immutable | no | yes |\n| linux_mutable | yes | yes |\n| macos | yes | yes |\n| windows | yes | yes |\n\nBefore running any local-build e2e gate, consult the structured host-eligibility\nverdict instead of re-deriving the skip reason in prose: run\n`scripts\u002Fe2e-preflight.sh eligibility`, which prints exactly one line matching\n`^(eligible|skip:[a-z0-9-]+)$`. Proceed with the local-build gate only on\n`eligible`; on any `skip:\u003Creason>` (e.g. `skip:no-podman-user-session` in the\nCowork sandbox, which has no `\u002Frun\u002Fuser\u002F\u003Cuid>`, or `skip:smoke-lock-held` when a\nparent\u002Flocal sibling smoke already owns the host lock) record the verdict once\nand skip the local-build gate without re-litigating it. Pinned by\n`litmus:e2e-eligibility-probe-shape`.\n\nRules:\n\n- Local-build e2e uses `\u002Fbuild-install-and-smoke-test-e2e`.\n- On macOS the local build that gate exercises is\n  `scripts\u002Fbuild-macos-tray.sh` (the `\u002Fbuild-macos-tray` skill wraps it and\n  files findings to `plan\u002Fissues\u002Fmacos-build-findings-\u003CDATE>.md`);\n  `.\u002Fbuild.sh --install` is refused on Darwin by design (723-whrx), so there\n  is no build.sh install path to look for.\n- Published-release e2e uses `\u002Fsmoke-curl-install-and-test-e2e`.\n- Destructive substrate reset is expected setup on Tillandsias smoke hosts.\n  `podman system reset --force` is a precondition for Linux idempotence tests,\n  not a blocker. Do not pause, ask for confirmation, or skip the e2e gate for\n  fear of wiping Podman when `TILLANDSIAS_DESTRUCTIVE_RESET_OK` is unset or `1`.\n  Only treat reset as blocked when the environment explicitly sets\n  `TILLANDSIAS_DESTRUCTIVE_RESET_OK=0`.\n- If the plan records a latest tested release older than the current GitHub\n  release, prioritize curl-install e2e.\n- File every finding as a plan packet; write a PASS report for clean runs.\n- **Host-qualify any report filename another host could produce the same\n  day (1004-fue3).** The smoke runbook once templated its report path from\n  release and UTC date with no host field; two platforms smoking one release\n  on one day collided add\u002Fadd at land time, and the naive resolution — \"take\n  one side\" — silently deleted a platform's result. Name each report or\n  per-host finding with the host baked in (`\u003Chost_kind>-\u003Chost_id>`, or the\n  hostname), never a bare subject-and-date. The smoke template carries the\n  field now; a hand-written findings path (`…-findings-\u003CDATE>.md`, the shape\n  named above for `\u002Fbuild-macos-tray`) still does not, so add it yourself\n  (drill: plan\u002Fissues\u002Ffleet-restart-2026-09-12.md, Two lanes, one report filename).\n\n## Mutable Linux Coordinator Duties\n\nOnly `linux_mutable` performs global coordination:\n\n1. Run `\u002Fmultihost-orchestration` after worker drain or when sibling branches\n   advanced.\n2. Merge eligible `origin\u002Fwindows-next` and `origin\u002Fosx-next` work into\n   `linux-next`, with explicit conflict mediation if needed.\n3. Run more frequent local-build e2e gates than other hosts.\n4. Run `\u002Fmerge-to-main-and-release` only when `linux-next` is green, plan\n   evidence is current, and no release is already in flight.\n   Read the `cloud.usage` MCP tool first (order 1966-47vt): Cloudflare at\n   ≥ 2,700 of 3,000 build minutes this month means no merge to main unless\n   the fix is urgent.\n5. After a release succeeds, ensure the plan records the new latest release so\n   immutable Linux hosts know to run curl-install e2e.\n6. **Move the project's openspec CLI forward deliberately (order 1441-myz3)**.\n   `openspec\u002Fcli-version` is the project's ONE openspec version. Forges install\n   exactly it (`ensure_openspec_pinned`, lib-common.sh) and never refresh it to\n   @latest, so a fresh forge's \u002Fopsx sets match the committed ones and launch\n   leaves the checkout clean. Keeping the pin current is the coordinator's\n   job, once per cycle and cheap when nothing is due. Run it on a CLEAN tree\n   based on `origin\u002Flinux-next` (a `work\u002F\u003Corder>` ref or the coordinator's\n   own checkout), with npm on PATH (host or `tillandsias-builder`):\n   ```bash\n   scripts\u002Fopenspec-pin.sh check    # ok:openspec-pin-current:\u003Cv> | due:openspec-bump:\u003Cpin>->\u003Clatest> | unknown:…\n   scripts\u002Fopenspec-pin.sh bump     # only on due: (or `bump --to \u003Cv>` to re-level at the current pin)\n   scripts\u002Fopenspec-pin.sh drift    # must print ok:openspec-generated-matches-pin before committing\n   ```\n   `bump` installs the new version into a version-keyed cache, runs\n   `openspec update --force` with an ISOLATED openspec config (the profile is\n   derived from the committed workflows, never from the machine running it),\n   writes the pin, and never commits. On `bumped:openspec:\u003Cold>->\u003Cnew>:\u003Cn>-paths`,\n   commit everything it changed as ONE change, subject\n   `chore(openspec): bump CLI \u003Cold> -> \u003Cnew>`, and land it like any work ref.\n   On `review:openspec-bump:…`, stop and read stderr. It names either\n   generated files that still disagree with the pin, or a superseded copy the\n   CLI left behind instead of overwriting (1.13.2: \"Left 11 files in .codex\u002F\n   that differ from the copy in .agents\u002F\"). Remove only the copy the CLI names\n   as superseded, re-run `drift` to ok, and commit that removal in the SAME\n   change. Paths outside the generated surface mean something unexpected\n   happened: do not commit, and file a packet. `unknown:` (registry\n   unreachable) waits for the next cycle. Changing the workflow profile is a\n   separate decision; it is never a side effect of a bump. This is the only\n   sanctioned way the generated \u002Fopsx sets move. Launch-generated dirt is\n   refused (step 4 of Start Of Cycle), never committed.\n\n## Cycle Metrics (report before the handoff)\n\nRun `scripts\u002Fcycle-metrics.sh --cycle-start \u003CStart-Of-Cycle UTC> [\u003Csince-ref>]`\nand include its output verbatim in the final handoff. It emits one `key=value`\nline per block — branch on those, never on prose. `--cycle-start` is the UTC\nyou recorded at Start-Of-Cycle (e.g. `2026-09-04T06:00:00Z`); without it the\n`repeat:` line measures the last three hours, not this cycle.\n\nEvery handoff MUST carry these lines; the two questions they answer are\ndistinct — measure before you optimize:\n\n- **`mcp:`** — \"are the servers used?\" Per-server call volume (`servers=`,\n  `plan-expert-calls=`). Today only the plan expert is instrumented; the other\n  servers are named `uninstrumented-see-682-m8ek`, not faked as zero.\n  Also carries **`health=`** (order 737-zcj5) — `ok` \u002F `down:\u003Ccsv>` \u002F `absent` \u002F\n  `unprobed` — sourced from the health probe, NOT from usage. Call volume cannot\n  see an outage: a server that is down writes no usage rows, and neither does one\n  nobody called, so both render as absence in every count on this line.\n  `health=unprobed` is deliberately not `health=ok`; reporting an unmeasured\n  expert as healthy is the order-531 shape.\n\n- **`mcp_outage:`** — emitted ONLY when a probe recorded a non-up state\n  (`records=`, `health=`, `log=`). Its absence on a healthy cycle is the\n  negative control, not an omission. When present, it is the ledger trace of the\n  outage: the handoff pastes these metrics verbatim and the loop-status entry is\n  built from the handoff, so the outage reaches `plan\u002Floop_status.d\u002F` without any\n  agent choosing to write it down.\n- **`expert_accuracy:`** — \"are the experts RIGHT?\" The groundtruth pass-rate\n  (`pass=\u002Ftotal=\u002Frate=`), graded against the committed rung-1 query set. Distinct\n  from `answer_rate`: an expert can answer every question yet cite spans that do\n  not support the answer. Accuracy is pass\u002Ftotal of graded cases, never call\n  volume. It reads `deferred source=litmus:expert-groundtruth-harness` when no\n  binary can grade in-cycle (then the quick-tier gate carries it).\n\n- **`flow:`** — \"does work-done-per-cycle outrun the fixed per-cycle overhead as\n  batches grow?\" The ROLLING packets-per-cycle view (`cycles=`,\n  `avg_completed_per_cycle=`, `avg_commits_per_cycle=`, `overhead_ratio=`) over a\n  per-host append log. `overhead_ratio` is total commits per total completed\n  packet — the fixed per-cycle cost amortized across the work it produced — and\n  is the number the greedier-batching decision (682-yiz7) consumes: if larger\n  batches amortize overhead, this ratio FALLS as batch size rises. It reads\n  `source=absent` until this host has appended at least one flow record.\n\n  Each cycle MUST append its flow record so the rolling view stays live. Emit it\n  here, right after running `scripts\u002Fcycle-metrics.sh` for the handoff and before\n  Finalization commits — best-effort, the emit never fails the cycle:\n  ```bash\n  scripts\u002Fcycle-metrics.sh --emit-flow \\\n    host=\u003Cthis-host> \\\n    batch_epic=\u003Cfrom select-work-batch `batch: epic=`> \\\n    batch_seed=\u003Cfrom `batch: seed=`> \\\n    batch_size=\u003Cfrom `batch: size=`> \\\n    budget=\u003Cfrom `batch: budget=`> \\\n    claimed=\u003Cpackets this cycle claimed> \\\n    completed=\u003Cpackets this cycle completed> \\\n    filed=\u003Cnew packets\u002Fissues this cycle filed> \\\n    commits=\u003Cfrom cycle-metrics `repo: commits_this_cycle=`> \\\n    plan_open=\u003Copen packet count> plan_total=\u003Ctotal packet count>\n  ```\n\n- **`timing:`** — \"where does the cycle's wall-clock go?\" The ROLLING view over a\n  per-host duration log (`steps=`, `build_check_ms_avg=`, `litmus_ms_avg=`,\n  `slowest=\u003Cstep>:\u003Cms>`). \"Time spent building, testing\" is the most likely\n  bottleneck and was invisible until the build\u002Ftest\u002Flitmus entry points began\n  appending one duration record per heavy step (packet 682-emvg). `build.sh\n  --check` (the local gate), each `scripts\u002Flocal-ci.sh` litmus phase, and each\n  `scripts\u002Frun-litmus-test.sh` suite now self-instrument — best-effort, the\n  timing write never changes the wrapped step's exit code or output. It reads\n  `source=absent` until this host has run one instrumented step. `slowest` names\n  the single step to attack first.\n\n- **`repeat:`** — \"which steps were paid REPEATEDLY inside THIS cycle?\" The\n  within-cycle count view over the same timing log (`window=`, `steps=`,\n  `top3=\u003Cstep>=\u003Ccount>,...`), order 1001-q3zf. Count, not duration: a gate\n  re-run after every rebase costs its duration TIMES the rounds, and only the\n  product is actionable. Pass `--cycle-start \u003Cyour Start-Of-Cycle UTC>` (or\n  export `TILLANDSIAS_CYCLE_START_TS`) so the window is this cycle and not the\n  default last three hours: `scripts\u002Fcycle-metrics.sh --cycle-start\n  2026-09-04T06:00:00Z`. Reads `source=absent` when the timing log is missing.\n\n- **`recur:`** — \"which steps are paid on EVERY cycle, and what do they cost\n  cumulatively?\" The cross-cycle view over the last 7 days (`window=`, `runs=`,\n  `steps=`, `top3=\u003Cstep>:runs=\u003Cn>:total_ms=\u003Ct>:avg_ms=\u003Ca>:fail_pct=\u003Cp>,...`),\n  ranked by total_ms — a cheap step paid three hundred times outranks an\n  expensive one paid twice. Step names contain colons (`step:...`,\n  `check:litmus-pre-build`), so parse an entry FROM THE RIGHT: the trailing\n  `:key=value` fields never contain a colon; the step is everything before the\n  first `:runs=`.\n\n- **`skippable:`** — \"which expensive, repeated, outcome-invariant steps could\n  be memoised or skipped?\" This is the operator's instrument for \"repeated work\n  that wastes every cycle \u002F expensive work that may be cached or skipped\"\n  (2026-09-03). A candidate ran at least `min_runs=` times, averaged at least\n  `floor_ms=`, and NEVER changed outcome in the window, so every run after the\n  first bought no information. Entries are\n  `\u003Cstep>:runs=\u003Cn>:avg_ms=\u003Ca>:fail_pct=\u003Cp>:saved_ms_upper=\u003Cs>`, parsed from the\n  right like `recur:`. **`saved_ms_upper` is a BOUND, not a saving** —\n  total_ms minus one run; the log carries no input identity, so nothing here\n  can say a run WOULD have hit a cache. Paste it as a bound. Do not file a\n  skip-or-memoise packet from one host's reading: the coordinator's cross-host\n  recurrence audit (coordinate-multihost-work) acts only when the same step\n  tops `skippable:` on two or more hosts.\n\nThe two lines worth reading first:\n\n- **`answer_rate`** — the experts' USEFULNESS. Not call count. An expert called\n  two hundred times that refuses two hundred times is heavily used and\n  completely useless, and a call counter reports that as healthy adoption. That\n  is not hypothetical: order 531 had every `plan_answer` returning\n  `confidence=unsupported` (the forge was seeded from a pre-expert branch) while\n  launch state truthfully reported `experts: ready`.\n- **`verdict`** — the single fact to look at first. `attention:` is not a\n  failure; it is the cycle naming its own weakest point.\n  `attention:expert-answered-nothing-check-base-branch` is the order-531\n  signature and means the ARTIFACT is wrong, not that the questions were hard.\n\nTwo rules about these numbers:\n\n- **Never report a metric the tooling did not produce.** `experts_substitution`\n  reads `unknown` because it needs the agent harness's tool log, which is not in\n  this repo. Leave it unknown. An estimated number makes an unmeasured thing\n  look measured, which is worse than reporting nothing.\n- **Never propose making expert metrics reward activity.** `answered` is\n  reachable only via citations the compiled expert emits when it resolved a real\n  packet or path, so calling tools more cannot raise the rate. A change that\n  lets `answered` be reached without citations converts a quality signal into a\n  volume signal and must be refused on that ground.\n\n## Finalization\n\nBefore exit:\n\n1. Reduction-engine capture check: confirm every \"this isn't great\" observation\n   from this cycle is filed in `plan\u002Fissues\u002F` (classified `research\u002F`,\n   `exploration\u002F`, `enhancement\u002F`, or `optimization\u002F`) and, where reduced,\n   promoted to a `plan\u002Findex.yaml` packet. An unfiled finding blocks exit. A\n   dirty-start preflight refusal performs no reduction cycle; it uses the final\n   handoff exception above and exits without touching the checkout.\n2. Refresh `plan\u002Findex.yaml` if this cycle changed active work, blockers,\n   tested release, or host assignments. Record THIS cycle's status as a NEW\n   `## Cycle` fragment in `plan\u002Floop_status.d\u002F` via\n   `tillandsias-plan loop-status-append --host \u003Chost> --ts \u003CUTC-ISO> --file fragment.md`\n   (`\u003C fragment.md` and a bare path also work; order 1004-8vkv) — never\n   edit the shared `plan\u002Floop_status.md` directly, or a concurrent host's\n   status write conflicts for the same reason the old monolithic ledger did\n   (packet 582-nqw5). The folded view (`tillandsias-plan loop-status`) is the\n   status every host sees; `loop-status-compact` folds fragments into the base\n   when drift makes it eligible.\n\n   **A long cycle's `--ts` legitimately predates its write, and `--backfill` is\n   the sanctioned path for it (order 801-w4pn).** `--ts` must agree with the\n   host clock within 900s or the write is refused; a cycle that read the clock\n   at Start Of Cycle and appends at Finalization two hours later trips that by\n   construction. Do not widen the window and do not invent a fresh timestamp —\n   the limit is what catches a fabricated hour, and re-reading the clock would\n   silently relabel when the work happened. Pass `--backfill` with the real\n   timestamp, or omit `--ts` entirely when \"now\" is genuinely the right stamp:\n\n   ```bash\n   tillandsias-plan loop-status-append --host \u003Chost> --ts \u003Ccycle-start-UTC> --backfill --file fragment.md\n   ```\n\n   THE FRAGMENT MUST BE SUPPLIED EXPLICITLY. `--file \u003Cpath>`, `\u003C path` and a\n   bare path argument all work. Before order 1004-8vkv a bare path was silently\n   dropped and the command fell through to stdin, which on an inherited socket\n   (a forge agent's stdin, by construction) blocked for 26 minutes at 0.0%% CPU.\n   It is now refused in 5s naming the explicit forms, but supplying the input\n   explicitly is still the invocation to type.\n\n   `--backfill` only reaches BACKWARD (a future `--ts` is still refused), so it\n   waives nothing the limit exists to protect, and the refusal already names it.\n2b. **Ask which litmus specs cover the files you touched** (order 748-tkjx),\n   BEFORE the gate rather than after the next host finds the red:\n\n   ```bash\n   scripts\u002Flitmus-covering-specs.sh --run --changed      # the specs to re-run\n   scripts\u002Flitmus-covering-specs.sh \u003Cpath>...            # one file, with detail\n   ```\n\n   `.\u002Fbuild.sh --check` runs NO litmus (deliberate — the suite is minutes, and\n   a gate that slow gets bypassed with `--no-verify`), so a green gate plus the\n   spec you happened to be working in can both pass over another spec's broken\n   pin. That is measured, twice: on 2026-08-15 an edit to\n   `images\u002Fdefault\u002Flib-common.sh` left `litmus:startup-context-addendum-shape`\n   red through a green `--check` and a passing 7\u002F7 run of the agent's own spec;\n   on 2026-08-28 three tests were found red back to `af745f3fd` only because a\n   full suite happened to run (921-vtf4). `lib-common.sh` alone is covered by\n   twelve specs across four lanes.\n\n   ADVISORY and cheap (~90ms over the whole corpus, no build). It answers from\n   committed data — each test's declared `workspace contains` artifacts plus its\n   commands — so there is no second list to drift. `match:declared` is an\n   authored coverage claim, `match:command` is coverage the preconditions never\n   declared; `binding:unbound` means no spec binds that test, so it executes in\n   no suite (885-92iu) and is excluded from the count and from `--run`. A path\n   no litmus references answers `ok:litmus-coverage:0-spec(s)` and nothing\n   else — an editor of an uncovered file is not nagged.\n\n2c. **Report split parents still competing with their own children**\n   (order 750-zrt4):\n\n   ```bash\n   tillandsias-plan split-parents   # parent\u003CTAB>status\u003CTAB>child:status,...\n   ```\n\n   A packet whose work has been split keeps `ready` and gains a `split_into`\n   list, and only `ready` is claimable — so a fully-delegated parent stays in\n   the pool forever. Measured 2026-08-14\u002F15: `select-work-batch.sh linux`\n   reported `urgent=mirror-identity-lane-sidecar-and-sshd` on four consecutive\n   cycles and no host claimed it (eleven design rungs behind a 3-hour\n   estimate), while one level up 606-bvnp ranked #1 claimable with all four\n   slices already spoken for. Both were fixed by hand, which depended on an\n   agent noticing a four-cycle stall.\n\n   REPORTS ONLY — it names the children and their statuses so you can see where\n   the work went, and changes nothing. Resolve one by setting the parent\n   `blocked` with an event naming the children (accurate: it cannot progress\n   without them), or, if it genuinely retains work of its own, declare\n   `retains_direct_work: true`. **Never `obsoleted`** — that status satisfies\n   dependents and would falsely unblock work that is still waiting on the\n   rungs.\n\n3. Validate touched YAML with a parser, using the one that EXISTS where you are:\n   `tillandsias-policy validate-yaml \u003Cfiles>` where built, else\n   `yq . \u003Cfile> >\u002Fdev\u002Fnull`, else `ruby -ryaml -e \"YAML.load_file('\u003Cfile>')\"`.\n   **`ruby` is NOT in the forge image; `yq` is** — a skill that names only ruby\n   sends a forge agent to a tool that does not exist, and the tool sitting next\n   to it is `python3`, which is FORBIDDEN for committed automation (see\n   `plan\u002Fissues\u002Fmeta-orch-enhancement-opportunities-2026-06-20.md` order 63).\n   Its presence on PATH is not permission. The forge startup context lists what\n   is actually available.\n3b. **Re-verify the credential BEFORE the gate** (order 892-aw9p):\n\n   ```bash\n   scripts\u002Fcheck-credential-channel.sh reverify\n   ```\n\n   The Start-Of-Cycle guard runs once and cannot see a credential that dies\n   afterwards. MEASURED on calmecacpilli 2026-08-25: it returned\n   `ok:gh-keyring-push-verified`, two pushes succeeded on that credential, and\n   ~50 minutes later the third failed with `remote: Invalid username or token`.\n   Nothing the guard measured was wrong — the verdict was true when issued. Its\n   RESULT simply outlived the thing it checked, which is the same shape as a\n   stale gate stamp (887-bz88).\n\n   Run it HERE, immediately before `.\u002Fbuild.sh --check`, because that is the\n   last point where the remaining cost is still worth saving: a dead credential\n   then costs the gate's wall-clock (40s here, 276s on the slowest host) instead\n   of being discovered after it, with the work done and the exit contract\n   forbidding an unpushed exit. Not per push — the healthy path must not pay a\n   round trip for every git operation, and a guard slow enough to notice is a\n   guard that gets bypassed.\n\n   On `blocked:credential-expired-mid-cycle` the credential WORKED and then\n   stopped; that is distinct from never having had one, and the printed remedy\n   is the OPERATOR re-seeding the token (`tillandsias --github-login`), not\n   seeding a store. An agent never runs `gh auth refresh` or `gh auth login`\n   itself (1025-a896: a re-auth on one host evicts the token on every other;\n   1497-ahmd corrected the guard, which used to print it). Do NOT discard the\n   cycle's work to get unstuck — salvage first (872-c9nd) and report blocked\n   with the salvage ref.\n\n3c. **EVERY LEDGER WRITE HAPPENS BEFORE THE GATE, NOT AFTER IT** (yolanda,\n   2026-09-02). The gate stamp hashes the CONTENT of every tracked and\n   untracked file in the worktree, so a ledger write after a green gate\n   creates a new `plan\u002Findex.d\u002F` or `plan\u002Floop_status.d\u002F` file, moves the\n   digest, and the pre-push hook then refuses a tree whose CODE the gate\n   validated perfectly. Order your Finalization so that `append-event`,\n   `set-field`, `loop-status-append` and any issue file all land FIRST,\n   then gate once, then commit and push.\n\n   MEASURED: three extra full gates in one cycle on windows, about 25\n   minutes, plus a fourth on this host the same day. Both agents\n   rediscovered the ordering by trial; it was written down nowhere, which\n   is why it is here now rather than in a message that scrolls away.\n\n   The one exception is the attestation ledger, which CANNOT precede the\n   gate — `record` attests the head that finalization produces. That is\n   why step 9 re-verifies and re-derives; it is not a second chance at\n   the gate.\n\n   DO NOT diagnose this from the refusal message: it lists paths whose\n   MTIME is newer than the stamp, while the decision is made on CONTENT.\n   A merge or a regeneration that rewrites bytes identically appears in\n   that list without being the cause, and the file that actually moved\n   the digest may not appear at all. `scripts\u002Fgate-stamp.sh verify` is the\n   authority.\n\n\n   **USE THE ONE COMMAND THAT DOES 4-6 IN THE RIGHT ORDER** (order 859-4jny,\n   discoverability gap found 2026-09-03):\n\n   ```bash\n   scripts\u002Fland-on-platform-branch.sh [branch] [attempts]   # -> ok:land:\u003Csha>:attempt-N\n   ```\n\n   It fetches, rebases, GATES, pushes, and then PROVES the commit landed by\n   asking the remote (`git merge-base --is-ancestor HEAD origin\u002F\u003Cbranch>`) —\n   because neither a zero exit status nor a `\u003Cbranch> -> \u003Cbranch>` line in the\n   output is sufficient evidence, and both have reported LANDED for a refused\n   push. It refuses non-retryable failures at once with their remedy (auth) and\n   retries only a lost race.\n\n   **Never read a land or gate verdict through a pipe (1137-da83).** Three\n   false claims in one hour on two hosts: `scripts\u002Fland-on-platform-branch.sh\n   … | tail -25` read as exit 0 when the land had exited 3 and named its gate\n   log — the tool was nearly filed against for the defect its header exists\n   to prevent — and `tasklist … | head -2; echo rc=$?` reported `head`'s\n   status, published to a peer as a two-host difference that did not exist.\n   Capture the command's own status (`out=\"$(cmd 2>&1)\"; rc=$?`) or `set -o\n   pipefail`. If you use PIPESTATUS, snapshot the array as the very next\n   command (`ps=(\"${PIPESTATUS[@]}\")`); any intervening command resets it,\n   and the one everyone writes — `a=$?; b=\"${PIPESTATUS[0]}\"` — yields 0 and\n   0. On Windows, `$?` through `wsl.exe -d \u003Cdistro> -- bash -lc` from Git\n   Bash is always 0 (1155-jurn): canary `false; echo \"$?\"` before trusting\n   any status through it (drill: plan\u002Fissues\u002Ffleet-restart-2026-09-12.md, What the pipe-verdict fixture found — extends the coordinator's rule entry below, which named this fixture as its follow-up).\n\n   WHY THIS IS NAMED HERE AND NOT LEFT TO BE DISCOVERED. Steps 4, 5 and 6 are\n   three manual acts whose ORDER is the whole contract, and a host that\n   hand-rolls them can invert them. That is not hypothetical: on 2026-09-03 a\n   forge inverted gate-and-push TWICE in one session — once under real urgency\n   (an ephemeral container, work not yet durable) and once with no urgency at\n   all — while spending that same session filing defects about instruments that\n   report success without measuring anything. Its improvised loop\n   (`fetch && rebase && push`) had NO GATE IN IT BY CONSTRUCTION.\n\n   The tool that cannot make that mistake had existed since 859-4jny and this\n   skill named it ZERO times, so every host was taught the hand-rolled ritual\n   and none were taught the safe one. Documentation was not the gap and neither\n   was discipline: the host had run `salvage-dirty-worktree.sh` earlier in the\n   same cycle, so it was not unaware of its tooling. **Push is what \"I am done\n   with this\" feels like**, and the action that feels like finishing must be the\n   action that is correct — so the finishing command is named here, first,\n   before the three steps it replaces.\n\n   Fall through to 4-6 by hand only when this refuses for a reason it names.\n4. Run the local gate: `.\u002Fbuild.sh --check` and fix what it reports.\n   An unparseable or unformatted push poisons every downstream clone. Push CI\n   no longer exists on any working branch — only the manually-dispatched\n   release workflow remains (litmus:github-actions-budget) — so this gate is\n   the ONLY trunk protection. Do not push past a red gate (evidence case:\n   `plan\u002Fissues\u002Flocal-gate-evidence-query-packets-clippy-2026-08-09.md`).\n\n   Terminology (851-gpb5): this skill called this step \"the pre-push gate\"\n   for months while methodology used the SAME name for a different rule —\n   the step-6 merge below — and the collision kept that rule invisible.\n   Here \"local gate\" always means `.\u002Fbuild.sh --check`; \"pre-push gate\" is\n   reserved for methodology's `pull_merge_cadence.pre_push_gate`.\n5. Commit targeted files only.\n6. Satisfy methodology's pre-push gate (`pull_merge_cadence.pre_push_gate`,\n   `methodology\u002Fmulti-host-development.yaml`), then push the relevant branch.\n   On a non-`linux-next` branch (`osx-next`, `windows-next`, any shared\n   non-trunk branch; `agent\u002F*` and `salvage\u002F*` are exempt) that gate\n   requires, before EVERY push — not just at cycle start:\n\n   ```bash\n   git fetch origin && git merge origin\u002Flinux-next   # resolve conflicts locally\n   ```\n\n   The v5 pre-push hook enforces the merge half on the two platform branches\n   (`scripts\u002Fhooks\u002Fpre-push-linux-next-merged.sh`, installed by\n   `scripts\u002Finstall-hooks.sh`); the fetch half stays yours — the hook can\n   only compare against the `origin\u002Flinux-next` your last fetch recorded. If\n   the hook refuses, merge and push again; never `--no-verify` past it.\n7. If a startup boundary was recorded, run the guard's `verify` mode. A guard\n   failure is a blocker: do not attempt destructive Git cleanup. Finalization\n   never deletes, restores, or resets a worktree path.\n\n   **Do NOT remove `$boundary_dir` here** (order 725-bu54). Retirement belongs\n   to the NEXT cycle's `snapshot`, which retires the previous boundary before\n   taking its own. Removing it here treats this Finalization as THE end of the\n   cycle — but an operator-driven loop has no single exit, and a cycle that\n   continues after a completed Finalization then finds its own boundary gone\n   and cannot attest. That happened twice in one night and cost a valid marker.\n\n   Re-running `verify` after further commits is correct and expected: it still\n   compares against the boundary taken BEFORE any work, and re-stamps the head\n   it observed so the marker matches what was actually pushed.\n8. Confirm there are no uncommitted changes created by this cycle and the\n   branch is not ahead of upstream. Pre-existing dirty paths may remain only\n   when the boundary guard verifies they are byte-identical to startup.\n\n   Then prove the cycle's FINDINGS survive it (order 741-3y48):\n\n   ```bash\n   scripts\u002Fcheck-forge-findings-persisted.sh\n   ```\n\n   A GATE, not advisory — non-zero means work already done is about to be thrown\n   away. It covers `plan\u002Findex.d\u002F`, `plan\u002Floop_status.d\u002F`, `plan\u002Fissues\u002F` and\n   `plan\u002Fmo-full-attestations.d\u002F`, and it catches what `git status` cannot: a\n   COMMITTED fragment that was never pushed presents as a clean tree and is one\n   teardown from gone. That is not hypothetical — on 2026-08-15 an in-forge\n   review filed three valid fragments, `tillandsias-plan check` accepted them,\n   and the container took all three with it; they survived only because a human\n   happened to be reading stdout. A cycle that files nothing prints\n   `ok:no-findings` and is silent, so a clean run stays quiet.\n\n   This matters most inside a forge, where the checkout is a clone that dies with\n   the container — but it is correct everywhere, and an unattended host that\n   commits without pushing loses the same work to the next `git reset`.\n9. Record the verified marker durably, then emit the terminal marker (orders\n   614-2gqx + 651-2x5s) as your FINAL output line. `record` derives-and-verifies\n   the marker exactly as `self` does and appends the verified line to the\n   per-host ledger (`plan\u002Fmo-full-attestations.d\u002F\u003Chost>.md`) so automation can\n   consume a real, reachable hash without parsing a transcript. The ledger\n   line attests the WORK head; committing it advances the head, so re-run the\n   guard `verify` (permitted: further commits are expected, step 7) and\n   re-derive ONCE more — the terminal marker must name the head that CONTAINS\n   the ledger record:\n   ```bash\n   # RUN `record` ONLY AFTER THE WORK PUSH HAS ACTUALLY SUCCEEDED, and check\n   # that it wrote. MEASURED on lenovinha 2026-09-03: `record` ran while HEAD\n   # was still unpushed and CORRECTLY REFUSED; a push-retry loop then landed\n   # the work WITHOUT re-running `record`; and the terminal `self` printed\n   # COMPLETE, because by then local and remote agreed. So the emitted marker\n   # was VALID and the durable ledger line — the thing automation actually\n   # consumes — was never written. A green marker is not evidence the ledger\n   # was appended.\n   #\n   # THE TRAP IS THE RETRY LOOP, not the ordering as written here: step 6\n   # already pushed, so this recipe is correct on the happy path. Insert a\n   # fetch\u002Frebase\u002Fretry between the push and `record` — which every host does\n   # on a busy trunk — and `record` is silently skipped on any iteration that\n   # refused. Re-run `record` after the LAST successful push, not the first\n   # attempt.\n   #\n   # THIS IS NOW ENFORCED, NOT ONLY ADVISED (order 974-uk95). `self` refuses a\n   # COMPLETE marker unless THIS cycle wrote a durable record: `record` stamps\n   # the head it recorded, the boundary guard's `snapshot` clears that stamp at\n   # Start Of Cycle, and a marker whose HEAD does not descend from a recorded\n   # head is refused. So the skipped-record case now fails LOUDLY — no marker,\n   # which every outer launcher already treats as failure — instead of printing\n   # a valid marker beside an empty ledger. BLOCKED is exempt: a cycle saying it\n   # did not finish must still be able to say so.\n   #\n   # The ordering is still yours to get right. The guard catches a skipped\n   # record; it cannot make a retry loop call `record` for you.\n   #\n   # AUDIT IT THE WAY THEY CAUGHT IT: grep the ledger for this cycle's head\n   # rather than trusting the marker.\n   #   grep -c \"$(git rev-parse HEAD)\" plan\u002Fmo-full-attestations.d\u002F\u003Chost>.md\n   # Expect the WORK head to appear, not the record commit's own head — the\n   # ledger line attests the work and committing it moves HEAD, which is why\n   # the terminal marker is re-derived one commit later.\n   scripts\u002Fmo-full-attest.sh record                                  # verify + append + print the marker\n   git add plan\u002Fmo-full-attestations.d\u002F && git commit -m \"record(mo-full): attest \u003Cbranch> cycle\"\n   git push\n   scripts\u002Fmeta-orchestration-worktree-guard.sh verify \"$boundary_dir\"   # re-stamp the new head\n   scripts\u002Fmo-full-attest.sh self                                   # terminal marker at the head containing the record\n   ```\n   Emit the FINAL `self` line verbatim as your final line — do not retype or\n   edit it. If any step prints `MO-FULL: FAIL …` and exits non-zero, do NOT\n   emit a marker — treat it as a blocker (a missing marker is itself the loud\n   failure). The ledger line and the emitted line differ by exactly the\n   bookkeeping commit; both are real commits the local gate\n   (`scripts\u002Fcheck-mo-full-attestations.sh`) verifies exist and are reachable.\n   This gives EVERY full-mode lane the same convergence verification the\n   litmus launcher's `check` applies to its one lane, and leaves a durable\n   record that outlives the transcript. The marker is the machine attestation\n   that finalization steps 1-8 all passed; the outer launcher rejects exit\n   zero without it. See \"Full-Mode Terminal Attestation\" above for the grammar\n   and invariants.\n\n9b. Release the checkout lock (order 873-zcim) — AFTER the terminal marker is\n   derived, as the cycle's last mutation:\n   ```bash\n   TILLANDSIAS_CYCLE_HOLDER_PID=$PPID scripts\u002Fcycle-checkout-lock.sh release\n   ```\n   The stale-reclaim bound (dead holder, or 3h) covers a cycle that dies\n   before reaching this line, so a crashed cycle cannot silence the cadence —\n   but do not lean on it: an explicitly released lock frees the checkout NOW,\n   a reclaimed one frees it up to three hours later, and on a 30-minute\n   cadence that is six skipped fires.\n\n9c. Reclaim the build cache when it is genuinely due (order 709-in2f,\n   methodology `build_cache_hygiene`) — LAST, after the lock is released, so a\n   full rebuild's cost is paid in the idle gap rather than inside the cycle:\n\n   ```bash\n   scripts\u002Fcheck-build-cache-sweep.sh   # exit 0 = NOT due; skip the body\n   ```\n\n   **Read the exit polarity before wiring anything to it.** It exits **0 when\n   the sweep is NOT due**, the same convention as `check-deslop-due.sh` and\n   `check-daily-maintenance.sh`: the actionable state is the non-zero one, so a\n   healthy steady state stays quiet under `set -e`. Branch on the verdict token\n   (`build-cache-sweep-not-due` \u002F `build-cache-sweep`), which a copy-paste\n   cannot invert.\n\n   Due when `target\u002F` exceeds 40 GiB, OR the marker is older than 14 days, OR\n   the marker is absent\u002Funreadable. On `due:`, run `cargo clean` (plus\n   `scripts\u002Fnix-toolbox.sh gc` where nix is present — never a bare\n   `nix store gc`, which would delete the whole persistent cache rather than\n   prune it), then stamp what actually ran:\n\n   ```bash\n   scripts\u002Fcheck-build-cache-sweep.sh stamp --host \u003Chost> \\\n       --action 'cargo-clean:\u003Cresult>,nix-gc:\u003Cresult>'\n   ```\n\n   `--action` is REQUIRED, for the same reason `check-daily-maintenance.sh`\n   requires `--steps`: a stamp recording that \"something happened\" without\n   recording what moves the unfalsifiability up a level instead of removing it.\n   Record `skipped-absent` \u002F `deferred-\u003Creason>` honestly.\n\n   The convergence check log — the file \"When the Gate Fails\" above orders\n   you to read FIRST — is NOT in `target\u002F` since order 888-vgs8: it lives at\n   `.cache\u002Fconvergence\u002Fcheck-logs.jsonl`, resolved by\n   `scripts\u002Fconvergence-log-path.sh`, so this sweep no longer erases the\n   failure history. The per-check logs under `target\u002Fconvergence\u002Fcheck-logs\u002F`\n   do go with it, as they always did; they are overwritten every run anyway.\n\n   BEST-EFFORT, NEVER A GATE: a failed sweep must not fail the cycle, and the\n   sweep must not run before the work. Ephemeral forges read `skip:forge-exempt`\n   and never sweep — their `target\u002F` dies with the container.\n",{"name":5,"description":7},"main","bf1668fd1df1b3363b826d083f060234cd2e1d0c","skills\u002Fmeta-orchestration",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:48:35",{"source":8,"skillName":5,"commands":62,"prompt":72,"zipAvailable":73},[63,66,69],{"tool":64,"command":65},"npx","npx skills add 8007342\u002Ftillandsias --skill meta-orchestration",{"tool":67,"command":68},"bunx","bunx skills add 8007342\u002Ftillandsias --skill meta-orchestration",{"tool":70,"command":71},"pnpm","pnpm dlx skills add 8007342\u002Ftillandsias --skill meta-orchestration","安装技能，技能地址：https:\u002F\u002Fgithub.com\u002F8007342\u002Ftillandsias\u002Fblob\u002Fmain\u002Fskills\u002Fmeta-orchestration\u002FSKILL.md",true,[],[76,104,127,145,167,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":15,"licenseFileUrl":6,"sourceHtmlUrl":108,"categories":109,"keywords":112,"publishedAt":47},"01M6H60EXYDCPSD1QGC89HM0ZC","smoke-curl-install-and-test-e2e","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.","https:\u002F\u002Fgithub.com\u002F8007342\u002Ftillandsias\u002Fblob\u002Fmain\u002Fskills\u002Fsmoke-curl-install-and-test-e2e\u002FSKILL.md",[110,111],{"categoryNo":19,"categoryName":20,"taxonomyType":21,"taxonomyTypeDesc":22},{"categoryNo":24,"categoryName":25,"taxonomyType":21,"taxonomyTypeDesc":22},[113,114,115,116,35,117,29,118,119,120,121,28,39,30,37,122,123,124,125,126],"test","e2e","curl","install","smoke curl install and test e2e","init","podman","issues","forge","short","never","clean","end","reset",{"skillNo":128,"name":129,"nameZh":6,"description":130,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":80,"licenseFileUrl":6,"sourceHtmlUrl":131,"categories":132,"keywords":133,"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",[],[134,86,135,136,137,40,121,138,37,139,92,93,140,52,141,142,99,143,144,103],"discipline","project discipline","pull requests","pull","history","branch","hooks","branches","drift","requests","which",{"skillNo":146,"name":147,"nameZh":6,"description":148,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":149,"categories":150,"keywords":151,"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",[],[152,153,154,155,120,156,157,30,158,159,160,161,162,163,164,165,97,32,103,166],"macos","windows","probe","probe macos tray on windows","CFG","health","daily","files","build","gated","local","shared","platform","module","expected",{"skillNo":168,"name":169,"nameZh":6,"description":170,"descriptionZh":6,"repositoryFullName":8,"ownerLogin":9,"ownerAvatarUrl":10,"ownerAccountNo":11,"ownerDisplayName":12,"repositoryNo":13,"starsCount":14,"licenseSpdxId":15,"licenseFileUrl":6,"sourceHtmlUrl":171,"categories":172,"keywords":173,"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",[],[29,174,37,175,33,176,177,103],"multihost orchestration","compatibility","alias","canonical",{"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,42,52,186,187,188,189,190,43,191,37,35,192,193,194,195,32,196,197,198],"merge","merge to main","merge to main and release","workflow","bump version","pr","open","bump","next","green","operators","trigger","cadence","fedora"]