Commit graph

2,449 commits

Author SHA1 Message Date
Meta Vens
b3ae787b7d Residue S5 and S8: pin the leaf door's 64-byte bounds and NUL, name the harness's real path
The leaf's own door test, slug_validate_applies_the_dotted_grammar, checked
the grammar but never pinned the 64-byte bound on the whole name, the
64-byte bound on a lone label, or NUL as a refused label byte. Extends it
with a two-label 64/65-byte pair (each label far under 64, so only the
whole-name check can be the one refusing 65), a direct Label check at
64/65 bytes (no whole-name wrapper to interfere), and a NUL case. Adds
three matching mutation entries to tools/eureka-cut10-epiphany-mutations.psd1
that drop each check in turn; all three die under the extended test.

The suite's own header still named the deleted repo-local harness path.
Corrected to the Eureka skill's copy, GameCult/Eureka.

Verified: cargo test -p epiphany-pipeline --lib, 35/35. Full mutation
suite through the Eureka harness: 5/5 killed (G1, G1L, S5whole, S5label,
S5nul), M0 green.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 07:38:05 +02:00
Meta Vens
104c0bf255 Close Cut 10 on its stated invariants, and name the residue
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 07:09:53 +02:00
Meta Vens
4f41706f3d Record the Cut 10 fourth fix batch, and correct the S1d claim
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 06:17:15 +02:00
Meta Vens
9d3a3efd56 Fill the F6 gap in its owner: a public slug door on Slug
Slug::validate_slug applies the crate's own dotted_text grammar, the
same check every Slug field is held to, following PipelineRef::validate_ref's
pattern. Named validate_slug rather than validate so it does not shadow
Bounded::validate for in-crate callers.

Adds a leaf test covering one valid dotted name and refusals for fullwidth
characters, .., both path separators, the empty string, and an empty label.

Self's ruling on the F6 fork, 2026-09-22: fill the gap in its owner rather
than leaving Huginn's PipelineInstance wrapper beside it.

Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
2026-09-22 04:30:33 +02:00
Meta Vens
b4aab3f7c3 Record Soul on the third fix batch, and rule the slug check into the leaf
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 04:19:21 +02:00
Meta Vens
ed36236f72 Record the Cut 10 third fix batch, and flag the slug check living beside its owner
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 03:24:12 +02:00
Meta Vens
ff8ba146f8 Record Soul on the Cut 10 second fix batch: separator folding admits the wrong mind
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 02:36:59 +02:00
Meta Vens
5743fcf4be Map the body plane for oversize answers: three cuts, two questions
Imagination's map (Opus), placed by Self. BP-1 gives cultnet-rs the reference's
content-plane chunk messages; BP-2 moves the pins together; BP-3 makes the
daemon defer an oversize answer instead of refusing it. Q-BP1 (which physical
path) and Q-BP2 (what the summary is) are open for the operator. BP-1 waits on
selection Cut 1's Rust commit, because both edit cultnet-rs contracts.rs.

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-22 02:01:23 +02:00
Meta Vens
2876a82799 Send the harness to the repo that owns the process
It lived here because this repo needed it first, and the memory organ had been
reaching across a boundary for it. It takes the repository as a parameter, so
one copy serves every campaign and a fix to it fixes all of them.

Every earlier reference here to the Epiphany path is history and no longer
resolves.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-17 02:39:04 +02:00
Meta Vens
9cfbdeb314 Pin the arm that was recorded as unpinnable
The paragraph explaining why that dispatch arm could not be pinned is deleted
from the code and from the entries header, because it was wrong, and the probe
that disproved it is now a committed test. The size gate is pinned on its
boundary rather than near it, and an instance name that differs only in case
stands beside the ones that differ in length and prefix.

