docs: anchor pool and move-guest liveness rules - #149
Conversation
Repair the integration half of the memory-model revision and the cross-references it left stale. - Restore the story pointer at memory.md §3.6; it named a chapter heading that no longer exists, so the link resolved to nothing. - Point the sections whose rules the revision changed (§3.1, §3.2, §3.6, §4.1, §4.5, §4.6) at the new story chapter; §4.6 had no pointer at all. - Restore the story's placement chapter to its previous wording: the chapter predates this change, and its in-prose spec reference is a commit-pinned permalink rather than a living relative link. - Update the glossary entries for anchor cell and arena placement, which still described a scope-local anchor region. - Record the both-sides-guests move restriction in lifetimes.md, the home of move legality, as §1.10 with a summary row. - Restore the arena-granularity latitude and the destruction-timing distinction dropped from §3.1 and §3.2, and note that the fixed-size region reclaims nothing individually. - State how the anchor pool avoids issuing identity 0, restore the address formula, drop a contrast with storage the language has no form for, and square the segmented-offset diagram. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016YnNCXtguHg4tSbLCtTT2c
|
Important Review skippedAuto incremental reviews are disabled on this repository. Please check the settings in the CodeRabbit UI or the ⚙️ Run configurationConfiguration used: Repository: zane-lang/coderabbit/.coderabbit.yaml Review profile: ASSERTIVE Plan: Pro Plus Run ID: You can disable this status message by setting the Use the checkbox below for a quick retry:
📝 WalkthroughWalkthroughThe memory specification now defines regioned scope arenas, segmented offsets, dynamic reuse, and a runtime-global anchor pool. Lifetime rules add guest-liveness checks for moves, while glossary entries, stories, README text, and cross-references are updated to match. ChangesMemory model rules
Estimated code review effort: 2 (Simple) | ~10 minutes Possibly related PRs
🚥 Pre-merge checks | ✅ 5✅ Passed checks (5 passed)
✨ Finishing Touches🧪 Generate unit tests (beta)
Comment |
There was a problem hiding this comment.
Actionable comments posted: 2
🤖 Prompt for all review comments with AI agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
Inline comments:
In `@spec/memory.md`:
- Line 521: Update the “Move guest liveness” summary in memory.md to distinguish
all cases: reject moves when both sides have live guests, use the surviving
side’s anchor only when exactly one side has live guests, and document that when
neither side has live guests no anchor survives; if the moved-from slot remains
readable, §4.5 lazily allocates an anchor for the new guest.
- Line 253: Clarify the scope-drain guarantee in spec/memory.md at lines 253-253
to describe the lifetime of promoted payloads, not source-arena allocations or
all reachable guests. In spec/glossary.md at lines 188-189, state that promotion
copies the fixed-size representation or handle while transferring the dynamic
backing store without copying. In stories/memory.md at line 43, replace
stack/heap terminology with fixed-size representation and dynamic scope-arena
terminology.
🪄 Autofix (Beta)
Fix all unresolved CodeRabbit comments on this PR:
- Push a commit to this branch (recommended)
- Create a new PR with the fixes
ℹ️ Review info
⚙️ Run configuration
Configuration used: Repository: zane-lang/coderabbit/.coderabbit.yaml
Review profile: ASSERTIVE
Plan: Pro Plus
Run ID: 0243aa4a-691b-49cf-9695-aad167964a92
📒 Files selected for processing (5)
README.mdspec/glossary.mdspec/lifetimes.mdspec/memory.mdstories/memory.md
|
|
||
| Each region is a separate chain of fixed-size **1 MiB chunks** mapped from the OS on demand. A chunk belongs to exactly one region: fixed-size slots and dynamic backing stores never coexist in the same chunk. A region maps no chunk until its first allocation. When its current chunk cannot satisfy an allocation, the runtime maps another chunk for that region, assigns it the next **chunk id**, and makes it current. | ||
|
|
||
| Scopes nest last-in-first-out, and their arenas nest with them: both regions of a scope are unmapped in full the moment the scope drains (§3.2, [`lifetimes.md`](lifetimes.md) §2.1). Arena granularity is an implementation choice, like boolean packing (§3.4) and placement (§3.5) — the compiler may fold several lexical scopes into one arena. What the language fixes is the observable behavior: memory a scope allocates outlives every guest that can reach it and is released together when the scope drains. |
There was a problem hiding this comment.
🗄️ Data Integrity & Integration | 🟠 Major | ⚡ Quick win
Keep physical allocation lifetime separate from logical hosting lifetime.
The affected text mixes arena placement, promotion, and object reachability. Fixed-size representations may be promoted to a parent arena, dynamic backing stores transfer without copying into storage whose lifetime covers the destination, and the source arena may unmap while guests continue through the global anchor.
spec/memory.md#L253-L253: rewrite the scope-drain guarantee so it describes promoted payloads rather than claiming source allocations outlive all reachable guests.spec/glossary.md#L188-L189: state that promotion copies the fixed-size representation/handle, not the dynamic backing store.stories/memory.md#L43-L43: replace stack/heap wording with fixed-size and dynamic scope-arena terminology.
📍 Affects 3 files
spec/memory.md#L253-L253(this comment)spec/glossary.md#L188-L189stories/memory.md#L43-L43
🤖 Prompt for AI Agents
Verify each finding against current code. Fix only still-valid issues, skip the
rest with a brief reason, keep changes minimal, and validate.
In `@spec/memory.md` at line 253, Clarify the scope-drain guarantee in
spec/memory.md at lines 253-253 to describe the lifetime of promoted payloads,
not source-arena allocations or all reachable guests. In spec/glossary.md at
lines 188-189, state that promotion copies the fixed-size representation or
handle while transferring the dynamic backing store without copying. In
stories/memory.md at line 43, replace stack/heap terminology with fixed-size
representation and dynamic scope-arena terminology.
There was a problem hiding this comment.
Addressed in the two spec sites; declining the story site.
spec/memory.md §3.1 — agreed, the sentence was inherited from the pre-promotion wording and is false once a payload can be promoted out of a draining scope. The guarantee is now stated as reachability rather than as memory outliving guests: a scope's memory is released together when that scope drains, no guest ever resolves into released memory, and an escaping value is promoted out first with its guests following the canonical anchor (§3.5, §3.7, §4.5).
spec/glossary.md §3.25 — agreed, "copied (promoted) into a parent arena" glossed over the split. It now says promotion copies the fixed-size bytes (the inline payload, or the handle of a dynamically-sized type) while a dynamic backing store transfers to the new host without being copied, matching §3.5.
stories/memory.md line 43 — declining. That line is a paragraph of an earlier chapter written when the model really was stack-versus-heap, and stories in this repo accumulate rather than being rewritten to match the present spec (contributing/writing-stories-docs.md §5). Its in-prose spec reference is a commit-pinned permalink to the commit where that wording was normative, so the link and the prose agree at the pinned revision. This PR in fact restores that line: it had been rewritten into current terminology, which also downgraded the permalink to a living relative link. The fixed-size/dynamic terminology belongs in the new chapter "Two payload streams, and the anchor that leaves the scope", where it already appears.
Generated by Claude Code
There was a problem hiding this comment.
🧩 Analysis chain
🏁 Script executed:
#!/bin/bash
set -euo pipefail
printf '%s\n' '--- glossary: promotion definition ---'
nl -ba spec/glossary.md | sed -n '180,200p'
printf '%s\n' '--- story: historical wording and reference ---'
nl -ba stories/memory.md | sed -n '35,50p'
printf '%s\n' '--- story-writing convention ---'
fd -a '^writing-stories-docs\.md$' contributing -x sh -c 'nl -ba "$1" | sed -n "1,180p"' sh {}
printf '%s\n' '--- current scope-drain wording ---'
nl -ba spec/memory.md | sed -n '245,270p'
printf '%s\n' '--- pinned GitHub links near the historical story passage ---'
rg -n -C2 'github\.com/.+/(blob|commit)/[0-9a-f]{7,}|stack|heap|fixed-size|dynamic' stories/memory.mdLength of output: 1043
🏁 Script executed:
#!/bin/bash
set -euo pipefail
show_range() {
file="$1"
start="$2"
end="$3"
printf '%s\n' "--- ${file}:${start}-${end} ---"
awk -v start="$start" -v end="$end" 'NR >= start && NR <= end { printf "%6d %s\n", NR, $0 }' "$file"
}
show_range spec/glossary.md 180 200
show_range stories/memory.md 35 50
show_range contributing/writing-stories-docs.md 1 180
show_range spec/memory.md 245 270
printf '%s\n' '--- relevant story references and terminology ---'
grep -nE -C 2 'github\.com/.+/(blob|commit)/[0-9a-f]{7,}|stack|heap|fixed-size|dynamic' stories/memory.md || trueLength of output: 83309
@TheLazyCat00, verified. The revisions at spec/memory.md Line 253 and spec/glossary.md Line 188 correctly separate source-arena reclamation from promoted payload reachability and dynamic-store transfer.
I also agree with declining the stories/memory.md change. Its historical stack/heap account is backed by a commit-pinned permalink, and preserving it follows contributing/writing-stories-docs.md §4.2 and §5’s append-don’t-overwrite convention. No further changes are needed.
🐇📜
Address review on the promotion and move-liveness wording. - State the drain guarantee as reachability: a scope's memory is released at drain and no guest resolves into released memory, with an escaping value promoted out first and its guests following the canonical anchor. The previous phrasing claimed source-arena memory outlives every guest that can reach it, which promotion breaks. - Say in the glossary that promotion copies the fixed-size bytes — the inline payload or the handle — while a dynamic backing store transfers without being copied. - Complete the move-liveness summary row with the case where neither side has live guests: a moved-from slot that stays readable anchors lazily. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016YnNCXtguHg4tSbLCtTT2c
…ename receiver to subject (#151) * add one-shot memory spec fix workflow * clarify host overwrite slot reuse * Add one-shot memory layout updater * Specify arena regions and dynamic backing-store reuse * Add one-shot review fix updater * Remove inactive review updater * Use global recyclable anchor pool * Align memory story with global anchors * Clarify anchor layout and rehosting conflicts * Align memory story with anchor rules * Preserve memory story and append allocator revision * docs: anchor pool and move-guest liveness rules (#149) * docs: fix review defects in the arena and global-anchor change Repair the integration half of the memory-model revision and the cross-references it left stale. - Restore the story pointer at memory.md §3.6; it named a chapter heading that no longer exists, so the link resolved to nothing. - Point the sections whose rules the revision changed (§3.1, §3.2, §3.6, §4.1, §4.5, §4.6) at the new story chapter; §4.6 had no pointer at all. - Restore the story's placement chapter to its previous wording: the chapter predates this change, and its in-prose spec reference is a commit-pinned permalink rather than a living relative link. - Update the glossary entries for anchor cell and arena placement, which still described a scope-local anchor region. - Record the both-sides-guests move restriction in lifetimes.md, the home of move legality, as §1.10 with a summary row. - Restore the arena-granularity latitude and the destruction-timing distinction dropped from §3.1 and §3.2, and note that the fixed-size region reclaims nothing individually. - State how the anchor pool avoids issuing identity 0, restore the address formula, drop a contrast with storage the language has no form for, and square the segmented-offset diagram. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016YnNCXtguHg4tSbLCtTT2c * docs: sharpen the scope-drain guarantee and the move-liveness summary Address review on the promotion and move-liveness wording. - State the drain guarantee as reachability: a scope's memory is released at drain and no guest resolves into released memory, with an escaping value promoted out first and its guests following the canonical anchor. The previous phrasing claimed source-arena memory outlives every guest that can reach it, which promotion breaks. - Say in the glossary that promotion copies the fixed-size bytes — the inline payload or the handle — while a dynamic backing store transfers without being copied. - Complete the move-liveness summary row with the case where neither side has live guests: a moved-from slot that stays readable anchors lazily. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_016YnNCXtguHg4tSbLCtTT2c --------- Co-authored-by: Claude <noreply@anthropic.com> * Clarify rehosting storage relocation Define rehosting as copying the complete hosted representation into destination-owned storage. Inline bytes move into the destination slot, dynamic backing stores relocate into equal-size destination-region allocations, old source storage ceases to be live, and the source host-capable slot becomes a guest through the canonical tether. Keep anchor bookkeeping O(1) in the number of guests while stating the physical relocation cost explicitly. Align the normative memory model, glossary, and design story, and complete the glossary's verb list with operators and lambdas. * Add temporary forwarding-anchor update workflow * Specify forwarding anchors for merged host identities * docs: bare symbols are no longer guest sources; add the 'T borrow mode A new `&` may now be minted only from a field access or an `&T` parameter. A bare symbol stays a place expression but is no longer a guest source, so nothing can point at a local's own hosting slot and the slot stays free to be overwritten or moved from. This is what makes the aliasing case that started this — a guest to `main`, then `second = main` — a compile error at the line that mints the guest rather than a question about what the guest then denotes. Removing that source leaves a hole where a bare symbol needs to reach a callee, so reference types gain a third passing mode: `'T`, a borrow. The three modes are now `T` (swallow), `&T` (guest), and `'T` (borrow, any place including a bare symbol, read and mut for the call only, never stored, returned, or moved). A reference receiver written bare is an implicit `'T` borrow; `this &T` is the guest receiver a method writes when it stores or returns the receiver. Consequences carried through: a returned `&T` must be rooted in an `&T` parameter; a field reached through a borrow is not a guest source either; overloads may not differ only by passing mode; an `&` field and a recursive `#variant` case are fed from a field or an `&` parameter, so a recursive structure is rooted in a field rather than a bare local. The anchor system is unchanged. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017AYiJXjzCPEDfYRW1ZtxH7 * docs: story chapters for the guest-source restriction and the three modes stories/memory.md gains "The slot that could not be pointed at" — the five-line aliasing program, the roads tried in order (smarter guests, the name/location/object middle layer, immovable objects, no guests at all) and why each failed, and the narrowing that finally settled it. Then "Three ways to hand over an object": why an `&T`-parameter exemption would have needed interprocedural inference, how the borrow fell out of that, why the receiver became a borrow too, and the defence of `'` over redefining `&`. stories/lifetimes.md gains "Where a guest may be rooted" — what the source rule did to the scope check and the return rule, and why a field reached through a borrow is not a guest source either. Spec sections point into the new chapters; in-prose references are pinned to b10eaed. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017AYiJXjzCPEDfYRW1ZtxH7 * docs: address CodeRabbit review on #151 - CLAUDE.md: the guest-source guard was end-anchored, so it matched no line carrying a `// ILLEGAL: ...` comment — which is every deliberate bad example in the spec. It now tolerates an inline comment and trailing whitespace, and catches all three (memory.md 150/159, lifetimes.md 27) instead of none. - glossary.md §3.1, §3.33, §3.36: mirror memory.md §2.8's exclusion of field accesses whose base chain passes through a `'T` borrow. Without it the glossary made `borrowed.field` a legal guest source while the canonical rule rejected it. - syntax.md §3.1, §3.2: scope the three passing modes to reference types. A value parameter is always a read-only borrow and a value receiver is borrowed, so neither selects a mode; the unqualified wording contradicted effects.md §2. - memory.md §3.1: tag the segmented-offset diagram fence `text`. It was the only untagged opening fence in spec/. - memory.md §4.8: stop promising unchanged reuse order under thread-local anchor caches. Which free slot an allocation receives is unobservable from the source language, so §3.2's LIFO describes the central pool rather than binding an implementation; what a cache may not change is identity uniqueness, the §4.6 retirement events, and the lifetime guarantees resting on them. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017AYiJXjzCPEDfYRW1ZtxH7 * docs: second CodeRabbit round on #151 - memory.md §2.9: the borrow paragraph said a borrow "cannot be stored in a field, and cannot be returned" and then that a value is copied when bound into "a field or return store" — a flat contradiction. Split the two: the borrow is never storage, but binding *through* one copies the value, and the copy escapes fine. A reference type has no copy, so a `'T` leaves nothing. - glossary.md §3.33: restore the place requirement the shortened wording lost. "A field access not rooted in a borrow" would have admitted `makeCar().engine`; mirror memory.md §2.8 in full. - CLAUDE.md: the guard now accepts a leading-underscore private name (`_engine`) and tab-formatted assignments. Prose rewritten to say what the guard does — it matches a bare-symbol right-hand side only, so every hit is a candidate bug and the legal forms never appear. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017AYiJXjzCPEDfYRW1ZtxH7 * docs: third CodeRabbit round on #151 - CLAUDE.md: the guard's prose claimed the legal sources "never match". That is true only of a field access, which `.` excludes syntactically. An `&T` parameter is written bare, so `r &Node = source` inside a callee matches and is correct — the reviewing rule now lists it as a keep, checked against the enclosing signature rather than the line. - glossary.md §3.27: the borrow entry still carried the contradiction fixed in memory.md §2.9 — "cannot be stored, returned, or moved" against a value being copied into a fresh slot. Scope it to the borrow itself. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017AYiJXjzCPEDfYRW1ZtxH7 * docs(meta): make the glossary a required stop when a rule changes Two findings on #151 were the same defect: a rule was corrected in its canonical home and its glossary entry left paraphrasing the superseded version, so the spec contradicted itself until review caught it. Both times the author missed it, which makes it a habit worth writing down rather than a one-off slip. Adds it to the "Before you edit" list: after editing any normative rule, grep spec/glossary.md for the concept and update the entry in the same commit. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017AYiJXjzCPEDfYRW1ZtxH7 * docs: the borrow is the non-swallowing way to pass a bare symbol "Passing a bare symbol into a call is the borrow mode's job" overstated it: a bare symbol is a move-source (lifetimes.md §1.2), so a plain `T` parameter swallows one perfectly well. `'T` is the only *non-swallowing* mode that accepts a bare symbol, which is the claim the surrounding rules actually support. Corrected in all three places that carried it — memory.md §2.8.1 (canonical), glossary.md §3.36, and the foundations.md bullet — rather than only where the review pointed, since the imprecision started in the canonical home and propagated from there. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017AYiJXjzCPEDfYRW1ZtxH7 * docs: tighten two guest-source summaries - foundations.md §7: the bullet said a guest is minted "from a field access or an `&T` parameter", which over-approximates memory.md §2.8.1 — the base must be a place and must not be reached through a `'T` borrow. Named both qualifiers compactly rather than reproducing the rule; foundations.md is a map that defers to canonical homes. - memory.md §2.8.1: "a field, a container element, a callee" listed where a guest may live, not what may mint one, and was read as the latter. Says it in the precise terms instead — an `&` field, a container element, an `&T` parameter inside a callee. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017AYiJXjzCPEDfYRW1ZtxH7 * docs: never write ' on this; add a forward pointer in the anchor story Maintainer review on #151. The receiver was specified two ways at once: memory.md §2.9 said a bare `this T` on a reference type is an implicit `'T` borrow, and then every example in that same section wrote `this 'Car`. Decided in favour of the implicit form — `'` is never written on `this`. The rule is forced rather than chosen. If the marker were required on the receiver, a bare `this T` would have to mean the method swallows its own receiver, which no method wants; so the borrow has to be the bare meaning, and `this 'T` is then a second spelling for the default. It also makes the two type worlds agree: value and reference receivers are both borrows and both written bare, with `&` the single marker `this` may carry. Applied to memory.md, functions.md, lifetimes.md, syntax.md, glossary.md, and effects.md — including dropping the `this 'ReceiverType` production from syntax.md §3.2 and the function-type form in §2.9. stories/memory.md: the segmented-offset chapter still ends on the one-cell promotion model, which the later global-pool chapter superseded. Stories are append-only, so rather than rewrite it, that chapter now carries a forward pointer naming what did not survive and why — the cell leaving the payload stream, and one-cell promotion failing once both sides of a move are anchored. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017AYiJXjzCPEDfYRW1ZtxH7 * docs(stories): keep stories/memory.md strictly append-only against main Maintainer ruling on #151: the story is append-only, and that is verified by diffing against main — an existing chapter is not edited, and a new chapter goes at the end rather than being slotted into the middle. Two violations, both now gone: - One sentence in "The last table problem, and the segmented offset" had been rewritten (it came in with the PR 147 commits, and I then appended a forward-pointer paragraph to the same chapter, which is the same violation again). Both reverted; that chapter is byte-identical to main. - "Two payload streams, and the anchor that leaves the scope" had been inserted between two chapters that already existed on main. Moved to the append position, after "Two vocabularies" and before the chapters this PR adds — which is also the right chronology, since the arena and anchor work came after the host/guest rename. The correction the forward pointer was carrying now lives where it belongs, in the appended chapter: it names the one-cell promotion claim from the segmented-offset chapter and says what retires it — that the claim holds only while a payload has one cell to rewrite, and fails once both sides of a move are anchored. `git diff origin/main -- stories/memory.md` is now additions only. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017AYiJXjzCPEDfYRW1ZtxH7 * docs(meta): state the append-only story rule literally, with a check The story guide licensed exactly what review just rejected: §5 said to "open a new chapter (or extend the relevant one)", which reads as permission to edit an existing chapter, and it said nothing about where a new chapter goes. Both gaps were used in this PR — a chapter was edited and another was inserted between two that already existed. §5 now spells out the two teeth: an existing chapter is not touched at all, not even to bolt a forward pointer onto its end, and a new chapter goes at the end of the file rather than into the middle. The correction a forward pointer would carry belongs in the new chapter, naming the older chapter's claim. Both are mechanically checkable, so the guide and CLAUDE.md now carry the check — `git diff origin/main -- stories/<topic>.md | grep -E "^-[^-]"` must print nothing. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017AYiJXjzCPEDfYRW1ZtxH7 * docs: the receiver is never a swallow position, and say why properly Maintainer asked why bare `T` borrows on `this` when the default for `T` is swallowing. Fair — the justification I had written was wrong. It said the borrow "has to be" the bare meaning because otherwise a method would swallow its own receiver, which implies the swallow reading was ever on the table. It never was. main already says a reference receiver is an implicit `&` reference "(never swallowed)", and memory.md §2.9 on main says the same. So the receiver has never been a swallow position, and bare `T` meaning swallow is a rule about ordinary parameters. What this PR changes is only *which* non-swallowing mode a bare receiver is — guest before, borrow now — because the call-site receiver is usually a bare symbol, which §2.8.1 no longer admits as a guest source. §2.9 now states that, says plainly that bare `T` does not mean the same thing in both positions, and names the pre-existing rule that makes it consistent rather than arguing from convenience. The §2.9 mode table is scoped to parameters, and functions.md §2.4 and both summary rows match. Co-Authored-By: Claude Opus 5 <noreply@anthropic.com> Claude-Session: https://claude.ai/code/session_017AYiJXjzCPEDfYRW1ZtxH7 * docs: say which sense of "receiver" each rule means "Receiver" was doing three jobs at once — the object a method is called on, the `this` parameter that fixes the passing mode, and the call-site expression that supplies the object — and the rule that it is never a swallow position is about the second of those, not the first. Define the three in functions.md §2.1, add a glossary entry, and use the precise term wherever the distinction carries weight. * docs: rename receiver to subject "Receiver" is Smalltalk residue — a call was a message and the object received it. Zane has no messages, so the word named nothing: it neither fought its old meaning nor fed the new one, it was simply dead metaphor. "Subject" puts the concept in the register the spec already chose when it named callables verbs. A call reads subject-verb-object, and the subject is what the verb acts from. Merged story chapters keep the old word — they record the language as it was — so the term is split across the two trees by construction. Also records that append-only is per pull request, not per commit: chapters a branch has not merged yet are still drafts. * docs: tell the receiver-to-subject story Appends "What does a receiver receive?" to stories/functions.md: the word arrived free with the object model and went unexamined until a rule about `this` forced us to say which of its three senses we meant, and then until someone asked what a receiver receives. Records the dead metaphor, the grammar register that supplied the replacement, the candidates weighed, and the cost — merged chapters keep the old word, so the two doc trees disagree by design. Pointer added from functions.md §2.1; README row updated. * docs(meta): make the stories guide the source of truth for append-only The rule lived in two places at once, and CLAUDE.md — which is agent notes, not contributor documentation — had grown a full normative restatement of it. Now the story guide §5 owns the rule and says how it is enforced (by hand, by author and reviewer; there is no CI), and CLAUDE.md keeps only the command to run and the two ways sessions have actually got it wrong: editing a merged chapter, and refusing to edit an unmerged one. --------- Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> Co-authored-by: Claude <noreply@anthropic.com>
Clarify the anchor cell allocation model and add move-guest liveness constraints to the spec and stories.
Summary
This change documents two related refinements to the memory and lifetime models:
Anchor pool architecture: Anchor cells are allocated from a single global pool (not per-scope), with immediate reuse safety guaranteed by scope rules. The glossary definition is updated to reflect this.
Move-guest liveness rule: A move into an initialized host is rejected when both source and destination have live guests, since one hosting lineage can only carry one anchor identity. This is formalized in
lifetimes.md§1.10 with examples.Key changes
spec/memory.md:0as an identity (first slot of first page reserved)spec/lifetimes.md:spec/glossary.md:README.md: Updated stories table entry formemory.mdto reflect chunked bump arenas focusstories/memory.md: Partial diff shown; full story chapter on two-payload-streams scenario added (not fully visible in truncated diff)Implementation notes
The anchor pool model ensures O(1) anchor operations under concurrency while maintaining immediate reuse safety through lexical scope guarantees. The move-guest liveness rule prevents the impossible case where a single anchor cell would need to carry two distinct guest identities.
https://claude.ai/code/session_016YnNCXtguHg4tSbLCtTT2c
Summary by CodeRabbit