One grid, three platforms

Same component, same row type, same columns. Everything platform-shaped is data in CloudPlatform and values on the row — not branches in the view. Below is what each actually renders from what its API actually returns.

16 Aug 2026 · drawn from the three adapters' real row construction, not from wishes

The question this drawing raised, and it is not the one I set out to answer. On Meet a child row is another session — you joined twice, two interviews, two files worth analysing. On Zoom a child row is the same session rendered four ways — speaker view, gallery view, shared screen, audio-only. Ticking two Meet children gets you two interviews. Ticking two Zoom children gets you the same 45 minutes twice, and Bristlenose will analyse it as two participants. Same visual structure, opposite meaning. See panel 3.

Google Meet

Both clocks. Attendees from the calendar. 1:N is rare — it means you joined the same meeting twice. No Expires column: hasPerFileExpiry is false because Drive has no per-file expiry and retention is an admin policy.

Import from Google Meet
martin@finca342.org
Last 30 days
Filter
MeetingScheduledRecordedSizeStatus
Wed 13 Aug
P04 Interview
Priya Raman · Simon Ellery
09:30
1h
09:34
52m 11s
1.1 GB
P05 Interview
Dana Okonkwo · Simon Ellery
11:00
1h
Recording 1
11:02
32m 04s
618 MB
Recording 2
11:41
38m 19s
701 MB
2 meetings · 3 recordings · 3 you can fetch

Two children = two interviews. The count in the footer is honest and the button does what it says.

Microsoft Teams

Always flat — one recording per meeting, so the outline never grows a triangle. Attendees from calendarView. Duration is never known (duration: nil in every row), and the Expires column is declared but Graph does not serve it.

Import from Microsoft Teams
martin@bristlenose.onmicrosoft.com
Last 30 days
Filter
MeetingScheduledRecordedSizeStatus
Wed 13 Aug
P04 Interview
Priya Raman · Simon Ellery
09:30
1h
09:34
1.1 GB
P05 Interview
Dana Okonkwo · Simon Ellery
11:00
1h
11:02
1.3 GB
Team standup
Tomas Lind · Aoife Brennan
14:00
30m
14:01
210 MB
3 meetings · 3 you can fetch

Footer says "3 meetings" only — meetings and recordings are the same number, so the second noun is withheld. The red dashes are the real gap: Teams knows when a recording started and never how long it ran.

Zoom

1:N is routine, not rare — yieldsMultipleMediaFiles is true for Zoom alone. Attendees never arrive and the line simply isn't there — saying "no roster" on every row would read as a fault the researcher is expected to fix. Expires is real, from the account's auto-delete.

Import from Zoom
martin@finca342.org
Last 30 days
Filter
MeetingScheduledRecordedSizeExpires
Wed 13 Aug
P04 Interview
09:30
1h
in 12 days
Speaker view
09:34
52m 11s
1.1 GB
Gallery view
09:34
52m 11s
1.2 GB
Shared screen
09:34
52m 11s
640 MB
Audio only
09:34
52m 11s
48 MB
1 meeting · 4 recordings · 4 you can fetch

Every child has the same start and the same duration, because they are one session. "Import 4 Recordings" produces four files of the same 52 minutes, and s01 will group them by stem or not at all — either one session with four videos, or four participants who said identical things.

MeetTeamsZoom
Meeting clockeventcalendarViewmeeting.start_time
Recording clocknew, unprovencreatedDateTimeper file, unused
Durationnew, unprovennevermeeting's, not the video's
Attendeesyesyesnever
Organiseryesnever setnever set
Expires columnhiddendeclared, unservedreal
Children meananother sessionsame session, another rendering

So: one codebase, and the conditions are already data rather than branches. CloudPlatform holds windowChoices, hasPerFileExpiry, yieldsMultipleMediaFiles and the vendor strings; the row carries attendees, duration, organiser. Every difference above renders as an absence — a dash, a missing column, a blank subtitle — not as a different layout. That is the design working. Except the last row of the table, which is not an absence but a different meaning wearing the same shape, and no amount of platform data fixes that.