All six new entries survived the shipped suite before this batch, so none of
them is a mutant that could never have failed. The entry count recorded here
was wrong and is corrected from the file itself.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-17 01:31:26 +02:00
Meta Vens
ca17451a26 Rule the oversize document onto the body plane
A body the control plane cannot carry travels the transfer that exists for
exactly that, and the control plane carries the summary and a reference to it.
Raising the window only moves a number we would keep revising, and bounding
documents smaller argues with what a cut spec honestly is.

The refusal stays as the backstop. A caller that cannot be given an answer is
told so by name rather than left listening to silence.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-17 01:05:16 +02:00
Meta Vens
d138bf73de Record Soul on the fix batch, and a gap that was not one
The measurements hold under an independent probe and the transport itself
agrees, so the document that cannot be read back is a fact rather than an
inference. The gate refuses exactly where the transport gives up, and the
refusal is small enough to always arrive.

The arm reported as impossible to mutate was not. A probe built from the
crate's public surface kills both mutants, and it gets committed, because a
kill that lives in an agent's scratchpad is not evidence anyone can rerun.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-17 00:59:31 +02:00
Meta Vens
3325f515c8 Rule the read side: ordinals, deletions, and titles in the leaf
A receipt now records where it falls in the order, so a page is a position
rather than a guess, and the store takes the version that costs nothing today.
The two hardcoded endpoints go rather than surviving as presets of the thing
that replaced them. The leaf gains titles, because a catalog row showing only
an identifier is not a catalog, and it rides the same version bump instead of
asking for a second one.

The vocabulary itself is not ours: it fills the hole in CultNet, and the organ
becomes a consumer of it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-17 00:37:16 +02:00
Meta Vens
67947a29fa Record the Cut 10 fixes and the document that cannot be read back
An answer too large to send is now refused by name instead of vanishing, and
the three rules that were pinned by fixture luck are pinned by fixtures that
resemble each other. Measuring the refusal turned the size question into a
different one: a cut spec at the leaf's own bounds does not fit, so admission
accepts a document this door can never return. That is an asymmetry rather
than a limit and it goes to the operator.

One mutation entry was refused rather than faked, and the reason is written
where the next reader will find it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-17 00:25:58 +02:00
Meta Vens
7cc18fcb3a Keep the prior-art facts where they can be reread
An Eyes pass established what already exists for a typed query surface, inside
the substrate first and in published work second, with an evidence pointer for
every claim. It found no reusable shape in our own runtimes, three flat option
structs invented independently because no general one exists, and a citation
hop query we built and deleted with its host surface rather than on its merits.

It lands in the repository because a facts file that lives only in a scratchpad
is the same failure as a harness that lives only in a scratchpad, which this
campaign has now paid for twice.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-17 00:21:47 +02:00
Meta Vens
44f89035a7 Record Soul on Cut 10, and rule that a large answer refuses
The organ answers typed refusals over the wire and holds no rule beside the
mind, which is what the cut was for. It also loses any answer too large for
the window, without a word to the caller, and the spec's idea of document size
was never the leaf's. A response that will not fit is now refused by name,
carrying its size and the limit, and the window rises to the worst case a
single document can reach. No truncation, no pagination the caller did not
ask for.

Three rules turned out pinned by luck rather than by tests, among them the
instance check, whose mutants survived because no fixture pair had ever shared
a length.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 23:43:22 +02:00
Meta Vens
b1e919e6f6 Record Cut 10 and the nine places the map was wrong
The organ answers over the hub, the daemon holds no rule of its own, and the
instance check has one owner. Every discrepancy this cut hit was the map's
rather than the Body's, including a constant that does not exist in CultLib
and a mutant that could not fail because the thing it broke released the port
on its way out.

