Cut 15 fix batch: Soul's claims are not bounded by Hands' promises

Self's triage of Soul's first pass on hands/cut15-typed-state:
- Soul views every ruling the cut_spec cites and makes one claim per
  ruling, beside the promises; Hands' self-report never bounds the pass.
- Only Self closes a finding Fixed, after a Soul pass on the fix holds.
  Finding and verdict reads filter faculty Soul; faculty being
  attribution-only joins a new substrate-gaps table in campaign-state.md.
- A fork before Hands' first commit ends the pass with the question
  alone; the blocked-spec check reads questions raised in a spec.
- One rule for an organ that does not answer: missing tools stop, one
  retry on Unavailable (admit replays are safe), then a resumable stop
  that never sends the record as prose.
- Survivor triage goes in deviations, one entry per survivor, because
  MutationRecord has no reason field (a recorded gap).
- The target document is written and committed before the campaign and
  target cite it; Self's checklist names working_branch and target_doc.
- Operator directions are rulings with no answers and the words verbatim.
- One Rehydrate definition with a no-campaign / unknown-slug branch;
  per-brief recipes; Eyes reads the mind read-only; the postmortem
  template sources from the mind.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
Meta Vens 2026-09-30 15:37:19 +02:00
commit 272f5ca5d3
5 changed files with 222 additions and 94 deletions

View file

