feat(p8): meeting-studio demo + smoke-calendar; P8 verification green

Task 8.7: apps/meeting-studio (Vite, port 5178) — schedule a meeting, invite
attendees, toggle per-attendee recording consent, generate transcript (BLOCKED
until unanimous consent — KG-14), summarize, see AI summary + action-item inbox.
scripts/smoke-calendar.mjs proves the P8 guarantees end to end: direct schedule,
consent gate BLOCKED→READY (KG-14), summary linked to a P7 ai_artifact, action
items, attendee-visibility exclusion (Scenario 6), meeting_request genesis,
simulated provider sync (idempotent).

P8 verification: 95 tests green, pnpm -r build all packages+demos, boundary
passes and fails on meeting-web->service, smoke-calendar PASS, prior smokes
(realtime/inbox/support/adapter/route/ai) PASS.

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-07-01 18:22:24 +05:30
parent ca9498ce83
commit e11964b8bc
8 changed files with 289 additions and 0 deletions
+32
View File
@@ -0,0 +1,32 @@
import { createRoot } from 'react-dom/client';
import { MeetingProvider } from '@insignia/iios-meeting-web';
import { useEffect, useState } from 'react';
import { App, SERVICE } from './App';
const APP_ID = 'portal-demo';
async function devToken(userId: string): Promise<string> {
const r = await fetch(`${SERVICE}/v1/dev/token`, {
method: 'POST',
headers: { 'content-type': 'application/json' },
body: JSON.stringify({ appId: APP_ID, userId, name: userId }),
});
if (!r.ok) throw new Error(`devToken ${r.status} (service running with IIOS_DEV_TOKENS=1?)`);
return ((await r.json()) as { token: string }).token;
}
function Root() {
const [token, setToken] = useState<string | null>(null);
useEffect(() => {
void devToken('meeting-studio').then(setToken);
}, []);
if (!token) return <div style={{ padding: 16, fontFamily: 'sans-serif' }}>loading</div>;
return (
<MeetingProvider serviceUrl={SERVICE} token={token}>
<App token={token} />
</MeetingProvider>
);
}
const el = document.getElementById('root');
if (el) createRoot(el).render(<Root />);