Keyboard shortcuts

Press ← or → to navigate between chapters

Press S or / to search in the book

Press ? to show this help

Press Esc to hide this help

eddy

eddy lists recorded meetings across meeting services and fetches their transcripts. It holds one part per service: wispr first, then webex and teams. Each part lists the meetings its service recorded since its cursor, keys each meeting, writes its transcript as raw files, and prints one capture line per meeting. millpond takes those lines and records each meeting once, as an unread capture in an inbox (millpond’s book). No model runs while a part lists. A meeting becomes signals later, when a reader session reads its transcript (115).

eddy in one pass Three meeting services, Wispr Flow, Webex and Microsoft Teams, each feed one of eddy's parts. A part lists recorded meetings and fetches each transcript, and prints capture lines that millpond checks, dedupes by key and banks. No model runs inside that listing. What a listing leaves is an unread capture in the inbox, in git, which points at the raw transcript in the host's raw bank, never in git. A reader session takes the unread capture later and writes its signals. SERVICES EDDY'S PARTS MILLPOND WHAT A LISTING LEAVES a listing: arithmetic, and no model runs (115) Wispr Flow MCP over HTTP Webex transcripts API Microsoft Teams Graph transcripts wispr lists, fetches · first webex lists, fetches · later teams lists, fetches · later lines millpond land checks each line dedupes by key banks the raw files Unread captures the inbox, in git; no excerpt, so no signal yet <host>:<path> Raw transcripts as served, and one line per turn; the raw bank, never in git A reader, later a session reads the transcript and writes signals (113) eddy's work ends when millpond holds the capture. Reading a meeting is judgment, so a session does it.
A part lists one service's recorded meetings and fetches each transcript. millpond takes the lines, so each meeting lands once, as an unread capture whose transcript stays on the host. No model runs until a reader takes the capture later.

Why it exists

Decisions that should change a repository’s work are often made in meetings. Each meeting is recorded on whichever service hosted it, and each service keeps its transcripts behind its own interface and its own sign-in.

Two jobs stand between a recorded meeting and the work it should change. Listing is arithmetic: which recordings exist, which are new since the last listing, and when each meeting began. Reading is judgment: which sentences commit someone to something, and who said them. Flywheel’s statement keeps the two apart. Enumerating source events and writing captures runs unattended, and turning a capture into signals is a session’s judgment that never runs unattended (115).

eddy is the unattended half, for meetings. It knows every meeting service it has a part for, and nothing of signals.

What it promises

  • Each meeting lands once. A part keys a meeting by its service and the meeting’s own id, so every host and every run gives one meeting one key, and millpond keeps one capture per key (111).
  • A meeting counts from the day it was held. A capture’s event_at is when the meeting started, never when it was captured (118).
  • A meeting’s words stay on the host. The transcript is raw material. The capture points at it, and none of it enters git (111).
  • Every meeting reaches the inbox unread. No meeting capture carries an excerpt, so millpond writes no signal for it and charges a reader instead (115).
  • One meeting never stops the rest. A part names a meeting it failed to fetch in the run’s last line and goes on to the next.

Where it stops

eddy lists, fetches and prints. millpond writes each capture, banks the raw files and keeps each part’s cursor. eddy writes no record, keeps no list of what it reported, cuts no excerpt and reads no meeting into signals. Which inbox records a part’s meetings, on which host the part runs and how often are the host’s to say, in millpond’s settings or a fleet’s list. eddy never learns which inbox records its meetings.

What becomes of a meeting

A reader reads an unread meeting capture into signals, and curation gives each signal one move, joining some into items (curation and moves). An item goes to one worktree or into crew’s plan, and the work it becomes lands through sluice.

An item that asks a question, such as how to settle what a meeting left open, goes to a sounding (a question, sent to a sounding). One session works the question in a worktree of its own and ends on a conclusion, which the operator accepts, sends back for another round, or drops (sounding’s book). The operator can also open a sounding with /sound on a decision a meeting left open, the meeting’s transcript among its sources. Once a conclusion is accepted, millpond keeps it as the item’s record, and curation answers a later signal on the same subject by naming it (116).

eddy takes part in none of this. Its work ends when millpond holds the capture.

Where it sits