Several loosening mutations the brief required turned out unfalsifiable and
were replaced. That replacement is the first thing Soul is told to attack: a
loosening swapped for an easier target is a hole wearing a green tick.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 23:18:00 +02:00
Meta Vens
add4f9d093 Write the schema-phase postmortem
Epiphany's stake in the campaign closed with the leaf owning the schemas and
nothing else. The record keeps the scars: a store deleted whole after the
operator rejected it, a grammar redesigned on its third patch, a fix that
introduced a replay regression, a harness that ate the work it was testing,
and the five corrections the operator had to make to the agents' model.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 22:46:17 +02:00
Meta Vens
c6d24a44ea Record the ref validator and rule where the grammar stops
One door now opens onto the reference grammar, and both read doors refuse a
ref that is no ref before answering over it. The leaf owns the shape of an
id; per-kind local shape stays with admission, where the sequence rules
already live, and a resolution's key is derived rather than written, so
nothing malformed reaches the write path. The status header is rewritten to
what has actually landed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 22:44:32 +02:00
Meta Vens
5cda0886bd Open one door onto the reference grammar
Ruling 1 leaves the schemas and the key grammar with the leaf, and the read
side in Huginn must refuse a `PipelineRef` whose kind and id disagree rather
than answer the nothing a lookup finds. `Bounded` is `pub(crate)`, so nothing
outside could ask.

`PipelineRef::validate_ref` delegates to that impl at the field name `ref`, so
the grammar keeps one owner and the wrappers and `pipeline_id` stay where they
are. A method, as `prepare` and `decode` are, because it concerns one public
type; `validate_ref` rather than a bare `validate`, because an inherent
`validate` would shadow `Bounded`'s for every in-crate holder of a
`PipelineRef`.

The test holds every sample document's own key to be a reference of its own
kind, and refuses a kind that is not the id's and a trailing dot at `ref.id`.
It also pins the boundary rather than assuming it: a resolution id missing the
per-subject sequence its writer always composes is still well formed here. The
leaf reads an id kind-deep, and the local's per-kind shape is admission's rule.

Entries R1 and R2 in `tools/eureka-cut8-epiphany-mutations.psd1`: the door that
answers `Ok(())` to everything, and the door that reads the kind segment alone.

