Skip to main content

Turn meeting transcripts into a temporal context graph for coding agents.

Project description

Meeting → Context Graph

Turn meeting transcripts into a temporal context graph that a coding agent reads to write and update code. Each meeting updates the same graph.json, and git history records how decisions evolved.

Meetily (capture + transcribe, free)  ─►  context_graph CLI  ─►  graph.json (git)  ─►  coding agent

Why a graph, not just notes

Every node has a status (active / superseded / deprecated) and a supersedes list. When a later meeting reverses a decision, the old node is marked superseded and a new active node links to it via a SUPERSEDES edge. So the graph always shows current truth and what changed.

Setup

pip install -r requirements.txt
export GROQ_API_KEY=...      # free key from console.groq.com  (PowerShell: $env:GROQ_API_KEY="...")

Usage

# --- recommended: pull straight from Meetily's local DB (recording -> transcript) ---
python -m context_graph meetily-list                 # see recent Meetily meetings
python -m context_graph ingest --meetily             # ingest the LATEST Meetily meeting
python -m context_graph ingest --meetily-id <id>     # ingest a specific Meetily meeting

# --- batch: catch up on many meetings at once (oldest first, one commit each) ---
python -m context_graph ingest --new                 # every Meetily meeting not yet in the graph
python -m context_graph ingest --since 2026-07-01    # meetings created on/after a date
python -m context_graph ingest --since 2026-07-01 --new   # both filters combined
python -m context_graph ingest --all                 # every Meetily meeting

# --- other input sources ---
python -m context_graph ingest transcripts/m1.txt --meeting-id 2026-07-12-kickoff
python -m context_graph ingest --paste "we'll use REST and Postgres" --meeting-id m1
python -m context_graph ingest --audio meeting.mp3 --meeting-id m1   # Groq Whisper fallback

python -m context_graph ingest ... --dry-run   # preview changes, no write/commit
python -m context_graph show                    # print current active nodes
python -m context_graph delta                   # git diff of last meeting's changes

# render the graph from the terminal (no Slack needed)
python -m context_graph viz --out graph.png                 # PNG
python -m context_graph viz --format mermaid --out g.mmd    # Mermaid text
python -m context_graph viz --format dot --active-only      # DOT, hide superseded

# check graph integrity (dangling edges, supersedes cycles, duplicate concepts)
python -m context_graph validate

# export the ACTIVE-only spec for the coding agent (grouped by feature)
python -m context_graph export --format md --out spec.md
python -m context_graph export --format json --out spec.json

# scope to a separate project graph -> context-graphs/<name>.json
python -m context_graph ingest samples/m1-kickoff.txt --meeting-id m1 --project payments
python -m context_graph export --project payments

# multi-project meeting: split ONE transcript across per-project graphs automatically
python -m context_graph ingest big-meeting.txt --meeting-id m1 --route

Multi-project meetings (routing)

When one meeting discusses several projects, --route makes the extractor label each node with a project and fans the nodes out into separate context-graphs/<project>.json files — each with its own temporal history, supersession, and export spec. Known projects are discovered from the existing graph files, so labels stay consistent meeting to meeting; a genuinely new project name auto-creates its graph. Cross-cutting items go to general.

Cross-project dependencies are preserved: an edge between nodes in different projects (e.g. Billing DEPENDS_ON an Auth decision) is stored in the source project's graph as a namespaced reference auth:decision-api-graphql, surfaced in that project's export spec (so the coding agent sees the dependency) and exempt from validation's dangling-edge check.

In the Slack bot, set CG_ROUTE_PROJECTS=1 and the bot routes each uploaded meeting by content, replying with a per-project breakdown + one graph image per project touched (instead of assuming the channel = the project).

Entity resolution (how meetings merge without duplicating)

When a later meeting revises a decision, the pipeline decides NEW vs DUPLICATE vs CHANGE (supersede) using, in order:

  1. Explicit supersession — the extractor is shown the current active nodes and emits supersedes: [id] when a statement replaces one. Most reliable.
  2. Embedding similarity (optional) — if sentence-transformers is installed (or GEMINI_API_KEY is set) nodes are matched semantically, so req-user-login and req-authentication-flow can still merge. pip install sentence-transformers to enable; without it the system falls back to string/concept matching (no error).
  3. String/concept matching — id-prefix + token overlap. Always available.

Use export to hand the coding agent a clean current-state spec (no history), and validate in CI to catch a corrupt graph before an agent acts on it.

Meetily integration (recording → transcript)

Meetily records system+mic audio locally and transcribes it for free — no meeting bot needed. It stores everything in a SQLite database, which this CLI reads read-only:

OS Database path
Windows %APPDATA%\com.meetily.ai\meeting_minutes.sqlite
macOS ~/Library/Application Support/com.meetily.ai/meeting_minutes.sqlite
Linux ~/.local/share/com.meetily.ai/meeting_minutes.sqlite

The path is auto-detected; override with --meetily-db PATH if needed. With --meetily the meeting-id is auto-derived from the meeting's date + title (e.g. 2026-07-12-design-review), so you don't pass --meeting-id. Speaker source is labeled You: (mic) / Others: (system audio).

