# Brief templates These are starting points. Fill in every `<>` placeholder. Each brief should let its agent act without asking what the invariants are. Campaign state is typed: a brief gives ids and recipe names, and never pastes or paraphrases a spec, a ruling or a finding. The agent reads those itself. Recipes are in `campaign-state.md`. Every brief that reads or admits campaign state carries: - the campaign slug ``, and the session label `` for its admissions; - the Rehydrate block below, as the agent's first step, with `` set to the recipes that brief names. Every dispatch names its `subagent_type` and its model. The type is the faculty's lowercase name (`imagination`, `hands`, `soul`, `eyes`, `modeling`, `life`) and loads that faculty's charter from `~/.claude/agents/`; a `general-purpose` dispatch loads no charter, so the brief would carry the whole faculty alone. The charter owns identity, method and boundaries; the brief owns the task. Model: Sonnet for Hands, probes, search and Life; Opus for Imagination and for Soul over a cut that puts the foundation at risk. Never leave it as "default", which inherits the root's model. Every agent is capped at about 300k context or 150 calls. At the cap it commits what is verified, admits its report with what is undone, and stops; Self dispatches a fresh continuation agent with the report id. Do not stop because the scope merely looks large. This block is the one definition of rehydration; the other files point here. ## Contents - Rehydrate (every faculty that touches campaign state) - Self: open a campaign, rule, triage - Imagination: settle identity, lifecycle and authority - Imagination: map or refresh a cut - Hands: execute a cut - Soul: falsify executed work - Life: phase boundary - Eyes: gather evidence --- ## Rehydrate ``` Campaign state lives in the instance's mind, through the huginn CLI (huginn whoami, admit, view, query; `huginn --help`). Recipes are in references/campaign-state.md. 0. If `huginn` does not run in your shell, stop and report that. Never work from prose or memory instead. 1. Run `huginn whoami`. On Unavailable, retry once; if it still does not answer, stop and report the error. Self will continue you once the mind answers. 2. Run the campaigns recipe. If there is no campaign, or is not among them, stop and report which. 3. Run , with root = , and view every id this brief names. Admit as faculty , agent , session . A refusal names the rule that refused: fix the batch and admit again. InvalidInput and TooLarge are the same: fix the call (or narrow it) and retry. Retrying an admit is safe (AlreadyAdmitted). Unavailable after one retry, any other isError, or the mind going away mid-pass: stop where you are and report the step; never send your record as prose. A denial headed "This is a deliberate hold" is the near-neighbour check, not a refusal: read the listed records; if none is the same decision send the identical call again, otherwise revise the batch. ``` ## Self: open a campaign, rule, triage Self's own checklist; Self admits as `SelfFaculty`. ``` Open: check `huginn` runs, then `huginn whoami` (the mind's instance document, :instance:self, already exists). Write the target document and commit it on the working branch. Then admit the campaign (slug, title, every repo a cut may touch, working_branch, target_doc = a DocRef to that commit) and target revision 1 (labelled invariants, not in scope, canonical implementations, doc = the same DocRef). Run the substrate-gaps query in campaign-state.md, so the campaign starts knowing which workarounds are in force. Rule: for each operator answer, a ruling (answers, choice, authority, and operator_quote when the words matter). A direction that answers no question is a ruling with no answers, authority Operator, and the words verbatim in operator_quote. A ruling's operator_quote and text carry only what the operator said; Self's reading goes in a question, or is clearly marked as Self's (three supersedes on 2026-10-07 came from text she never said). A changed ruling carries a resolution superseding the old one, in the same batch. Status, not only words: a ruling's text says whether her words decide, illustrate or sketch. Examples she gives are examples, never a closed list, and a remark made while thinking aloud is advice input, not a ruling at all. The same holds for a campaign's title and a target: they name the problem, not her first examples of it. (aetheria-fauna, 2026-10-13: her "krill, minnows, sharks, whales" became the campaign title, the target and every brief, and the lore pass wrote exactly those four. Operator: "I mentioned krill, minnows, whales and sharks and that ended up being the whole ecosystem somehow".) A creative or content pass (lore, design text, catalog content, art direction) is briefed to develop and challenge: its inputs, her sketches and the existing canon alike, are drafts. Its report ends with what it added beyond its inputs and where it would change them, her ideas and existing content included. Triage each open finding: a Hands brief, then a Fixed resolution admitted by Self only after a Soul pass on the fix's report holds; a question raised in the finding; a follow_up plus a Deferred resolution; or a Recorded or Withdrawn resolution. A missing tool or surface a faculty worked around is a follow_up owned by the missing thing's owner. Before a Hands brief, check that the spec is not blocked by an open question raised in it (campaign-state.md, specs with no report). hand_off is parked (Huginn Cut 12): one mind, no transfer. ``` ## Imagination: settle identity, lifecycle and authority Dispatch: `subagent_type: imagination`, model Opus. Run this once, before any cut is mapped. It answers the questions that cause re-cuts, and it needs almost no source. ``` Migration: . Produce the model page in . Do not map cuts, do not write code, do not commit; the root agent commits. Rehydrate (recipes: target in force, rulings in force, open questions and follow-ups). Read enough of the Body to enumerate the persistent kinds. Orient and probe through scripts, one call per question, output at most 150 lines. Wait only through `tools/wait-on.sh` (never `true`, `echo` or `sleep`), write only under `//`, and use `py -3` for Python. Give one table, a row per persistent kind: - Identity: what names it. Is the namespace stated? Is the name injective? Can two different things collide? Is any part of it derived, and from what? - Lifecycle: what happens to it over time. Created, revised, superseded, withdrawn, reinstated, transferred, deleted, replayed. For each, what the record looks like afterwards and what is now in force. - Authority: who decides. One owner per decision. Name the forbidden writers. Then admit, in one batch, a question for everything only the operator can answer: options, the recommended label, and what depends on the answer. An empty cell is the finding. Say so plainly rather than inventing a plausible value. Report the cells you could not fill, the source you checked, and the question ids you admitted. ``` ## Imagination: map or refresh a cut Dispatch: `subagent_type: imagination`, model Opus. ``` Migration: . Admit a cut_spec for so Hands can go straight to the cut with little reading. Map nothing further ahead (SKILL.md step 1, "Map only what is about to run"): later cuts are one line each in the prose map's cut sequence. Admit only cut_specs, their superseding resolutions, and questions. In the prose map at , edit body facts and rationale. Also edit the model page whenever a probe changes a row's identity, lifecycle or authority. Imagination wrote that page in 0b, and a model a cut contradicts is stale steering text. Do not commit; the root agent commits. Do not change code in any repo. Scratch probes under // are fine. Orient and probe through scripts: one call per question, output at most 150 lines. Wait only through `tools/wait-on.sh` (never `true`, `echo` or `sleep`), write only under `//`, and use `py -3` for Python. Budget 40-80 calls and about 250k context. Rehydrate (recipes: target in force, rulings in force, open questions and follow-ups, specs with no report, one cut's record for ). Body facts to verify (not trust): - - - Every mechanism claim must come from a probe or a source read, not a name. Record each probe and its result in the prose map's body facts, and cite them from the spec by DocRef rather than restating them. The cut_spec's fields are the spec standard. Beyond filling them: - file_changes against base , for code that exists - file_changes are Hands' context pack. Each range is exact at base and is the window Hands needs for that change, at most 100 lines (split a longer site). A new file goes in adds, never as a line-1 anchor. Write no prose about lines moving. After admitting, run `py -3 tools/context-pack.py `: every anchor must read SAME and each window must show what its change names, or admit a revision. - cite in `rulings` every ruling in force the cut rests on - the deploy owner: for any cut that changes what a service needs (transport, env, dependency, state), the recipe, binding and runbook that must admit it, changed in the same pass (Ghostlight, 2026-09-23) - every seam with a foreign owner: the owner's code or published schema the fixture is built from, not our own struct - refreshing a spec: admit revision N+1 with a resolution superseding revision N by it, in one batch; never a second spec for the same cut If a cut would not fit one Hands pass under , admit its first part as the spec, with its own verification, and add the rest to the prose map's cut sequence. Where only the operator can decide, admit a question with a recommended option, raised in the spec it blocks. Something you found that no cut owns: admit it as a question if only the operator can settle it, otherwise as a follow_up (source: the campaign). Report: the ids you admitted and the HEAD you pinned to. ``` ## Hands: execute a cut Dispatch: `subagent_type: hands`, model Sonnet. ``` Cut: . The spec is . Rehydrate (no recipes: view the spec and each ruling it cites, operator directions included). Follow the spec; do not redesign it. If the Body contradicts it, fix the smallest thing that keeps its intent true and record the discrepancy in the report's deviations. If you hit a real operator fork, admit it as a question raised in the spec, stop, and report. If that happens before your first commit, the pass ends there: report the question id and its receipt, and admit no cut_report (a report needs a commit). Repo/branch: at HEAD . Check that git status is clean first. Pinned siblings: . Do not change them. Before any grep or Read, expand the pack: `py -3 tools/context-pack.py `. An anchor that reads NEW for a path the spec does not create, OUT_OF_RANGE, UNRESOLVED, or GONE outside deletes is a spec discrepancy: record it in deviations. When the brief names a worktree, every tool call's path goes under it: Read, Edit and Write as well as the shell's working directory. An absolute path into the main checkout silently edits the wrong tree. Standing rules (the skill's own; the campaign's rulings are the ones the spec cites, read by id): - Gaps are filled in their owner, never with local helpers. - Delete before adding. No shims. - One rule, one path. A simpler case of the rule (one lane, one cell, an empty set) runs through the general path, not a fast path beside it. If a second path looks necessary, stop and report it; do not build it. - An error, log line or refusal never echoes an input value, and that includes a path, a URL or a line of the offending config. Name the field and the error code. Test it with a canary value: no byte of the canary may appear. Soul found this class twice on 2026-09-30: Heimdall's secret reader printed a URL bound as a path, and TOML parse errors quote the whole `KEY = "value"` line. Every rule the spec or the operator names gets a behavioural test. Measure the suite with , scoped to this cut's diff (`--since:` or the tool's equivalent), against the final spelling of the code. The report's mutations (at most 64) holds every survivor and the kills Soul should rerun; put the totals (generated, caught, unviable, missed) in verification evidence. Triage every survivor by name and line: killed by a new test, killed by fixing a degenerate fixture, or equivalent with a one-line reason. The mutation record has no field for that reason, so each survivor also gets one deviations entry (what: its label; why: the triage). A survivor that weakens a rule and cannot be killed says so there, not hidden. Code no tool reaches gets behavioural tests at the layer where the rule is decided, never a committed mutation suite (operator, 2026-09-22). A fix for a proxy-for-truth defect is not done until every other site that draws a conclusion from the same class of evidence has been enumerated and ruled on in writing, including sites outside the repo. Name the inference, not the line. And a change to how a test reports — an ignore, a filter, a skip, a guard — is followed by running every command in the owning runbook verbatim and reading what it prints: that surface is the one a test suite cannot check. A test's inputs come from the production path the rule is about. A helper that re-spells what production prints, parses or derives makes the test agree with a copy, and the rule then breaks in production with the suite green. A green run is not evidence until it shows a non-zero count for the tests you meant to run. Paste the count for each named file. On StreamPixels, all three of these produced a green that had run nothing, or the wrong thing: - A `node --test` glob that matches no files exits 0. - A package script's `--dir .` made vitest discover zero tests (`cc71ce2`). - `pnpm --filter X test -- ` ran the whole suite instead of the named files (`4624b53`). Set environment variables only on the step that needs them. Exporting `DATABASE_URL` for the whole job silently moves `app.test.ts` onto the Postgres driver (`e019de0`). "Pre-existing" is not a diagnosis. A failure that is not yours still gets a one-line cause: what it depends on, and whether it has ever passed on a clean checkout. Several agents waved a StreamPixels test through as pre-existing. It read a git-ignored, licensed asset pack and had never passed on a clean checkout (`27053f9`). Reproducing a failure at the base commit proves nothing when both runs share the cause, for example a Windows file lock on the same machine. A hand mutation hits the rule at the layer it protects: the production call site, observed where the consequence lands (disk, the kernel, the request sent). Mutating a helper or an in-memory mirror proves the helper, not the rule; a later write can hide the deleted one. When a claim is "behaviour unchanged", a value captured from the new code is not evidence. Pin it with a value computed at the base commit. Detached scripts: confirm the log starts within 60 s; a script that dies on a parse error is silent otherwise. Wait on one with `tools/wait-on.sh`. Shared build caches: record a full path list before building, not only counts, and delete exactly the new paths afterwards. Counts cannot attribute hardlinked or rewritten outputs. When a cut deletes, list every rule that had a test before and has none after. A rule that still exists in code with its only test deleted is the failure mode of subtraction; either the rule goes too, or it gets a test in the same cut. Context is a budget, and a worker that fills it gets careless before it gets stuck. Aetheria's stats and shield cuts ran Hands past 400k tokens and the late work in those runs is where the sloppy claims appeared: a mutation reported against code that had moved, a failure called environmental without a check, a table printing numbers the old code never produced. Self sized this cut to fit one head (SKILL.md, step 3); keep it fitting: - **Verify once, at the end.** Not after every edit. A full mutation sweep and a batchmode compile per edit is most of a long run's spend and proves nothing the final sweep will not. One job carries the build, the scoped tests and the mutation run, so the queue and the compile are paid once. - **Orient in one script.** One Bash call prints git status, the base and the pack (`tools/context-pack.py`). Independent reads, views and greps go in one parallel message. - **Bound every observation.** No command prints more than about 150 lines. Logs go to a file; read `tail -n 60` or `grep -n -m`, and read windows of a file, never the whole of anything over about 300 lines. After editing, `py -3 tools/context-pack.py --since ` reprints only the changed windows; re-read only files you edited. - **Read the spec by id, not the map.** The cut_spec is bounded and holds only this cut; a worker that reads 900 lines of map to find 60 has spent its budget before it starts. - **Keep expensive scaffolding alive across cuts** (a pinned dependency worktree, a warm build) rather than creating and removing it per pass. - **Hand back rather than push through.** A worker that finds itself far past the work it was briefed for commits what is verified, reports the remainder honestly, and stops. A partial with clean evidence is worth more than a complete report written from a full head. "Far past" means the worker's context really is filling. It does not mean the remaining scope looks large. Two Sonnet passes on the selection cut stopped at about 150k tokens with no fork, one of them after fourteen tool calls. Each said the remaining work "did not fit the budget". Both had been pointed at a 1,500-line map instead of given only their cut. So state the scope as one deliverable, and say the budget is sufficient for it. The hand-back clause is for a head that is actually full, not for a job that looks big. - **Run every consuming test project, and report each count.** Before reporting, list every test project that references an assembly, package or crate the cut changed, found from the project files rather than from memory. Run each one at the head, and put one evidence line per project in the report: its name and its pass, fail and skip counts. "Did not build" is a result and must appear as one. A project you could not run is listed in `undone`. Scars from 2026-10-01 and 2026-10-02: - An earlier Soul hold on C2a covered a range in which a Caching test was already red. - The R1 merge into C2a was reported green while GameCult.Mesh.Tests did not compile at any commit of the range. That broken build hid a High finding: Mesh's own zero-byte reader. Long jobs: wait for them and finish, and never end your turn before your report. Each turn end reaches Self as a notification and costs a read of its whole context. Start the job as one background shell (run_in_background) with `SUMMARY=//.log` in front of `tools/stopgap/ygg-verify.sh`, a fresh log path per job. Then wait in the foreground, one call at a time: `tools/stopgap/ygg-verify.sh wait //.log` blocks for at most 270 s (run it with a Bash tool `timeout` of at least 280000 ms: the default 120 s backgrounds the call and costs a wake), so your cache stays warm, and prints the bounded summary when the job is done. If it prints `RUNNING s` (exit 99), call it again. Exit 98 means the launcher is gone with no verdict: rerun the job, do not guess its outcome. A call longer than 5 minutes rewrites your whole context. Never run a second watcher on the same job, never use a timer shorter than 60 s in a loop of your own, and send no interim message. Every other wait goes through `tools/wait-on.sh`, never a loop of your own. Prefer `tools/wait-on.sh log ` with `WAIT_PID=` whenever the job writes a done line (a build, a Unity batchmode run, a script that echoes `DONE`): it is the only form that can tell success from a crash, because a dead pid with no match is exit 98. `tools/wait-on.sh pid []` is only for a process with no completion evidence; it prints `GONE (no completion evidence)` and its exit 0 means "gone", not "succeeded". `tools/wait-on.sh file ` is for an output file written last. The regex is an ERE; an invalid one is exit 3. Exit 3 means the regex is invalid: fix it, never retry it unchanged. Every job gets a fresh log path (put the job's own unique name or a timestamp in it; for Unity, a new `-logFile` path per launch), and a waiter is never pointed at a log a previous job wrote: a reused log's old done line reads as success at once, and an offset cannot fix that because truncating writers (`>`, Unity `-logFile`) rewrite below it. Same contract as the ygg-verify wait: pass a Bash tool `timeout` of at least 280000 ms, it blocks at most 270 s, exit 0 is done with a bounded log tail, `RUNNING s` (exit 99) means call it again, exit 98 means the thing is gone with no completion evidence. Bare `true`, `echo waiting` and `sleep` calls are forbidden as polling: on 2026-10-07 and before, Hands and Soul runs made 974 idle `true`/`echo` calls and 324 `sleep` calls (49 refused by the harness), each one a model turn that waited on nothing. Write only under your own scratchpad subdirectory, `//`: a shared `job.sh` or probe file gets overwritten (one Soul clobbered `job.sh` and `SoulProbe.cs`, 2026-10-07). `` is the name Self gives this dispatch, unique among agents in flight, never the bare faculty name: two Hands both writing under `hands/` overwrote each other's job scripts on 2026-10-09. Python: use `py -3`, which works from Git Bash and PowerShell alike. Bare `python` hit the Windows Store stub in 65 calls (2026-10-07). Self pastes this wait protocol into a brief verbatim, never as a shortened "wait mode": abbreviated, agents ended their turns mid-job three times on 2026-10-07. Mutation tools run on schemata or copies and never edit the tree. A Soul probe that mutates by hand works on a scratch copy: the stopgap's container or a throwaway clone, never the working tree. Warnings: measure from a forced rebuild and compare distinct messages; cargo replays warnings only when it actually rebuilds. Semantic properties ("exactly one call site", "this step actually runs"): prefer a semantic tool (a Clippy lint, the type system) over a text scanner, or state the scanner's limits in the test itself. If you work around a missing tool, service or typed surface, say in the report's deviations what was missing and what it would have prevented. The workaround is not the finding; the gap is. Commits: - Small and pushed. - Stage explicit paths only; never `git add -A`. - Never amend a commit or force-push. Self and other agents commit on the same branch while you work. Fix a commit with a new commit. On a rejected push, `git pull --rebase`, then push. - In Git Bash, one call: `git add && git commit -F- <<'MSG' ... MSG && git push`. Never commit from PowerShell (it writes a BOM and breaks here-strings). - End each message with the attribution trailer. - Before every push, build and run the test project the commit touches. A commit that does not build is never pushed; if a local commit could not build, say so in its message and make the pushed head build. Verification: . - No test run of any size on Starfire: a "quick" local suite counts. Only Windows-only checks the brief names run there (py-msgpack-default h1 ran two Python suites locally on 2026-10-12, red for Windows-only reasons). - Verify through `tools/stopgap/ygg-verify.sh` with `SUMMARY=` (above): read the summary, and open the full log only at a named failing test, with `grep -n -A 40`. Hand mutants go in one list to `tools/mutation-table.sh`, one job for all of them. - Stryker `--mutate` ranges are character offsets, not lines, into the file as Stryker reads it: the bytes of the checkout the job runs in. Line endings there follow `.gitattributes`, not the platform: CultLib's `packages/cultmath/src/**` is `eol=crlf`, so even the Linux container checks it out with CRLF. Compute the offsets inside the job from that checkout's file, never from `git show` (index LF) or a different clone. Then check that the run reports mutants inside the method you meant to measure. A run whose ranges hit nothing tests nothing, and a green with zero mutants tested is not evidence (line-scoped runs tested nothing, 2026-10-06; LF offsets on a CRLF file missed the code under test, cut-bls-input-field.s3, 2026-10-11). On Aetheria, Stryker.NET 5.0.0 has no test filter and runs the whole suite per pass (about 86 minutes, modifier-subtypes 2026-10-09): budget one pass, never a second to read a truncated tail (write its report to a file), and give Soul hand mutants through `tools/mutation-table.sh` instead. - Aetheria verify jobs set `DOCKER_ARGS='-v /home/gamecultadmin/eureka-verify/pins:/pins -v /home/gamecultadmin/eureka-verify/lfs-aetheria:/lfs:ro'` (jobs that read sibling repos add `-v /home/gamecultadmin/eureka-verify/repos:/repos:ro`). `/lfs` is content-addressed: for each LFS file the tests read (`GameData/Aetheria.cc`, `Assets/Resources/Settings.asset`), read the oid from the checked-out pointer and copy `/lfs/` over it; copying by path leaves the pointer and fails 200+ tests. Pass both pins to the build: `-p:CultLibRoot=` and `-p:CultMathRoot=` a `/pins` directory holding the sha Aetheria pins for each. From the CultMath 0.3 pin cut on (branch `eureka/aetheria-release-cultmath-0-3-pin` and everything after its merge) the revision guard runs on Linux and reads git, so both must be git clones, not exports: CultLib `/pins/cultlib-git-45c2f40`, CultMath `/pins/cultlib-614fd44`; an export pin fails at `VerifyCultLibRevision` with git exit 128 before compiling. Older branches use CultLib `/pins/cultlib-45c2f40` and CultMath `/pins/cultlib-6d5e209` (a CultMath pin lacking `erf` fails to compile). `ls /pins` in the job when unsure. The lot-product and emoji merges each lost three runs to this (2026-10-08); follow-up `aetheria-release:follow_up:aetheria-verify-job-script` replaces this recipe with a project-owned script. - Revert incidental asset churn. Budget: if the cut can't land coherently, stop at a pushed, building commit boundary with no half-deleted authority, and put what remains in undone. Don't edit the prose map. Admit one cut_report for , attempt , and no resolution of any finding: Self closes a finding Fixed only after Soul holds the fix (campaign-state.md). A fix batch is the next attempt on the finding's in-force spec, on that spec's branch; if the fix cannot land there, stop and report, because Self or Imagination must admit a revised spec first. Its fields: - commits (builds: false for any that don't build), and the range; the head must be one of the commits - verification: one evidence entry per build, test run and grep, with the command as locator and the counts as result - mutations: every survivor and the kills Soul should rerun (at most 64), each with its exact edit (before and after) and whether it failed as expected; totals go in verification, each survivor's triage in deviations - deviations: spec discrepancies you fixed, each with why - forks: the question ids you admitted - in a fix batch, each finding id you addressed with the commit you believe fixes it, as a labelled promise for Soul to measure - structural_delta: lines, dependencies, formats and targets removed or added - landed_names, undone, and promises: each thing you claim the cut now guarantees, labelled, for Soul to measure Report to Self, and nothing else: the cut_report id and receipt, and, for output too long for an evidence line, the scratch path that holds it. No narrative of the pass, no restating the brief or the report. ``` ## Soul: falsify executed work Dispatch: `subagent_type: soul`, model Opus when the cut puts the foundation at risk, else Sonnet. ``` Cut: . Falsify the promises of the executed commits in the scope below. Admit one verdict and its findings, and nothing else. - Use a temporary detached worktree for other checkouts, and remove it afterwards. - Do not run unless told. - Check the report's per-project test counts against the project files yourself. A consuming test project missing from the report is a finding, and you run it. - Long jobs and waits: Self pastes the Hands brief's `Long jobs` block here verbatim (the canonical wait protocol, including the scratch subdirectory and `py -3` rules); do not reword or shorten it. - Bound every observation: no command prints more than about 150 lines, logs go to files, and you read windows of them. Scope: . Rehydrate (recipes: target in force, rulings in force, one cut's record for ), then view the report (its range and its promises), the cut_spec it cites, and every ruling the spec cites. `py -3 tools/context-pack.py ` prints the cut's sites at that head. Admitting your verdict is a write to the mind, not to a repo. Hands' promises are one input, not the boundary of the pass. Falsify every promise, every ruling the spec cites, every operator direction in force (even one admitted after the spec; in the operator's own words), and every target invariant the cut touches, and specifically: - - - - - - - - - - rerun the builds, tests and captures yourself, but pay for each one once. Every verify job queues for a shared slot, so the number of jobs, not the compile, is what makes a pass slow. While probing, run only the test binaries or files the cut touches and the ones that name its rules. Run the full suite exactly once, at the end. Put that run in the same job as your mutation run where you can, since that job pays for the build anyway. Batch probes into one job script rather than one job each. Run the mutation tool in parallel (`--jobs 3`), and skip by name any test that a follow-up records as flaky, so that its flakes cannot count a surviving mutant as killed. Dump the range once (`git diff .. > //range.diff` plus `--stat`) and grep that file instead of re-running `git show` per file. Hand mutants go in one list to `tools/mutation-table.sh`, never one job each. Before recommending a mechanism as the fix direction, check that it was not already built and deleted. Run `git log -S ''` and `git log --grep` on the owner's files, run the precedent recipe, and read the scars in SKILL.md. If it was tried, cite the commit that removed it and say why the new situation differs, or recommend something else. (2026-09-30: a Soul pass recommended writer-thread ordered delivery in CultCache. That scheduler was built in `bcae483` and deleted in `4562340`, 34 minutes later, for deadlocking, and Imagination re-proved the deadlock.) Rerun the mutation tool on the range yourself; do not trust Hands' survivor triage. Challenge each "equivalent" call that is not a float boundary flip: measure it, as a mutant that changes how a thing is built can leave what it does untouched, and one that looks cosmetic can move damage to the wrong side of a ship. Admit one verdict (pass ) and its findings in one batch: - one claim per promise in the report, Holds, Falsified or Unproven, each with its evidence (the numbers: test counts, entries killed, the survivors you retriaged) and the report's mutation labels it reran - one claim per ruling the spec cites and per operator direction in force, its text starting with the ruling id (a claim has no ruling field), whether or not Hands promised anything about it - claims of your own for what you attacked beyond those - each finding Confirmed or Plausible, with its locations (file:line), failure scenario, severity, origin, and the target invariant labels it breaks. A Falsified claim names a Confirmed finding. Report to Self, and nothing else: the verdict id and receipt, and one sentence on whether the cut closes. No narrative of the pass, no reasoning about mutants that died. scope is the fix batch's cut_report and its diff, plus one rerun of the suite. Do not re-derive the whole cut unless an invariant moved. ``` ## Life: phase boundary Dispatch: `subagent_type: life`, model Sonnet. ``` Phase boundary: . The authoritative record is the campaign's mind and the prose map and target doc; don't edit those, and admit nothing. Rehydrate (recipes: rulings in force, open questions and follow-ups) to check memory against the mind. Surfaces: . Budget at most 25 calls: inventory the surfaces in one script, then make the edits. Candidates for durable memory: . Check each against its owner first, the mind included, and don't duplicate what the owner records. A memory that restates a ruling or spec is a second copy: point at the id or retire it. Retire or supersede stale claims instead of adding corrections next to them. Falsify at least one persisted claim against the Body. Proving something is gone is the claim most likely to be wrong, because the check that looks for it is usually a grep and prose reflows. A phrase split across a line break, rewrapped, re-cased or re-spelled is still live steering text and an exact search will not see it. Search for the shortest distinctive fragment, search the concept and not the phrasing, and read the surrounding text before reporting a removal. Report: surfaces inspected, the claim you checked, mutations made, and proposals for operator-owned surfaces. If you worked around a missing tool or surface, say what was missing and what it would have prevented. ``` ## Eyes: gather evidence Dispatch: `subagent_type: eyes`, model Sonnet. ``` Write findings to //.md and return a short summary. For a prior-art or literature pass, Self commits that file to /docs/research/.md before the fork goes to the operator (SKILL.md step 2, "Research is always kept"); write it to be read there. Budget at most 40 calls: transcripts by script, never whole reads, waits only through `tools/wait-on.sh`, writes only under `//`, Python as `py -3`, and fetches batched in parallel. You read the campaign's mind with query and view only, through the Rehydrate block (recipes: ); you never admit. Sources: - - (grep with targeted patterns; never read whole) - Produce facts with evidence pointers (SHA, file:line, transcript line). Mark anything inferred as "(inferred)". ```