`cargo test -p epiphany-pipeline --lib` 34 passed, 0 warnings; `cargo check -p
epiphany-core --lib --tests` clean; the four Epiphany suites green-and-killed
through the harness. No schema and no lock moved.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 22:31:26 +02:00
Meta Vens
01cf2d4482 Rule Q22 and Q23: request/response over the hub, presence after deploy
The organ's surface is request and response over CultNet's hub, since
admission and typed queries are request/response by nature and a
publication cannot reply from its sink. The Eve operator surface lands as
its own cut after the daemon lives beside Odin, so the advertisement is
built against a Verse that exists.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 22:25:01 +02:00
Meta Vens
9d63f0dc55 Refresh Cut 10 against the landed organ
The daemon is one process over one mind: it opens the owned store, binds
one socket, and serves admission and the read side over CultNet through
the hub, with the wire vocabulary in the organ's library per Q13. The
instance check moves to one place both admission and the reads call. The
index seam is a port with a no-op impl whose error cannot change an
outcome. Two questions for the operator: the surface's shape, and where
the Eve operator surface lands.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 22:20:25 +02:00
Meta Vens
c1ae5cdf10 Close Cut 9 and mark the design sections it supersedes
The read side lands on one owner for in-force, which the same mutant
proves by failing both suites. History is a first-class view in sequence
order with withdrawn records and their reasons, as the Q17 ruling
required. Soul held every promise and found two loosenings the entries
file had called unfailable, and one fixture the open-items test needed;
all three are bounded and in Hands. The design sections D4, D6 and D7 now
say which of their sentences the landed code made false.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 21:59:54 +02:00
Meta Vens
fb18395fe3 Close the Cut 6d follow-up
A replayed hand-off withdraws the assignment it withdrew, found by
content, and the arm no path could reach is gone. Forty-six tests,
sixty-seven entries killed. One tooling scar recorded: the Bash tool
mangles a Windows target-directory path, so cargo here runs through
PowerShell only.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 21:00:02 +02:00
Meta Vens
b2d4f16d67 Refresh Cut 9 against the landed organ
The read side takes the derivations admission already owns by moving
them whole into one module both call, so one mutant kills both suites.
History is a first-class view in sequence order with withdrawn records
and their reasons, which is what the Q17 ruling required. Two of the old
five functions die as query presets. No text filter until the index
exists.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 20:59:07 +02:00
Meta Vens
00624c8f24 Close the Cut 6d follow-up well enough to map Cut 9
Replay reproduces what it derived and a withdrawal cannot reinstate over
a later record, under scopes Hands extended to targets and cut specs when
the brief's own test needed them. Soul's scoped pass found the replay
still picking the wrong subject past nine transfers of one repo, and a
dead arm; both land before Cut 12. A replay refusing once its scope has
advanced is recorded as a ruling-20 limit the views must not hide.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 20:44:50 +02:00
Meta Vens
94df3a8fc7 Record Soul's pass on the Cut 6d follow-up, and rule the reinstatement case
The reopen and transfer paths hold over real stores. Two things do not:
replaying a batch that derived a write is refused instead of answered
from its receipt, and a withdrawal of a withdrawal can put an earlier
record back in force beside a later one. The second gets a rule that
extends Q19's own rationale. The depth cap's wording is corrected to the
nesting reading the code and the ruling implement, and Cut 12 learns that
history imports one record per batch.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 20:10:48 +02:00
Meta Vens
1e11427425 Record the Cut 6d follow-up and bring Cuts 8, 9 and 12 to the ruled shape
The organ now enforces the sequences, ignores withdrawn resolutions when
deciding what is in force, and refuses a withdrawal of a withdrawal. The
Cut 8 rule table says so instead of describing the collision-based shape
it replaced; Cut 9 carries the recursive derivation and the history views
the Q17 ruling requires; Cut 12 says withdrawal rather than supersession
and models no return.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 19:47:28 +02:00
Meta Vens
d5a36c2a29 Pin the two sequences the all-ones fixtures hid
Soul's pass over the Cut 6d suite found two rules nothing tested. Every
nested fixture sat at `sequence: 1` at both levels, where a resolution's own
sequence and the one its subject already ends in are indistinguishable, so a
mutant that copies the subject's survived. And no test resolved a
stewardship, the other sequenced kind, so nothing held its own sequence into
the resolution key the way M27 holds a nested resolution's.

Two tests. `every_level_of_a_nesting_keeps_its_own_sequence` builds a chain
that differs at every level -- `question.Q1.n9`, then `.n10`, `.n0`, `.n12`
-- and reads it back level by level, each level's subject recovered whole and
each level's own sequence last. `a_resolution_of_a_stewardship_reads_back`
resolves both assignments of one repo, pins the two keys apart, and nests a
withdrawal over each. Entries S6 and S11 carry the mutants they kill.

The nesting test's doc comment records the spelling limit while it is in
hand: the leaf emits `n<N>` as `u32` writes it, so `n01` is never emitted,
but a hand-built id ending `n01` or `n1x` is a legal label and no business of
a grammar that reads keys. Nothing canonicalises it either -- it names a
document the leaf would never key, which admission's A7 reads as a missing
referent.

Suites: 6d seven entries killed, M0 green; 6b, 6c and cut8-epiphany
unchanged and green. 33 tests, no warnings.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 19:20:24 +02:00
Meta Vens
ded1a81c91 Record Soul's pass on the Cut 6d leaf half
Every code promise held, including that a subject whose own local ends in
something shaped like a sequence cannot be confused with one. Two coverage
gaps sit on the paths the next cuts lean on and land with the Huginn
follow-up that moves the pin.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 19:10:02 +02:00
Meta Vens
32fbea4797 Record the Cut 6d leaf half
Resolutions and stewardships carry a writer-set sequence that ends their
key, so a subject's history and a repo's history each sit under one
prefix. The leaf makes the key and compares nothing; admission owns the
next-number rule. Two schemas regenerated, no epoch moved, every earlier
suite still killed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 18:45:47 +02:00
Meta Vens
b82c76dfd6 Add the Cut 6d mutation suite
Five entries, each restoring the permissiveness the shape it pins
removed: M23 and M24 the one-per-subject and one-per-repo keys, M25 and
M26 the sequence anywhere but last, M27 a nested subject stripped of its
own sequence on the way into the key. Each dies on the test named beside
it, M0 green.