Meetings need not be live. A previously-recorded call works two ways: (1) import the recording into Meetily (its audio-import feature transcribes it into the same DB, then --meetily picks it up), or (2) point the CLI straight at the file with --audio old-meeting.mp3 (Groq Whisper transcribes it, no Meetily needed).

Other inputs: pasted minutes (--paste), a plain transcript file, or the built-in Groq Whisper fallback for a raw audio file (--audio).

Slack bot (audio in → graph image out)

Let anyone on the team drop a meeting recording into a channel and get the context graph back as a rendered image — no CLI needed.

User uploads meeting.wav ─► bot transcribes (Groq) ─► ingest ─► posts changelog
                                                              └─► uploads graph PNG

Mentions: @bot graph (post the image), @bot show (list active nodes), @bot delta (git diff since last meeting).

Run it (Socket Mode — no public URL needed)

pip install -r requirements.txt          # includes slack-bolt, graphviz, requests
export SLACK_BOT_TOKEN=xoxb-...           # bot token
export SLACK_APP_TOKEN=xapp-...           # app-level token, scope connections:write
export GROQ_API_KEY=...
export CG_GRAPH_PATH=graph.json           # optional
python -m context_graph.slackbot

Slack app setup: enable Socket Mode; subscribe to events message.channels and app_mention; bot scopes app_mentions:read, channels:history, files:read, files:write, chat:write (add groups:history for private channels). Invite the bot to the channel.

Graph rendering

The image is rendered by context_graph/viz.py:

  • Graphviz (preferred, fully offline) — install the system binary (choco install graphviz on Windows, apt install graphviz, brew install graphviz); the graphviz pip package wraps it.
  • mermaid.ink (automatic fallback if dot isn't found) — renders via a free web service. ⚠️ This sends the graph to an external host; install Graphviz to keep confidential meetings local.

Encoding: node color = status (green active / grey superseded / amber open question), shape = type (Decision ◆, Requirement ▢, Constraint ⬡, …), and SUPERSEDES edges are red dashed. Check viz.available_renderer() to see which backend is active.

Contract for the coding agent

Read graph.json and treat it as follows:

  • Current requirements = every node with "status": "active". Obey these.
  • Ignore nodes with "status": "superseded" or "deprecated" as current truth — but use them to know what to remove or replace.
  • OpenQuestion nodes are NOT decided — do not assume an answer; flag them.
  • What changed since last meeting = git diff HEAD~1 HEAD -- graph.json (or python -m context_graph delta). A node flipping to superseded plus a new active node linked by a SUPERSEDES edge = "replace the old implementation with the new one."
  • Edges tell you structure: IMPLEMENTS, DEPENDS_ON, BLOCKS, SUPERSEDES, DECIDED_IN, RELATES_TO.

Node shape

{
  "id": "decision-api-style",
  "type": "Decision",
  "title": "API uses GraphQL",
  "content": "Switch the public API from REST to GraphQL.",
  "status": "active",
  "source_meeting": "2026-07-19-review",
  "created_at": "2026-07-19T10:00:00+00:00",
  "supersedes": ["decision-api-rest"],
  "confidence": 0.9,
  "owner": "Priya"
}

Scope (v1)

Included: transcript/paste/audio input, Groq extraction, temporal merge with supersession, JSON graph + git history, CLI.

Deferred: MCP server, Neo4j/Graphiti engine, meeting bot, embedding-based dedup, GUI. See the plan file for rationale.

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

meetmind-0.1.0.tar.gz (48.6 kB view details)

Uploaded Source

Built Distribution

If you're not sure about the file name format, learn more about wheel file names.

meetmind-0.1.0-py3-none-any.whl (47.0 kB view details)

Uploaded Python 3

File details

Details for the file meetmind-0.1.0.tar.gz.

File metadata

  • Download URL: meetmind-0.1.0.tar.gz
  • Upload date:
  • Size: 48.6 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.11

File hashes

Hashes for meetmind-0.1.0.tar.gz
Algorithm Hash digest
SHA256 d81ba1d0c219206aeba20242b565d24aca77c4ab44debe5705c415ef93d09600
MD5 47477a4daf7d35b1eb4bd7d49b04d791
BLAKE2b-256 e89f70102421dfde9c8dfbbf59d563ed7b8e2a711b629eb5b96ccf45fa9257c6

See more details on using hashes here.

File details

Details for the file meetmind-0.1.0-py3-none-any.whl.

File metadata

  • Download URL: meetmind-0.1.0-py3-none-any.whl
  • Upload date:
  • Size: 47.0 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/6.2.0 CPython/3.10.11

File hashes

Hashes for meetmind-0.1.0-py3-none-any.whl
Algorithm Hash digest
SHA256 06eb5204e7e03e8c16e5e56fdf2eb17d110a604af19b599714e1f652894bf80f
MD5 72082371965800aee6e7a759630797e2
BLAKE2b-256 16795a84dd5999d9509606691df82369c1fdba4c9107350c4089d2c64a6584e3

See more details on using hashes here.

Supported by

AWS Cloud computing and Security Sponsor Datadog Monitoring Depot Continuous Integration Fastly CDN Google Download Analytics Pingdom Monitoring Sentry Error logging StatusPage Status page