hcengineering / hcengineering/platform
Bug: Meeting minutes not shown in Room view - collection counter never incremented
- Dominant language
- TypeScript
- Stars
- 27.7k
- Forks
- 2.2k
- PR merge metrics
- No merged PRs in 30d
Description
### Describe the bug
After a meeting ends, the Room detail view shows **"No meeting minutes"** even though MeetingMinutes documents exist in the database with transcription data. The transcription pipeline works correctly (love-agent -> OpenAI STT -> aibot -> transactor -> CockroachDB), but the UI never renders the results.
### Environment
- **Version:** v0.7.353 (`hardcoreeng/*` images)
- **Database:** CockroachDB (single-node, self-hosted)
- **Deployment:** Dokploy template (docker-compose)
### Steps to reproduce
1. Start a meeting in any Room (e.g., "All hands")
2. Enable transcription (click the transcription button)
3. Speak for 30+ seconds so OpenAI STT generates transcriptions
4. End the meeting
5. View the Room detail page -> "Meeting minutes" section shows **"No meeting minutes"**
### Evidence from database
MeetingMinutes documents exist with correct data:
```sql
SELECT _id, _class, "attachedTo", data->>'status', data->>'transcription', data->>'title'
FROM meeting_minutes
WHERE "attachedTo" = '';
```
Returns 4 rows, the most recent with `"transcription": 8` (8 saved transcript messages). The data is there, the UI just can't see it.
### Root cause
The `MeetingMinutesSection.svelte` component guards rendering on the `meetings` collection counter:
```svelte
// plugins/love-resources/src/components/MeetingMinutesSection.svelte
{#if meetings > 0 && viewlet}
{:else}
{/if}
```
The `meetings` counter on the Room is **never incremented** because MeetingMinutes are created using `createDoc` / `createTxCreateDoc` instead of `addCollection` / `createTxCollectionCUD`.
**Client-side creation** (`plugins/love-resources/src/meetings.ts`):
```typescript
await client.createDoc(love.class.MeetingMinutes, core.space.Workspace, {
attachedTo: room._id,
status: MeetingStatus.Active,
title: await getNewMeetingTitle(room),
attachedToClass: love.class.Room,
collection: 'meetings'
})
```
**Server-side trigger** (`server-plugins/love-resources/src/index.ts`):
```typescript
const tx = control.txFactory.createTxCreateDoc(
love.class.MeetingMinutes,
core.space.Workspace,
{
attachedTo: info.room,
status: MeetingStatus.Active,
title: `...`,
attachedToClass: love.class.Room,
collection: 'meetings'
},
_id
)
```
The collection counter trigger in `server/packages/middleware/src/triggers.ts` only increments counters when `attachedTo`, `attachedToClass`, and `collection` are **top-level transaction properties**. `createDoc` puts `attachedTo`/`collection` inside `attributes` (the document data), not as top-level transaction properties. Only `addCollection` / `createTxCollectionCUD` promotes these to the top level. So the trigger never fires, and the Room's `meetings` counter stays at 0/undefined.
Additionally, the `@Model` decorator for `MeetingMinutes` extends `core.class.Doc` (not `core.class.AttachedDoc`), which means `hierarchy.isDerived(love.class.MeetingMinutes, core.class.AttachedDoc)` returns `false` even though the TypeScript class extends `TAttachedDoc`:
```typescript
// models/love/src/index.ts
@Model(love.class.MeetingMinutes, core.class.Doc, DOMAIN_MEETING_MINUTES)
export class TMeetingMinutes extends TAttachedDoc implements MeetingMinutes, Todoable {
```
### Suggested fix
**Fix 1:** Change the `@Model` decorator to extend `core.class.AttachedDoc`:
```typescript
@Model(love.class.MeetingMinutes, core.class.AttachedDoc, DOMAIN_MEETING_MINUTES)
```
**Fix 2:** Change client-side creation to use `addCollection`:
```typescript
await client.addCollection(
love.class.MeetingMinutes,
core.space.Workspace,
room._id,
love.class.Room,
'meetings',
{
status: MeetingStatus.Active,
title: await getNewMeetingTitle(room),
description: null
}
)
```
**Fix 3:** Change server-side trigger to use `createTxCollectionCUD`:
```typescript
const innerTx = control.txFactory.createTxCreateDoc(
love.class.MeetingMinutes,
core.space.Workspace,
{
description: null,
attachedTo: info.room,
status: MeetingStatus.Active,
title: `${roomName} ${date}`,
attachedToClass: love.class.Room,
collection: 'meetings'
},
_id
)
const tx = control.txFactory.createTxCollectionCUD(
love.class.Room,
info.room,
core.space.Workspace,
'meetings',
innerTx
)
```
### Impact
- **Transcription pipeline is unaffected.** love-agent, OpenAI STT, and aibot all work correctly. Transcripts are written to the `meeting_minutes` table via the transactor.
- **Data is preserved.** MeetingMinutes documents and their transcription ChatMessages exist in the database. Only the UI display is broken.
- **Affects all self-hosted deployments** on v0.7.353 using CockroachDB. May also affect Huly Cloud (unclear if the `worker` service compensates).
### Workaround (for self-hosted deployments on CockroachDB)
Manually reconcile the counter for all Rooms across all workspaces:
```sql
-- Fix meeting minutes counter on all Rooms/Offices (all workspaces)
UPDATE love
SET data = jsonb_set(COALESCE(data, '{}'::jsonb), '{meetings}', (
SELECT COALESCE(to_jsonb(count(*)), '0'::jsonb)
FROM meeting_minutes
WHERE "attachedTo" = love._id
AND "workspaceId" = love."workspaceId"
)::jsonb)
WHERE _class IN ('love:class:Room', 'love:class:Office');
```
This sets the `meetings` field on each Room to the actual count of MeetingMinutes. Refresh the browser after running.
**Note:** The counter will not auto-increment for future meetings until the upstream code is fixed.
### Related issues
- #8785 - Meeting minutes not shown in UI when room is deleted
- #7303 - Meeting minutes tracking
Contributor guide
No contributing guide indexed for this repository
Assessment
This issue has not been assessed yet.