The file records what has no entry and why: the `n` marker is a fixture
pin, the `u32` type has no runtime mutation, and date-invariance is
covered by M24's test asserting a stewardship local is exactly two parts.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 18:37:12 +02:00
Meta Vens
9699751f00 Key a resolution and a stewardship by sequence
A subject's resolutions and a repo's assignments on a mind each carried
one key, so the second record of either overwrote the first and a
withdrawn resolution could not be kept under its subject. Both keys now
end in a writer-set `sequence: u32`, `n<N>`, last so the history of a
subject or a repo is one key prefix and R2 keeps that prefix exact:
`question.Q1.n` cannot match `question.Q10.n1`, and a withdrawal keys one
nesting out under the resolution it withdraws.

`assigned_on` stops being a key input and stays a field, validated where
every field is, so the same assignment recorded on two days is one
document and a repo transferred away and back on one day does not
collide. A hand-off is unchanged in shape and key: a transfer back is the
same document with the instances swapped, and no field names a return.

Nesting arithmetic moves with the shape: each nesting prepends
`resolution.` and appends `.n<s>`, so a chain composes `14 * (d - 1) + L`
bytes against `LOCAL_MAX`, and both fixtures key four deep. The leaf
refuses no sequence value -- not `0`, not a gap -- as it refuses no
`revision` value; which sequence a document may claim and which record is
in force are admission's, and are not in this crate. `pipeline_id` gains
no arm and no key is parsed back.

Two schema files regenerate from the derivation, gaining the property,
the required entry and the new doc comments. No epoch moves: no store is
written at this epoch and no reader is pinned to the file.

