[role plan] 役割別 context 基盤 — role を first-class primitive にする(移行後に着手)

内向き roadmap「役割別に束ねる(define)」strand の本丸。**gate:現行の LogModule 構造移行 + データ型/最低 primitive 観の確定が landed してから着手**。設計は合意済(2026-06-03 の設計対話)。

## 北極星
特定の役割をこなす agent に、その役割に効く context を集めて渡す基盤。in-context 改善ループを「消費者(role agent)」視点で言い直したもの。

## 確定した設計
- **role = content domain の新 aggregate**(post / group / curation / agent_account の兄弟)。独立 LogModule にはしない ── role は forever 保持・低頻度で、bounded activity の agent_run domain とは性質が違う(独立化すると agent_run の「bounded activity log」意図と混ざる)。
- **role ≠ 揮発 handle**。handle(`claude:<worktree>`)は task 毎に揮発。role は粗くて持続する担当領域ラベル(別軸)。
- **role の context recipe = 2 層**:人手 bundle = curation を role に keyed / 宣言的 slice = dataset query を role に紐付け(dataset 抽象が来てから、今は seam だけ)。
- **意図タグ(n_01KSN4MNZ8)= recipe の素材**。curation と統合せず役割分担(意図タグ = 素材 / curation = role 向け手編み recipe)。

## task(移行後、下から積む)
1. role aggregate の最小スキーマ確定(id / label / owner / recipe 紐付け)。`AggregateType::Role` + content Event variant + projection table。
2. role → context recipe 紐付け:(a) curation を role に keyed(すぐ可)/ (b) dataset query 紐付けの seam(中身は dataset 抽象後)。
3. role → context 解決の read 口(gateway read 経路)。
4. 「意図タグ = recipe 素材 / curation = 手編み recipe」を docs / skill に明記(① 決着)。
5. agent が role を名乗る配線(揮発 handle と別軸)。

この後 → 供給(retrieval / 遡る軸 n_01KSN1B2QT)→ 使用実績で磨く(credit → ranking)。

消費者として n_01KSPGCZT9「領域別 agent dispatch」がこの基盤の上に乗る。

---

## 現行型の棚卸し(2026-06-03 / data-type review n_01KT4GKHR9 の材料)

本番 event log 全件(~4,000 events)を構造分解した結果。role 最小スキーマ + 移行の data-type review の両方の土台。

**envelope(全 event 一律・型付き)**:`ev_id / ts(TIMESTAMP) / actor(did) / author_handle / aggregate_id / event_type / source_event_id / correlation_id`。→ **id・owner・時刻はここで賄える**(payload に重複させない)。

**payload 構造(aggregate → event 件数 → 形)**
- agent_account: created(143)`{handle, created_by_did}` ✅ 単一(`display_name` は event に無く常に空)
- anchor: anchor_event(1)`{action, target_post_id, selector:{…, start:UBIGINT, end:UBIGINT, …}}` 唯一の nested+UBIGINT、利用 1 件
- curation: created(10)/updated(18)/deleted(1)`{title, body, members:[VARCHAR], audience_group_id}`(updated は audience 無し / deleted 空)✅ ほぼ単一
- group: created`{name,by_did}` / member_added`{member_did,by_did,pubkey?}` / deleted・enc`{by_did}` ⚠️ `by_did` が envelope actor と重複
- post / post_created(997):**6 形** = `body ⊕ encrypted_payload` × `±source` × `±parent_post_id` ⚠️ 最多バラつき(body/encrypted は原則的、±source 緩い)
- post / tag_event(2654):`{action, tag:[VARCHAR], rationale?}` ⚠️ **flat tag なのに array** / **rationale 約 55% のみ**
- post / post_ref_event(29):`{action, target_post_id, kind, rationale?}`
- post / post_updated(25):`{body}`(暗号 post 更新は非対応)
- post / post_deleted(100):空(理由 / actor は envelope 頼み)
- post / feedback_requested(4)・answered(4):`{…, options:[VARCHAR], allow_rationale:BOOLEAN, retracted:BOOLEAN}` ✅ BOOLEAN 型付き

**バラつき / cleanup 候補(→ data-type review 行き)**
1. **AggregateType の粒度不揃い** ── tag(2654)・ref・feedback は `aggregate_type="post"` の下、anchor は独立 type。最大ボリュームの tag が primitive でない。
2. **flat tag が `[VARCHAR]` array のまま**(multi-segment 時代の遺物、scalar 化候補)。
3. **rationale(=意図)が optional で約半分** ── role recipe の素材なのに捕捉が不安定。
4. post_created の **±source が緩い**(body⊕encrypted の XOR は原則的)。
5. payload 内 did が envelope actor と重複(group の `by_did` 等)。

**role への含意**:role の形 ≈ **curation の形** = `label`(= title 相当)+ `recipe`(= curation の `members:[VARCHAR]` パターンを流用 + query seam)。id / owner / 時刻は envelope から無料。→「role = curation 兄弟」を実データが裏付け、**recipe = curation member パターン再利用が自然**(新規発明不要)。