headwater does for releases what eddy does for meetings (headwater’s book). Each stands alone with its own Claude Code and herdr plugins, and each carries a Flywheel plugin whose adapter parts feed millpond. millpond is the inbox both of them print into. sounding takes the questions a meeting leaves open (sounding’s book). Flywheel later runs the same parts on its tick and takes the same lines (215, 231), and a part never knows which host ran it.

How to read this book

The chapters are the design: eddy on its own, a part per service, what every part shares, a meeting’s raw files, running a part, and how others add a service. A glossary and the open questions follow. Their source is the capture design, design/capture/design.md. eddy has no statement of invariants yet, so the book has no appendix. A number in parentheses points into Flywheel’s statement, design/flywheel-next/requirements.md.

eddy on its own

eddy is a tool for meetings first and an adapter second. It stands alone as headwater does: one core that lists and fetches meetings across services, and one plugin per host beside the core. A person who installs only eddy reads their meetings with it. A host that runs millpond takes the same listings as captures through eddy’s Flywheel plugin.

eddy's core and its three plugins eddy's core lists recorded meetings and fetches transcripts, and holds the code every part shares. Three plugins sit beside it. plugins/claude pulls a transcript into a Claude Code session. plugins/herdr shows the day's meetings in a pane. plugins/flywheel holds an adapter part per service, whose capture lines millpond runs, and Flywheel's tick later. Only the Flywheel plugin's parts reach an inbox. THE CORE A PLUGIN PER HOST WHAT IT GIVES eddy's core lists recorded meetings fetches a transcript per service it has a part for the code every part shares plugins/claude Claude Code plugins/herdr herdr plugins/flywheel an adapter part per service A transcript in a session for a person asking about one meeting The day's meetings in a pane across every service with a part Capture lines for millpond run by millpond, later by Flywheel's tick Only the Flywheel plugin's parts reach an inbox. The other two write nothing anywhere.
eddy is one core with a plugin per host. A person reaches meetings through the Claude Code and herdr plugins. millpond reaches them through the Flywheel plugin's adapter parts, and only those parts print captures.

The core

The core knows each meeting service eddy has a part for: how to list the meetings it recorded, and how to fetch one meeting’s transcript. It also holds the code every part shares: the key, the meeting’s details, the raw layout and the rule that skips a meeting too short to hold anything. What every part shares and A meeting’s raw files describe it. Every plugin calls the core, so the pane, the session and an adapter part all see the same meetings under the same keys.

The plugins

eddy keeps one plugin per host under plugins/, beside its core, as headwater does:

PluginHostGives
plugins/claudeClaude Codepulls a meeting’s transcript into a session
plugins/herdrherdrshows the day’s meetings
plugins/flywheelFlywheel, and millpondone adapter part per meeting service

A plugin is the installable unit in every host, and it holds parts of the kinds its host takes. Flywheel’s statement calls it a package (228, 284).

The Claude Code plugin serves a person working in a session who wants one meeting in front of them: what was agreed, who asked for what. It pulls the transcript into that session and records nothing. The herdr plugin shows the day’s meetings, from every service eddy has a part for, in a pane beside the person’s work.

The Flywheel plugin holds the adapter parts, one per meeting service, and nothing else. millpond runs a Flywheel plugin’s adapter parts and ignores the rest of it, so eddy’s parts run under millpond today and under Flywheel’s tick later, with no change (215, 231).

Alone, and beside an inbox

eddy needs no inbox. A person with only eddy’s Claude Code and herdr plugins lists and reads meetings, and nothing about them is kept anywhere.

A host that runs millpond names a meeting part in an inbox’s settings, and the part’s listings become captures. The inbox then works in any of its three setups: on its own, with crew, or with Flywheel (millpond’s three setups). Moving from one setup to the next changes the host and the curator. eddy’s parts stay as they were, so no meeting is captured twice.

A part per service

A part is eddy’s code for one meeting service, run as an adapter. Its own code does two things: it lists the meetings its service recorded since its cursor, and it fetches each meeting’s transcript. Everything else a part does, every other part does the same way, and the next chapter describes it.

