Files
council/docs/structure/initial-plan.md
T
jpmschweitzerandClaude Opus 4.7 7a20b7f4ae add project documentation and archived design plan
CLAUDE.md so future Claude Code sessions have the five-phase workflow,
web-access rule, clarification-flag rules, tool permissions per agent,
and modification conventions at hand on session start.

README.md as the vault-facing overview for anyone opening this repo in
Obsidian, including the roster and where to find session artefacts.

docs/structure/initial-plan.md archives the design decisions that shaped
the current scaffolding — useful context when extending the system.

Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
2026-04-19 15:25:51 +02:00

593 lines
33 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# Plan: Council of 10 + Researcher + Scribe + Moderator
## Context
`/var/mnt/data/projects/council/` is empty. The user wants a Claude Code project — used from the CLI **and** opened as a single Obsidian vault rooted at the repo — that runs a structured multi-agent deliberation on problems posed by the user.
Roles:
- **Moderator** (the main Claude Code session) interviews the user for context, orchestrates phases, narrates visibly, and brokers tie-breaks. Only the Moderator talks to the user.
- **Researcher** (Naima Quéré, Sonnet) is the **only** sub-agent with web access. She runs a pre-session research pass off the brief, and is re-invoked on demand when members flag gaps during debate. Writes per-topic research notes into the session directory as a shared evidence base.
- **10 Voting Members** deliberate in three phases (initial answer → debate/revise → vote). Members **cannot** browse the web; they rely on the shared research package.
- **Scribe** (Ansel Voss, Haiku) transcribes the proceedings as phases complete, writes the canonical session files.
- **The User** answers the Phase 0 interview, answers any Phase 3 clarification questions raised by members, and breaks vote ties when they occur.
Sessions are the core artefact — one directory per session at the repo root.
### Decisions locked in during planning
| Decision | Choice |
|---|---|
| Command trigger | `/council <problem>` |
| Voting cast | 10 voting members, "wild eclectic mix" |
| Non-voting cast | Researcher (Sonnet) + Scribe (Haiku) |
| Voting | **Transparent** — answers attributed by name; self-votes allowed; ties → **user breaks the tie** |
| Models | Sonnet 4.6 for initial answers / vote / memory updates / Researcher; Opus 4.7 for debate/revise; Haiku 4.5 for Scribe |
| Research access | Only Researcher and Moderator have `WebSearch`/`WebFetch`. Members request research via Phase-3 flags. |
| Pre-session research | Moderator writes the brief after interview; Researcher immediately runs a pre-session research pass off the brief; members open Phase 2 with a ready-made research package. |
| Clarification flag | `User clarification needed` can be raised by **any** agent in **any** phase (Researcher in Phase 1, members in Phases 2 / 3 / 4). Moderator batches, asks the user via `AskUserQuestion`, and appends answers to `brief.md`. Phase-specific handling in the orchestration section. |
| Research-gap flag | `Research gap` can be raised by Researcher (before Phase 1) or members (Phase 3). Moderator consolidates and re-invokes the Researcher. Round-2 research files carry `round: 2`. |
| Follow-up loop bound | At most **one** bounded extra revision round in Phase 3 (triggered by Phase-2 or Phase-3 flags). Further flags in later rounds are logged to `outcome.md` as open questions, not acted on. |
| Storage | Repo root is the Obsidian vault; sessions at `sessions/<slug>/` |
| Session slug | `YYYY-MM-DD_<short-kebab-case>`; `-2`, `-3`, … appended on same-day collisions |
| Obsidian version | Assume ≥1.9 (Bases) |
| User visibility | User sees only Moderator narration. No raw tool output, no inter-agent packets. |
## The Cast
### 10 Voting Members (wild eclectic mix)
| # | Name | Prior job(s) | Personality | Lens |
|---|---|---|---|---|
| 1 | **Elif Tavşan** | Retired stage magician & cold-reading coach | Playful, watchful, fond of misdirection | Spots sleight-of-hand in arguments; suspicious of "obvious" framings |
| 2 | **Dr. Wren Okafor** | Deep-sea marine biologist → systems ecologist | Calm, patient, thinks in decades | Feedback loops, unintended consequences, long-time-horizon reasoning |
| 3 | **Magnus Holt** | Bankruptcy lawyer → insolvency law lecturer | Dry, adversarial, pessimism as craft | Failure modes — "what happens when this breaks?" |
| 4 | **Sister Beatrix Vale** | Benedictine nun → hospice counselor | Gentle, unflappable, never moralizes | Meaning, grief, what actually matters |
| 5 | **Nikolai "Niko" Prochazka** | Soviet cosmonaut trainer → wilderness survival instructor | Blunt, impatient with abstractions | Operational execution, checklists, ruthless prioritization |
| 6 | **Dr. Ingrid Vaasa** | Theoretical physicist (QFT) → independent researcher | Abstracts aggressively, reaches for the simplest model | First-principles reasoning, toy models, symmetries/invariants |
| 7 | **Kai "Breaker" Lindholm** | Pro skateboarder → skatepark architect | Kinetic, improvisational, body-first thinker | Embodied intuition, iteration, "does it feel right?" |
| 8 | **Cassian Vire** | Investigative journalist → speculative-fiction novelist (doorstopper systems-SF; Stephenson × Hamilton flavor) | Restless, tangent-prone, maximalist; infodumps if un-moderated | Systems-level extrapolation across long horizons; civilizational-scale consequence-chaining |
| 9 | **Marcelo "Marco" Tintori** | Trained painter (Bologna) → 20 years as a corrections officer → runs a prison art program | Dry, darkly funny, slightly melancholy; allergic to piety | Institutional reality vs. theory; dignity of the specific; absurdity as a signal of misalignment |
| 10 | **Mari Koskela** | Marine engineer on cargo ships (12 years) → PhD anthropology of maritime labor → independent ethnographer | Patient, observant, dry humor; asks "what do they actually do?" before "what does the spec say?" | How humans actually inhabit the systems they build; practice vs. procedure; ritual, labor, power |
Slugs: `tavsan`, `okafor`, `holt`, `vale`, `prochazka`, `vaasa`, `lindholm`, `vire`, `tintori`, `koskela`.
### Non-voting: Researcher
**Naima Quéré** — ex-investigative journalist → national-archive research librarian → independent OSINT analyst. Slug: `researcher`. Model: Sonnet.
- Only sub-agent with `WebSearch` / `WebFetch`.
- Methodical, skeptical-but-fair; cites sources with URL + access date; flags conflicting evidence and uncertainty explicitly.
- Writes one file per topic into `sessions/<slug>/research/`.
- Runs twice at most per session: Phase 1 (pre-research off the brief), and optionally Phase 3b (follow-up on research gaps flagged by members).
- **May flag `User clarification needed` at any point during Phase 1** — before starting (if the brief is too vague to research usefully), or mid-research (if ambiguity surfaces once she starts digging). Either way, she returns early with 1-3 concrete questions; Moderator asks the user via `AskUserQuestion`, appends answers to `brief.md`, then re-invokes her.
- Does not opine on the council's question.
### Non-voting: Scribe
**Ansel Voss** — former court stenographer and municipal archivist. Slug: `scribe`. Model: Haiku 4.5.
- Writes canonical session files (`initial-answers.md`, `revised-answers.md`, `votes.md`, `outcome.md`) as phases complete.
- Neutral — verbatim where it matters, summarizing where it helps. Never editorializes. Keeps Obsidian frontmatter and wikilinks tidy.
### Moderator
**The main Claude Code session** (not a sub-agent). Responsibilities:
1. **Phase 0**: 2-4 context questions to the user via `AskUserQuestion`. Writes `sessions/<slug>/brief.md`.
2. **Phase 1**: invokes Researcher with the brief to produce the pre-session research package.
3. Narrates between phases (≤ ~10 lines per update).
4. **Phase 3**: collects `Research gap` and `User clarification needed` flags from members; runs Researcher and/or `AskUserQuestion` as needed; triggers one bounded second revision round if either fired.
5. **Phase 5**: tallies votes; on tie, presents tied answers to the user via `AskUserQuestion` (full answer as option preview).
6. Invokes Scribe and the memory-update batch.
7. Never prints raw tool-call output — always distils.
## Architecture
### Directory layout
```
council/ # ← repo root = Obsidian vault
├── CLAUDE.md # Claude Code guidance
├── README.md # Vault-facing overview
├── .claude/
│ ├── agents/
│ │ ├── council-tavsan.md # 10 voting members (model: sonnet)
│ │ ├── council-okafor.md
│ │ ├── council-holt.md
│ │ ├── council-vale.md
│ │ ├── council-prochazka.md
│ │ ├── council-vaasa.md
│ │ ├── council-lindholm.md
│ │ ├── council-vire.md
│ │ ├── council-tintori.md
│ │ ├── council-koskela.md
│ │ ├── council-researcher.md # Naima Quéré (sonnet, web tools)
│ │ └── council-scribe.md # Ansel Voss (haiku)
│ └── commands/
│ └── council.md # /council <problem> orchestration
├── council-members.base # Obsidian Base: roster
├── council-sessions.base # Obsidian Base: session index
├── docs/ # meta-docs about this project (not live data)
│ └── structure/
│ └── initial-plan.md # archived copy of this plan (step 1 of implementation)
├── members/
│ ├── tavsan/
│ │ ├── persona.md # character sheet + frontmatter
│ │ ├── journal.md # append-only session-log entries
│ │ ├── on-the-user.md # accumulated observations about the user
│ │ └── revisit.md # open questions/topics to come back to
│ ├── okafor/
│ ├── holt/
│ ├── vale/
│ ├── prochazka/
│ ├── vaasa/
│ ├── lindholm/
│ ├── vire/
│ ├── tintori/
│ ├── koskela/
│ ├── researcher/
│ │ └── persona.md # persona only — no journal
│ └── scribe/
│ └── persona.md # persona only — no journal
└── sessions/ # ← the core of the repo
└── 2026-04-19_self-host-email/ # one dir per /council run
├── brief.md # moderator writes (Phase 0)
├── research/ # researcher writes (Phase 1 + optional 3b)
│ ├── fastmail-reliability.md
│ └── self-hosting-risks.md
├── initial-answers.md # scribe: Phase 2 verbatim, attributed
├── revised-answers.md # scribe: Phase 3 critiques + revised (round 1 + optional round 2)
├── votes.md # scribe: Phase 4 votes + tally
└── outcome.md # scribe: canonical session file (Obsidian Base target)
```
`.claude/` can be hidden in Obsidian's file-explorer settings; it doesn't break anything if visible. Wikilinks are folder-qualified (e.g. `[[members/vaasa/persona|Dr. Ingrid Vaasa]]`, `[[sessions/2026-04-19_self-host-email/outcome|Self-host email?]]`).
### Per-member memory layout
Each voting member owns `members/<slug>/`. Every file in that directory is read at the start of every invocation.
**`persona.md`** — seed character sheet with frontmatter:
```markdown
---
type: council-member
slug: tavsan
name: "Elif Tavşan"
prior_job: "Retired stage magician & cold-reading coach"
lens: "Pattern recognition, misdirection, skepticism of the obvious"
voting: true
model: sonnet
---
# Elif Tavşan
**Personality:**
**Voice:**
**Things she notices first:**
```
**`journal.md`** — append-only; one entry per `/council` run (newest on top), with wikilinks to the session outcome and to members referenced.
```markdown
---
type: council-journal
slug: tavsan
---
# Journal — Elif Tavşan
## 2026-04-19 — [[sessions/2026-04-19_self-host-email/outcome|Should I self-host my email?]]
- **Stance:** Let the vendor carry the risk; switch only when it bites.
- **Revised answer gist:** …
- **My vote:** [[members/vaasa/persona|Vaasa]] — simplest model; the rest was theatre.
- **Outcome:** Vaasa won 4-3-2-1.
- **Lesson:** I lean toward misdirection-spotting; useful for grand plans, noise on small ones.
```
**`on-the-user.md`** — slow-growing picture of the user; update only when something non-obvious comes up.
**`revisit.md`** — checklist of questions/topics to come back to.
Researcher and Scribe have only `persona.md` — they write session files, not journals.
### Session directory layout
**`sessions/<slug>/brief.md`** — Moderator writes after Phase 0 interview:
```markdown
---
type: council-brief
date: 2026-04-19
slug: 2026-04-19_self-host-email
problem: "Should I self-host my email or use Fastmail?"
---
# Brief — Should I self-host my email?
## Question
{verbatim user prompt}
## Clarifications from the Phase-0 interview
- Time pressure: none — exploring.
- Constraints: single user, €20/mo soft budget, comfortable with Linux admin.
- Decision criteria: reliability > cost > sovereignty.
## Research threads to investigate (for the Researcher)
- Fastmail reliability + recent incidents
- Self-hosted-mail deliverability today (SPF/DKIM/DMARC, IP reputation)
- Migration cost and lock-in
-
## What a good answer looks like
A recommendation with the conditions under which the recommendation flips.
## Additions from Phase-1 clarifications
<!-- present if the Researcher flagged `User clarification needed` before researching; otherwise absent -->
## Additions from Phase-2 clarifications
<!-- present if members flagged clarifications after initial answers; otherwise absent -->
## Additions from Phase-3 clarifications
<!-- present if members flagged clarifications during debate; otherwise absent -->
```
**`sessions/<slug>/research/<topic-slug>.md`** — Researcher writes, one per topic:
```markdown
---
type: council-research
session: 2026-04-19_self-host-email
topic: "Fastmail reliability"
round: 1
---
# Fastmail reliability
## Summary
One or two paragraphs — what the evidence says, in Naima's analytic voice.
## Evidence
- [status.fastmail.com — incidents 20242026](https://status.fastmail.com/history) (accessed 2026-04-19)
-
## Uncertainty / conflicting sources
-
```
Round-2 research files (from Phase 3b follow-ups) set `round: 2`.
**`initial-answers.md`, `revised-answers.md`, `votes.md`** — Scribe writes after each phase. `revised-answers.md` has sections for Round 1 and (if any) Round 2. `votes.md` includes each member's vote + rationale and the tally.
**`outcome.md`** — canonical session file (picked up by the Obsidian Base):
```markdown
---
type: council-session
date: 2026-04-19
slug: 2026-04-19_self-host-email
problem: "Should I self-host my email or use Fastmail?"
participants: [tavsan, okafor, holt, vale, prochazka, vaasa, lindholm, vire, tintori, koskela]
winner: vaasa
tied: false
tie_broken_by_user: false
votes: {vaasa: 4, okafor: 3, vale: 2, tintori: 1}
had_research_gap_round: false
had_phase1_clarification: false
had_phase2_clarification: false
had_phase3_clarification: false
open_questions_at_vote: []
tags: [email, self-hosting, infra]
---
# Outcome — Should I self-host my email?
See [[brief]], [[initial-answers]], [[revised-answers]], [[votes]].
## Winner — [[members/vaasa/persona|Dr. Ingrid Vaasa]] (4 votes)
{verbatim winning revised answer}
## Vote tally
{table from votes.md}
```
### Obsidian Bases
**`council-sessions.base`**:
```yaml
filters:
and:
- note.type == "council-session"
properties:
note.date: {displayName: Date}
note.problem: {displayName: Question}
note.winner: {displayName: Winner}
note.tied: {displayName: Tied}
note.tie_broken_by_user: {displayName: User tiebreak?}
note.had_research_gap_round: {displayName: Extra research?}
note.had_phase1_clarification: {displayName: Phase-1 clarif?}
note.had_phase2_clarification: {displayName: Phase-2 clarif?}
note.had_phase3_clarification: {displayName: Phase-3 clarif?}
note.tags: {displayName: Tags}
views:
- type: table
name: All sessions
order: [file.name, note.date, note.problem, note.winner, note.tied, note.tags]
sort:
- property: note.date
direction: DESC
```
**`council-members.base`**:
```yaml
filters:
and:
- note.type == "council-member"
properties:
note.name: {displayName: Name}
note.prior_job: {displayName: Prior job}
note.lens: {displayName: Lens}
note.voting: {displayName: Votes?}
views:
- type: table
name: The Council
order: [note.name, note.prior_job, note.lens, note.voting]
```
## Orchestration — `/council <problem>`
Load-bearing file: `.claude/commands/council.md`. Every phase produces an internal data flow (sub-agent calls) **and** visible user output (Moderator narration).
### Phase 0 — Context interview (Moderator ↔ User)
1. Moderator reads `$ARGUMENTS`, proposes a session slug (`YYYY-MM-DD_<short-kebab>`), creates `sessions/<slug>/`.
2. Generates 2-4 targeted clarifying questions via `AskUserQuestion`: constraints, time pressure, who's affected, decision criteria, what a good answer looks like.
3. Writes `sessions/<slug>/brief.md` — problem, user's answers, constraints, a first-pass list of research threads.
**User sees:** the clarifying questions, then: "Brief written to `sessions/.../brief.md`. Sending to the Researcher for a pre-session pass."
### Phase 1 — Pre-session research (1 × Sonnet Researcher; may trigger user-clarification sub-step)
Moderator invokes `council-researcher` with the brief. The Researcher is told: "You may return a `## User clarification needed` section at **any point during your work** — before starting (if the brief is too vague to research) or mid-research (if ambiguity surfaces as you dig). 1-3 concrete questions only the user can answer. If you have no clarifications, proceed to research and produce topic files."
**If Researcher flags clarifications:**
- Moderator consolidates → `AskUserQuestion` (up to 4 questions) → appends answers to `brief.md` under `## Additions from Phase-1 clarifications` → re-invokes Researcher once (she now has the updated brief). Max one clarification round at this phase.
**If Researcher proceeds:**
- Identifies 5-10 concrete topics from the brief's "Research threads" section (expanding where she thinks useful).
- Runs web searches; synthesizes.
- Writes one `sessions/<slug>/research/<topic-slug>.md` per topic (frontmatter `round: 1`).
- Returns a short table of contents.
**User sees:** either the clarification question block (if Researcher flagged), then a confirmation, then: list of topics researched, file count, "Research package ready in `sessions/.../research/`. Handing to the Council."
### Phase 2 — Initial Answer (10 × Sonnet, parallel; members may flag clarifications)
10 `Agent` calls in parallel. Each member reads: the brief, all files in `sessions/<slug>/research/`, its own `members/<slug>/` files. Returns:
- `## Initial answer` (self-contained)
- `## Confidence (1-5)`
- Optional `## User clarification needed` — 1-2 concrete questions only the user can answer that would change the answer. Still produce the initial answer as the member's best current shot.
Members **must** cite research-file filenames when a claim leans on them.
**If any member raises clarifications:** Moderator consolidates + dedupes → `AskUserQuestion` (up to 4 questions) → appends answers to `brief.md` under `## Additions from Phase-2 clarifications`. The updated brief flows into Phase 3; Phase 2 is **not** re-run (cost avoidance — Phase 3 is where revision happens anyway).
After collection, Moderator invokes Scribe to write `sessions/<slug>/initial-answers.md` (verbatim, attributed, including any clarification flags raised).
**User sees:**
> **Moderator:** 10 initial answers in. One-line summaries:
> - **Tavşan:** <≤15 words>
> - **Okafor:** <≤15 words>
> - …
>
> [if any clarifications were raised:] Clarifications requested from you — see next question block.
> (Moderator then hits `AskUserQuestion`.)
>
> Written to `initial-answers.md`. Moving to debate + revise on Opus.
### Phase 3 — Debate + Revise (10 × Opus, parallel, with optional bounded follow-up)
Moderator assembles the debate packet: the 10 attributed initial answers. Dispatches 10 `Agent` calls with `model: "opus"`, each given:
- problem + brief + research files + debate packet + own memory
- phase directive:
> Critique the other 9 (one paragraph each). Produce a `Revised answer` (self-contained). `What changed and why` (≤3 bullets).
>
> If information is missing and would change your answer, include **one or both**:
> - `## Research gap` — one or two specific, searchable questions. Be concrete.
> - `## User clarification needed` — one or two questions only the user can answer.
>
> Either way, still produce your `Revised answer` as your best current shot.
**Moderator handling after Phase 3a returns:**
- **If any member raised `Research gap`:** Moderator consolidates gaps → dedupes → invokes Researcher for a second run, writing new files to `research/` with `round: 2`.
- **If any member raised `User clarification needed`:** Moderator consolidates the questions → uses `AskUserQuestion` with up to 4 questions → appends the user's answers to `brief.md` under `## Additions from Phase-3 clarifications`.
- **If either fired**, Moderator runs one **bounded second revision round** (10 × Opus): members see their first-round revised answer + the new information and produce a final revised answer. Hard cap at one follow-up loop; further flags in round 2 are noted but not acted on.
Scribe writes `revised-answers.md` (with Round 1 and, if present, Round 2 sections).
Outcome flags `had_research_gap_round` / `had_user_clarification_round` in `outcome.md` frontmatter reflect whether these fired.
**User sees:**
> **Moderator:** Revisions in. Notable shifts:
> - **Tavşan:** held ground / softened on X / pivoted to Y
> - …
>
> Research gaps flagged by [members]: running round-2 research on [topics].
> (or: "No research gaps or clarifications requested.")
>
> Clarifications requested from you — see next question block.
> (Moderator then hits `AskUserQuestion` with the consolidated clarification questions.)
>
> Moving to vote on Sonnet.
### Phase 4 — Vote (10 × Sonnet, parallel, transparent; late clarifications noted but not acted on)
Moderator assembles the ballot: the 10 final revised answers, **attributed by name** (no anonymization — per user: "the agents will be reading each other's arguments and will already have an idea who is saying what; anonymity mostly hides things from me").
Dispatches 10 `Agent` calls, each given:
- problem + brief + ballot (attributed) + own memory
- "Reply with `## Vote: <slug>` on its own line (e.g. `## Vote: vaasa`), then `## Rationale` (one sentence). Self-votes are allowed. You may add an optional `## User clarification needed` section if something still bothers you — it will be surfaced to the user in the outcome as an open question, but will not delay the vote."
Voter-raised clarifications at this point are **informational** — Moderator surfaces them in `outcome.md` under `## Open questions raised at vote` and does not re-run earlier phases. (Enforces the one-bounded-loop rule.)
Scribe writes `votes.md` with each member's vote + rationale, any clarification flags, and the tally.
### Phase 5 — Tally, tie-break, present, archive
1. **Moderator tallies.**
2. **No tie:** prints voting table + full winning answer; invokes Scribe to write `outcome.md`.
3. **Tie:** Moderator calls `AskUserQuestion` — one option per tied answer. `description` = 1-paragraph scribe-style summary + key differentiator. `preview` = verbatim full answer. User picks → winner. `outcome.md` records `tied: true`, `tie_broken_by_user: true`.
4. **Memory update batch**: 10 parallel Sonnet `Agent` calls, each told the final outcome + their own vote + the winner; each appends to `members/<slug>/journal.md` (and updates `on-the-user.md`/`revisit.md` if warranted). Returns one-line confirmations.
**Final user output:**
```
| Voter | Voted for (snippet) |
|---|---|
| Elif Tavşan | Dr. Ingrid Vaasa — "Strip to the minimal model…" |
| Dr. Wren Okafor | Dr. Wren Okafor (self) — "Treat this as a coupled…" |
| Magnus Holt | Dr. Ingrid Vaasa — "Least hidden state, least failure" |
| Sister Vale | Dr. Wren Okafor — "The decision underneath the decision" |
| Niko Prochazka | Dr. Ingrid Vaasa — "Cleanest checklist" |
| Dr. Vaasa | Dr. Ingrid Vaasa (self) — "Toy model is the argument" |
| Kai Lindholm | Marcelo Tintori — "Feels human" |
| Cassian Vire | Dr. Wren Okafor — "Scales across a century" |
| Marcelo Tintori | Sister Vale — "Cuts the theatre" |
| Mari Koskela | Dr. Ingrid Vaasa — "Matches observed practice" |
**Result:** Dr. Ingrid Vaasa wins with 4 votes.
---
## Winning answer — Dr. Ingrid Vaasa
<verbatim winning revised answer>
---
Session logged → `sessions/2026-04-19_self-host-email/`
```
### Moderator output discipline
- Each between-phase update ≤ ~10 lines.
- Never dumps raw sub-agent output or tool-call content.
- If the user asks "what did X say?" mid-flow or after, Moderator can print that specific member's full answer on request.
- On sub-agent errors/timeouts, surfaces which members failed and whether to retry or proceed with fewer.
## Tool permissions per agent
Enforced via each sub-agent's `tools:` frontmatter; reiterated in each system prompt.
| Agent | Read | Write/Edit | Grep/Glob | WebSearch / WebFetch |
|---|---|---|---|---|
| Voting members (×10) | ✓ | only in own `members/<slug>/` | ✓ | ✗ |
| Researcher (Naima Quéré) | ✓ | only in `sessions/<slug>/research/` | ✓ | ✓ |
| Scribe (Ansel Voss) | ✓ | in `sessions/<slug>/` except `research/` | ✓ | ✗ |
| Moderator (main session) | ✓ | anywhere | ✓ | ✓ |
Path-level write scoping is a convention reinforced in each system prompt; Claude Code sub-agents share the filesystem, so the social contract matters.
## CLAUDE.md content (sketch)
```markdown
# CLAUDE.md
This file provides guidance to Claude Code (claude.ai/code) when working with code in this repository.
## What this repo is
A "Council of 10" deliberation system, with a dedicated Researcher and a Scribe, orchestrated by the main Claude Code session as Moderator. Sessions are the core artefact — one directory per session at `sessions/<slug>/`. The repo root is an Obsidian vault.
## Running a council session
`/council <problem>` — the only entry point. Orchestration in `.claude/commands/council.md`. Phases:
- **0. Context interview** — Moderator ↔ user via `AskUserQuestion`. Moderator writes `sessions/<slug>/brief.md`.
- **1. Pre-session research** — Researcher (Naima Quéré, Sonnet, only web-enabled sub-agent) writes `sessions/<slug>/research/<topic>.md` files off the brief. May flag `User clarification needed` before researching if the brief is too vague.
- **2. Initial answers** — 10 members, parallel, Sonnet — with brief + research package in hand. Members may flag `User clarification needed`; answers append to `brief.md` and flow into Phase 3 (Phase 2 is not re-run).
- **3. Debate + Revise** — 10 members, parallel, Opus. Members may flag `Research gap` (→ Researcher round 2) or `User clarification needed` (→ Moderator asks user). If either fires, one bounded second revision round happens.
- **4. Vote** — 10 members, parallel, Sonnet. Ballot is **transparent** (attributed by name). Self-votes allowed. Any last clarification flags are surfaced in `outcome.md` as open questions without re-running earlier phases.
- **5. Tally + Tie-break + Archive** — Moderator tallies. On tie: `AskUserQuestion` with tied full answers as option previews. Scribe writes `outcome.md`. Final Sonnet batch updates each member's `journal.md`.
## Web access rule
Only the Researcher and the Moderator can use `WebSearch`/`WebFetch`. Council members cannot. Members who need more info flag it in Phase 3 via `## Research gap`.
## User clarification is available in every phase
Any agent may flag `## User clarification needed` in any phase (Researcher in Phase 1, members in Phases 24). The Moderator batches the questions, asks the user via `AskUserQuestion`, and appends the answers to `brief.md`. Handling depends on the phase: Phase 1 → re-run Researcher once; Phase 2 → updated brief flows into Phase 3; Phase 3 → one bounded follow-up revision round; Phase 4 → surfaced in `outcome.md` only, no re-run.
## Moderator responsibilities
The main Claude Code session is the Moderator — the user's only window into the proceedings:
1. Narrates between phases (≤ ~10 lines per update).
2. Runs the Phase-0 interview and the Phase-3 user-clarification sub-interviews.
3. Consolidates research-gap flags and re-invokes the Researcher when warranted.
4. On vote ties, presents tied full answers via `AskUserQuestion`.
5. Never prints raw tool output.
## Directory map
- `.claude/agents/council-*.md` — 10 voting members + `council-researcher.md` + `council-scribe.md`
- `.claude/commands/council.md``/council` orchestration
- `members/<slug>/` — per-member memory (`persona.md`, `journal.md`, `on-the-user.md`, `revisit.md`)
- `sessions/<slug>/` — one directory per session (`brief.md`, `research/`, `initial-answers.md`, `revised-answers.md`, `votes.md`, `outcome.md`)
- `council-sessions.base`, `council-members.base` — Obsidian Bases at repo root
## Memory protocol
Each voting member reads every file in its `members/<slug>/` directory at the start of every invocation. Every `/council` run produces:
- One `journal.md` entry per voting member (mandatory, via the Phase-5 memory batch).
- Updates to `on-the-user.md` and `revisit.md` only when non-obvious.
- One full session directory at `sessions/<slug>/`.
Researcher and Scribe have persona files only; no journals.
## Obsidian conventions
Every markdown file has YAML frontmatter with a `type` property (`council-member`, `council-journal`, `council-brief`, `council-research`, `council-session`). Wikilinks are folder-qualified. Two `.base` files provide table views.
## Modifying the council
- Swap a voting member: edit `.claude/agents/council-<slug>.md` and `members/<slug>/persona.md` (mirror both).
- Add a voting member: create the agent def, seed `members/<newslug>/`, update the roster (and the "10 members" count wording) in `.claude/commands/council.md`.
- Researcher and Scribe are singletons — edit their files directly.
```
## Verification
After implementation, verify end-to-end:
1. Run `/council "Should I self-host my email or use Fastmail?"` — expect:
- Phase 0 `AskUserQuestion` (2-4 questions); `sessions/2026-04-19_self-host-email/brief.md` appears.
- `sessions/.../research/*.md` files appear from the Researcher's pre-session pass.
- 10 distinct initial answers cited against research files.
- `revised-answers.md` with Round-1 revisions; if any member flagged a `Research gap` / `User clarification needed`, verify Round 2 + updated brief.
- Transparent vote: ballot shows authors; votes + rationale logged.
- `outcome.md` with complete frontmatter, wikilinks, and verbatim winning answer.
- Each of the 10 `members/<slug>/journal.md` gains one new entry referencing the session.
2. `council-sessions.base` in Obsidian shows the new session (sorted by date DESC).
3. `council-members.base` shows all 10 voting members + Researcher + Scribe, with `voting: false` for the latter two.
4. Run a second, unrelated question (`/council "How do I tell my sister I'm not coming to her wedding?"`) — personas stay in character; memories from run 1 don't inappropriately bleed in; fresh session directory.
5. Force a close vote (or wait until one happens). On tie: Moderator hits `AskUserQuestion` with tied full answers as option previews; `outcome.md` records `tie_broken_by_user: true`.
6. Run a question that the Researcher clearly can't fully answer upfront; expect at least one member to raise a `Research gap`, Researcher to produce a round-2 file, and Round-2 revised answers to appear.
7. Verify no voting member has `WebSearch`/`WebFetch` in its `tools:` frontmatter; only Researcher does.
8. Confirm Moderator narration stays concise; no raw sub-agent output leaks into user-facing text.
## Critical files to create (in order)
1. **`docs/structure/initial-plan.md`** — copy of this plan archived into the repo, so it lives alongside what it describes. Written first thing when implementation starts.
2. `CLAUDE.md`, `README.md`
3. `.claude/agents/council-tavsan.md``council-koskela.md` (10 voting members)
4. `.claude/agents/council-researcher.md` (Naima Quéré)
5. `.claude/agents/council-scribe.md` (Ansel Voss)
6. `members/<slug>/persona.md` × 12 (10 voting + researcher + scribe) — with frontmatter
7. `members/<slug>/{journal.md, on-the-user.md, revisit.md}` × 10 voting members — empty-with-header
8. `council-sessions.base`, `council-members.base`
9. `.claude/commands/council.md` — orchestration (save for last; depends on everything above)