Place the read-side consumer map, record the residue batch, fix BP-3's orphan claim
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
parent
b3ae787b7d
commit
9701b8eedf
3 changed files with 1260 additions and 2 deletions
|
|
@ -515,7 +515,7 @@ format or JSON schema file (see section 5).
|
|||
|
||||
| Add | Owner | Live consumer | Protected invariant | Why an existing owner cannot serve |
|
||||
|---|---|---|---|---|
|
||||
| `huginn-mind/src/wire.rs:81-90`: `HuginnMindResponse::Deferred(DeferredAnswer)` with `DeferredAnswer { manifest: CultMeshCdnArtifactManifest }` under Q-BP2 A, or plus the typed summary under B; `status()` (`:97-102`) answers `accepted` for it. A hand-written `JsonSchema` for the manifest inside Huginn, as the selection consumer cut does for `Selection`. `schemas/cultnet/huginn.mind_response.v1.schema.json` is regenerated. **The schema id stays `v1`**, because no client of it exists (Cut 13 is unbuilt) | `huginn-mind` (types only) | the daemon, Cut 13 | the reference rides the response schema, so there is no second vocabulary for a client | `HuginnMindResponse` is the only response a client decodes |
|
||||
| `huginn-mind/src/wire.rs:81-90`: `HuginnMindResponse::Deferred(DeferredAnswer)` with `DeferredAnswer { manifest: CultMeshCdnArtifactManifest }` under Q-BP2 A, or plus the typed summary under B; `status()` (`:97-102`) answers `accepted` for it. The manifest's schema is embedded through a `#[schemars(schema_with)]` field attribute returning a `$ref` to its published schema, as the selection consumer cut now does for `Selection` (corrected 2026-09-22: a hand-written `impl JsonSchema` for a foreign type is `E0117`, the orphan rule). `schemas/cultnet/huginn.mind_response.v1.schema.json` is regenerated. **The schema id stays `v1`**, because no client of it exists (Cut 13 is unbuilt) | `huginn-mind` (types only) | the daemon, Cut 13 | the reference rides the response schema, so there is no second vocabulary for a client | `HuginnMindResponse` is the only response a client decodes |
|
||||
| `huginn-daemon/src/bodies.rs` (new), `DeferredBodies`: a map from chunk hash to bytes with reference counts, and a map from content hash to `(chunk hashes, bytes, last_touched)`. `retain(manifest, chunks, now)`, which is idempotent on the content hash and refreshes it; `chunk(hash, now) -> Option<&[u8]>`, which refreshes the owning bodies; `expire(now)`; eviction least-recently-touched first when the total is over budget. Constants: `DEFERRED_CHUNK_BYTES = 256 * 1024`; `MAX_DEFERRED_BODY_BYTES = 64 MiB`; `DEFERRED_BUDGET_BYTES = 256 MiB`; `DEFERRED_TTL = 60 s`, which is twice `session_timeout`, and is a field of `ServeOptions` (`:70-79`) with that default | `huginn-daemon::serve` | `deliver`, `answer` | retention is bounded in bytes and time, and a body is never evicted while its chunks are being served within the TTL | The mind must not hold transport artifacts. `cultnet-rs` owns no retention policy, and should not, because the policy is this service's memory budget |
|
||||
| `serve.rs`: `deliver(reply, message_id, operation, runtime_id, bodies, now)` replaces `within_window`. It encodes the envelope. If the envelope is `<= MAX_RESPONSE_BYTES`, the reply is sent unchanged. Otherwise it takes the **payload bytes**, the named MessagePack of the response. If they are `<= MAX_DEFERRED_BODY_BYTES`, it calls `pack_content("huginn.mind_response", "package", "", "application/vnd.gamecult.huginn.mind-response+msgpack", now, payload, DEFERRED_CHUNK_BYTES)`, then `bodies.retain`, and answers `Deferred`. Otherwise it answers `Refused(ResponseTooLarge { bytes: payload_len, limit: MAX_DEFERRED_BODY_BYTES })` | `huginn-daemon::serve` | `answer` | **the one owner of how an answer is delivered.** Three outcomes, in that order, and nothing else decides | — |
|
||||
| `serve.rs:165-194`, `answer`: a new `CultNetMessage::ContentChunkRequest` arm calls `cultnet_rs::answer_content_chunk_request(request, \|h\| bodies.chunk(h, now))`. The error text at `:188-192` names the third family. The signature gains `bodies: &mut DeferredBodies`, and `run` (`:257-305`) owns one and passes it | `huginn-daemon::serve` | the client's fetch | a chunk is answered on the requester's own session, like every other frame | — |
|
||||
|
|
@ -651,7 +651,7 @@ format or JSON schema file (see section 5).
|
|||
- Removes about 35 lines (`within_window` 35, the stated-limit doc 8) and
|
||||
8 mutation entries.
|
||||
- Adds about 190 lines: `bodies.rs` about 110, `deliver` about 35, the
|
||||
`answer` arm 8, the wire variant with its hand-written `JsonSchema` about
|
||||
`answer` arm 8, the wire variant with its `schema_with` `$ref` about
|
||||
35.
|
||||
- Tests are about +220 net over the rewritten two.
|
||||
- Entries: 8 removed, about 20 added.
|
||||
|
|
|
|||
|
|
@ -545,6 +545,53 @@ schema-ownership phase inside Epiphany, not because the campaign stops.
|
|||
restores the bytes it captured at M0, and never checks whether the current
|
||||
bytes are the mutant it wrote (`eureka-mutations.ps1:163-175, 393, 415`).
|
||||
Fixed in the Eureka repository in the same batch.
|
||||
- **The residue batch landed** (Sonnet). Commits:
|
||||
- Huginn `65c46aa`: seals `path_for`, adds N1 entries on all three sites
|
||||
(`open_with` now dies), the U+2010 fold, and gate fixtures that vary the
|
||||
operation and runtime id independently.
|
||||
- Huginn `f7e0d02`: moves the leaf pin to `b3ae787b`, which carries S5
|
||||
(64-byte bounds and NUL pinned) and S8. The lockfile also picked up a
|
||||
`getrandom` 0.4.3→0.3.4 change as a side effect.
|
||||
- Eureka `5d2bd3e`, H1: the harness saves a mid-run edit as
|
||||
`.eureka-mutation-overwritten`, prints `EDIT LOST`, and fails the run.
|
||||
Demonstrated before and after.
|
||||
|
||||
Tests: mind 65, daemon 20, leaf 35. Every suite is fully killed:
|
||||
|
||||
| Suite | Killed |
|
||||
|---|---|
|
||||
| leaf | 5/5 |
|
||||
| Cut 8 | 67/67 |
|
||||
| Cut 9 | 38/38 |
|
||||
| Cut 10 | 77/77 |
|
||||
|
||||
There is one `cultcache-rs`. **Soul's check of the residue is
|
||||
dispatched.** It covers two things. First, `path_for` became
|
||||
`store_path_for` behind a test-support feature, and a consumer that turns
|
||||
the feature on might reach the bypass again. Second, the lockfile side
|
||||
effect.
|
||||
- **The read-side consumer cut is mapped** at `notes/eureka-read-side-cut.md`
|
||||
(Imagination, Opus). Cuts in order:
|
||||
- **P-1 and P-2:** CultLib, before merge. Now folded into selection's
|
||||
R-G and R-M.
|
||||
- **RS-L:** leaf epoch v2, titles, and the `OrgRepo` and `Label` doors.
|
||||
- **RS-2:** subtraction.
|
||||
- **RS-1:** receipt v2 with ordinals, and the epoch gate moved ahead of
|
||||
the type gate.
|
||||
- **BP-2, widened:** one pin move.
|
||||
- **RS-3:** the consumer, including the value door for S6.
|
||||
|
||||
Its appendix carries the summary type, copied from a session scratchpad
|
||||
that will not survive.
|
||||
|
||||
Probed facts:
|
||||
- The seven old relations each equal one selection.
|
||||
- Admission order cannot be recovered from the clock: 31 receipts carry
|
||||
5 distinct seconds.
|
||||
- Today's opener refuses an old store by the wrong gate.
|
||||
|
||||
**Operator questions Q-RS1 (titles) and Q-RS2 (whether `huginn-mind` may
|
||||
link `cultnet-rs`) are open.**
|
||||
- *History:* **Cut 10 stays open until the fourth fix batch lands** (Hands, Sonnet): N1
|
||||
through the leaf check, one generated separator test for N3, fixtures that
|
||||
vary the operation and the runtime id for N4, and the prose fixes for N5
|
||||
|
|
|
|||
1211
notes/eureka-read-side-cut.md
Normal file
1211
notes/eureka-read-side-cut.md
Normal file
File diff suppressed because it is too large
Load diff
Reference in a new issue