What a part owns and what it shares Three parts, wispr for Wispr Flow's MCP endpoint, webex for Webex's transcripts API and teams for Microsoft Graph's meeting transcripts, each own only listing and fetching. Below them, one layer every part shares: the key's shape, the meeting's title, start, length and attendees, the raw layout, and skipping a meeting too short to hold anything. Below that, flywheel-next's capture crate holds the contract's types and key rules. OWN CODE, ONE PART PER SERVICE wispr Wispr Flow's MCP endpoint list fetch webex Webex's transcripts API list fetch teams Microsoft Graph's transcripts list fetch Shared by every part, in eddy the key's shape · title, start, length, attendees · the raw layout · skipping a meeting too short to hold anything flywheel-next's capture crate the contract's types and key rules, JSON in flight, used by millpond, Flywheel, headwater and eddy
A part's own code is listing and fetching from its service. What every meeting part shares is written once in eddy, and the contract's types and key rules once in flywheel-next's capture crate. Adding a service adds one box to the top row.

The parts

PartSourceKeyWhen
wisprWispr Flow’s MCP endpoint, over HTTPmeeting/wispr/<meeting id>first
webexWebex’s transcripts APImeeting/webex/<meeting id>when a partition records on Webex
teamsMicrosoft Graph’s meeting transcriptsmeeting/teams/<meeting id>when a tenant’s administrator consents

wispr comes first. Wispr Flow serves its meetings through an MCP endpoint over HTTP. The part is an MCP client of that endpoint, with a sign-in of its own, and calls the endpoint’s tools from its own code. No Claude session runs to list meetings, since a listing is arithmetic and runs unattended (115).

webex reads Webex’s transcripts API. eddy gains it when a partition records its meetings on Webex.

teams reads Microsoft Graph’s meeting transcripts. Graph serves a tenant’s transcripts only to an application the tenant’s administrator has consented to, so the part comes when an administrator consents.

Its sign-in

A part that signs in to its service keeps that sign-in itself. The host’s only job is to hand the part what the plugin declared:

  • On millpond the user signs in once per host, and the part keeps the sign-in from then on.
  • On Flywheel the host places the secrets the plugin declares (228).

Either host starts the part with each declared secret in its environment, under the secret’s declared name. A fleet’s user makes a part’s sign-in once per host, beside the other sign-ins that host holds.

Its cursor

A part lists the meetings its service recorded since its cursor. The cursor is the part’s own, and millpond treats it as opaque: millpond keeps the last cursor from a run that ended in its done line and hands it back on the next run. A part works with no cursor at all. Listing a window again is safe, because millpond dedupes by key, so a lost cursor costs one wider listing and no second capture (111).

Its tests

eddy tests each of its parts by replaying the service’s recorded responses, so a part’s tests need no account, no sign-in and no network. A part counts as a meeting part when it also passes the meeting checks in the conformance pack, which How others add a service describes.

What every part shares

The parts share everything but the service. eddy writes four things once, and every part calls them: the key’s shape, the meeting’s details, the raw layout, and the rule that skips a meeting too short to hold anything. A part’s own code reads its service in the service’s terms and hands the shared code one shape of meeting. The raw layout has a chapter of its own, A meeting’s raw files.

The key

A part keys a meeting by its service and the meeting’s own id:

meeting/<service>/<meeting id>

<service> is the part’s name, such as wispr, and <meeting id> is the id the service gives the meeting. The key is the meeting’s identity: every host and every run gives one meeting one key, and millpond holds one capture per key (111). Every meeting key starts with meeting, so none starts with /, captures or moves, which the contract refuses (the key).

The key is what lets a part forget. millpond looks every key up in the inbox before it writes, so a part keeps no list of what it reported and may list the same window as often as it likes. What a key cannot do is join two services: a meeting recorded on two services gets a key from each, and two captures.

One key per meeting per service On the left, a part runs at 09:00 and lists meetings m41 and m42, then runs at 12:00 and lists m42 and m43. millpond writes three captures; the second line for m42 is passed over and counted. On the right, one meeting recorded on Wispr Flow and on Webex gets two keys, meeting/wispr/a7f and meeting/webex/9921, and two unread captures. A reader reads them together and writes the second's signals once. ONE MEETING LISTED TWICE run, 09:00 meeting/wispr/m41 meeting/wispr/m42 run, 12:00 meeting/wispr/m42 meeting/wispr/m43 millpond three captures; m42's second line is passed over and counted One meeting has one key on every host and in every run, so a part lists any window again and keeps no list of what it reported. ONE MEETING RECORDED TWICE One meeting recorded on Wispr Flow and on Webex meeting/wispr/a7f meeting/webex/9921 Two captures, both unread A reader reads them together and writes the second's signals once
The key is a meeting's identity on its service. A window listed twice gives each meeting one capture. A meeting recorded on two services gets two keys and two captures; eddy cannot know they are one meeting, and its reader joins them.

