Version. 0.2
Date. 2026-08-21
Status. Open scoping item. Named design work with a real blocker — not a deferral and not a caveat. Markdown primary — the consumer is Claude Code and change-request drafting.
Changes from v0.1. Ground-truthed against the engine at 09fa09e rather than described from the W2 close. Three things change. The render path has two actors, not one (§1a) — and one of them already holds a seeded role identity and could mint today. render_specialist_binding is already an identity register (§1b), which reframes question 1 from should per-binding actors become identity rows to there are two registers, do they converge. And two tables now carry a foreign key to agent_identities (§1c), which did not exist when v0.1 was written and makes the collision structural rather than doctrinal. §3's statement is corrected — precisely, not softened. v0.1 stands as sibling.
Origin. Surfaced building CR-2026-227 (W1), confirmed at CR-2026-229 (W2). Operator ruling 2026-08-20: file as its own scoping item; do not improvise the model to close it faster. That ruling stands and this version does not close it.
Two identity models are in the engine and they do not line up.
agent_sessions.agent_identity_id references agent_identities, whose natural key is role and whose rows are seeded by migration 0113. One identity per role, platform-wide.render_specialist_binding (migration 0045) carries agent_actor_id per (engagement_id, declared_render_type_id). That identity is durable, survives restarts, and is the identity that actually acts when a render is produced.There is no role a render specialist can mint a session under.
New in v0.2. v0.1 treated the render path as one thing. It is two, and they are stuck for different reasons.
| Actor | Identity | Can it mint today? |
|---|---|---|
| RenderDispatchAgent | Seeded role render_dispatch, resolved through require_agent_identity against the roster loaded at startup | Yes. It has an agent_identities row and nothing prevents it |
| AnthropicRenderSpecialist | binding.agent_actor_id — a bare UUID in the binding table, no agent_identities row | No. Nothing to mint against |
The dispatch agent is the seed-induction case again. CR-2026-227 item 3 already gave it a resolved, durable identity — the code comment at render_specialist_bootstrap.py records that it was uuid.uuid4() before. It resolves an identity, constructs its ActorRef, and writes UNSESSIONED_ACTION_ID into it. It is not blocked. It simply does not mint.
So "the render path is ungoverned" is two claims of very different size: one closable at roughly the cost of seed induction, one requiring the register question below.
One qualification, and it matters. The bootstrap's own comment says the dispatch agent's actor is purely an audit handle — Phase 10 writes nothing to Memory through it, attributing instead to the operational render_jobs table. So minting for dispatch would govern the dispatch act and not the production act. Governing the dispatch agent is worth doing and does not govern the render.
render_specialist_binding is already an identity registerNew in v0.2, and it reframes the central question.
Each binding row carries agent_actor_id, agent_display_name, instruction_version, and system_prompt. That is an identifier, a name, a versioned instruction set, and the instruction content itself — per (engagement, declared render type), durable, created when an operator declares a render type.
agent_identities carries an identifier, a display name and a role, per role, seeded at migration time.
These are two identity registers with different grains and different creation moments, and the older one predates the newer by 68 migrations. The binding register is arguably richer: it carries the instruction set, which agent_identities does not, and which agent_sessions.instruction_version pins at mint.
**So question 1 is not should per-binding actors become identity rows. It is: two registers exist; do they converge, and if so which way?** That is a different and larger question, and it should be asked in those terms.
agent_identitiesNew in v0.2 — this landed after v0.1 was written and makes the collision structural.
agent_sessions.agent_identity_id → agent_identities (CR-2026-227, migration 0113)agent_lifecycle_events.agent_identity_id → agent_identities (CR-2026-231, migration 0115) — the one thing every lifecycle event has
A per-binding actor cannot be recorded in either table without one of: becoming an agent_identities row, the foreign keys being loosened, or a second identity column being added to both.
v0.1 could describe the mismatch as a doctrinal question about identity grain. It is now enforced by two foreign keys, and any answer has a migration attached. That raises the cost of every option below and it should be known before scoping, not discovered during it.
Minting the rendering room under a role would attach a session to an identity that is not the one acting. The session row would name a platform-wide identity; the ActorRef on the resulting events names a specific per-binding actor. Both would be in the record and one would be false.
That is not a rounding error in an audit system. The claim being built is that the record says who did what. A session naming the wrong actor is worse than no session, because no session is a visible absence and a wrong session is an invisible falsehood.
Nor is flattening specialists onto the roster acceptable — ruled at the W1 close: per-binding identity that works is not replaced with a coarser per-role one for tidiness.
v0.1 said the freeze switch does not reach the render path at all. True in effect, imprecise in cause, and the precision matters because the two halves cost differently.
Corrected:
render_dispatch is a seeded identity; freezing it would refuse the next mint, if there were a mint to refuse.
Both actors now carry UNSESSIONED_ACTION_ID (CR-2026-232), so the absence is recorded at all four construction sites rather than appearing as a blank. The gap is legible. It is not smaller.
Per-binding session minting — sessions whose granted identity is the actor that acts.
Open questions, none improvised here:
agent_identities rows, the natural key is no longer role alone, and the SEED ruling's reasoning must be revisited rather than assumed to extend — it was reasoned from an enumerable set, and bindings are created at runtime.agent_identities natural-key ruling and the SEED ruling (CR-2026-227, 2026-08-20). Per-binding actors are created at runtime when an operator declares a render type, so they are not enumerable at migration time. This is the direct collision and the heart of the item.agent_lifecycle_events — the second foreign key (§1c). Any answer touching identity grain touches migration 0115's table.agents/unsessioned_baseline.py under render_specialists, and that group's stated discharge path is this item. When this closes, those entries leave the baseline.standing-notes/loomworks-standing-note-two-records-and-what-crosses-between-them-v0_1 — a per-binding grant lands in the operational record like any other, so §3's boundary test applies unchanged.Not H0 scope. H0 is complete and traversable end to end without it, and the traversal exercises the shaping path because shaping is where the identity model is complete, not because it is the safer path to run.
It is the first thing that should be scoped after H0, because §3 is a real hole in the coverage guarantee and O1's whole premise is that the chokepoint list is only as good as its coverage.
§1a's split may change that sequencing — one half is small and unblocked. Whether to take it separately is question 6, and this note does not answer it.
It does not choose among questions 1–3. It does not amend the SEED ruling or the natural-key ruling. It does not answer SR-1. It does not split the dispatch agent out. It does not touch the baseline. And it does not treat §1a's dispatch-agent gain as equivalent to governing the render — it is not.
DUNIN7 — Done In Seven LLC — Miami, Florida Loomworks Scoping Item — Per-Binding Session Minting — v0_2 — 2026-08-21