2209a19eb7
First test run (Oshkosh GO Transit internal kickoff, via the actual
installed skill, not Claude manually walking the SKILL.md) surfaced real,
fixable gaps. All fixed here:
1. Print CSS bug (root cause, found by Bryan): section{break-inside:
avoid-page} plus whole-table break-inside:avoid caused a 14-page,
mostly-blank PDF. Fixed: sections can split across pages now; only
cards/table-rows avoid splitting, with repeating table headers.
2. SO/PO lookup was wrongly scoped out of this brief type by default.
Wrong -- an internal kickoff about a real sale needs the SO/PO as much
as any external brief would. Scope is now by topic nature (commercial
vs. purely internal), not by brief-type name.
3. Contact-info lookup (not just name resolution) is now an explicit
standing step in attendee capture, starting from a linked SO/PO's own
Odoo contacts when one exists.
4. Added the MPM Technical Reference System (a 131-file Drive registry:
brand, platform, display tech, products, engineering, concepts, proof)
as a standing reference for part-number/product verification --
previously unknown to this skill.
5. Pulled the real run's improved _topic-state.md schema back into the
spec: confidence tags (verified/stated/open), a folder-layout header,
numbered-vs-proposed open items, a Findings/flags section. These
emerged from real use and are now documented, not one-off.
6. Meeting transcript archival (a Meeting Transcripts/ subfolder) is now
a standing step, not something that has to be asked for.
7. section-structure.md: flow and specbar are now marked validated (real
examples: Oshkosh deployment sequence, billing milestones). Added the
meeting-vs-proposed open-items badge pattern and a standard
confidentiality footer note for this brief type.
None of this was a failure of judgment in the moment -- these are gaps
between what the file said and what real use needed, now closed.
303 lines
20 KiB
Markdown
303 lines
20 KiB
Markdown
---
|
|
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, and contacts (customer/partner/sales-rep records tied to an SO/PO)
|
|
- **Google Workspace** (MCP) — Gmail, Google Chat, Drive, Sheets
|
|
- **Google Drive** — the topic's continuity folder (`_topic-state.md` + brief history
|
|
+ `Meeting Briefs/` + `Meeting Transcripts/`)
|
|
- **MPM Technical Reference System** — a Drive-based product/technical knowledge
|
|
registry (131 entity files as of 2026-09-22: brand voice, platform/software,
|
|
display technologies, products, engineering, concepts, proof/evidence). Read
|
|
`_INDEX.md` first — it's the routing table — then only the specific files a claim
|
|
actually needs. This is where part numbers, model codes, and product/technical
|
|
claims get verified; it is not this skill's content to maintain, only to reference.
|
|
|
|
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: `<Topic Name> — 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 — ALWAYS, before anything else
|
|
Open `_topic-state.md` in the topic folder. **This is not optional and does not need
|
|
to be asked about — do it automatically, every run, as the first real action.** If it
|
|
doesn't exist, this is the topic's first run: create it immediately with the schema
|
|
below, then expect a fuller interview in the following steps since there's no history
|
|
to draw on yet.
|
|
|
|
**Schema — refined 2026-09-22 against a real production run** (Oshkosh GO Transit
|
|
kickoff), which improved on the original design in ways worth keeping permanently:
|
|
- **Confidence tags** on every factual claim: `verified` (checked against a source
|
|
document — an SO, a PO, an Odoo record), `stated` (said by someone in the meeting or
|
|
by the person running the brief, not independently confirmed), `open` (unresolved —
|
|
including outright conflicts between two sources, e.g. an address that differs
|
|
between a PO and its matching SO). Do not present a `stated` fact with the same
|
|
confidence as a `verified` one.
|
|
- **Folder layout** section at the top of the manifest, documenting what's actually in
|
|
the topic folder (including subfolders Brief didn't create, like a pre-existing
|
|
`Financial/` folder) — self-documenting, so opening the manifest alone orients
|
|
someone to the whole folder.
|
|
- **Links** table: linked Odoo Project ID, SO, PO, Chat Space, Plaud recording
|
|
pattern, relevant Gmail thread(s), and — critically — the actual **people**
|
|
resolved from those records (customer contact, reseller/partner contact, MPM sales
|
|
rep), each with role, email, phone, and its confidence tag. See step 4.
|
|
- **Decisions ledger** and **Open items ledger** as two separate tables. Open items
|
|
get sequential numbers (1, 2, 3...) for things actually assigned/committed in the
|
|
meeting, and a separate `P`-prefixed series (P1, P2...) for things *suggested*
|
|
during the meeting but not yet formally assigned — don't conflate a live suggestion
|
|
with a committed action item.
|
|
- **Findings / flags** section for meta-observations worth carrying forward that
|
|
don't fit the ledgers — e.g. "this topic's Plaud AI summary is unreliable, build
|
|
from the raw transcript" or a specific diarization error spotted at a timestamp.
|
|
This is where operational lessons about the data sources themselves get recorded,
|
|
not just facts about the topic.
|
|
- **Related documents** table for cross-referencing other MPM document types about
|
|
the same real-world topic (pre-mortems, BAI build docs, a technical reference
|
|
registry, etc. — see CW-027 Concept.md's rewrap-vs-harvest principle; don't merge
|
|
their content into this ledger, just reference them).
|
|
- **Brief history** log (date/type/mode/file link(s) — both HTML and PDF if a PDF
|
|
exists).
|
|
|
|
Append to this file; don't rewrite history. On every subsequent run, read the whole
|
|
thing before doing anything else — it's the difference between starting fresh and
|
|
starting from zero.
|
|
|
|
### 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 — and resolve real contact info, always
|
|
- **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 — cross-reference against Odoo to resolve real contact info
|
|
(email, phone, title, company), not just a confirmed spelling of a name. **This is
|
|
a standing step, not something to be asked to do:** if the topic has a linked SO
|
|
or PO, pull the Odoo contacts tied to those records first (customer contact,
|
|
reseller/partner PM, sales rep) — this is usually faster and more accurate than a
|
|
generic contact search, and surfaces exactly who the real counterparts are even
|
|
if they weren't in the meeting. If someone's name as heard doesn't match Odoo
|
|
cleanly (a misheard surname, a title mismatch), flag it in Findings/flags as
|
|
`open` rather than silently picking one.
|
|
- **If a speaker's diarization didn't resolve 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," but scope by what the *topic* actually is, not a
|
|
fixed list per brief type:
|
|
- 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 Order / Purchase Order — pull whenever the topic is a real customer or
|
|
reseller engagement, not just for vendor-partner-brief/status-update-brief.**
|
|
Correction from initial design: an *internal* kickoff meeting about a *real sale*
|
|
(an internal-meeting-brief, by audience) still needs the SO/PO — that's where the
|
|
scope, the customer, the reseller/partner, and the real contacts actually live. The
|
|
dividing line is the topic's nature (commercial engagement vs. purely internal
|
|
process work like a booth build), not the brief type's name. Search Odoo by
|
|
customer/topic name if not already linked in the manifest.
|
|
- **Part numbers / product/technical claims — check them against the MPM Technical
|
|
Reference System** (a Drive-based registry; read `_INDEX.md` first, then
|
|
`_RULES.md` for the confidence-tag contract, then only the specific entity files
|
|
the topic needs — e.g. `30-products/model-code-grammar.md` for verifying a model
|
|
number's structure, or the relevant `30-products/*` file for a named display
|
|
family). Don't guess at whether a model number or part number is right — verify it
|
|
here, or flag it `open` if the registry doesn't resolve it (e.g. a variant with no
|
|
assigned code yet). This registry is a genuine dependency, not this skill's own
|
|
content to maintain — see Dependencies.
|
|
|
|
Helpdesk ticket review is still a deliberate, manual exception (see below) — not
|
|
pulled automatically regardless of topic type.
|
|
|
|
### 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). Small brief-specific CSS additions beyond the shared stylesheet
|
|
(e.g. a status-source badge, a role subtitle under an attendee's name) are fine —
|
|
append them, don't fork the canonical rules to get the same effect.
|
|
|
|
**Footer confidentiality note — standard for this brief type.** internal-meeting-brief
|
|
is, by definition, internal content. End the footer with an explicit statement of that
|
|
(e.g. "Internal. Do not forward to [named external party]." when the topic has one) —
|
|
validated in the Oshkosh brief, where this genuinely matters: the brief discusses a
|
|
reseller/customer deal in more candid terms than anyone would want forwarded to that
|
|
customer.
|
|
|
|
### 8. Archive — the brief, the transcript, and the manifest update
|
|
- Save the generated HTML into the topic folder's `Meeting Briefs/` subfolder
|
|
(`YYYY-MM-DD <Meeting> - <Mode> Brief.html`). If a PDF was also generated, save it
|
|
alongside with the matching name.
|
|
- **Save a plain-text copy of the meeting record into a `Meeting Transcripts/`
|
|
subfolder** (`YYYY-MM-DD <source name> - Transcript.txt`) — a standing step, not
|
|
something to be asked for. This matters beyond convenience: it makes the topic
|
|
resilient to the source connector being unavailable later (Plaud specifically has
|
|
had real, live connector problems this project — see Resolved limitation below), and
|
|
it's the raw material a future brief needs if it has to re-derive something the
|
|
original brief didn't capture.
|
|
- Update `_topic-state.md`: append to the brief-history log (both file links), update
|
|
the decisions and open-items ledgers (carry forward anything still open, close
|
|
anything resolved, add new items with the correct sequential/P-prefixed numbering —
|
|
see step 2), update the attendee list and any newly-resolved contact info, update
|
|
Findings/flags with anything learned this run, 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.
|
|
|
|
## First real invocation — findings (2026-09-22)
|
|
|
|
The first time this skill ran from an actual installed invocation (not Claude manually
|
|
walking through this file) — a recap brief for an Oshkosh GO Transit internal kickoff.
|
|
Real, valuable findings, each fixed in this revision:
|
|
|
|
1. **Print CSS bug — fixed.** `section{break-inside:avoid-page;}` and whole-table
|
|
`break-inside:avoid` in the shared stylesheet's `@media print` block caused a
|
|
14-page, mostly-blank PDF: any section taller than the remaining space on a page
|
|
got pushed whole to the next page, leaving the gap behind blank. Fixed in
|
|
`assets/brief-components.css`: sections can split across pages now; only the small
|
|
atomic elements (cards, individual table rows) avoid splitting, with table headers
|
|
repeating on each new page. A correctly-generated PDF from the same content came out
|
|
6 clean pages.
|
|
2. **SO/PO lookup was wrongly scoped out by default — fixed.** Original design said
|
|
Sales/Purchase Orders "aren't typically relevant" to this brief type. Wrong: an
|
|
internal kickoff about a real sale needs them just as much as an external brief
|
|
would. Corrected in step 5 — the deciding factor is whether the topic is a
|
|
commercial engagement, not which brief type is generating the document.
|
|
3. **Contact-info lookup had to be manually requested — now a standing step.**
|
|
Resolving attendee names wasn't enough; real contact info (email, phone, title) for
|
|
external counterparts needed to be pulled from Odoo, and doing that well meant
|
|
starting from the linked SO/PO's own contacts rather than a generic search. Now
|
|
explicit in step 4, not something that needs to be asked for.
|
|
4. **Part number / product verification wasn't referenced at all — now is.** The
|
|
actual run needed to check a model variant and part number against MPM's product
|
|
catalog. The right source turned out to be the MPM Technical Reference System (see
|
|
Prerequisites) — added as a standing reference, not previously known to this skill.
|
|
5. **The manifest schema got meaningfully better in real use — pulled back into the
|
|
spec.** Confidence tags (verified/stated/open), a folder-layout header, split
|
|
numbered-vs-proposed open items, and a Findings/flags section for operational
|
|
observations (e.g. "this topic's Plaud AI summary is unreliable, build from the raw
|
|
transcript") all emerged from the real run and are now part of the documented
|
|
schema in step 2, not a one-off improvisation.
|
|
6. **Meeting transcript wasn't being archived — now a standing step.** The raw
|
|
transcript needed to be saved alongside the brief so future runs don't depend on
|
|
the source connector still being reachable. Now explicit in step 8.
|
|
|
|
None of these were failures of judgment in the moment — they're gaps between what
|
|
this file said and what turned out to actually be needed, now closed.
|
|
|
|
## 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.
|