---
name: thermograph-voice-summaries
description: The periodic job that digests NoteCat's voice transcripts into the docs. Read this when running the loop, or setting it up.
---

# Voice-transcript digest

A transcription bot (**NoteCat**) posts voice-to-text into a Discord transcript
channel. Raw transcript is high-volume and perishable — nobody re-reads an hour
of it, and it scrolls out of the channel. This job turns each window of it into
a durable summary in the docs repo. It is meant to run **every 30 minutes**, and
to be safe to run again if a run is missed or repeated.

## What the loop does, each run

1. **Find the window.** Read the most recent `summaries/` file with
   `summaries_list` + `docs_read`. The last timestamped section header tells you
   where the previous run stopped. If there is no file for today, start from the
   beginning of the day.

2. **Pull the transcript.** Read the transcript channel with the Discord tools
   (`discord_get_messages` on the channel NoteCat posts to — its id is in
   `community_channels` under the `transcripts` role, or `CENTRALIS_TRANSCRIPT_CHANNEL`).
   Take only messages newer than where the last run stopped. If nothing is new,
   **stop — do not write an empty summary.**

3. **Digest.** Write a summary that someone who was not on the call can read:
   - What was discussed and, more importantly, **what was decided**.
   - Action items, with who owns them if it is clear.
   - Open questions left unresolved.
   - Drop the filler. A summary is a claim about what happened, not a transcript.
   - Keep the grade-language rule: never call a percentile "hot" or "cold".

4. **Enrich with estate context.** A voice summary is more useful when it links
   to what the estate already knows. Where the conversation *genuinely* connects
   to something — a name, a topic, a decision, a number, a place, an incident —
   look it up and fold in a brief, **cited** note. Do not invent connections;
   only enrich what is actually there. Draw on:
   - **Repos, PRs, issues** — `forge_read`, `forge_repos`, `forge_prs`,
     `forge_issues` (was that refactor merged? is there an open issue for it?).
   - **Docs & notes** — `docs_search`, `docs_read`, `notes_search`, `notes_read`
     (has this decision a prior record? does a note contradict it?).
   - **App stats** — `sql_query` (read-only, never `write:true`) for users,
     subscriptions, notifications when a number is claimed or questioned.
   - **Climate stats** — `lake_query` / `lake_tables` over the ~45-year ERA5
     lake, and `grade_location` / `geocode` for a specific place. Keep
     grade-language: percentiles versus local history, never absolutes.
   - **What broke** — `logs_query`, `fleet_status` when an incident is mentioned.
   - **The public site / outside world** — `WebSearch`, `WebFetch`.

   Put this under a short **Related context** section, clearly separated from
   what was actually said, each point citing its source. This is estate lookup,
   not other Discord channels — the transcript-channel consent rule below still
   holds for anything Discord.

5. **Write it.** `summaries_write` with a `heading` naming the window
   (e.g. `war-room 14:00–16:20 UTC`). It appends a timestamped section to
   `summaries/YYYY-MM-DD.md` and commits straight to main. Do not open a PR —
   this runs too often for that, and the direct-commit path exists for exactly
   this.

6. **Surface it.** Post a short version into **#voice-summaries** (Owners
   category) with the Discord tools, linking the committed file, so owners see it
   without opening the repo. The full digest lives in the docs file; the channel
   post is the headline plus decisions and action items.

## Turning transcript into a decision record

The pipeline is **voice → transcript → summary → doc**. This job owns the middle
arrow. When a summary contains a decision that should outlive the day — an
architecture choice, a commitment — promote it: a `notes_write`, or a
`docs_write` into `architecture/` as a proper decision record. The summary is
the raw material; the decision record is the publication.

## Idempotency and safety

- **Anchor on the last section's timestamp**, never on wall-clock assumptions —
  that is what makes a re-run harmless and a missed run self-healing.
- **Never invent content.** If the transcript is garbled or thin, say so briefly
  and summarize what is legible. A confident summary of a bad transcript is
  worse than a short honest one.
- **Only the transcript channel, for Discord.** Do not pull from other Discord
  channels; this is a voice digest, and the transcript channel is where consent
  was given. Estate lookup in step 4 (repos, docs, stats, the lake, the public
  site) is a different thing and is fine — it enriches, it does not eavesdrop.
- **Enrich read-only.** The estate lookups are reads. Never mutate while
  digesting — no `sql_query(write:true)`, no `docs_write`/`forge_write`. The only
  writes a digest makes are `summaries_write` and the `#voice-summaries` post.
- If `CENTRALIS_TRANSCRIPT_CHANNEL` / the `transcripts` role has no id yet, there
  is nothing to do — report that the source is not configured and stop.

## Scheduling it

Runs on a cron routine every 30 minutes (see `deploy/routines/voice-summaries.md`).
The routine is just "load this skill and do it"; all the logic lives here, so
changing the behavior is editing this file, not the schedule.
