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>
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
# 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. Ten Claude Code sub-agents with distinct personas (plus a Researcher and a Scribe, both non-voting) deliberate on problems posed by the user through a structured five-phase workflow. **The main Claude Code session acts as the Moderator** — the user's only window into the proceedings.
|
||||
|
||||
The repo root is an Obsidian vault. Sessions are the core artefact of the project, one directory per session at `sessions/<slug>/`.
|
||||
|
||||
The full design is archived at `docs/structure/initial-plan.md`.
|
||||
|
||||
## Running a council session
|
||||
|
||||
`/council <problem>` — the only entry point. Orchestration lives 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 or during researching.
|
||||
- **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 (via `model` override in the `Agent` call). 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 (Haiku) writes `outcome.md`. Final Sonnet batch updates each member's `journal.md`.
|
||||
|
||||
## Moderator responsibilities (this is you — the main session)
|
||||
|
||||
The main Claude Code session is the Moderator. The user **cannot** see sub-agent tool calls, Read output, or inter-agent packets. You are their only window.
|
||||
|
||||
1. Narrate between phases — ≤ ~10 lines per update. State what just happened and what's next.
|
||||
2. Run the Phase-0 interview via `AskUserQuestion` before the Council sees anything.
|
||||
3. Consolidate `Research gap` and `User clarification needed` flags when they appear; re-invoke Researcher or `AskUserQuestion` as appropriate.
|
||||
4. On vote ties, present tied answers via `AskUserQuestion` with full answers as option previews.
|
||||
5. Never dump raw sub-agent output into user-facing text — always distil.
|
||||
|
||||
## Web access rule
|
||||
|
||||
Only the **Researcher** and the **Moderator** can use `WebSearch` / `WebFetch`. Council members cannot — they rely on the shared research files in `sessions/<slug>/research/`. Members who need more info raise `## Research gap` in Phase 3.
|
||||
|
||||
## User clarification is available in every phase
|
||||
|
||||
Any sub-agent may include a `## User clarification needed` section in their output, at any phase:
|
||||
- **Phase 1 (Researcher)** — before or mid-research → Moderator asks user, appends answers, re-invokes Researcher once.
|
||||
- **Phase 2 (Members)** — after initial answers → Moderator asks user, appends answers; updated brief flows into Phase 3 (Phase 2 is not re-run).
|
||||
- **Phase 3 (Members)** — during debate → one bounded follow-up revision round.
|
||||
- **Phase 4 (Voters)** — informational only; surfaced in `outcome.md` as "Open questions raised at vote" without re-running.
|
||||
|
||||
Hard cap: at most **one** follow-up revision round per session.
|
||||
|
||||
## 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 the root
|
||||
- `docs/structure/initial-plan.md` — archived design document
|
||||
|
||||
## 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 something non-obvious comes up.
|
||||
- One full session directory at `sessions/<slug>/`.
|
||||
|
||||
Researcher and Scribe have persona files only — no journals.
|
||||
|
||||
## Tool permissions per sub-agent
|
||||
|
||||
| Agent | Read | Write/Edit | 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 enforced in each system prompt — sub-agents share the filesystem, so the social contract matters.
|
||||
|
||||
## Obsidian conventions
|
||||
|
||||
Every markdown file under the vault has YAML frontmatter with a `type` property (`council-member`, `council-journal`, `council-brief`, `council-research`, `council-session`). Inter-document references use folder-qualified wikilinks (e.g. `[[members/vaasa/persona|Dr. Ingrid Vaasa]]`). Two `.base` files at the root provide table views.
|
||||
|
||||
## Modifying the council
|
||||
|
||||
- **Swap a voting member:** edit both `.claude/agents/council-<slug>.md` and `members/<slug>/persona.md` (mirror the changes).
|
||||
- **Add a voting member:** create the agent def, seed `members/<newslug>/`, then update the roster and the "10 members" wording in `.claude/commands/council.md`.
|
||||
- **Researcher and Scribe are singletons** — edit their files directly.
|
||||
@@ -0,0 +1,55 @@
|
||||
# Council
|
||||
|
||||
A Claude Code deliberation system with a persistent memory layer, browsable as an Obsidian vault.
|
||||
|
||||
You pose a question; a council of ten distinct personas (plus a Researcher and a Scribe) deliberates through a structured five-phase workflow, produces a voting table, and hands you the winning answer. Every session leaves a full transcript and persistent memory behind.
|
||||
|
||||
## Quick start
|
||||
|
||||
Inside the repo in Claude Code:
|
||||
|
||||
```
|
||||
/council <your question>
|
||||
```
|
||||
|
||||
The Moderator (the main Claude Code session) will interview you briefly for context, then kick off the Council. You'll be asked follow-up questions along the way — to clarify the brief, resolve research gaps, or break vote ties. At the end you get a voting table and the full winning answer; everything is archived to `sessions/<slug>/`.
|
||||
|
||||
## The Council
|
||||
|
||||
10 voting members, wild eclectic mix:
|
||||
|
||||
- **Elif Tavşan** — retired stage magician & cold-reading coach
|
||||
- **Dr. Wren Okafor** — deep-sea marine biologist → systems ecologist
|
||||
- **Magnus Holt** — bankruptcy lawyer → insolvency-law lecturer
|
||||
- **Sister Beatrix Vale** — Benedictine nun → hospice counselor
|
||||
- **Nikolai "Niko" Prochazka** — Soviet cosmonaut trainer → wilderness survival instructor
|
||||
- **Dr. Ingrid Vaasa** — theoretical physicist (QFT) → independent researcher
|
||||
- **Kai "Breaker" Lindholm** — pro skateboarder → skatepark architect
|
||||
- **Cassian Vire** — investigative journalist → speculative-fiction novelist
|
||||
- **Marcelo "Marco" Tintori** — trained painter → 20 years as a corrections officer
|
||||
- **Mari Koskela** — marine engineer on cargo ships → anthropologist of maritime labor
|
||||
|
||||
Plus two non-voting roles:
|
||||
|
||||
- **Naima Quéré** (Researcher) — the only sub-agent with web access.
|
||||
- **Ansel Voss** (Scribe) — transcribes proceedings and writes session files.
|
||||
|
||||
See `council-members.base` for the full roster as a table view in Obsidian.
|
||||
|
||||
## Browsing sessions in Obsidian
|
||||
|
||||
Open this repo as an Obsidian vault. The two Bases at the root provide table views:
|
||||
|
||||
- **`council-sessions.base`** — every session, sortable by date / winner / whether a tie happened.
|
||||
- **`council-members.base`** — the full roster with prior jobs and lenses.
|
||||
|
||||
Individual session files live at `sessions/<slug>/`:
|
||||
- `brief.md` — the Moderator's brief from the Phase-0 interview
|
||||
- `research/*.md` — the Researcher's per-topic notes
|
||||
- `initial-answers.md`, `revised-answers.md`, `votes.md` — phase transcripts
|
||||
- `outcome.md` — the canonical session file (winner, tally, full winning answer)
|
||||
|
||||
## Deeper docs
|
||||
|
||||
- `CLAUDE.md` — guidance for Claude Code when working inside this repo
|
||||
- `docs/structure/initial-plan.md` — the full design document
|
||||
@@ -0,0 +1,592 @@
|
||||
# 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 2024–2026](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 2–4). 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)
|
||||
Reference in New Issue
Block a user