@ -40,7 +40,7 @@ its own brief. A faculty that grades its own work has lost the point.
| Faculty | Runs against | Admits | Must not |
|---|---|---|---|
| **Imagination** | the Body (source, docs, probes), plus the target | `question`s and `cut_spec`s specified to `file:line`; body facts and rationale go to the prose map | commit code, choose a product fork silently |
| **Imagination** | the Body (source, docs, probes), plus the target | `question`s and `cut_spec`s specified to `file:line`, and `follow_up`s for work no cut owns; body facts and rationale go to the prose map | commit code, choose a product fork silently |
| **Hands** | one `cut_spec` | small pushed commits, then one `cut_report` | redesign the spec, work around a fork |
| **Soul** | Hands' *executed* commits | one `verdict` and its `finding`s | edit or commit a repo, or review a plan (a pass on a plan is Imagination) |
| **Life** | memory surfaces | nothing: named mutations and proposals | touch Body code, restate what an owner records |
@ -59,14 +59,21 @@ finished when Hands can go straight to the cut.
### 0. Reach the mind, map the substrate, scope, target
- **Call `whoami` first.** If `reachable` is false, stop and tell the operator.
Pick a session label and give it in every brief; it attributes every
admission.
- **Check that the `eureka-state` tools are in this session.** If they are
absent, stop and tell the operator: a server registered after the session
started needs a new session. Never fall back to prose.
- **Call `whoami`.** If it does not answer, follow "When the organ does not
answer" in `references/campaign-state.md`: one retry, then stop. Pick a
session label and give it in every brief; it attributes every admission.
- **Map the real substrate before you propose anything.** Run parallel read-only
exploration of the old system and the new one, of any prior attempts and why
they failed (git history, rollbacks), and of every consumer across repos.
- Admit the stewardships, the `campaign` and the `target` (Self's checklist in
`references/briefs.md`). The target holds the ends, not the means: labelled
- **Write and commit the target document first**, on the campaign's working
branch: its rationale, and the design truths the migration will produce. The
`campaign` and the `target` cite it by `DocRef`, and a `DocRef` names a
commit.
- Then admit the stewardships, the `campaign` and the `target` (Self's
checklist in `references/briefs.md`). The target holds the ends, not the means: labelled
invariants that must survive (wire parity, one owner per decision, what the
operator refuses to lose), and what is explicitly **not** a consumer. For
example, AetheriaEve was "taxidermy", and saying so up front saved every later
@ -177,12 +184,15 @@ Templates are in `references/briefs.md` and `references/campaign-state.md`.
### 2. Operator rulings
Put the open questions to the operator together, from the open-items recipe,
Put the open questions to the operator together, from the open-questions recipe,
each with its options, recommendation, and what depends on the answer. Self
admits every answer as a `ruling` that answers its question, keeping the
operator's words in `operator_quote` when they carry meaning a paraphrase would
lose. A ruling that changes an earlier one supersedes it by a `resolution`,
never by an edit, so the rulings-in-force recipe shows one live design.
lose. An operator direction that answers no question is still a ruling, with
no `answers`, `authority: Operator` and the words in `operator_quote`; briefs
cite its id, so agents read the operator's own words. A ruling that changes an
earlier one supersedes it by a `resolution`, never by an edit, so the
rulings-in-force recipe shows one live design.
**The operator channel is this session.** Eureka has no Persona: Self is the
operator-facing surface, because a question costs one message and loses no
@ -232,7 +242,9 @@ nothing is pasted or paraphrased. The brief says:
- **Follow the spec, do not redesign.** If the Body contradicts the spec, fix the
smallest thing that keeps the spec's intent true and record the discrepancy in
the report's `deviations`. If it is a real fork, admit it as a `question`
raised in the spec, **stop, and report**.
raised in the spec, **stop, and report**. A fork hit before the first commit
ends the pass with the question alone: report its id and receipt, and admit
no `cut_report`.
- **Gaps are filled in their owner, never worked around locally.** If CultMath
lacks a function, CultMath gets it; the consumer does not grow a helper.
- **Delete before adding.** No shims, no compatibility layers the map did not
@ -249,9 +261,10 @@ nothing is pasted or paraphrased. The brief says:
name: a behavioural test is missing, a fixture is degenerate (see below),
or the mutant is equivalent and gets a one-line reason. Boundary flips on
float thresholds are equivalent by default and are not chased. The score is
not a gate; the triaged survivor list is the record. It goes in the report's
`mutations`, and a survivor that stays alive goes in `deviations` or becomes a
`follow_up`. Soul reruns the tool on the range rather than trusting Hands'
not a gate; the triaged survivor list is the record. Every mutation goes in
the report's `mutations`; each survivor also gets a `deviations` entry with
its triage, because the mutation record has no field for it (a substrate gap
in `references/campaign-state.md`). Soul reruns the tool on the range rather than trusting Hands'
triage.
- **No committed hand-written mutation suites, and no fallback harness.**
The operator ruled this on 2026-09-22: "Better to have nothing than a
@ -322,8 +335,11 @@ not fine in the same working tree, and never while a Soul pass reads that tree.
### 4. Soul falsifies
Brief Soul with the `cut_report` id and the session label. The report carries
the exact range and Hands' promises; the target in force carries the operator
invariants. Point Soul at the specific places a shortcut would hide. Soul:
the exact range and Hands' promises. **Soul's claims are not bounded by what
Hands chose to promise.** Soul also views every ruling the `cut_spec` cites and
makes one claim per ruling, and measures the target invariants the cut touches.
Hands' self-report is one input to attack, never the list of what gets checked.
Point Soul at the specific places a shortcut would hide. Soul:
- reruns builds, tests and captures itself instead of trusting the report;
- reruns a selection of Hands' mutations, and designs its own that are not plain
@ -333,8 +349,8 @@ invariants. Point Soul at the specific places a shortcut would hide. Soul:
real compiler, run the other runtime's decoder;
- checks the invariant at the layer where it would actually fail (wire bytes,
another runtime, the editor, the GPU), not only in the unit test;
- admits one `verdict`, measuring every promise in the report, together with
its `finding`s: each `Confirmed` or `Plausible`, with locations, a failure
- admits one `verdict`, with a claim for every promise and for every cited
ruling, together with its `finding`s: each `Confirmed` or `Plausible`, with locations, a failure
scenario, a severity and the target invariants it breaks.
Soul works read-only on repos. It creates temporary worktrees for anything that
@ -358,8 +374,8 @@ exists.
For each finding in force, decide:
- **fix now:** brief Hands with the finding's id; the landing closes it
`Fixed`;
- **fix now:** brief Hands with the finding's id. Only Self closes the finding
`Fixed`, and only after a Soul pass on the fix's report holds;
- **operator fork:** a `question` raised in the finding, with a recommendation;
- **defer:** a `follow_up` with the reason it can wait, and the finding
resolved `Deferred` to it;
@ -408,7 +424,8 @@ later.
After each cut:
- Progress is a query, not a section to update: the recipes for specs with no
report, reports with no verdict, and open items.
report (minus those blocked on a question), reports with no verdict, and open
questions, follow-ups and findings.
- Self reconciles the subtraction ledger with the ledger recipe (each spec's
`estimate` against its reports' `structural_delta`). A miss is allowed, but
it must be explained. The CultCache core missed its size
@ -429,10 +446,11 @@ and reconciles the target doc with the Body.
query it. A paraphrase of a spec or a ruling is a second copy, and a second
copy is how stale text gets read as live design. Tell the operator what
matters in words. Tell agents the id.
- **When the organ is unreachable, stop.** Say so to the operator and wait, or
work on something that does not touch campaign state. Never keep the record in
prose or memory "until it is back": that is a second copy, and it breaks the
invariant that the mind is the only store.
- **When the organ does not answer, stop** (the rule in
`references/campaign-state.md`). Say so to the operator. Continue a stopped
agent with `SendMessage` once `whoami` answers. Never keep the record in prose
or memory "until it is back": that is a second copy, and the mind is the only
store.
- **Keep the prose map current.** After a ruling changes a design, sweep the
map's body facts and rationale, and the target doc, for the old version the
same day. The specs and rulings need no sweep, because their resolutions
@ -479,7 +497,8 @@ and reconciles the target doc with the Body.
is remembered only as "the docs got messy". This is not a reason to wait on
the missing thing or route work to it: work around it and leave evidence. The
evidence is a `follow_up` whose source is the document where the run felt the
gap, and whose owner is the missing thing's owner.
gap, and whose owner is the missing thing's owner. The gaps already known are
listed in `references/campaign-state.md`.
- **Never claim an agent's result before its notification arrives.**
## Git and tooling rules (scars)

View file

@ -9,7 +9,10 @@ ruling or a finding. The agent reads those itself. Recipes are in
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.
- the Rehydrate block below, as the agent's first step, with `<recipes>` set to
the recipes that brief names.
This block is the one definition of rehydration; the other files point here.
## Contents
- Rehydrate (every faculty that touches campaign state)
@ -26,15 +29,19 @@ Every brief that reads or admits campaign state carries:
## Rehydrate
```
Campaign state lives in the instance's mind, through the eureka-state tools.
1. Call whoami. If reachable is false, stop and report that; do not work from
prose or memory instead.
2. Run the recipes named for your faculty in references/campaign-state.md,
with root = <c>.
3. view any id this brief names.
Campaign state lives in the instance's mind, through the eureka-state tools
(whoami, admit, view, query). Recipes are in references/campaign-state.md.
0. If those tools are not in your tool surface, stop and report that. Never
work from prose or memory instead.
1. Call 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. isError means no
answer: stop and report it.
names the rule that refused: fix the batch and admit again. Retrying an admit
is safe (AlreadyAdmitted). Any other isError, or the mind going away mid-pass:
stop where you are and report the step; never send your record as prose.
```
## Self: open a campaign, rule, triage
@ -42,20 +49,30 @@ answer: stop and report it.
Self's own checklist; Self admits as `SelfFaculty`.
```
Open: whoami (the mind's instance document, <instance>:instance:self, already
exists). For each repo in scope with no stewardship in force, admit a
stewardship (sequence = latest + 1). Then admit the campaign (every repo a cut
may touch) and target revision 1 (labelled invariants, not in scope,
canonical implementations, doc = the committed target document).
Open: check the eureka-state tools are present, then whoami (the mind's
instance document, <instance>:instance:self, already exists). Write the target
document and commit it on the working branch. For each repo in scope with no
stewardship in force, admit a stewardship (sequence = latest + 1). 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).
In the first campaign, admit a follow_up for each substrate gap listed in
campaign-state.md.
Rule: for each operator answer, a ruling (answers, choice, authority, and
operator_quote when the words matter). A changed ruling carries a resolution
superseding the old one, in the same batch.
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 changed ruling carries a resolution superseding the old one,
in the same batch.
Triage each finding in force: a Hands brief (Fixed on landing), a question
raised in it, 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.
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.
```
@ -70,8 +87,8 @@ You are Imagination for <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: rulings in force, open items; view the target in force).
Read enough of the Body to enumerate the persistent kinds.
Rehydrate (recipes: target in force, rulings in force, open questions and
follow-ups). Read enough of the Body to enumerate the persistent kinds.
Give one table, a row per persistent kind:
- Identity: what names it. Is the namespace stated? Is the name injective? Can
@ -100,8 +117,9 @@ prose map at <path>, edit only body facts and rationale. Do not commit; the
root agent commits. Do not change code in any repo. Scratch probes in
<scratchpad> are fine.
Rehydrate (recipes: rulings in force, open items, specs with no report, one
cut's record for <cuts that constrain this one>; view the target in force).
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>
@ -130,18 +148,23 @@ verification.
Where only the operator can decide, admit a question with a recommended
option, raised in the spec it blocks.
Report: the ids you admitted, findings you could not assign to a cut, and the
HEAD you pinned to.
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
```
You are Hands for <cut>. The spec is <cut_spec id>. Rehydrate, then view the
spec and each ruling it cites. 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.
You are Hands for <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.
@ -165,10 +188,12 @@ cites, read by id):
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. Triage every survivor in the report's mutations by name and line: killed
by a new test, killed by fixing a degenerate fixture, or equivalent with a
one-line reason. A survivor that weakens a rule and cannot be killed goes in
deviations, not hidden. Code no tool reaches gets behavioural tests at the layer where the
code. Record every mutation in the report's mutations. 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
@ -304,7 +329,7 @@ narrative of the pass, no restating the brief or the report.
```
You are Soul for <cut>. Soul preserves invariants by falsifying the promises
Hands made about executed work: shortcuts, split authority, trivial tests.
Admit findings only.
Admit one verdict and its findings, and nothing else.
- Do not edit or commit in any repo.
- Restore after every mutation and leave the tree clean.
- Use a temporary detached worktree for other checkouts, and remove it
@ -318,12 +343,15 @@ Admit findings only.
Yielding to announce the wait is the same violation: block in-turn or read
the finished output, never end the turn to say you are waiting.
Scope: <cut_report id>. Rehydrate, then view the report (its range and its
promises), the cut_spec it cites, and the target in force (the operator
invariants, by label). Admitting your verdict is a write to the mind, not to
a repo.
Scope: <cut_report id>. Rehydrate (recipes: target 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. Admitting your verdict is a write to
the mind, not to a repo.
Falsify every promise in the report, and specifically:
Hands' promises are one input, not the boundary of the pass. Falsify every
promise, every ruling the spec cites (operator directions included, 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
@ -371,7 +399,9 @@ 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
- claims of your own for what you attacked beyond the promises
- one claim per ruling the spec cites, naming the ruling id, 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.
@ -389,8 +419,9 @@ cut unless an invariant moved.
```
Phase boundary: <what landed, as cut_report ids>. The authoritative record is
the campaign's mind (read it through the recipes; you admit nothing) and the
prose map and target doc; don't edit those.
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>.
@ -418,7 +449,8 @@ what was missing and what it would have prevented.
```
You are Eyes. Read only. Write findings to <scratchpad>/<name>.md and return a
short summary.
short summary. 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>

View file

@ -41,8 +41,23 @@ The instance and the daemon are the server's configuration
answers `AlreadyAdmitted`, so retrying a batch is safe.
- **`isError: true` means no answer:** `Unavailable` (the daemon is down or
unreachable), `Rejected` (it refused the envelope), `Misconfigured`,
`TooLarge`, `Unencodable`, `InvalidInput` or `Internal`. When this happens,
stop and say so. Never keep the record somewhere else meanwhile.
`TooLarge`, `Unencodable`, `InvalidInput` or `Internal`.
### When the organ does not answer
This is the one rule for every faculty.
1. **The tools are missing** from the session's tool surface: stop and tell the
operator (a subagent tells Self). A server registered after the session
started appears only in a new session. Never fall back to prose.
2. **`Unavailable`:** retry the same call once. A cold semantic embed after an
idle spell took over 15 s live, which is the client's whole timeout.
Retrying `admit` is safe, because an exact replay answers `AlreadyAdmitted`.
3. **Still no answer, or any other `isError`:** stop. A subagent reports the
error and the step it stopped at, and stays resumable: Self continues it
with `SendMessage` once `whoami` answers. Never send the record to Self as
prose, and never keep it anywhere else meanwhile. The mind is the only
store.
## The document set
@ -57,12 +72,12 @@ mismatch. The root is the campaign slug, or the instance for `instance`,
| `campaign` | `self` | Self | title, repos (each stewarded), working branch, target doc | |
| `target` | `r<rev>` | Self | invariants (`label`, `statement`), not in scope, canonical implementations, doc | |
| `question` | `<label>` | Imagination; Hands or Soul for a fork | title, question, options (≥2), recommended, depends, raised in | `raised_in` |
| `ruling` | `<label>` | Self | answers, choice, ruling, operator quote, date, authority | `answers` |
| `ruling` | `<label>` | Self | answers (none for an operator direction), choice, ruling, operator quote, date, authority | `answers` |
| `cut_spec` | `cut-<cut>.r<rev>` | Imagination | repo, branch, base, depends on, first, deletes, keeps and moves, adds, file changes, authority map, verification, estimate | `rulings`, `questions` |
| `cut_report` | `cut-<cut>.h<attempt>` | Hands | commits, range, verification evidence, mutations, deviations, forks, structural delta, landed names, undone, promises | `cut_spec`, `forks` |
| `verdict` | `cut-<cut>.s<pass>` | Soul | range, claims (each with an outcome, evidence, findings, promise, mutations) | `cut_report`, `findings` |
| `finding` | `cut-<cut>.s<pass>.<label>` | Soul, in the verdict's batch | confidence, severity, claim, invariants, locations, failure scenario, evidence, origin | `verdict` |
| `follow_up` | `<label>` | Self | source, repo, locations, item, why it can wait, owner | `source` |
| `follow_up` | `<label>` | Self; Imagination for work no cut owns | source, repo, locations, item, why it can wait, owner | `source` |
| `resolution` | `<subject kind>.<subject local>.n<seq>` | whoever closes the subject | subject, sequence, outcome, rationale, date | `subject`, and the outcome's referents |
| `hand_off` | `<to>.<repo>.<date>` | Self (parked: Cut 12) | from, to, repo, documents, reason | `documents` |
@ -78,6 +93,10 @@ Rules that shape a batch (the rest arrive as refusals):
- A ruling that `answers` a question derives that question's `Answered`
resolution in the same commit. Its `choice` must be one of the question's
option labels. `operator_quote` is allowed only with `authority: Operator`.
- An operator direction that answers no question is a ruling with no
`answers` and no `choice`, `authority: Operator`, and the operator's own
words in `operator_quote`. Specs and briefs cite it by id, so every agent
reads the operator's words rather than a paraphrase.
- A revision above 1 (of a target or a cut spec) needs, in its own batch, a
resolution that supersedes the previous revision by it.
- A cut spec cites only rulings in force, and a report only a spec in force.
@ -106,6 +125,10 @@ reversal.
Campaigns, cut reports, verdicts and instances have no resolution.
Only Self closes a finding `Fixed`, and only after a Soul pass on the fix's
report holds the claim the finding broke. Hands never resolves a finding: a fix
that closes itself is the self-grading the pipeline exists to prevent.
## Selection vocabulary
`query.selection` is CultNet's typed selection:
@ -157,23 +180,31 @@ or `view` one id, to read the prose fields.
## Recipes
These are the campaign's progress view. `<c>` is the campaign slug. Each recipe is
the `query` tool's whole input.
the `query` tool's whole input. Agents run them from the Rehydrate block in
`briefs.md`, which is the one definition of rehydration.
**Rehydrate.** Run `whoami`, and stop if `reachable` is false. Then:
**Campaigns:**
```json
{ "selection": { "schemas": ["epiphany.pipeline.campaign.v2"] } }
```
- **No campaign at all:** the mind is new. Self opens one (SKILL.md step 0).
Any other faculty stops and reports it.
- **`<c>` is not in the list:** the slug is wrong or the campaign is in another
mind. Stop and report; never create a campaign to fit a brief.
**Stewardships in force** (Self, when opening a campaign):
```json
{ "selection": { "schemas": ["epiphany.pipeline.stewardship.v2"],
"fields": [{ "index": "in_force", "op": "any_of", "values": ["true"] }] } }
```
```json
{ "selection": { "schemas": ["epiphany.pipeline.campaign.v2"] } }
```
Then run the campaign's rulings in force and open items (below), and `view` its
target, or query `target` with `root` = `<c>`, `in_force` = `true` and
**Target in force:** `target`, with `root` = `<c>`, `in_force` = `true` and
`projection: document`.
**Rulings in force:**
**Rulings in force**, operator directions included:
```json
{ "selection": { "schemas": ["epiphany.pipeline.ruling.v2"],
@ -181,15 +212,31 @@ target, or query `target` with `root` = `<c>`, `in_force` = `true` and
{ "index": "in_force", "op": "any_of", "values": ["true"] }] } }
```
**Open items** (questions not answered or withdrawn, findings and follow-ups not
closed):
**Open questions and follow-ups:**
```json
{ "selection": { "schemas": ["epiphany.pipeline.question.v2", "epiphany.pipeline.finding.v2", "epiphany.pipeline.follow_up.v2"],
{ "selection": { "schemas": ["epiphany.pipeline.question.v2", "epiphany.pipeline.follow_up.v2"],
"fields": [{ "index": "root", "op": "any_of", "values": ["<c>"] },
{ "index": "in_force", "op": "any_of", "values": ["true"] }] } }
```
A question's header carries `raised_in`. A spec named there is **blocked on the
operator**, not waiting on Hands.
**Open findings**, admitted by Soul:
```json
{ "selection": { "schemas": ["epiphany.pipeline.finding.v2"],
"fields": [{ "index": "root", "op": "any_of", "values": ["<c>"] },
{ "index": "in_force", "op": "any_of", "values": ["true"] },
{ "index": "faculty", "op": "any_of", "values": ["Soul"] }] } }
```
Add `severity` any of `Blocker` and `High` for the blocking ones. `faculty` is
declared attribution, not checked by admission (see the gaps below), so a
finding or verdict from any other faculty is a defect to raise, not a record to
use.
**Specs with no report.** This is one query: `cited` with `exists: false` is
the substrate's absent inbound hop.
@ -200,9 +247,15 @@ the substrate's absent inbound hop.
"cited": { "role": "cut_spec", "exists": false } } }
```
Before briefing Hands on one of them, check whether it is blocked: `question`,
`in_force` = `true`, with `"cites": { "target": { "schemaId":
"epiphany.pipeline.cut_spec.v2", "recordKey": "<spec id>" }, "role":
"raised_in" }`. A match means the spec waits on a ruling.
**Reports with no verdict** (Soul's queue): the same shape, over
`epiphany.pipeline.cut_report.v2`, with `"cited": { "role": "cut_report",
"exists": false }` and no `in_force`, because reports are never resolved.
"exists": false }` and no `in_force`, because reports are never resolved. The
hop cannot filter the citing verdict's faculty.
**A subject's history**, newest first:
@ -215,10 +268,9 @@ the substrate's absent inbound hop.
A withdrawn resolution is listed with the withdrawal as its status.
**One cut's record:** `schemas` set to `cut_spec`, `cut_report`, `verdict`,
`finding` and `resolution`, with `root` = `<c>` and `cut` = `<label>`.
**Blocking findings:** `finding`, with `root`, `in_force` = `true`, and
`severity` any of `Blocker` and `High`.
`finding` and `resolution`, with `root` = `<c>` and `cut` = `<label>`. When
reading its verdicts and findings, check that `admission.provenance.faculty` is
`Soul`.
**The ledger:** `cut_spec` and `cut_report` with `root` = `<c>` and
`projection: document`. Compare each spec's `estimate` with its reports'
@ -229,6 +281,22 @@ A withdrawn resolution is listed with the withdrawal as its status.
`ruling`, `resolution` and `finding` with `root` = `<c>`, plus
`"semantic": { "text": "<the question in plain words>", "top_k": 10 }`.
## Substrate gaps
The skill works around each of these, and Self admits each as a `follow_up`
(source: the campaign, owner as named) in the first campaign, so the gap is
counted rather than forgotten. Add to this list when a run works around
something new.
| Gap | What the skill does meanwhile | Owner |
|---|---|---|
| `faculty` is attribution only. Admission does not check that verdicts and findings come from Soul, or that rulings come from Self. | Recipes filter `faculty`, and readers check provenance. | Huginn admission, with the Epiphany schema owner |
| `MutationRecord` has no field for why a survivor is equivalent, and a report holds at most 64 mutations. | Every mutation goes in `mutations`. Each surviving mutation gets one `deviations` entry (`what`: its label; `why`: the triage). Deviations hold at most 32, so more survivors than that means the cut was too big. | `epiphany-pipeline` |
| A `cut_report` needs a commit (`range.head`), so a pass that stops at a fork before its first commit leaves no report. | Hands admits only the question and reports its id. The blocked-spec check reads it. | `epiphany-pipeline` |
| The faculty enum says `MindSteward`; the faculty is Life. | Life admits nothing, so nothing is mislabelled today. | `huginn-mind` |
| No tool supplies the session's id. | Self picks a session label and passes it in every brief. | `eureka-state` |
| The reports-with-no-verdict hop cannot filter the citer's faculty. | Soul's queue is checked against the verdict's provenance. | CultNet selection |
## The prose map
`docs/<campaign>-map.md` holds:

View file

@ -1181,3 +1181,10 @@ code path", and "such obviously unnecessary split authority should never pass a
`verdict` and its findings; admitting is a Mind write, so Soul stays read-only on repos.
- Self stops when the organ is unreachable and keeps no second copy meanwhile. "Record the substrate you
needed and did not have" stays, and the record is now a `follow_up`.
- Soul's first pass on this change (Self's triage, same day) found the claim set bounded by Hands'
self-report. Soul now makes one claim per ruling the spec cites, beside the promises; the operator
reaffirmed that Soul loops are "the whole thesis behind Eureka". Only Self closes a finding `Fixed`,
after a Soul pass on the fix holds. The same batch added: one rule for an organ that does not answer
(missing tools, one retry on `Unavailable`, a resumable stop); a Hands exit for a fork before the first
commit; operator directions as rulings with no `answers`; the target document committed before its
`DocRef`s are admitted; and a substrate-gaps table in `campaign-state.md`.

View file

@ -1,8 +1,10 @@
# Postmortem template
Write the postmortem when the migration closes, from evidence: commits, the cut
map, Soul reports and transcripts. Use an Eyes pass to gather facts first. Report
the delta and the scars, not a victory lap.
Write the postmortem when the migration closes, from evidence: commits, the
campaign's mind, the prose map and transcripts. From the mind, take each cut's
record, each subject's history and the ledger (recipes in `campaign-state.md`);
cite document ids rather than restating them. Use an Eyes pass to gather facts
first. Report the delta and the scars, not a victory lap.
```
# <Migration> postmortem
@ -19,7 +21,7 @@ there was one.
One row per cut: dates, SHA ranges, Soul passes, and the notable finding.
## Structural delta
Estimate against actual, per repo. What was deleted, added and parked.
Estimate against actual, per repo, from the ledger recipe. What was deleted, added and parked.
## What Soul caught
Defects that green tests had passed, grouped by kind (concurrency, wire parity,