A meeting recorded twice is the reader’s to join, because only a reading tells that two transcripts hold one conversation. The reader reads the two captures together and writes the second’s signals once (millpond’s reader).

The meeting’s details

Every part reads four details of a meeting from its service and hands them to the shared code in one shape:

DetailBecomes
titlethe capture’s title, the one line a person reads in a list
startthe capture’s event_at, in RFC 3339
lengththe input to the skip, below
attendeespart of the meeting’s record; the contract gives them no field, and Open questions holds where they travel

When the meeting started

A meeting capture’s event_at is when the meeting started, never when a part listed it or millpond captured it, because weight counts by event date (118). A meeting a part lists a week late counts from the day it was held, so a backlog reaches curation in the order its meetings happened.

Skipping a short meeting

A part prints no capture for a meeting too short to hold anything. The meeting’s length decides the skip, so every run and every host skips the same meetings, and a skip needs no record. Where the line falls is open.

A meeting’s raw files

A part writes each meeting’s transcript twice, under the raw directory millpond hands it: once as the service served it, and once as a plain copy with one line per turn. The capture line names both files in its raw field. Neither file enters git.

Two files

  • The transcript as served is the service’s own form, whole: whatever structure, speaker labels and timings the service gave. It keeps everything the service recorded, so a later reading loses nothing to a conversion eddy made.
  • The plain copy has one line per turn, a turn being what one speaker says before the next speaker starts. Every part writes the same plain shape, so a reader meets one form of transcript whatever service recorded the meeting.

The layout is shared code, so wispr, webex and teams lay a meeting out the same way, and a part added later inherits it.

The line goes to git, the files stay on the host

A capture line is small. It holds what millpond checks and what enters git as the capture: the key, the source, event_at, the title, the url and the names of the raw files. A raw file is the material, and a long meeting’s transcript runs to megabytes.

A meeting's line and its raw files A part prints one capture line and writes two raw files for a meeting. The line becomes an unread capture in the inbox, in git, which curation, crew and herdr's pane read. The two files, the transcript as served and a plain copy with one line per turn, go to the host's raw bank under the capture's name, never into git. The capture points at them as host and path. A reader session, millpond's verbatim check and a person following the pointer read the raw files. A part prints one line, writes two files The capture line key, source, event_at, title, url, the files' names small: one per meeting Two raw files the transcript as served a plain copy, one line per turn up to megabytes The inbox, in git an unread capture, no excerpt The raw bank on the host, under the capture's name; never in git <host>:<path> READ BY curation crew and its planner herdr's inbox pane READ BY a reader session the verbatim check a person following the pointer
A part's line becomes the capture in git, and its two files go to the host's raw bank, which the capture points at. A meeting's words never reach GitHub: only a reader, millpond's verbatim check and a person following the pointer read them.

Only millpond reads the line (landing a capture). It writes the capture into the inbox, in git, banks the raw files in the host’s raw bank under the capture’s name, and gives the capture a pointer of the form <host>:<path> (217h). The raw bank is millpond’s (what stays on the host). Raw transcripts stay outside version control, and the capture cites them (111), so a meeting’s words never reach GitHub with the record.

A hosted Flywheel adds one rule: raw material a capture points at is never read on a host serving more than one flywheel. A reading that must follow the pointer runs on the operator’s own machine or a pool host (263).

Who reads them

Three readers use a meeting’s raw files once millpond banks them:

  • A reader session. A meeting capture has no excerpt, so its transcript is the reader’s whole input. The reader’s instructions are the inbox’s data, never eddy’s (119). They say what makes a signal, how to name a speaker a transcript leaves unnamed, and how the operator draws signals from a meeting.
  • millpond’s verbatim check. millpond refuses a signal whose excerpt does not appear verbatim in its capture’s raw material (the verbatim check). Every excerpt a reader takes from a meeting is therefore a quote from one of these two files.
  • A person following the capture’s pointer to the transcript itself.

