649 lines
38 KiB
Markdown
649 lines
38 KiB
Markdown
# 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 `<c>`, and the session label `<session>` for its
|
|
admissions;
|
|
- the Rehydrate block below, as the agent's first step, with `<recipes>` 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 <c> is not among
|
|
them, stop and report which.
|
|
3. Run <recipes>, with root = <c>, and view every id this brief names.
|
|
Admit as faculty <Faculty>, agent <your name>, session <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>: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: <migration>. Produce the model page in <prose map
|
|
path>. 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 `<scratchpad>/<agent>/`, 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: <migration>. Admit a cut_spec for <the next cut, and at most a
|
|
sibling Self will run beside it> 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 <path>, 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
|
|
<scratchpad>/<agent>/ 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 `<scratchpad>/<agent>/`, 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 <cuts that constrain
|
|
this one>).
|
|
|
|
Body facts to verify (not trust):
|
|
- <repo@SHA>
|
|
- <tags>
|
|
- <API or behaviour claims>
|
|
|
|
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 <sha>, 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 <spec id> <worktree
|
|
at base>`: every anchor must read SAME and each window must show what its
|
|
change names, or admit a revision.
|
|
- code Hands must see but not change goes in `reads` (path and line range at
|
|
base, at most 100 lines, a `why` of at most 200 bytes, at most 16 per spec),
|
|
never as prose path:line in first, adds, keeps_moves or a change, unless it
|
|
is in another repo. Give a `symbol` on a read or file_change whose lines
|
|
define or call a named thing, written as it appears there. After admitting,
|
|
the tool at base must show every anchor SAME (or NEW, for a path the cut creates) with no SYMBOL_MISSING, 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 <Self's context budget, SKILL.md
|
|
step 3>, 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. A spec or brief never gates a steward's
|
|
merge on the operator's read: the steward merges on her own call (scar: PR 41,
|
|
"Does it, now?").
|
|
|
|
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: <cut>. The spec is <cut_spec id>. 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: <repo> <branch> at HEAD <sha>. Check that git status is clean
|
|
first. Pinned siblings: <repo@sha>. Do not change them.
|
|
Before any grep or Read, expand the pack: `py -3 tools/context-pack.py <cut_spec
|
|
id> <worktree>`. An anchor that reads NEW for a path the spec does not create,
|
|
OUT_OF_RANGE, UNRESOLVED, a MISSING read, SYMBOL_MISSING, or GONE outside
|
|
deletes is a spec discrepancy: record it in deviations. The pack lists the
|
|
callers of every symbol; grep beyond them only for what the pack names as cut.
|
|
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 <the ecosystem's mutation tool>, scoped to this cut's diff
|
|
(`--since:<base>` or the tool's equivalent), against the final spelling of the
|
|
code. For Rust the tool is `tools/cargo-mutants.sh <repo> <head> <base> [workdir]`,
|
|
run ONCE per pass, at the end: it scopes each file's mutants to that file's tests,
|
|
confirms every survivor on the full suite and shards over free slots. After killing
|
|
survivors with tests, rerun only those names (`NAMES=<file of the MISSED names>`),
|
|
never a second whole-diff sweep; a flaky test is skipped with
|
|
`TEST_ARGS='--skip <name>'`. 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 -- <files>` 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 <cut_spec id> <worktree> --since <the HEAD you
|
|
started from>` 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=<scratchpad>/<agent>/<job>.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 <scratchpad>/<agent>/<job>.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 <n>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 <log> <done-regex>` with `WAIT_PID=<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 <pid> [<log>]` 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 <path>` 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 <n>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, `<scratchpad>/<agent>/`:
|
|
a shared `job.sh` or probe file gets overwritten (one Soul clobbered `job.sh`
|
|
and `SoulProbe.cs`, 2026-10-07). `<agent>` 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 <paths> && 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: <exact builds, tests, captures, negative greps>.
|
|
- 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=<log>` (above):
|
|
read the summary, and open the full log only at a named failing test, with
|
|
`grep -n -A 40`. Rust mutants go to `tools/cargo-mutants.sh` (one job, scoped,
|
|
confirmed, sharded), hand mutants in one list to `tools/mutation-table.sh`; never
|
|
an inline `cargo mutants` command.
|
|
- 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/<oid>` 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 <cut_spec id>, attempt <n>, 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: <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 <expensive runtime> 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: <cut_report id>. Rehydrate (recipes: target in force, rulings in force,
|
|
one cut's record for <cut>), 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 <cut_spec id>
|
|
<worktree at the report's head>` 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:
|
|
- <the load-bearing claim, and what would make it false>
|
|
- <where split authority could hide. Two paths that decide the same rule are
|
|
a defect whether or not they agree today, so report the split itself as
|
|
CONFIRMED and do not spend the pass proving the paths equivalent. Look for
|
|
a survey or check that picks between an "ordinary" and a "special" case of
|
|
one rule, and name the single path that replaces both>
|
|
- <which tests might pin spelling instead of behaviour; rerun N mutations,
|
|
including ones that are not plain reverts>
|
|
- <the layer where the invariant really fails: wire bytes, another runtime's
|
|
decoder, the editor, the compiler, a legacy file decoded independently>
|
|
- <for a sealed or private boundary: attack constructibility from an external
|
|
scratch crate or consumer, not path privacy. Try every public constructor the
|
|
language gives away: Deserialize and other derives, Default/From impls,
|
|
public fields, functions returning mutable references. A compile_fail test
|
|
pins a name; on stable rustc it does not even pin the error code>
|
|
- <for rejection tests: forgeries must be shaped like real values (same length,
|
|
prefix, case and alphabet), or a weakened comparison passes them all>
|
|
- <for any text scanner, grep assertion or line pin: try evasions (aliases,
|
|
function values, formatting, control flow around the pinned text such as
|
|
`if false` or `true ||`). A scanner is a tripwire with stated limits, not
|
|
proof of a semantic property>
|
|
- <leftover greps>
|
|
- <for every seam with another owner: build the fixture from that owner's code
|
|
or schema and prove both directions; a fixture that restates our struct can
|
|
only agree with its author>
|
|
- 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 Rust mutants through
|
|
`tools/cargo-mutants.sh` (it shards; do not add `--jobs`), skipping any test a
|
|
follow-up records as flaky with `TEST_ARGS='--skip <name>'`; other ecosystems
|
|
run their tool in parallel (`--jobs 3`) and skip by name, so that a flake cannot
|
|
count a surviving mutant as killed.
|
|
Dump the range once (`git diff <base>..<head> > <scratchpad>/<agent>/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 '<distinctive identifier>'` 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 <n>) 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.
|
|
|
|
<For a second or later pass on the same cut:> 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: <what landed, as cut_report ids>. 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: <memory dirs and files>. Budget at most 25 calls: inventory the
|
|
surfaces in one script, then make the edits.
|
|
|
|
Candidates for durable memory: <ruling ids, scars>. 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 <scratchpad>/<agent>/<name>.md and return a
|
|
short summary. For a prior-art or literature pass, Self commits that file to
|
|
<repo>/docs/research/<topic>.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
|
|
`<scratchpad>/<agent>/`, 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: <as needed>); you never admit.
|
|
|
|
Sources:
|
|
- <repos and ranges>
|
|
- <transcripts> (grep with targeted patterns; never read whole)
|
|
- <docs>
|
|
|
|
Produce facts with evidence pointers (SHA, file:line, transcript line). Mark
|
|
anything inferred as "(inferred)".
|
|
```
|