Cut 6b's M2 is re-anchored on the new parts line, as N7 and N8 re-anchored
Cut 6's M12 and M13.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 18:26:46 +02:00
Meta Vens
ceeffabf26 Close Cut 8 as ruled today
Every promise of the fix batch held under non-revert mutations. What
remains belongs to the key-sequence follow-up: a withdrawal of a
withdrawal is not yet refused, and reopening a subject needs admission's
in-force derivation to ignore withdrawals as well as the key to allow a
second number. Six test gaps ride with it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 18:25:50 +02:00
Meta Vens
b693f9f3b3 Map Cut 6d: resolution history and stewardship by sequence
Two key shapes gain a writer-set sequence so a subject's resolutions and
a repo's stewardships keep their history under one prefix, with the
in-force record derived as the latest not withdrawn. A hand-off stays a
transfer with no lease field. Two schema files regenerate, no epoch moves,
and the Huginn follow-up commit is named for when the pin moves.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 18:19:25 +02:00
Meta Vens
542dc1848c Rule Q19 and Q20: no double withdrawal, and stewardship by sequence
A withdrawal is final and a reopened subject resolves again at the next
number. Stewardship keys by a per-repo sequence rather than a date, so
two transfers of one repo in one day do not collide and both histories
use one mechanism. Q18's substance stands; its wording is superseded.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 18:12:16 +02:00
Meta Vens
e306964d04 Record the Cut 8 fix batch
The epoch gate checks what the spec said it checks, the organ mints no
leaf refusal, one swap and every strong read are pinned, and every rule
row the suite could not see regress now has a mutation. Self's Q17
default was reverted before it mattered. The gap the ruling leaves until
the leaf's key sequence lands is named as the reason Cut 6d precedes Cut 9.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 18:08:48 +02:00
Meta Vens
ec0ff804bc Make Q17 carry its own conditions
The operator questioned the model behind keeping withdrawn resolutions.
The answer is that the ruling matches the campaign's standing rule of
never overwriting, and that the record only earns its keep if Cut 9 shows
a subject's history and Cut 11 indexes withdrawals with their reasons.
Both are now requirements on those cuts.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 18:04:58 +02:00
Meta Vens
76167f0a2a Correct Q18: a hand-off is a transfer, not a lease
Self read the operator's lease example as the general case. It is one
case: a steward can also spin off a new steward permanently. A hand-off
is a transfer of stewardship with no lease field; a lease is two of them.
The date-keyed stewardship stands because it is what lets a repo come
back at all.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 17:59:53 +02:00
Meta Vens
993600fd6b Rule Q17 and Q18 in the operator's words
A resolution is the record of how a subject was closed; withdrawn ones are
kept under the subject and a subject can be resolved again. A hand-off is
a lease: a campaign's steward borrows another steward's authority over a
repo and returns it. Both are key changes in the leaf, free today, mapped
together as one cut. Self's default on Q17 was withdrawn before it landed.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 17:56:34 +02:00
Meta Vens
87d3420c31 Record Soul's Cut 8 pass, and raise Q17 and Q18
The owners hold at the layer where they fail: a mind copied under another
instance is refused, a second process is refused, and the digest moves
with content alone. What did not hold was the epoch gate, which took the
first record and checked nothing about it, and fifteen rule rows the suite
could not see regress. One sentence of the spec contradicted the key
grammar and becomes a question: whether a resolution can be undone.
Another surfaces for Cut 12: whether a stewardship can come back.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 17:45:42 +02:00
Meta Vens
3bd0826d48 Rule out a hidden dependency on the leaf
The workspace's inverse dependency tree lists the leaf alone in every
dependency kind, so the recompile of epiphany-core after a leaf-only
change was a shared target directory evicting a fingerprint under another
session's build, the accepted cost of sharing one directory. Not a
dependency, and not the explanation Hands gave.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 17:28:03 +02:00
Meta Vens
32b638dcec Record the leaf's serialisation derives, and a recompile that should not have happened
The document and refusal types now serialise with a tag equal to the kind
name, which is what lets Cut 10 carry a batch without a second registry.
An unexplained recompile of epiphany-core after a leaf-only change is
recorded as suspect for the next Soul, not accepted on the explanation
offered, because the core is not a dependent of the leaf.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 17:27:31 +02:00
Meta Vens
b4b17fc895 Serialise the pipeline envelope and its refusals
The leaf owns the document and refusal types, so it owns their
serialisation. Huginn's admission batch cannot derive Serialize while
PipelineDocument does not, and mirrors PipelineRefusal through a
serde(remote) definition kept in step by hand; neither is the wire's
business.

PipelineDocument is adjacently tagged on the kind name: a document on a
wire is { kind, value }, and kind is exactly PipelineKind::name(), so a
reader dispatches on the kind segment it already knows from the key and
needs no second registry mapping variant spellings to kinds. Adjacent
rather than internal because a value is a named map of its own.
PipelineRefusal stays externally tagged, serde's default, which is what
keeps every variant's field and value on the wire under their own names.

No kind, field, type id or epoch moves, and the published per-kind
schemas are untouched: the envelope is the wire's shape, not a document's.