A sounding opened on a decision a meeting left open takes the meeting’s transcript as one of its sources (sounding’s book).

eddy writes the files and nothing about what they mean. A transcript that leaves a speaker unnamed reaches the raw bank unnamed, and the reader names the speaker by the inbox’s instructions.

Running a part

A part is a command that prints the capture contract. millpond starts it, reads the lines it prints and banks the files it writes, and Flywheel’s tick later starts it the same way (215, 231). The contract is the one way captures reach an inbox, and millpond’s book describes it whole (the capture contract, and running adapters).

How a host starts a part

eddy’s Flywheel plugin declares each adapter part: its command, the shape of its configuration and the secrets it needs (228). millpond reads the same declaration Flywheel reads, and runs the part as

eddy capture wispr --raw-dir <dir> [--cursor <c>]

with the part’s configuration in the file the CAPTURE_CONFIG environment variable names, and each declared secret in the environment under its declared name. A part that signs in to its service keeps that sign-in itself (A part per service).

millpond starts a part in one of two ways:

  • millpond run <part> makes a fresh raw directory, starts the part with that directory and the part’s last cursor, and lands what the part prints. It then keeps the new cursor and the run’s status: its exit, its failures and the tail of its standard error.
  • millpond tick runs every part of an inbox whose schedule is due, so one timer on a host serves every part there. A schedule is five-field cron, and a run missed while the host slept is caught up once (231).

An inbox’s settings name the one host whose tick runs each part. An inbox checked out on two hosts therefore runs a meeting part once, on the host that holds its sign-in.

What a part prints

A part writes JSON Lines to standard output, and each line holds exactly one of three keys: capture, cursor or done.

One run of the wispr part millpond run starts eddy capture wispr with a raw directory, the last cursor, the configuration and the secrets. The part asks Wispr Flow for meetings recorded since the cursor and gets them with their details. For each meeting not too short to hold anything, it fetches the transcript, writes two raw files and prints one capture line to millpond. It then prints its cursor and its done line, and millpond keeps the cursor and the run's status. No model runs in any step. millpond run wispr eddy capture wispr Wispr Flow starts it: raw dir, cursor, config, secrets meetings recorded since the cursor each meeting with its details FOR EACH MEETING NOT TOO SHORT fetch its transcript the transcript writes two raw files {"capture": …} {"cursor": …} {"done": {listed, failed}} millpond keeps the cursor and the run's status no model runs in any step (115)
millpond starts a part with a raw directory, its last cursor, its configuration and its secrets. The part asks its service for meetings since the cursor, writes each transcript as raw files and prints one capture line per meeting, then its cursor and its done line.

A run of the wispr part that lists three meetings, lands two and fails to fetch the third prints four lines:

{"capture": {"key": "meeting/wispr/m42", "source": "meeting", "event_at": "2026-10-16T15:00:00Z", "title": "Inbox planning", "raw": ["m42/transcript.json", "m42/turns.txt"]}}
{"capture": {"key": "meeting/wispr/m43", "source": "meeting", "event_at": "2026-10-16T17:30:00Z", "title": "Release review", "raw": ["m43/transcript.json", "m43/turns.txt"]}}
{"cursor": "2026-10-17T04:30:05Z"}
{"done": {"listed": 3, "failed": [{"what": "meeting/wispr/m44", "why": "HTTP 502"}]}}

A meeting capture fills the contract’s fields this way:

FieldA meeting part writes
keymeeting/<service>/<meeting id>
sourcemeeting
event_atwhen the meeting started
titlethe meeting’s title
urlwhere the meeting lives on its service, when the service gives it an address
rawthe transcript as served and the plain copy, as paths under the raw directory
excerptnever present

A meeting capture never carries an excerpt. A meeting is not its own excerpt: what it says becomes signals only through a reader’s judgment (115). millpond therefore writes no signal for it and marks it unread, which charges a reader.

The cursor line is the part’s own and opaque to millpond. The done line ends a complete run with its counts and the meetings that failed.

A run that fails

One failed meeting never stops the others. A part names it in the done line’s failed list, with what failed and why, and carries on with the next meeting.

A run that exits without done, or with a status other than 0, keeps every capture already taken, since captures are idempotent. Its cursor does not advance, and millpond records the run as failed. The next run lists the same window again from the old cursor, and millpond passes over every key it already holds.

