"Lesson 6가 ChromeEmbed의 모든 부분 흐르는 JSON object zoom in: host-context payload. 모든 field 정당화, 모든 field가 panel iframe이 의존하는 계약."
Full shape
Content script의 extractContext()가 반환:
{
type: 'pippa:host-context',
payload: {
host_kind: 'web-page',
snapshot_at: '2026-05-16T01:23:45.000Z',
host_id: chrome.runtime.id,
source: location.href,
human_label: document.title || location.hostname,
favicon: faviconHref(),
selection,
viewportText,
readableText: viewportText, // compat alias
wordCount,
viewport: { width, height, scrollX, scrollY, devicePixelRatio },
scrollPosition: { y: scrollY, ofPageHeight: pageHeight },
language: document.documentElement?.lang || navigator.language || '',
frameUrl: location.href,
isTopFrame: window.top === window
}
}
Identity field
host_kind— ChromeEmbed 엔 항상 'web-page'. PIPPA-EMBEDS framework가 이거 기대. Adobe-embed가 'adobe-app', Calendar가 'gcal-event' 등. Downstream 렌더링 위한 discriminator.host_id— extension의 runtime id. cwkPippa가 다른 installed instance (multi-Chrome-profile setup) 의 메시지 구별하게.source— user가 있는 canonical URL. cwkPippa가 이걸 'capturing from example.com/article' 로 surface.human_label— fallback-chained title. Chat thread label로 사용.favicon— UI affordance 위해.
Content field
selection— 현재 highlighted 텍스트 (또는 최대 5 분 전의 cached selection).viewportText— user의 현재 viewport 안 텍스트, walker-추출 spatially sorted (Lesson 3).readableText— viewportText의 다른 이름이야. cwkPippa의 옛 코드가 'readableText' 를 읽거든. 이름을 하나 더 달아 둔 덕분에 ChromeEmbed가 그쪽을 안 깨뜨려. cwkPippa가 'viewportText' 로 완전히 넘어가면 그때 걷어낼 계획이고.wordCount— cwkPippa UI 위한 quick metric ('1,247 words in view').
Viewport field
viewport: { width, height, scrollX, scrollY, devicePixelRatio }— user 창을 실제 픽셀로 잰 값이야. 이걸로 cwkPippa가 좁은 화면이나 고해상도 디스플레이에 맞춰 UI를 바꿀 수 있어.scrollPosition: { y, ofPageHeight }— user가 페이지 세로 어디쯤 와 있는지랑 전체 높이야. 이걸로 cwkPippa가 '이 글의 60% 쯤 왔어' 같은 걸 말해 줄 수 있어.
Metadata
snapshot_at— ISO 형식 시각이야. cwkPippa가 '5 초 전에 본 화면 기준이야' 라고 알려 줄 수 있게 해 줘.language— cwkPippa가 매칭 locale로 응답 format 에 유용.frameUrl과isTopFrame— Lesson 2에서 본 SW의 합치는 로직에 쓰여. 안쪽 frame이 올려 보낸 것도 이 값을 달고 오니까, SW가 그걸로 맨 위 frame의 스냅숏을 덮어쓸지 말지 판단할 수 있어.
왜 schema, '그냥 DOM 보내기' 아님
Fixed payload shape의 규율이 이럴 때 payback:
- 다른 embed가 compose. PIPPA-EMBEDS framework가 모든 embed (Chrome, Adobe, Mail, Calendar) 가 같은 field 이름의 host-context 생산 기대. cwkPippa가 uniformly 렌더.
- Versioning. Payload v1 → v2 bump 필요하면, 오늘
version: 1field 추가하고 내일 확인. - Compatibility.
readableTextalias가 정확히 fixed schema가 enable 하는 종류의 migration aid. Schema 없이는 모든 consumer가 추측해야. - 들여다보기 좋아. cwkPippa 로그에 이 context가 찍혔을 때, 무슨 항목이 있는지 추측할 필요 없이 정돈된 기록처럼 그냥 읽히거든.
Payload 에 없는 것
일부러 부재:
- 문서 HTML 전체 — 너무 크기도 하거니와, '지금 보이는 것' 이라는 의미 자체가 사라져.
- 화면 사진 — 저장 비용이 커. 잘라낸 조각 정도라면 나중에 항목으로 붙일 수는 있고.
- tab 방문 기록 — ChromeEmbed가 다룰 범위 밖이야. cwkPippa는 이미 자기 대화 기록을 갖고 있고.
- user가 누구인지 — 피파는 cwkPippa session에서 이미 알고 있어. extension이 실어 보낼 정보가 아니야.
Field 추가가 feature로 정당화될 때 저렴. speculatively 추가는 schema 시끄럽고 bridge 느리게 만듬.
한 payload shape, 모든 field 정당화, 모든 field가 계약. Schema가 ChromeEmbed를 다른 embed와 composable 하게 만드는 것. 그것 없이는 각 embed가 'context' 재발명 하고 cwkPippa가 다 special-case 해야.
PIPPA-EMBEDS framework 각도. ChromeEmbed v0.1이 첫 PIPPA embed. Ship 하는 host-context schema가 future embed (Adobe, Mail, Calendar, IDE) 위한 제안된 계약. cwkPippa가 uniformly 렌더. embed의 유일한 job이 native host가 제공하는 어떤 것이든 schema field 채우기. 그게 win — 각 새 embed가 from-scratch UI가 아닌 한 payload format 가진 content-script-and-bus shape.