every_document_and_refusal_serialises_and_reads_back round-trips every
sample document and every refusal variant through serde_json and
rmp_serde, and holds each derived schema's variant list to the thirteen
kinds by name and to the four refusals. Mutations D1 (the tag rename
removed) and D2 (a refusal's field skipped) are both killed by it.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 17:26:30 +02:00
Meta Vens
dfbc5700bc Record the Huginn half of Cut 8
The organ opens a mind fail-closed over CultCache's owned store, lands a
batch whole with a receipt naming its bytes, and admits through one
ordered path with every cross-document rule in it. Twenty mutations,
twenty killed, inside the build budget. One finding for Cut 10: the leaf
must derive serialisation on the document and refusal types before a
batch can cross a wire.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 17:21:09 +02:00
Meta Vens
78238ebabc Record the harness repair batch, and say whose lock it is
The harness now handles a sidecar that outlives its file and a nested
sidecar without a raw exception, and the leaf's doc comments describe the
leaf. Cut 8's store paragraph now says the single-writer mechanism is
CultCache's owned store and its compare-and-swap batch, with redb as the
engine beneath, after the operator caught the misattribution.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 16:55:19 +02:00
Meta Vens
aef0e1bf5a Describe the pipeline leaf by its own contract, not by Huginn
Doc comments only. The crate doc, `prepare`, `register_pipeline_document_types`,
`ForeignDocument`, `PIPELINE_SCHEMA_EPOCH` and `validate_pipeline_write_envelope`
spoke of "the memory organ" and "Huginn" in the present tense as a consumer
that exists; Huginn's crates are empty stubs at this commit. Each now says what
the item does and guarantees, and where a consumer must be named, calls it the
organ that will admit these documents. The sentence claiming Huginn pins the
foreign-document rule against its real receipt type is gone; no such test
exists.

`decode` now says what it does not do: it validates neither bounds nor the
key. A decoded document is a typed read, and `validate_pipeline_write_envelope`
is the check before a write.

No code change: `cargo test -p epiphany-pipeline --lib` is 27 passed with no
warnings, and `schemas/cultnet/` and `Cargo.lock` are untouched.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 16:54:16 +02:00
Meta Vens
b3bd4a82e4 Repair a missing file from its sidecar and stop on a nested one
Soul's XF: a sidecar whose file was gone hit the `if`/`else` empty-array
collapse of Windows PowerShell 5.1, so `Find-FirstDifference` threw a raw
`ArgumentNullException`, the sidecar stayed, and every later run in that
repo died the same way before M0. A missing file is now its own case,
decided before any comparison: it is recreated from the sidecar, whose
bytes are the only copy, hash-verified, and the run says so.
`Find-FirstDifference` refuses a null array with the harness's own words.

Soul's XG: a sidecar of a sidecar was repaired in enumeration order, so
the inner sidecar's body became the file and the outer one then crashed
on its missing target. No run leaves that shape and the two cannot be
ordered, so the repair pass now stops before touching anything, naming
both files.

Soul's F2: the `.eureka-mutation-overwritten` copy was written before the
restore was attempted, so a locked target (XC) left a copy claiming an
overwrite that never happened. The copy is still written first, because
once the restore lands it is the only home of the pre-repair bytes; a
restore that fails without opening the file removes it again, and one
that changed the file before failing keeps it and says so.

Every repair step now sits inside one `try`/`catch` per sidecar, so the
"could not repair" message is the error that escapes, with the cause
appended, never a bare .NET exception.

Reproduced against a scratch copy with Soul's soul-cut8e-harness-attack:
XF recreates the file and removes the sidecar; XG stops with both files
named and the target untouched; XC leaves no overwritten copy. XA, XB,
XD, XE, XH, XI unchanged. An empty existing file beside a sidecar (XK)
repairs without the null path.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 16:51:14 +02:00
Meta Vens
0b8d60a685 Record Soul's pass on the Epiphany half of Cut 8
The door holds from outside: the four functions and the constant are
reachable, the wrappers and the id reader are not, and every kind
round-trips through the public path with its own key. Huginn pins
a65c6420. What Soul found is a harness that crashes without a word when a
sidecar outlives its file, and doc comments that describe an organ nobody
has built yet.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 16:46:25 +02:00
Meta Vens
5a71c4bb3e Rule Q13 and Q15: types from huginn-mind, and mind.redb
The client depends on the organ's library for types only, pinned by a grep
that it never opens or admits. The mind file is named for the engine that
holds it, because the selector and Studio both key on the extension. The
engine's provenance is recorded beside the ruling so nobody asks again.

Co-Authored-By: Claude Fable 5.1 <noreply@anthropic.com>
2026-09-16 16:39:16 +02:00