What millpond does with each line

millpond checks each line and refuses one with a bad key, a missing field or an empty excerpt, naming it in the run. It looks the key up in every capture the inbox holds and passes over a key it already holds. It banks the raw files, writes the capture with its pointer, marks the capture unread, and records the run, which a fleet’s doctor reads from millpond status --json. millpond’s book holds each of those steps (landing a capture).

How others add a service

eddy holds parts for the services most partitions record on. Every other meeting service reaches an inbox by one of three routes: a meeting plugin someone else publishes, the generic MCP part, or the folder drop. One test admits a part to the first two: it passes the meeting checks in the conformance pack, and then it counts as a meeting part, the equal of eddy’s own.

Four routes into an inbox for meetings eddy's own parts, others' meeting plugins in the plugin index, and the generic MCP part all pass the meeting checks in flywheel-next's conformance pack. They print captures whose source is meeting. The folder drop, millpond's built-in adapter, takes any file and prints captures whose source is folder. All four print contract lines into millpond, which keeps one capture per key. FROM THE COMMON SERVICE TO ANY FILE eddy's own parts wispr, webex, teams; tested by replaying responses Others' meeting plugins their own repositories, in the plugin index (228) The generic MCP part any MCP endpoint that serves transcripts The folder drop any file; millpond's built-in adapter The meeting checks in the conformance pack source: meeting No meeting checks no meeting part source: folder Contract lines into millpond land, one capture per key
The common services live in eddy. Anyone else's meeting part sits beside them in the plugin index once it passes the same meeting checks, and a generic part takes any MCP endpoint that serves transcripts. The folder drop takes every file the rest leave. All four print the same contract.

The meeting checks

The conformance pack is flywheel-next’s: contract lines in, and the records a host must write from them expected. It proves millpond and Flywheel as hosts and every adapter part, and its meeting checks decide which parts count as meeting parts. eddy’s parts pass the same checks as anyone else’s, so a part in eddy carries no standing a published part lacks.

A part from anyone depends on flywheel-next’s capture crate for the contract’s types and key rules, as eddy’s parts do, and prints the contract with it.

A part in eddy

A service most partitions record on gets its part in eddy, beside wispr, webex and teams. The part brings its listing, its fetching and its service’s recorded responses, which its tests replay. Every other piece it needs is eddy’s shared code: the key’s shape, the meeting’s details, the raw layout and the skip (What every part shares).

A plugin of one’s own

Anyone can publish a meeting plugin of their own. It is a Flywheel plugin holding a meeting part, kept in its author’s repository at a tag, and listed in the plugin index beside eddy’s (228). The index is a file, and the shipped set is the default index. A plugin declares the set version it needs, the shape of its configuration and the secrets it needs, and a host registers it by its content hash (224, 228).

millpond and Flywheel run a published part as they run eddy’s: the same command line, the same raw directory, the same lines. Nothing in a host tells eddy’s parts from anyone else’s.

The generic MCP part

For the long tail, a generic part lists meetings from any MCP endpoint that serves transcripts. Its configuration names the endpoint. It is an MCP client, as wispr is, so no Claude session runs to list meetings through it. A service whose endpoint serves transcripts reaches an inbox through the generic part before anyone writes it a part of its own.

The folder drop

The folder drop takes the rest. A file dropped in a watched folder is one capture: a meeting transcript someone downloaded by hand, an email saved as .eml, a PDF.

  • Its adapter is Flywheel’s folder adapter, built into millpond from flywheel-next’s adapters crate: millpond capture folder <dir> prints contract lines (the folder drop).
  • Its key is folder/<folder name>/<sha256 of the file>, so a file dropped twice, or under another name, is one capture (111).
  • Its event_at is the date the file’s name begins with, or else the file’s last write.
  • Its source is folder, and no capture carries an excerpt. A reader reads each one and tells a transcript from an email by what it holds.

The folder drop is no meeting part and passes no meeting checks. A service that sends many files of one kind earns a part of its own, and until it has one the folder takes its files. millpond also carries Flywheel’s meeting transcript adapter, millpond capture meeting, from the same crate (215). Its captures carry no excerpt either, and a reader reads them (the meeting file).

A meeting that arrives by two routes, a transcript dropped in the folder and the same meeting listed by a part, carries two keys and so becomes two captures. Its reader reads them together and writes the second’s signals once, as for any meeting recorded twice.

