Body facts, model page and rationale for the context-pack cuts in eureka-substrate. The cut specs are the typed record in the mind. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
363 lines
23 KiB
Markdown
363 lines
23 KiB
Markdown
# Context pack: map (eureka-substrate, 2026-10-08)
|
|
|
|
Imagination pass `imagination-context-pack`, session `self-2026-10-08`, for
|
|
ruling `eureka-substrate:ruling:context-pack-resolving-anchors`. Evidence:
|
|
`F:\Projects\eureka-toolcall-patterns-2026-10-08.md` (Eyes facts) and
|
|
`F:\Projects\eureka-context-pack-prior-art-2026-10-08.md` (prior art).
|
|
The cut_specs and the question are the typed record; this page holds body
|
|
facts, the model page and rationale only.
|
|
|
|
Pinned heads: Eureka main `0bb414d92728db61d2d587d749c94970ed2e5582` (also the
|
|
head of `hands/toolcall-relief`, whose changes are uncommitted in
|
|
`C:\eureka-toolcalls`); CultLib `05e67014`; Huginn `6b496eba`; Epiphany
|
|
`4006b14b`; Aetheria `e75083fe`.
|
|
|
|
## Body facts
|
|
|
|
Scratch: `C:\Users\Meta\AppData\Local\Temp\claude\F--Projects-CultLib\8ee3cab1-a20c-498d-a46b-e503a25ac030\scratchpad\cp\`
|
|
(`anchor-map.sh` prototype, `mindview.py`, `mindq.py`, `drift.py`, `all.json`).
|
|
This scratchpad is volatile; Hands re-derives from the specs, not from it.
|
|
|
|
B1. Diff-hunk line mapping resolves a (base, path, start, end) anchor onto any
|
|
later tree with git alone. Prototype `anchor-map.sh` parses `git diff -U0
|
|
<base> <target> -- <path>` hunk headers: hunks wholly before the range shift it
|
|
(MOVED), a hunk overlapping it marks it TOUCHED and widens the range by its net
|
|
lines, no hunk is SAME; `git diff -M --name-status` gives rename (RENAMED) and
|
|
delete (GONE). Target may be a commit or the working tree (`git diff <base>`
|
|
with no second commit). Dependencies: git and awk; no ctags, rg or tree-sitter.
|
|
|
|
B2. Real spec, real drift: `cultmath-tapes:cut_spec:cut-affine-shaders.r2`
|
|
(base `a7966142`) mapped onto `05150acd` (the merge the affine-shaders Hands
|
|
started from). Result: `CultMath.hlsl:509-510` MOVED to 510-511 (the same two
|
|
`#include` lines, checked by `git show`); `GlslMirrorTests.cs:317-319` TOUCHED,
|
|
mapped to 336-340, which is the end of `Families` with snoise-tie's two new
|
|
families inside it (checked); five anchors SAME. The spec's own prose carried
|
|
the workaround: "(GlslMirrorTests.cs:317-319 at a7966142; the lines move with
|
|
the merge)". `cut-huginn-persona-state.r2` carries another: "Hands re-takes the
|
|
anchor at the merged 13a/13b tip".
|
|
|
|
B3. Anchor accuracy at base: the four affine-shaders anchors read at
|
|
`a7966142` show exactly the code each `change` names
|
|
(`cultmath_iv_snoise_ball(float3, float)` at Interval.hlsl:83-89, the
|
|
`InlineData` list at HlslMirrorTests.cs:64-68, the presence asserts at
|
|
HlslSourceCompatibilityTests.cs:34-35, the Interval.hlsl lines in
|
|
build-unity-package.ps1:86-87). Imagination's line numbers are right at base;
|
|
what goes wrong is drift.
|
|
|
|
B4. Drift across the whole mind (`drift.py` over `all.json`: 203 cut_specs,
|
|
143 cut_reports, 1,260 file_changes). For every spec with a report and a local
|
|
repo, each file_change was mapped from `spec.base` to the first report's
|
|
`range.base`, the tree Hands started on. 557 anchors: SAME 444 (79.7%),
|
|
MOVED 64 (11.5%), TOUCHED 17 (3.1%), path absent at base 32 (5.7%). All 32
|
|
absent paths exist at the report head: they anchor files the cut creates
|
|
(none were typos). No base was unreachable. By repo: gamecult-site 55 of 125
|
|
drifted (44%), CultLib 17 of 245, Aetheria 5 of 127, Idunn 3 of 24, Bifrost 1
|
|
of 19, Epiphany, gamecult-ops and Huginn none. So about one anchor in seven was
|
|
stale when Hands first read it, concentrated in campaigns whose cuts land in
|
|
parallel.
|
|
|
|
B5. Worktree, rename, delete and failure probes (scratch clone of Eureka at
|
|
`0bb414d`): two lines inserted at 100 and line 185 edited, uncommitted:
|
|
`briefs.md:50-60` SAME, `180-190` TOUCHED to 182-192, `300-310` MOVED to
|
|
302-312. A staged `git mv` reads SAME+RENAMED; a staged `git rm` reads GONE.
|
|
Unreachable base prints `UNRESOLVED base <sha> not in this clone: git fetch
|
|
origin <sha>`; path absent at base prints `UNRESOLVED <path> absent at base`.
|
|
Limit: an unstaged delete plus an untracked new file is not detected as a
|
|
rename (git's rename detection needs both sides in the index or a commit).
|
|
Windows Git Bash prints an LF/CRLF warning per diff on stderr; the tool must
|
|
discard stderr of these calls. Line numbers are unaffected by CRLF.
|
|
|
|
B6. Cost: rename detection over a whole tree takes about 0.5-1 s per call on
|
|
Aetheria (`git diff -M --name-status`), so the drift script, which ran it per
|
|
anchor, took over 10 minutes for 557 anchors. The tool runs it once per
|
|
invocation and one `-U0` diff per distinct path.
|
|
|
|
B7. Symbol by name alone is not an identity. `git grep -W` with git's csharp
|
|
driver (supplied without touching the repo through `git -c
|
|
core.attributesFile=<file>`) prints the whole enclosing function, but the
|
|
probe name `Dispose` matched several members in one file
|
|
(`CultMeshContentSessions.cs`), and a bare name has no namespace. A symbol is
|
|
usable as a check that the resolved window contains it, and as the key for a
|
|
caller list, not as the anchor itself. Git's built-in funcname drivers cover
|
|
csharp, rust, python, kotlin and cpp (usable for HLSL/GLSL), and none covers
|
|
TypeScript.
|
|
|
|
B8. Tool availability. Starfire: Exuberant Ctags 5.8 (Strawberry Perl; no
|
|
TypeScript, Kotlin or HLSL), rg (Codex's copy), no tree-sitter, Python 3.13
|
|
via `py -3` (no `tree_sitter` module), git 2.53, gawk, perl. Yggdrasil host:
|
|
git 2.47, python3, awk, perl; no ctags, no rg. So git plus the Python standard
|
|
library is the only toolset common to both.
|
|
|
|
B9. Caller lists: `git grep -n -w -F <symbol>` takes about 0.4-0.6 s on CultLib
|
|
and Aetheria. `cultmath_iv_snoise_ball` has 20 hits in 8 files, including docs
|
|
and fixtures. `Dispose` has 386 hits, so a caller list needs a cap, and above
|
|
the cap it needs per-file counts rather than lines (SWE-agent: more than 50
|
|
results returns none and asks for a narrower query).
|
|
|
|
B10. Unity YAML: across the three most-modified Aetheria prefabs, fileIDs
|
|
(`--- !u!<class> &<id>`) are unique within each file and survive edits
|
|
(Djinni.prefab at 122e9292: 440 of 446 ids shared across a 91-hunk commit;
|
|
Inventory 116 of 116; Longinus 107 of 107). Diff-hunk mapping works on YAML
|
|
as on code. `&<fileID>` is a good symbol for a YAML anchor.
|
|
|
|
B11. The spec can be read without the model copying it. `mindview.py` spawns
|
|
`~/.eureka/bin/eureka-state.exe` (the binding in `~/.claude.json`
|
|
`mcpServers.eureka-state`: command plus `EUREKA_INSTANCE` and
|
|
`HUGINN_ENDPOINT`), speaks MCP JSON-RPC over stdio (initialize, initialized,
|
|
tools/call view) and prints the document, in 1.3 s. eureka-state has no CLI
|
|
mode of its own (`crates/eureka-state/src/main.rs:298`, stdio MCP only).
|
|
|
|
B12. Schema facts for a typed home. `CodeLocation { path: Short, line: u32,
|
|
end_line: Option<u32> }` (Epiphany `epiphany-pipeline/src/lib.rs:463`) is
|
|
shared by cut_spec file_changes, finding and follow_up locations, and mutation
|
|
records. The epoch doc (`lib.rs:879-886`) says evolution is additive at
|
|
`epiphany.pipeline.epoch.v2`: "a new named field with a serde default". No
|
|
`#[serde(default)]` exists in the leaf yet, so the `value_types!` macro has
|
|
never carried one. Huginn pins the leaf by git rev
|
|
(`crates/huginn-mind/Cargo.toml:22`, `ef956865`), so a field reaches the mind
|
|
only after a leaf change, a Huginn re-pin and a daemon plus eureka-state
|
|
redeploy.
|
|
|
|
B13. The Hands brief already asks for a hand-made pack: "Orient in one script.
|
|
One Bash call prints git status, the base and the spec's anchor ranges (`sed
|
|
-n`)" (briefs.md:276-278 at 0bb414d). That reads the frozen line numbers, so it
|
|
reads the wrong lines for the one anchor in seven that has drifted (B4).
|
|
|
|
B14. Prose `path:line` references in spec text (first, adds, keeps_moves,
|
|
change): 224 across 99 of 203 specs. Imagination already writes read anchors
|
|
inline, untyped (for example "as iv_frustum_ball's FrustumBall check
|
|
(GlslMirrorTests.cs:191) does").
|
|
|
|
## Model page
|
|
|
|
| Kind | Identity | Lifecycle | Authority |
|
|
|---|---|---|---|
|
|
| Edit anchor | `(cut_spec id, file_changes index)`; content `(spec.repo, spec.base, path, line, end_line)`. Namespace: the spec's repo at its base commit, which is injective: one path and range at one commit. A short `base` is resolved with `git rev-parse --verify <base>^{commit}`, and ambiguity is a loud failure. | Created with a spec revision and immutable. Changed only by revision N+1 with a superseding resolution. Its position at a later tree is derived at read time, never stored. A path absent at base is a file the cut creates (B4); it belongs in `adds`, and the tool reports it as NEW. | Imagination writes it (admits the spec). Hands and the tool never rewrite it. A wrong anchor is a deviation in Hands' report and a revision by Imagination. |
|
|
| Read anchor (code to see, not to change) | **Empty cell.** It has no typed home. Today it is prose `path:line` (B14) with no namespace (basenames), no base and no check. | None: it is not a document. | None. This is question `context-pack-read-anchors`. |
|
|
| Symbol (a check and a caller key) | **Empty cell.** A name is not injective (B7). Its only sound role is a needle that the resolved window must contain, plus a caller-list key. | Would be the anchor's. | Same question. |
|
|
| Resolved anchor and window (the expanded pack) | `(spec id, worktree HEAD, working-tree state)`. Derived and never persisted. | Printed into Hands' context. Stale once Hands edits inside it, and re-expanded for edited anchors only with `--since <start sha>`. No cache, no pack file. | `tools/context-pack.py` derives it. Nothing stores it. A stored pack would be a cache pretending to be truth. |
|
|
| The reader tool | `tools/context-pack.py` in GameCult/Eureka. | Lands by Forgejo PR after a Soul pass. Pruned when no brief names it (tools/INDEX.md rule). | Eureka repo. Owns "what Hands sees of a spec's anchors at its tree". It does not own anchors and does not write the mind. |
|
|
| Measurement baseline | The Eyes report above and its scripts (`cls.py`, `an2/an3/an4.py`) under this session's scratchpad `eyes-toolcalls\`. | **Volatile.** The scratchpad is session-scoped, so the scripts can vanish before the re-measure. | Self (follow_up `context-pack-measurement`). |
|
|
|
|
## Rationale
|
|
|
|
**Anchor grammar: base-pinned line range, resolved by diff-hunk mapping.** The
|
|
candidates were: symbol paths (`File::Type.Member`), git funcname (`git grep
|
|
-W`, `git log -L :fn:file`), ctags, tree-sitter queries, LSP document symbols,
|
|
and a text needle plus line hint. Every one of them except the line range needs
|
|
a per-language parser, and most need a dependency that is missing on Yggdrasil
|
|
or on both hosts (B8). Unity YAML has no symbol grammar in any of them, and a
|
|
bare symbol name is not injective (B7). The spec already pins a full
|
|
coordinate, `spec.base` plus `path:line-end_line`, and git can carry that
|
|
coordinate onto any later tree, the working tree included (B1, B5). This is
|
|
the way Gerrit ports review comments across patch sets and GitHub marks a
|
|
comment outdated: the anchor is stored where it was made, and diffs carry it
|
|
forward. It is language-agnostic, needs only git, and fails loudly on every
|
|
path that cannot be carried (base unreachable, path absent, range past EOF,
|
|
file deleted). One anchor in seven needed carrying in practice (B4), and the
|
|
`sed -n` orient step reads those wrong today (B13).
|
|
|
|
**Why the edit anchors are the v1 pack.** file_changes already hold the
|
|
planner's localization at base, accurate when mapped (B3), which is
|
|
Agentless's and ORACLE-SWE's edit-location handoff. The tool turns them into
|
|
SWE-agent-shaped output: one status table first (lost-in-the-middle: the
|
|
summary at the top), then windows of at most 100 lines (the SWE-agent ablation
|
|
optimum; full-file views lost 5.3 points), then caller lists capped at 50
|
|
lines with per-file counts beyond that (the iterative per-hit search lost 6
|
|
points). An output cap keeps the pack from becoming the 20%-more-steps
|
|
AGENTS.md overview (Gloaguen et al.). Re-expansion with `--since` answers the
|
|
re-read finding (54%, 1,198 repeats with no edit in between): the edited
|
|
windows come back fresh and nothing else is reprinted, as in SWE-agent's
|
|
viewer auto-refresh and CORVUS's current-contents registry.
|
|
|
|
**Why read anchors and symbols are a question rather than a cut.** Three homes
|
|
exist: a typed field (an additive `CodeLocation.symbol` and a `reads` list on
|
|
cut_spec, three passes across Epiphany, Huginn plus a deploy, and Eureka, B12);
|
|
a `Pack:` line convention in `first` (free, but structure carried in prose);
|
|
or a sidecar pack file. The sidecar was rejected outright: it is a second store
|
|
with its own lifecycle that goes stale the day a spec is revised. Which of the
|
|
first two, and whether now or after measuring v1, decides schema work in the
|
|
mind's own leaf. The question records options, evidence and a recommendation.
|
|
Nothing in cuts context-pack-tool and context-pack-briefs depends on the
|
|
answer.
|
|
|
|
**Base for the Eureka cuts.** Both cuts edit `tools/test-tools.sh` and
|
|
`references/briefs.md`, which `hands/toolcall-relief` is changing (uncommitted
|
|
in `C:\eureka-toolcalls`; its branch head equals main `0bb414d`). The specs pin
|
|
`base 0bb414d` and anchor at it. Hands starts from main after that PR merges,
|
|
and the first thing context-pack-briefs does is resolve its own briefs.md
|
|
anchors through the tool that context-pack-tool lands (the +39 lines shift
|
|
them). If the PR has not merged, Hands stops.
|
|
|
|
**Subtraction.** Removed: the Hands orient step's `sed -n` of frozen ranges
|
|
(briefs.md:276-278) and the "reading a file twice is a smell" advice that the
|
|
tool replaces. Imagination's prose drift notes ("the lines move with the
|
|
merge", "re-take the anchor") are no longer needed and the map brief says so.
|
|
Not added: a parser per language, a cache, a pack file, or a mind field.
|
|
|
|
## Read anchors and symbols in the schema (2026-10-08, imagination-read-anchors)
|
|
|
|
Imagination pass `imagination-read-anchors`, session `self-2026-10-08`, for
|
|
operator ruling `eureka-substrate:ruling:context-pack-read-anchors`
|
|
(typed-fields-now). Cuts: `leaf-read-anchors` (Epiphany), `huginn-read-anchors`
|
|
(Huginn), `ops-read-anchors-upgrade` (gamecult-ops), `context-pack-reads`
|
|
(Eureka). Pinned heads: Epiphany origin/main `ef9568655e75bb6cb362a038e2739a5ac5e777ee`
|
|
(the rev Huginn pins; the local `F:\Projects\Epiphany` main is behind it at
|
|
`2bf39eef`), Huginn main `6b496eba8c8cfde7b93bb8bc46b1961abca52fd4`,
|
|
gamecult-ops main `7e233877dfb21f75d5bbe994641781f718098eac`, Eureka main
|
|
`0bb414d92728db61d2d587d749c94970ed2e5582`. Probes ran in detached worktrees
|
|
under this session's scratchpad `ra\`, removed afterwards.
|
|
|
|
### Body facts
|
|
|
|
B15. Stored payload encoding. `PipelineDocument::prepare` calls CultLib
|
|
`prepare_entry_named` (cultcache-rs at `8fc74c7`, `lib.rs:2244-2259`), which is
|
|
`rmp_serde::to_vec_named`: every value struct is a MessagePack map keyed by
|
|
field name. `decode` is `rmp_serde::from_slice` (leaf `lib.rs:745-751`). No
|
|
`deny_unknown_fields` exists in the leaf. Consequences: (a) an old document
|
|
lacking a new key decodes when the field is `Option` or carries
|
|
`#[serde(default)]`; (b) an old daemon reading a new document ignores the
|
|
unknown key, so after a rollback it serves such documents without the field
|
|
while the stored bytes keep it.
|
|
|
|
B16. Re-encoding is load-bearing. Admission prepares every write afresh
|
|
(`admission.rs:143-157`) and the receipt digest is over those payloads
|
|
(`receipt.rs:123-126`); A9 compares it with stored receipts to answer
|
|
`AlreadyAdmitted` (`admission.rs:164-166`). So if a document without the new
|
|
fields encoded differently after the change (for example `symbol: null` or
|
|
`reads: []` written out), replaying any pre-upgrade batch would stop answering
|
|
`AlreadyAdmitted`, and target invariant `stored-documents-valid` ("No change
|
|
re-keys, re-encodes or invalidates a document already in the mind") would
|
|
break. Hence `skip_serializing_if` on both fields, not only `serde(default)`.
|
|
|
|
B17. The macro. `value_types!` (`lib.rs:415-436`) emits a struct whose fields
|
|
carry only an optional `#[schemars(extend("maxItems"))]`; it has no way to put
|
|
a serde attribute on a field. `Bounded for Option<T>` exists (`lib.rs:79-83`);
|
|
`Vec` is validated only through the `[max]` list form (`list`, `lib.rs:110`).
|
|
`=> extra` is a struct-level validation hook (`campaign_repos_are_distinct`,
|
|
`lib.rs:452-468`). Refusal variants are pinned at five by the schema test
|
|
(`lib.rs:2717`), so new bounds must reuse `FieldBound` and `InvalidFormat`.
|
|
|
|
B18. Who constructs the changed structs. Epiphany: `CodeLocation {` 3 sites and
|
|
`PipelineCutSpec {` 1 test sample, all in `lib.rs`; no other Epiphany crate
|
|
builds them. Huginn: `CodeLocation {` in `huginn-mind/src/fixtures.rs:88`,
|
|
`huginn-daemon/src/daemon.rs:360`, `eureka-state/tests/client.rs:59`;
|
|
`PipelineCutSpec {` in `fixtures.rs:192`, `daemon.rs:361`, `client.rs:44`
|
|
(`admission.rs:432` uses `..spec.clone()` and needs no edit). Published schemas
|
|
that embed `CodeLocation`: Epiphany `schemas/cultnet/epiphany.pipeline.{cut_spec,cut_report,finding,follow_up}.v2.schema.json`;
|
|
Huginn `schemas/cultnet/huginn.mind_{request,response}.v1.schema.json`, pinned
|
|
byte for byte by `wire.rs:276-280`. The leaf's own check is
|
|
`pipeline_published_schemas_match_derivation` (`lib.rs:2723`), which writes the
|
|
derived copies to a temp dir on failure.
|
|
|
|
B19. Size calibration. `daemon.rs:349-356`'s `cut_spec` claims "every list the
|
|
leaf bounds filled to its maximum"; `client.rs:220-236` calibrates `fits` (180
|
|
file changes) under `MAX_RESPONSE_BYTES` and `wide` (256) over it. Filling the
|
|
new fields in the daemon builder keeps its claim true; filling them in the
|
|
client builder would move the calibration.
|
|
|
|
B20. Admission has no tree. Huginn holds no repository checkout; admission
|
|
checks bounds, formats, keys and cross-document rules only. "The symbol is in
|
|
the window at base" cannot be an admission rule. Its owner is the reader tool,
|
|
run by Imagination at base after admitting (cut context-pack-briefs) and by
|
|
Hands at its tree.
|
|
|
|
B21. Index text. `huginn-mind/src/index.rs:42-70` indexes a cut_spec's title,
|
|
first, adds and keeps_moves only, not file_changes. Leaving `reads` out keeps
|
|
the index text unchanged, so no reindex follows the upgrade.
|
|
|
|
B22. Deploy owner. Huginn is not an Idunn target: `runbooks/huginn-yggdrasil.md`
|
|
(gamecult-ops) calls it "an interim deployment: a hand-installed systemd unit",
|
|
retired by Idunn only in Huginn's 14-I, and says "No brake gates deployment of
|
|
this unit". Target r2 names the same runbook as the deploy's canonical
|
|
implementation. The live release is `releases/107552dc4b27b8856b043616ae74c2ebe7908b66`
|
|
(read-only `readlink` on Yggdrasil, unit active); Huginn main since then changes
|
|
docs only (`git diff --stat 107552dc..6b496eba -- crates Cargo.toml Cargo.lock`
|
|
is empty). The client is `C:\Users\Meta\.eureka\bin\eureka-state.exe`, whose
|
|
MCP `admit` input schema is derived at run time from the leaf types through
|
|
schemars (`eureka-state/src/main.rs:73`), so a rebuilt client publishes the new
|
|
fields with no hand edit; an agent session sees them only after it starts
|
|
anew. The runbook's rollback paragraph (`:109-113`) is specific to the 64-byte
|
|
key widening.
|
|
|
|
B23. The harvest. Target r2's canonical implementations put the leaf at Huginn
|
|
`crates/eureka-pipeline`, and Huginn `docs/eureka-self-cut.md:435` (harvest H1)
|
|
copies it there "from Epiphany head `4006b14b`", which is 5 commits behind
|
|
`ef956865`. H1 has no cut_spec yet (eureka-body has only questions and
|
|
rulings). If H1 copied from `4006b14b` after this change merges, it would drop
|
|
both leaf-key-bound and the new fields.
|
|
|
|
### Rationale
|
|
|
|
**Where the fields land.** The leaf still lives in Epiphany and Huginn pins it
|
|
by git rev, so the field goes into Epiphany's leaf, then Huginn re-pins, as the
|
|
ruling's option text names. Waiting for H1 would make this one Huginn cut
|
|
instead of two, but H1 is unscheduled. The operator accepted the three-pass
|
|
cost in her words. Follow-up `leaf-harvest-copies-head` records the constraint
|
|
on H1. If H1 merges before `leaf-read-anchors` starts, Self stops the cut and
|
|
Imagination re-maps it onto `crates/eureka-pipeline` (one Huginn cut, no
|
|
re-pin).
|
|
|
|
**Shape.** `CodeLocation.symbol: Option<Symbol>` everywhere a location is (file
|
|
changes, findings, follow-ups, mutations). It means the same thing in every
|
|
one: a name the location's lines must contain. `PipelineCutSpec.reads:
|
|
Vec<ReadAnchor>[16]` with `ReadAnchor { location: CodeLocation, why: Short }`.
|
|
It is a distinct type, not `FileChange`, because a read changes nothing and a
|
|
field named `change` would lie. Reads are in the spec's repo at its base, like
|
|
file_changes. A read in another repo stays prose in `first`, because a read
|
|
cannot pin another repo's commit. `Symbol` is a new bounded text: 1-128 bytes,
|
|
no whitespace or control character. It is new, so no stored document can fail
|
|
it. A read's window is bounded by an `=> extra` hook on `ReadAnchor`: `line >=
|
|
1`, `end_line >= line` (`InvalidFormat`), and span at most 100 lines
|
|
(`FieldBound`, limit 100). 100 is the window cap the tool already uses. No new
|
|
bound touches `CodeLocation`'s existing fields, because stored findings would
|
|
then stop validating.
|
|
|
|
**The macro owns "additive".** `value_types!` gains a per-field marker written
|
|
after the type and any list maximum, for example `symbol: Option<Symbol> =
|
|
absent` and `reads: Vec<ReadAnchor>[16] = absent`. It emits
|
|
`#[serde(default, skip_serializing_if = "Absent::absent")]`. Trait `Absent` is
|
|
implemented for `Option<T>` and `Vec<T>` only, and the validate expansion
|
|
names `<$ty as Absent>::$marker`, so a marker word other than `absent`, or the
|
|
marker on any other type, is a compile error. The epoch doc and the schemas
|
|
README then say this marker is how a field is added at v2. This replaces the
|
|
hope that every future author remembers both attributes (B16).
|
|
|
|
**No admission rule in Huginn.** Bounds are the leaf's, and Huginn applies them
|
|
through `validate` on every write. The symbol-in-window check needs a tree
|
|
(B20) and belongs to `context-pack.py`, which exits nonzero on
|
|
`SYMBOL_MISSING`.
|
|
|
|
**Deploy.** The owner is the gamecult-ops runbook's Upgrade section. It is not
|
|
Idunn: Idunn does not own this unit, and no brake applies (B22). The ops cut
|
|
generalises the rollback paragraph for additive fields and then executes the
|
|
Upgrade steps. One addition: the read-back test also asserts that every stored
|
|
document re-prepares to its stored payload bytes. That checks B16 on the live
|
|
mind, not only in a unit test.
|
|
|
|
**Eureka.** One new cut after both v1 cuts and the deploy. The v1 specs stay as
|
|
they are, because v1 must not wait on the deploy.
|
|
|
|
**Subtraction.** Removed: prose `path:line` read references in specs for the
|
|
spec's own repo (224 today, B14), replaced by checked reads; Imagination's
|
|
"re-take the anchor" notes; Hands' first-pass grep for callers of named
|
|
symbols. Added: one trait, one text type, one struct, one macro marker, two
|
|
fields, one tool section. Not added: an admission rule, a Huginn type, an
|
|
index change, or a second store.
|
|
|
|
B24. The admit door drops unknown keys silently. The batch that admitted these
|
|
specs had one file_change location with a stray `"symbol": null`. It was
|
|
admitted as Committed (receipt `mind-commit-c528cc24...`), and a view of
|
|
`cut-context-pack-reads.r1` shows that location without the key. This is B15(b)
|
|
at the JSON door: a session that started before the client swap will drop
|
|
`reads` and `symbol` and still report success. Follow-up
|
|
`gap-admit-drops-unknown-keys` (owner: Huginn eureka-state). Meanwhile the ops
|
|
cut makes agents restart, and context-pack-reads stops if its admit schema
|
|
lacks `reads`.
|
|
|
|
Admitted (receipts `mind-commit-c528cc24...`, `mind-commit-5d97a6ad...`):
|
|
`eureka-substrate:cut_spec:cut-leaf-read-anchors.r1`,
|
|
`cut-huginn-read-anchors.r1`, `cut-ops-read-anchors-upgrade.r1`,
|
|
`cut-context-pack-reads.r1`; follow-ups `leaf-harvest-copies-head` and
|
|
`gap-admit-drops-unknown-keys`. Order: leaf, then Huginn, then ops (deploy),
|
|
then Eureka. The Eureka cut also waits for both v1 cuts.
|