@ai-matrx/meet 0.7.6 → 0.7.8

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,5 +1,70 @@
1
1
  # Changelog — `@ai-matrx/meet`
2
2
 
3
+ ## 0.7.8
4
+ ### (next patch)
5
+
6
+ - **Fix — a refusal never reaches a person as a Python class name** (verifier, 2026-09-27): a
7
+ host's toast read "Internal server error: UnsupportedClientFeatureError". `readServerRefusal`
8
+ now skips raw server text (`Internal server error: …`, a bare `…Error` class, a snake_case
9
+ code) and falls through to the body's `user_message`, or to `SERVER_FAILED_SENTENCE`. The
10
+ three hand-copied refusal builders (`in-room.ts`, `management.ts`, `after.ts`) collapse into
11
+ ONE exported `refusalFromResponse(response, operation, fallbackRemedy)`, whose `message` is
12
+ the server's sentence — no `meet.x:` operation prefix — and whose `remedy` is the server's.
13
+ - **Fix — a refused Remove / Make host keeps its pane open WITH the sentence** : the confirm
14
+ pane now shows the server's refusal inline (`role="alert"`) with its buttons live; before it
15
+ stayed up silently.
16
+ - **Fix — every per-person menu offers "Message privately"**: a tile's menu (Room stage and a
17
+ host layout's strip, e.g. the Board) now opens the private chat through the store
18
+ (`snapshot.privateChatRequest`, answered by the one `ControlBar`); before only the People
19
+ panel could, so two menus for one person disagreed.
20
+ - **Fix — attendance is per PERSON, never per join**: an export listed the same attendee twice
21
+ under "attended". `attendanceReport` merges a person's joins (account = one person across
22
+ devices and rejoins; an accountless guest's rejoin, which gets a fresh `guest:<random>`
23
+ identity, is matched by the typed name) into one row — first arrival, last departure, total
24
+ time with overlaps counted once, and a new `joins` count. `notesDocument`'s "Attended" line
25
+ and the record view's "Who attended" use the new exported `uniqueAttendees` / `attendeeKey`.
26
+ - **Consumer action:** none (a consumer counting `bundle.attendees` itself should count
27
+ `uniqueAttendees(...)` instead).
28
+
29
+ ## 0.7.7
30
+ ### Meet wave 3: after the meeting
31
+
32
+ - **Fix — the room header on a phone** (2026-09-27, 390px): the header wraps into rows and
33
+ each host control stays one line; before, the title read "Hollo…" and "End meeting for
34
+ everyone" stacked into four underlined words.
35
+ - **Fix — a removed participant reads the server's sentence, not "invalid token: revoked"**
36
+ (2026-09-27, live room): a server-side disconnect now invalidates the cached room token, so
37
+ the next Join mints again and shows "A host removed you from this meeting."
38
+ - **Fix — a host's per-person menu opens beside its button** (2026-09-27, live room): the
39
+ popover was hidden but IN FLOW on its first frame, so the anchor it measured was button +
40
+ menu and it opened a full menu-height lower — Make host, Report and Remove from meeting were
41
+ below the fold. It is now fixed-positioned from the first frame, re-placed when the layout
42
+ moves, and pinned + scrollable when neither side of the button holds it.
43
+ - **Fix — the waiting room for people from another organization and for denied guests**
44
+ (2026-09-27, verified in a real room): a signed-in link-follower now knocks as `user:<id>`, the
45
+ identity the server's lobby row carries — before, the host saw two entries and admitting one
46
+ left the person waiting forever. A host's "Deny" now reaches the knocker (`onDenied` →
47
+ `engine.rejoin()`), and every token refusal (403/423/410) shows the SERVER's own sentence and
48
+ remedy instead of a developer note ("meet.token: the server refused this join (403)").
49
+ - **`core/after.ts`** (framework-free, exported from the root): `attendanceReport` /
50
+ `attendanceTotals` / `attendanceCsv` (who joined, when, how long — measured to the meeting's end
51
+ when a leave was never recorded — and as what: host, co-host, member, signed-in guest, guest,
52
+ assistant); `transcriptDocument(bundle, "txt" | "md" | "vtt")` (VTT cued from the recording's
53
+ start); `notesDocument` (summary, decisions, action items with owners, as Markdown);
54
+ `recordingOffsetMs` (a transcript moment as a position in the recording — `null` outside it,
55
+ never clamped) + `clockPosition`; `searchTranscript` (in-record search with match ranges);
56
+ `loadMeetingChat` (the saved chat of a finished meeting, a refusal returned as data);
57
+ `loadFollowUpDraft` / `sendFollowUp` (the recap email — `MEET_ROUTES.meetingFollowUp`,
58
+ `GET|POST /api/v1/meet/meetings/{id}/follow-up`; `dryRun` renders and queues nothing).
59
+ - **Repository:** `myRecordings({ includeArchived })` (`meet_my_recordings`), `searchMeetings(q)`
60
+ (`meet_search` — titles, agendas, current notes, final transcript lines; snippets mark hits
61
+ with ⟦ ⟧, split with `snippetRuns`), `renameRecording`, `setRecordingArchived` (soft delete;
62
+ an update RLS refuses is an error, never a silent success). `recordings(meetingId)` now leaves
63
+ archived recordings out of the record.
64
+ - **Consumer action:** none required. A test double that implements `MeetRepository` must add
65
+ the four new methods (`managementStubs()` refuses them by name); a fake PostgREST chain used
66
+ under `recordings()` must answer `.is()`.
67
+
3
68
  ## 0.7.6
4
69
 
5
70
  Automatic changed-only republish (docs/metadata drift since the last tag — see