Glossary

The words of the design, each defined once. eddy has no statement yet, so the capture design (design/capture/design.md) is the binding copy. A number in parentheses cites Flywheel’s statement.

eddy’s words

wordmeaning
the coreeddy’s code that lists and fetches meetings for each service it has a part for, with the code every part shares; every plugin calls it
meeting partan adapter part that passes the meeting checks, eddy’s or anyone’s
meeting checksthe checks in the conformance pack that an adapter part passes to count as a meeting part
generic MCP partthe adapter part that lists meetings from any MCP endpoint that serves transcripts
plugin indexthe file that lists published plugins, each a git repository at a tag; the shipped set is the default index (228)
capture lineone capture object of the capture contract, describing one event: its key, source, event_at, title, url and raw files
raw directorythe fresh directory a host hands an adapter part for one run, where it writes its raw files
a meeting’s raw filesthe transcript as served and the plain copy, a meeting part’s raw material
plain copya meeting’s transcript with one line per turn, the same shape from every part
turnwhat one speaker says in a meeting before the next speaker starts
verbatim checkmillpond’s refusal of a signal whose excerpt does not appear verbatim in its capture’s raw material

millpond’s words

millpond’s book defines these, and this page gives its definitions word for word (millpond’s glossary).

wordmeaning
adaptera program that knows one source: it lists the source’s events, keys each one, fetches the raw material, marks a capture that is its own excerpt, and prints contract lines (115)
adapter parta plugin’s part of the adapter kind: a command, the shape of its configuration, and the secrets it needs (228)
capturethe record of one source event: its key, its source, its event date and a pointer to its raw material; the same event captured twice is one capture (111)
capture contractthe JSON Lines an adapter prints and every host takes, each line holding exactly one of capture, cursor or done
conformance packcontract lines and the records a host must write from them, with the meeting checks; every host and every adapter part passes it
curationa Claude session that proposes one move per signal, in batches, through millpond’s tools; the operator accepts or changes each batch (116)
cursora value only its adapter understands, kept from the part’s last run that ended in done and handed back on the next
dedupemillpond’s lookup of each capture’s key in every capture the inbox holds, so a key lands once
event dateevent_at: when the event happened, never when it was captured (118)
excerptthe verbatim text a signal quotes from its source, with its position (113)
flywheel branchthe branch of crew’s state repository that holds a partition’s signals; it becomes the partition’s inbox
folder dropthe built-in adapter that makes one capture of each file dropped in a watched folder
inboxa git repository, or a branch in one, holding captures, signals, moves and items in Flywheel’s record formats
itemthe unit of work: the signals curation joined, one or many, with its brief and its sends; Flywheel’s proposed intent (109)
keya source event’s identity, the same from every host and every run (111)
meeting filethe built-in adapter for a meeting’s transcript file
operatorthe person who accepts or changes each batch of moves, sends items, and decides each conclusion; on its own, the user
partone thing of one kind in a plugin; an inbox’s settings name the adapter parts it runs
partitionin crew, one domain of work with its own teams and its own flywheel branch
pluginthe installable unit in every host, holding parts; Flywheel’s statement calls it a package, and a named set of parts a bundle (228, 284)
pointer<host>:<path>, where a capture’s raw material is banked (217h)
raw banka host’s store of raw material, under millpond’s data directory, keyed by inbox and capture; never in git
raw materialthe event as its source served it, whole: notes, a transcript, a log; the adapter writes it as raw files
readera Claude session that turns an unread capture into signals with millpond’s read tool
runone start of an adapter part by millpond run, complete when it ends in done
schedulewhen a part runs: five-field cron, a missed run caught up once
sendmillpond giving one item to one worktree, with its brief and an agent, or an item that asks a question to a sounding
settingsmillpond.toml at the inbox’s root: its parts, its cut, its reader command, and where items go
signalone assertion from a capture: its kind, who asserted it, its subjects, the assertion in a sentence, the verbatim excerpt with its position, and the claims it argues with; never changed once written (113)
sourcewhere events come from, named in each capture: release, meeting, folder, deploy
tickmillpond tick, which runs every part of an inbox whose schedule is due
unreada capture with no excerpt, waiting for a reader

sounding’s words

