From 3e2fb82d6a289bf034a2f5bcd89a25d48aac682a Mon Sep 17 00:00:00 2001 From: Jeremy Daer Date: Fri, 24 Jul 2026 22:12:53 -0700 Subject: [PATCH 1/3] Cross-ref rich-text attachments in recordable-subtypes absorption plan CloudFile and GoogleDocument are rich-text emitters; note that their absorption must carry their own `*_attachments` companion arrays so the rich-text projection coverage (rich-text-attachments-coverage) isn't silently missed when those subtypes land. --- spec/api-gaps/recordable-subtypes-doc.md | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/spec/api-gaps/recordable-subtypes-doc.md b/spec/api-gaps/recordable-subtypes-doc.md index de9f79bb..bce0b99c 100644 --- a/spec/api-gaps/recordable-subtypes-doc.md +++ b/spec/api-gaps/recordable-subtypes-doc.md @@ -85,6 +85,11 @@ Journal::Entry — there is no contract to model. do not model ahead of a BC3 contract. - Where Recording is polymorphic, extend the discriminated structure with the new `type` values. +- `CloudFile` and `GoogleDocument` are rich-text emitters: their responses + carry their own `*_attachments` companion arrays (see + [[rich-text-attachments-coverage]]). Model those members alongside the base + shapes at absorption time so the rich-text projection stays complete — a + newly-absorbed subtype must not silently drop its companion array. - Door now has its own documented surface (list/create/get/rename/trash) and is tracked under [[external-links-doors]] — model it there, not here. It still also appears as a string `type` value on generic Recording responses. From 026932e5c1e3646e9c1d3b34bc3e6eb88eee9ceb Mon Sep 17 00:00:00 2001 From: Jeremy Daer Date: Fri, 24 Jul 2026 23:11:58 -0700 Subject: [PATCH 2/3] Address review: correct #405 provenance to #408, link SearchResult attachments to #428 Copilot/human review on #427: the rich-text-attachments brief called #405 'this PR' and left the generic SearchResult attachments key untracked. #405 was the tracking issue; the merged PR is #408 (closes #405). Point the provenance at #408 and link the out-of-scope SearchResult.attachments bullet to its filed issue #428. --- spec/api-gaps/rich-text-attachments-coverage.md | 9 +++++---- 1 file changed, 5 insertions(+), 4 deletions(-) diff --git a/spec/api-gaps/rich-text-attachments-coverage.md b/spec/api-gaps/rich-text-attachments-coverage.md index 3381ae32..c2e99722 100644 --- a/spec/api-gaps/rich-text-attachments-coverage.md +++ b/spec/api-gaps/rich-text-attachments-coverage.md @@ -52,8 +52,9 @@ bc3_refs: > file metadata (documented in upstream `doc/api/sections/rich_text.md`, > addressed by bc3 #9980). The gap was SDK-side: the SDK modeled the rich-text > *strings* but not their companion attachment arrays. #400 shipped the first -> slice (`Todo.description_attachments`); **#405 completes coverage across every -> modeled rich-text decode path** and flips this entry to `absorbed-in-sdk`. +> slice (`Todo.description_attachments`); **#408 (closes #405) completes +> coverage across every modeled rich-text decode path** and flips this entry to +> `absorbed-in-sdk`. > This is absorption, not a provenance sync — the contract was already within > the current pin, so no repin. @@ -91,7 +92,7 @@ SDK decodes now carries its companion array, reusing `RichTextAttachment` + - **Generic `attachments` key on SearchResult** (`searches/show:25`): the recording's aggregate downloadable files, a *different* projection concern, not - a rich-text companion array. Not modeled; tracked separately if demanded. + a rich-text companion array. Not modeled; tracked in #428. - **everything/aggregates endpoints** (`everything/*`, which also render full partials): **unmodeled in the SDK** — no decode path exists to carry an array into. Covered by the separate `everything-aggregates.md` gap @@ -158,7 +159,7 @@ Complete. Shipped in two increments, both reusing `RichTextAttachment`: float-tolerant dimension representation — Go `types.FlexInt`, Kotlin `FlexibleIntSerializer` on a nullable `Int?`, Swift `Int32?`, Python `int | float`, Ruby nilable — is documented in SPEC.md §10 Type Fidelity. -2. **#405 (this PR):** `content_attachments` / `description_attachments` on the +2. **#408 (merged #405):** `content_attachments` / `description_attachments` on the remaining 17 structures (19 members) — 14 concrete `@required`, Gauge and the two polymorphic projections (SearchResult, Recording) optional/non-nullable — reusing `RichTextAttachment` and the same per-SDK decode assertions unchanged. From f975a26b48aec10483b9442fb18bebbff9436f8a Mon Sep 17 00:00:00 2001 From: Jeremy Daer Date: Fri, 24 Jul 2026 23:50:26 -0700 Subject: [PATCH 3/3] Address review: consistent #408 (closes #405) provenance phrasing Second occurrence said '#408 (merged #405)'; make both read '#408 (closes #405)'. --- spec/api-gaps/rich-text-attachments-coverage.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/api-gaps/rich-text-attachments-coverage.md b/spec/api-gaps/rich-text-attachments-coverage.md index c2e99722..2ec65953 100644 --- a/spec/api-gaps/rich-text-attachments-coverage.md +++ b/spec/api-gaps/rich-text-attachments-coverage.md @@ -159,7 +159,7 @@ Complete. Shipped in two increments, both reusing `RichTextAttachment`: float-tolerant dimension representation — Go `types.FlexInt`, Kotlin `FlexibleIntSerializer` on a nullable `Int?`, Swift `Int32?`, Python `int | float`, Ruby nilable — is documented in SPEC.md §10 Type Fidelity. -2. **#408 (merged #405):** `content_attachments` / `description_attachments` on the +2. **#408 (closes #405):** `content_attachments` / `description_attachments` on the remaining 17 structures (19 members) — 14 concrete `@required`, Gauge and the two polymorphic projections (SearchResult, Recording) optional/non-nullable — reusing `RichTextAttachment` and the same per-SDK decode assertions unchanged.