--- name: internal-meeting-brief description: Generate an MPM-branded internal meeting briefing document as a single-file HTML artifact — covers internal planning sessions, executive leadership meetings, and project team meetings (e.g. APTA planning, status reviews, internal design discussions). Produces agenda-mode (pre-meeting prep, pulling the previous meeting's transcript) or recap-mode (post-meeting summary, pulling the current meeting's transcript). Always use this skill when the user asks to "brief this meeting," "recap the meeting," "prep me for [meeting]," "write up the [meeting name] meeting," or names an internal MPM meeting/topic and wants it documented or summarized — even if they don't say "internal-meeting-brief" by name or don't mention CoWork/Brief explicitly. Part of the CW-027 Brief plugin family; see git.mpm.to/mpm/brief. --- # internal-meeting-brief Generates a single self-contained HTML briefing document for an internal MPM meeting, built on Brief's shared MPM-branded component library. Does the work of assembling the brief itself — pulling from connected tools — rather than requiring the person to hand-supply meeting notes. Read `assets/brief-components.css` and `references/section-structure.md` before generating any brief. The CSS is the canonical, only source of Brief's visual language — never re-derive it inline. The section-structure doc is the fixed-vs-dynamic contract for what this skill's output actually contains. ## Prerequisites This skill uses, but does not own, the following connected tools — confirm they're reachable before starting, and degrade gracefully (see Hard Rules) if one isn't. **Meeting record — the source varies. Ask, don't assume Plaud.** Recap mode needs *some* record of what was discussed; which kind depends on how MPM actually recorded that particular meeting, which isn't fixed. In rough order of how much structure they give you, and check whichever plausibly applies rather than defaulting to the first one tried before: - **Plaud** — if used, the official `Plaud` connector (`get_current_user`, `list_files`, `get_file`, `get_transcript`, `get_note`) — **not** the deprecated `Plaud MCP` connector. Resolve a recording's `file_id` via `list_files(query=...)` — never assume a Plaud web-app URL's slug is the API `file_id` directly; the real id carries an `of_` prefix the web URL doesn't show. `get_transcript` paginates (`next_cursor`) — loop until null. `get_note` returns the AI summary/action-items tab separately — worth pulling alongside the transcript. - **Google Meet transcript** — typically lands as a Google Doc in Drive (often in a "Meet Recordings" folder or attached to the Calendar event) — search Drive/Calendar, don't assume it doesn't exist just because Plaud has nothing. - **Teams transcript**, or any other recording tool MPM starts using — same principle: ask where it lives before concluding no record exists. - **No transcript at all** — perfectly valid. Fall back to whatever does exist for that meeting: the person's own notes, a task registry, prior emails/Chat about it. State plainly in Notes & Flags that no transcript was available and the brief is built from secondary sources — this is the never-fabricate rule applying to the *source*, not just the content. If it's not obvious which source applies, **ask the person** rather than trying each connector in sequence and treating empty results as "nothing exists here." An empty result from one source is not evidence the meeting has no record at all. Other tools this skill uses: - **Odoo** (MCP) — linked Project/tasks, Sales/Purchase Orders, Knowledge Base, Helpdesk tickets - **Google Workspace** (MCP) — Gmail, Google Chat, Drive, Sheets - **Google Drive** — the topic's continuity folder (`_topic-state.md` + brief history) If any of these fail outright (not just "returns nothing," but errors or times out), say so plainly in the generated brief's Notes & Flags section rather than silently omitting that source. See "Known limitation" below for a real, currently-open example. ## Workflow ### 1. Resolve the topic Every brief belongs to a project/topic, not just a meeting instance. Ask which topic/project this meeting is about if it isn't obvious from context. Search Google Drive for an existing topic folder (naming pattern: ` — Meeting Briefs`) before creating a new one. If an Odoo Project already exists for this topic and has an attached Drive folder, use that folder instead of creating a parallel one. ### 2. Read (or create) the continuity manifest Open `_topic-state.md` in the topic folder. If it doesn't exist, this is the topic's first run — create it with the schema below, and expect a fuller interview in the following steps since there's no history to draw on yet. `_topic-state.md` schema: linked Odoo Project ID / SO / PO, linked Google Chat Space, Plaud recording ID/pattern, last-meeting date, running open-items/decisions ledger, attendee list, learned spreadsheet task-registry column mapping (if this topic uses one — see step 5), brief-history log (date/type/mode/link), and a "Related documents" table for cross-referencing other MPM document types about the same real-world topic (pre-mortems, BAI build docs, etc. — see CW-027 Concept.md's rewrap-vs-harvest principle; don't merge their content into this ledger, just reference them). ### 3. Determine mode: Agenda or Recap Agenda mode (pre-meeting prep) pulls the *previous* meeting's record and any updates since. Recap mode (post-meeting) pulls the *current* meeting's record. Ask if not specified by the request. "Record" — see Prerequisites above — is whatever source actually applies for that meeting, not necessarily Plaud. ### 4. Capture and normalize attendees - **First run for this topic:** ask who's attending / who attended. - **Recurring topic:** pre-fill from the manifest's last attendee list and ask "same as last time, or any changes?" — not a blank-slate interview. - **Recap mode with a transcript available (any source):** prefer *actual* attendance from the transcript's speaker attribution over the pre-meeting expected list — someone who showed up unexpectedly and spoke shouldn't be treated as absent. - **Normalize into two groups:** - Internal MPM attendees — record by name for the brief; no further resolution needed (no external allowlist implications for this brief type). - External attendees (rare for this brief type, but possible) — cross-reference against Odoo contacts to resolve/confirm email addresses rather than trusting raw input. - **If Plaud's diarization didn't resolve a speaker to a name:** render the literal transcript label ("Speaker 1," "Speaker 3"). Do not guess a name from context, even when a guess feels obvious. Flag unresolved speakers in the Notes & Flags section. ### 5. Pull data, scoped to what this brief type actually needs Not a monolithic "pull everything" — internal-meeting-brief's real needs, based on the first run, are: - The meeting record (per mode, above) — the primary source, whichever tool it actually lives in - Gmail / Google Chat: updates since the manifest's last-meeting date, scoped by project/topic keywords, never a blanket search - Odoo Project tasks, if a linked project exists (expect this to be sparse or absent — PM-tool adoption is inconsistent; fall back to a spreadsheet task registry if the topic uses one, learned via a one-time interview on first use and stored in the manifest, never assumed to follow a universal schema) Sales/Purchase Orders and Helpdesk ticket review are not typically relevant to this brief type (they matter more to vendor-partner-brief and status-update-brief) — don't pull them by default. ### 6. Synthesize into the section structure Follow `references/section-structure.md` exactly: six fixed sections in order, dynamic sections only where the meeting's actual content has a structure that calls for one. Real, verified content over generic summary — carry forward specific facts (names, dates, exact technical decisions), not vague paraphrase. ### 7. Render Single self-contained HTML file. Include `assets/brief-components.css` inline (don't link out to it — the brief must survive as a standalone file). Include: sticky jump-nav, a working light/dark toggle (`data-theme` attribute, default light), and the `@media print` rules from the shared CSS (forces light, hides nav/toggle, avoids awkward page breaks). ### 8. Archive Save the generated HTML into the topic's Drive folder. Update `_topic-state.md`: append to the brief-history log, update the running open-items/decisions ledger (carry forward anything still open from this run), update the attendee list, update last-meeting date. ### 9. Present Hand the file to the person. Don't silently skip presenting it even if archived — the person needs to actually see and review it, not just trust it happened. ## Hard rules - **Never fabricate.** No matching Plaud recording, no linked Odoo data, an empty Gmail/Chat scan — say so plainly in Notes & Flags. A brief with visible gaps is correct; a brief with invented content to fill them is not. - **Bounded queries only.** Gmail/Chat scans are scoped by project keyword + date window from the manifest. Never an open-ended search. - **No live publishing yet.** This skill produces a local file only. Hosting/publishing (a shareable link, external access control) is CW-029 (Brief Server) — deliberately separate, deliberately not built yet. Don't attempt to stand up delivery infrastructure as part of running this skill. ## Resolved limitation (was open 2026-09-21, fixed 2026-09-22) Earlier attempts to pull this skill's first real test recording failed for two compounding reasons, now both understood: 1. The deprecated `Plaud MCP` connector's `list`/`search` tools returned empty results or timed out regardless of parameters — root cause not fully diagnosed, but moot: don't use that connector at all (see Prerequisites above). 2. Direct lookup via the *official* `Plaud` connector's `get_file`/`get_transcript` still 404'd, because the id taken from the Plaud web app's URL (`b0df60b679f31383f770d91db6b5bf46`) was missing the `of_` prefix the API's real `file_id` requires (`of_b0df60b679f31383f770d91db6b5bf46`). Resolving the id via `list_files(query=...)` instead of reading it off a URL fixed this immediately. Verified 2026-09-22: a live pull via the official connector for this same recording returned content matching the manually-uploaded transcript used to build the first real brief, confirming both that the fix works and that the original brief's content was accurate. Recap mode's live data path is now confirmed working end-to-end. ## Provenance Component library, tokens, and this workflow were derived from two real test runs (2026-09-21): a recap brief for a real APTA 2026 booth planning meeting, and a rewrap of an unrelated pre-mortem document to validate the component system against a different content shape. See CW-027's Concept.md (Drive) for full design history and the five other planned skills in this family (vendor-partner-brief, status-update-brief, five-whys-brief, kickoff-brief, development-brief) — none built yet.