sounding’s book defines these, and this page gives its definitions word for word (sounding’s glossary).

wordmeaning
conclusionconclusion.md: the answer, its evidence, what it would change, the work it proposes, and what stays open; the operator decides it
soundingone question, worked by one session in one place, ending on one conclusion; also the tool that runs them

Open questions

What the design does not settle, and where each question is held. A question leaves this page when it is ruled; the ruling lands in the record that holds it, and the chapter that rests on it is rewritten whole.

Awaiting a ruling

The capture design’s decisions await the operator’s ruling, plan step D2 in design/capture/plan.md. Two of them are eddy’s. A program lists meetings and a session reads them: eddy holds a part per meeting service, its Wispr part an MCP client that starts no Claude session, and others publish meeting plugins of their own. An adapter that wraps another tool’s domain ships with that tool, so eddy’s parts stay eddy’s. A third reaches a meeting’s signals downstream: an item that asks a question goes to a sounding, whose accepted conclusion is the item’s record. Until they are ruled, every chapter describes a design, and no statement stands behind it.

Held for eddy’s statement

eddy has no statement of invariants yet. It is to come, written from the capture design and reconstructed as headwater’s was, and the book then includes it as an appendix by anchor, as sluice’s book does. Each question below is the statement’s to settle.

  • What a cursor marks. A service makes a transcript some time after its meeting ends. A cursor at the newest meeting’s start passes over a meeting whose transcript was not ready when the part listed it. A cursor at when the service made each transcript available does not, and neither does a listing whose window overlaps the last, since millpond’s dedupe makes an overlap free.
  • A failed fetch and the cursor. A run that ends in done advances its cursor even when it names failed meetings. A part whose cursor passes a meeting it failed to fetch never lists that meeting again. The lean is a cursor that stops before the run’s earliest failure.
  • The meeting’s own id. A service may give every occurrence of a recurring meeting one id, and a transcript an id of its own. The key needs the id of the one recorded occurrence, and teams and webex each name which id that is. An id holding a / becomes one segment of the key.
  • Where length and attendees travel. The contract gives them no field. They travel in the raw files, as a header of the plain copy or a file of their own, or in a field Flywheel’s statement adds to the capture.
  • How short is too short. The length below which a part skips a meeting, whether it is part configuration, and whether a skipped meeting counts in the done line’s listed.
  • The raw files’ names and the plain copy’s line. The two files’ names, and what one line of the plain copy holds: its time, its speaker and its words. transcript.json and turns.txt in Running a part stand in until the statement names them.
  • The command’s name. Running a part uses eddy capture <service>, after headwater’s headwater capture.
  • What a part’s configuration holds. Whatever CAPTURE_CONFIG names for a meeting part beyond the sign-in: an account, the skip’s length, the generic part’s endpoint.
  • A sign-in nearing its end. A fleet’s doctor warns as a part’s sign-in nears its end (plan step S5). The contract has no line for a sign-in’s health, so the part reports it through its run’s status, a command of its own, or a field the contract gains.

Held for the conformance pack

flywheel-next publishes the pack with its meeting checks (plan step F2). Which checks those are is the pack’s to say. The design implies the shared parts of a meeting capture: the key’s shape, source meeting, event_at at the meeting’s start, no excerpt, and the raw layout.

Held for the contribution model

  • Where the generic MCP part ships, and how it keys. eddy’s Flywheel plugin is the home that fits the rule that a part wrapping a tool’s domain ships with that tool. Its key’s service segment comes from the endpoint its configuration names.
  • Whether eddy publishes its shared code. A published part depends on flywheel-next’s capture crate. It gets eddy’s key shape, raw layout and skip only if eddy publishes them as a library, and otherwise writes its own to pass the meeting checks.

Held by the capture design

The capture design’s own open section holds one question that reaches eddy’s parts: where a cursor lives when a single-host role moves hosts. A lost cursor costs one wider listing, which the dedupe absorbs.

Held for the first run

The meeting corpus already read is imported once into its inbox, keyed by its folders’ names (plan step E2, what comes in once). A meeting in that corpus that a part lists again gets a second capture under eddy’s key. The part’s first cursor can start where the corpus ends, or a reader can join the two as a meeting recorded twice. Which of those holds is for the step that first runs eddy on a fleet (plan step S5).