@agent-native/core 0.164.12 → 0.164.17

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.
Files changed (90) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/netlify.toml +4 -0
  3. package/corpus/templates/clips/actions/request-transcript.ts +10 -6
  4. package/corpus/templates/content/actions/_database-source-utils.ts +25 -2
  5. package/corpus/templates/content/actions/_database-utils.ts +2 -0
  6. package/corpus/templates/content/actions/_local-folder-source.ts +186 -2
  7. package/corpus/templates/content/actions/connect-local-folder-source.ts +23 -8
  8. package/corpus/templates/content/actions/disconnect-local-folder-source.ts +3 -3
  9. package/corpus/templates/content/actions/resolve-local-folder-conflict.ts +2 -2
  10. package/corpus/templates/content/actions/sync-local-folder-source.ts +130 -12
  11. package/corpus/templates/content/app/components/LocalFolderLiveSync.tsx +77 -0
  12. package/corpus/templates/content/app/components/editor/BubbleToolbar.tsx +298 -3
  13. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +354 -8
  14. package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +23 -1
  15. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +81 -1
  16. package/corpus/templates/content/app/components/editor/database/sidebar.tsx +36 -0
  17. package/corpus/templates/content/app/components/editor/extensions/NotionExtensions.tsx +18 -4
  18. package/corpus/templates/content/app/components/editor/local-source-write-state.ts +52 -0
  19. package/corpus/templates/content/app/components/sidebar/DocumentSidebar.tsx +244 -6
  20. package/corpus/templates/content/app/components/sidebar/local-source-hierarchy.ts +189 -0
  21. package/corpus/templates/content/app/hooks/use-create-page.ts +26 -4
  22. package/corpus/templates/content/app/hooks/use-documents.ts +83 -0
  23. package/corpus/templates/content/app/i18n-data.ts +239 -0
  24. package/corpus/templates/content/app/lib/desktop-content-files.ts +57 -1
  25. package/corpus/templates/content/app/lib/local-content-source-files.ts +210 -34
  26. package/corpus/templates/content/app/lib/local-folder-live-sync.ts +191 -0
  27. package/corpus/templates/content/app/root.tsx +2 -1
  28. package/corpus/templates/content/app/routes/_app.local-files.tsx +103 -38
  29. package/corpus/templates/content/docs/product/capabilities/content.source.file-folder.md +2 -2
  30. package/corpus/templates/content/docs/product/features/content.feature.bring-your-local-work.md +3 -3
  31. package/corpus/templates/content/docs/product/roadmap.md +2 -2
  32. package/corpus/templates/content/docs/solutions/2026-08-18-colored-text-highlighting-shape.md +693 -0
  33. package/corpus/templates/content/docs/solutions/2026-08-18-content-navigation-coherence-shape.md +482 -0
  34. package/corpus/templates/content/package.json +1 -0
  35. package/corpus/templates/content/shared/api.ts +25 -0
  36. package/corpus/templates/content/shared/nfm.ts +14 -3
  37. package/corpus/templates/factory/AGENTS.md +24 -29
  38. package/corpus/templates/factory/actions/get-slack-feedback-context.ts +8 -28
  39. package/corpus/templates/factory/actions/get-triage-config.ts +1 -0
  40. package/corpus/templates/factory/actions/govern-agent-native-pull-request.ts +67 -59
  41. package/corpus/templates/factory/actions/list-triage-items.ts +6 -1
  42. package/corpus/templates/factory/actions/reconcile-triage-run.ts +7 -1
  43. package/corpus/templates/factory/actions/save-triage-config.ts +27 -7
  44. package/corpus/templates/factory/actions/start-builder-for-item.ts +113 -31
  45. package/corpus/templates/factory/actions/view-screen.ts +12 -0
  46. package/corpus/templates/factory/app/components/factory/FactorySettingsView.tsx +457 -0
  47. package/corpus/templates/factory/app/components/factory/FactoryWorkspaceActions.tsx +53 -0
  48. package/corpus/templates/factory/app/components/layout/Layout.tsx +2 -0
  49. package/corpus/templates/factory/app/components/layout/Sidebar.tsx +3 -1
  50. package/corpus/templates/factory/app/hooks/use-navigation-state.ts +10 -7
  51. package/corpus/templates/factory/app/i18n/en-US.ts +3 -0
  52. package/corpus/templates/factory/app/routes/agents.tsx +22 -1
  53. package/corpus/templates/factory/app/routes/factory-settings.tsx +34 -0
  54. package/corpus/templates/factory/app/routes/factory.tsx +33 -323
  55. package/corpus/templates/factory/server/connectors/slack.ts +62 -0
  56. package/corpus/templates/factory/server/db/schema.ts +1 -0
  57. package/corpus/templates/factory/server/lib/slack-feedback-prompt.ts +30 -0
  58. package/corpus/templates/factory/server/plugins/agent-chat.ts +9 -8
  59. package/corpus/templates/factory/server/plugins/factory-migrations.ts +7 -0
  60. package/corpus/templates/factory/server/plugins/factory-scheduler-job.ts +43 -25
  61. package/corpus/templates/factory/server/triage/ai-services-git.ts +2 -0
  62. package/corpus/templates/factory/server/triage/pr-monitor.ts +2 -1
  63. package/corpus/templates/factory/server/triage/pr-policy.ts +197 -19
  64. package/corpus/templates/factory/server/triage/review-skill-alignment.ts +127 -0
  65. package/corpus/templates/factory/server/triage/slack-client.ts +79 -6
  66. package/dist/app-config/auth.d.ts +4 -0
  67. package/dist/app-config/auth.js +7 -0
  68. package/dist/app-config/schema.d.ts +3 -0
  69. package/dist/app-config/schema.js +2 -0
  70. package/dist/cli/code-agent-executor.js +6 -1
  71. package/dist/cli/code-agent-mcp-config.d.ts +2 -2
  72. package/dist/cli/code-agent-mcp-config.js +34 -9
  73. package/dist/client/MultiTabAssistantChat.js +28 -1
  74. package/dist/client/org/OrgSwitcher.js +8 -4
  75. package/dist/client/use-chat-threads.d.ts +1 -0
  76. package/dist/client/use-chat-threads.js +13 -3
  77. package/dist/collab/awareness.d.ts +2 -2
  78. package/dist/collab/routes.d.ts +1 -1
  79. package/dist/mcp-client/config.d.ts +11 -0
  80. package/dist/mcp-client/config.js +33 -26
  81. package/dist/notifications/routes.d.ts +3 -3
  82. package/dist/observability/routes.d.ts +5 -5
  83. package/dist/progress/routes.d.ts +1 -1
  84. package/dist/resources/handlers.d.ts +2 -2
  85. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  86. package/dist/server/auth.js +17 -3
  87. package/dist/server/realtime-token.d.ts +1 -1
  88. package/dist/server/transcribe-voice.d.ts +1 -1
  89. package/dist/vite/client.js +2 -0
  90. package/package.json +1 -1
@@ -0,0 +1,693 @@
1
+ # Add colored text highlighting to the Content editor
2
+
3
+ ## Summary
4
+
5
+ Content writers need Notion's familiar selected-text color interaction: one `A`
6
+ control containing named text and background colors, with the formatting
7
+ remaining part of the document after save, reload, collaboration, and canonical
8
+ serialization. The smallest useful slice exposes the editor's existing
9
+ persistent `notionSpan` mark through the existing selection bubble toolbar. It
10
+ does not create a second highlight object, reuse comment decorations as document
11
+ content, or add a new editor abstraction.
12
+
13
+ Source task: Bowerbird ID `69a7e1cf-249f-43c6-97a0-c14455c836d6`, supplied
14
+ title “Add colored text highlighting to Content editor.” The exact live task
15
+ record could not be recovered on 2026-08-18: the local vault returned no matching
16
+ note, Content's indexed read found neither the ID nor title, and its live lookup
17
+ was unavailable because of an A2A delegation cycle. The title and ID are direct
18
+ evidence from Alice's delegated Shape request; no unavailable task body, status,
19
+ or acceptance notes are inferred.
20
+
21
+ ## Notion parity audit status
22
+
23
+ On 2026-08-18 Alice authorized a read/write audit in the logged-in Codex in-app
24
+ browser, then explicitly authorized Notion desktop as the fallback. Shape
25
+ created Notion page
26
+ `3c0ccf6483ce808b8198d1a8ba36e519` at
27
+ `https://app.notion.com/p/tempoimmaterial/3c0ccf6483ce808b8198d1a8ba36e519`
28
+ and entered test text. The in-app browser connection then reset, so the audit
29
+ resumed in the logged-in Notion desktop app on the same page.
30
+
31
+ Directly observed in Notion desktop:
32
+
33
+ - Selecting `bravo` opens one floating selection toolbar and retains the exact
34
+ selection while its color UI is open.
35
+ - The toolbar's color entry is an `A` button. Activating it expands the color UI
36
+ inside that same floating toolbar rather than opening an unrelated document
37
+ or block-level control.
38
+ - The expanded UI contains, in order, a single-row **Recently used** area,
39
+ **Text color**, then **Background color**.
40
+ - Text color and background color each show a default choice followed by the
41
+ same nine hue families: gray, brown, orange, yellow, green, blue, purple,
42
+ pink, and red. The UI is a compact unlabeled swatch grid; color identity is
43
+ visual in the screenshot and therefore requires accessible names in Content.
44
+ - The same toolbar also exposes text style, bold, italic, underline,
45
+ strikethrough, Clear format, link/comment, and other selection operations.
46
+ Color is therefore one member of Notion's existing selection-formatting
47
+ interaction, not a separate highlight-only toolbar.
48
+
49
+ The desktop accessibility bridge exposed the selection and the color-panel
50
+ structure, but its coordinate action backend returned `noWindowsAvailable` for
51
+ the swatches. Applying a swatch, replacing it, selecting a mixed-color range,
52
+ and exercising default/clear and collapsed-caret behavior could not be directly
53
+ completed. Shape therefore treats those transition details as explicit Content
54
+ product decisions below rather than claiming they were observed Notion facts.
55
+ They are frozen for Work and must be proved in Content's real interface.
56
+
57
+ ## WORK PAUSED — RETURNING TO SHAPE
58
+
59
+ Work inspection found a material contradiction in the frozen architecture.
60
+ `notionSpan` can hold `color` and `bgColor` simultaneously in ProseMirror, but
61
+ `docToNfm` currently serializes `a.color || a.bgColor` into one `color`
62
+ attribute. When both are present, foreground wins and background is silently
63
+ lost on save. The existing NFM parser likewise derives foreground versus
64
+ background from one `_bg`-suffixed `color` value. Therefore the frozen combined
65
+ Notion interaction cannot satisfy its save/reload acceptance story by merely
66
+ exposing the existing mark.
67
+
68
+ This is direct source evidence from `templates/content/shared/nfm.ts`, not a
69
+ test failure or implementation preference. Shipping edits remain paused.
70
+
71
+ ### Material delta and options
72
+
73
+ 1. **Return to background-only highlighting.** Keep the existing NFM contract
74
+ unchanged and expose only background swatches. This is smallest, but it no
75
+ longer matches the observed combined Notion `A` interaction Alice requested.
76
+ 2. **Expose both palettes but make them mutually exclusive.** Choosing a text
77
+ color would clear background and vice versa. This preserves current NFM but
78
+ invents destructive behavior that is neither Notion-like nor humane.
79
+ 3. **Add backward-compatible dual-color NFM serialization. Recommended.** Keep
80
+ the existing single `notionSpan` mark and existing one-color spellings, while
81
+ adding an explicit background attribute only when needed so foreground and
82
+ background can coexist. Parsing accepts both old documents and the new
83
+ dual-color spelling; no database schema, second mark, or migration is added.
84
+
85
+ ### Old fingerprint
86
+
87
+ - Outcome: match Notion's combined selected-text color interaction.
88
+ - Governing architecture: expose existing `notionSpan.color` and
89
+ `notionSpan.bgColor` without changing canonical representation.
90
+ - Acceptance story: both attributes survive canonical save/reload.
91
+
92
+ ### Proposed replacement fingerprint
93
+
94
+ - Outcome and shipping surface remain unchanged.
95
+ - Governing architecture changes: the combined toolbar still updates the one
96
+ `notionSpan` mark, and NFM gains a backward-compatible dual-color spelling
97
+ that preserves both attributes while continuing to parse and emit established
98
+ one-color documents unchanged.
99
+ - Replacement acceptance story: the frozen combined interaction passes all
100
+ prior assertions, and additionally proves old foreground-only and
101
+ background-only NFM fixtures remain byte-stable while a dual-color fixture
102
+ round-trips both attributes without silent loss.
103
+ - Risk strategy remains `system-ready` without a feature flag because the
104
+ representation change is additive, locally reversible, and gated by focused
105
+ compatibility plus real-interface save/reload evidence.
106
+
107
+ Smallest decision required: approve option 3 and replacement story, or choose
108
+ option 1. Option 2 is not recommended.
109
+
110
+ ### Approval and Work restoration
111
+
112
+ Alice approved option 3 and invoked `$work` in the calling Codex task on
113
+ 2026-08-18. That exact user message approves the proposed replacement
114
+ fingerprint and acceptance story. The additive dual-color NFM architecture is
115
+ therefore frozen; the prior return-to-Shape pause is resolved and Work may
116
+ resume within the replacement envelope below.
117
+
118
+ ## Context and constituency
119
+
120
+ The constituency is signed-in Content writers editing the canonical rich-text
121
+ body of a Page in `BuilderIO/agent-native`, specifically
122
+ `templates/content`'s visual document editor. Today, selecting text opens a
123
+ bubble toolbar with persistent marks for bold, italic, strike, code, and link,
124
+ plus a comment command. There is no user-facing command in that toolbar for
125
+ persistent named text or background color.
126
+
127
+ The word “highlight” is overloaded in the current editor:
128
+
129
+ - Comment highlights are ProseMirror decorations derived from SQL-backed
130
+ comment anchors. Their source explicitly says they are presentation overlays,
131
+ not document marks, and they never enter NFM serialization.
132
+ - Selection fill and recent-edit highlights are also transient presentation.
133
+ - `notionSpan` is an existing inline document mark with `color`, `bgColor`, and
134
+ underline attributes. NFM serializes a background as
135
+ `<span color="yellow_bg">…</span>` and parses `_bg` values back into
136
+ `bgColor`; the editor renders the mark as `background-color`.
137
+
138
+ This shape uses “colored text highlighting” to mean the third behavior plus its
139
+ observed Notion companion: durable foreground and background attributes owned
140
+ by the document body through one combined color control.
141
+
142
+ ## Desired outcome
143
+
144
+ A signed-in writer selects ordinary inline text, opens one `A` color control,
145
+ and chooses a named text or background color. The exact selected characters
146
+ change immediately, the mark composes with existing inline formatting, and the
147
+ result remains equivalent through ordinary save, reload, collaboration,
148
+ copy/serialization, and parse paths. The writer can independently return text
149
+ or background color to Default without removing the other color or unrelated
150
+ marks.
151
+
152
+ ## Recommended behavior
153
+
154
+ ### Selection semantics
155
+
156
+ - The entry point appears in the existing bubble toolbar, which already opens
157
+ only for a non-empty text selection and excludes media, registry blocks, and
158
+ other atom-like nodes.
159
+ - Choosing a text or background color applies the existing `notionSpan` mark to the current
160
+ selection. It does not color an entire block merely because part of the block
161
+ is selected.
162
+ - A selection crossing compatible inline text in multiple ordinary text blocks
163
+ applies the mark to each selected text range using TipTap/ProseMirror's normal
164
+ mark semantics. Excluded nodes remain unchanged.
165
+ - This first slice does not expose a collapsed-caret command or set a stored mark
166
+ for future typing. With no non-empty selection, no color control is
167
+ shown.
168
+ - Applying a text color replaces only the selection's existing
169
+ `notionSpan.color`; applying a background replaces only `notionSpan.bgColor`.
170
+ Both preserve underline and all unrelated supported attributes. Choosing
171
+ Default clears only the attribute for that section; if the resulting
172
+ `notionSpan` has no remaining meaningful attributes, the empty mark may be
173
+ removed.
174
+
175
+ ### Color semantics
176
+
177
+ - Match Notion's observed combined color entry rather than inventing a separate
178
+ highlight-only control. The `A` panel contains Recently used, Text color, and
179
+ Background color in that order.
180
+ - Offer the existing bounded Notion-compatible foreground vocabulary and its
181
+ background counterpart:
182
+ `gray`, `brown`, `orange`, `yellow`, `green`, `blue`, `purple`, `pink`, and
183
+ `red`, plus Default; backgrounds use
184
+ `gray_bg`, `brown_bg`, `orange_bg`, `yellow_bg`, `green_bg`, `blue_bg`,
185
+ `purple_bg`, `pink_bg`, and `red_bg`.
186
+ - Display the choices as named, theme-legible swatches with accessible text
187
+ labels and selected state. Match the observed default-plus-nine order in both
188
+ sections; no color is silently applied before the writer chooses one.
189
+ - Store named tokens, not arbitrary CSS, hex, RGB, theme variables, or recent
190
+ custom colors. The existing NFM `_bg` token is the canonical serialized
191
+ value; rendering may map it to theme-appropriate visual colors.
192
+ - Default in the Text color section clears only foreground color. Default in the
193
+ Background color section clears only background color. The toolbar's existing
194
+ Clear format command remains broader and is not relabeled as highlight clear.
195
+ - Recently used shows the last named text or background color applied in the
196
+ current editor session. It is a convenience mirror of the palette choice, not
197
+ document content, user settings, or a new persisted preference.
198
+ - A uniform selection identifies its active text and background swatches. A
199
+ mixed selection identifies no single active swatch; choosing a color
200
+ normalizes only that color attribute across the selection.
201
+
202
+ ### Toolbar entry point
203
+
204
+ Add one compact `A` color control to `BubbleToolbar` in the existing inline
205
+ formatting group. Its expanded panel follows the observed Notion ordering:
206
+ Recently used, Text color, then Background color. Reuse the current shadcn
207
+ `Popover` pattern already used by the toolbar's text-style menu, Tabler
208
+ iconography, selection-preservation behavior, and focus restoration.
209
+ Opening the popover must not collapse the editor selection before the mark
210
+ command runs. Choosing a swatch applies immediately, closes the color panel,
211
+ and leaves the formatted text selected so the result and other toolbar commands
212
+ remain available.
213
+
214
+ No slash command, top-level document toolbar item, keyboard shortcut, raw-source
215
+ editor, Action, or agent-specific command is added in this slice. Agents already
216
+ edit the canonical NFM body through the ordinary document action surface; this
217
+ work does not add a parallel highlighting mutation API.
218
+
219
+ ### Persistence and serialization
220
+
221
+ - Keep `notionSpan` as the one inline fidelity mark; do not introduce a TipTap
222
+ Highlight extension or a second ProseMirror mark with overlapping meaning.
223
+ - Persist through the existing `VisualEditor` path:
224
+ ProseMirror document -> `docToNfm` -> canonical document save, and
225
+ NFM -> `nfmToDoc` -> ProseMirror document on load/reconciliation.
226
+ - Canonical NFM keeps the established single-attribute spellings: foreground is
227
+ `<span color="<name>">…</span>` and background-only is `<span
228
+ color="<name>_bg">…</span>`. When both coexist, foreground remains in `color`
229
+ and the background is added as `bg_color="<name>_bg"`.
230
+ - The result must remain stable across `docToNfm(nfmToDoc(value))` and through a
231
+ real editor save/reload. Unsupported or malformed color values must not be
232
+ coerced into a plausible supported highlight.
233
+ - Existing collaboration remains authoritative. Because the mark is document
234
+ content, it travels in the same ProseMirror/Yjs updates and save reconciliation
235
+ as bold, italic, links, and other inline marks.
236
+
237
+ ### Interoperability with existing marks
238
+
239
+ - Coloring composes with bold, italic, strike, code, underline, and link.
240
+ Applying, changing, or defaulting either color must not remove those marks.
241
+ - Link identity and destination survive coloring or defaulting a linked
242
+ selection. The canonical serializer's existing nesting remains authoritative.
243
+ - Foreground and background attributes imported from Notion remain independent:
244
+ changing or defaulting one preserves the other on the same span.
245
+ - Comment anchors and their decoration overlays remain independent. Applying a
246
+ durable background within commented text must not create, resolve, move, or
247
+ delete a comment. The UI must keep the comment's active/pending state legible
248
+ when both visual layers overlap.
249
+ - Inline atom nodes, code blocks as block nodes, media, registry blocks, and
250
+ locked/source components are not recolored by this command.
251
+
252
+ ## Options considered
253
+
254
+ 1. Add TipTap's Highlight extension. Rejected: Content already has a persistent
255
+ inline background representation and serializer. A second mark would create
256
+ two meanings and require a migration or normalization rule.
257
+ 2. Reuse `CommentHighlight`. Rejected: it is intentionally a transient
258
+ decoration derived from comment state and cannot represent canonical document
259
+ formatting.
260
+ 3. Add arbitrary color picking in the first slice. Deferred: it expands
261
+ validation, accessibility, theme, and portability without matching the
262
+ observed bounded Notion palette. Foreground named colors are included because
263
+ Notion exposes them in the same `A` interaction and Content's existing mark
264
+ already represents them.
265
+ 4. Expose the existing `notionSpan.color` and `notionSpan.bgColor` attributes
266
+ through one selection-toolbar control. Recommended: it matches the observed
267
+ Notion interaction while remaining the thinnest path to durable canonical
268
+ content.
269
+
270
+ ## Product classification
271
+
272
+ - Lane: contract fulfillment / local UI exposure of existing substrate.
273
+ - Feature: `content.feature.durable-foundations`.
274
+ - Capability: `content.author.document-editor`.
275
+ - Existing promise: the visual editor preserves canonical document content
276
+ through edits, reloads, collaboration, comments, authorized agent changes,
277
+ and export.
278
+ - Record change: none expected. The feature fulfills the existing rich-document
279
+ promise without changing Page, Blocks-field, Comment, or Action identity.
280
+
281
+ ## Explicit non-goals
282
+
283
+ - Gradients, opacity, custom colors, eyedroppers, organization palettes, or
284
+ theme authoring. A one-item Recently used presentation is in scope only to the
285
+ extent required for Notion parity; persistent cross-document color history is
286
+ not introduced without an existing local primitive.
287
+ - Whole-block background/color controls or changes to existing imported block
288
+ colors.
289
+ - PDF/EPUB research annotations, annotation rails, source-revision anchors, or
290
+ promotion between formatting and annotations.
291
+ - Comment highlighting behavior, anchor repair, comment color choice, or comment
292
+ schema changes.
293
+ - Search-result, collaborator-presence, recent-edit, or temporary selection
294
+ highlights.
295
+ - New database schema, migration, Action, API route, server contract, source
296
+ adapter, Notion sync policy, shared toolkit abstraction, or provider work.
297
+ - A slash command, keyboard shortcut, mobile long-press redesign, or agent-only
298
+ tool.
299
+ - Retrofitting arbitrary HTML/CSS colors or rewriting existing canonical NFM.
300
+ - Claiming the entire Document editor Capability or Durable foundations Feature
301
+ complete.
302
+
303
+ ## Architecture grounding and fit
304
+
305
+ Architecture grounding is **required and grounded** because the visible control
306
+ touches the editor's canonical serialization seam and must not accidentally
307
+ create a competing rich-text representation.
308
+
309
+ ### Demonstrated caller and exact request
310
+
311
+ A signed-in Content writer selects text in a Page's visual document editor and
312
+ asks to give that exact selection a durable colored background, change it, or
313
+ clear it.
314
+
315
+ ### Existing primitives
316
+
317
+ - `BubbleToolbar.tsx`: non-empty selection entry point; existing inline mark
318
+ commands; selection-preserving shadcn popover behavior.
319
+ - `VisualEditor.tsx`: Content-specific editor extensions, collaboration, and the
320
+ canonical persistence calls to `docToNfm`/`nfmToDoc`.
321
+ - `NotionSpanMark` in `NotionExtensions.tsx`: existing inline mark with
322
+ `color`, `bgColor`, underline, link metadata, parsing, and rendering.
323
+ - `shared/nfm.ts`: canonical `_bg` token parsing and serialization for inline
324
+ backgrounds.
325
+ - `CommentHighlight.ts`: explicit counterexample proving comment highlights are
326
+ decorations, not persistent marks.
327
+ - `content.author.document-editor`: the accepted canonical-content and
328
+ collaboration promise for the visual document surface.
329
+
330
+ ### Ownership boundaries
331
+
332
+ - The bubble toolbar owns the human gesture and accessible color chooser.
333
+ - TipTap/ProseMirror owns selection and mark application.
334
+ - `notionSpan` owns inline foreground/background/underline fidelity.
335
+ - NFM owns canonical text serialization and parsing.
336
+ - `VisualEditor` plus the existing collaboration/save stack owns persistence,
337
+ reconciliation, and reload.
338
+ - Comments continue to own anchor-backed annotation overlays separately.
339
+
340
+ ### Legacy contracts that remain unchanged
341
+
342
+ - Bold, italic, strike, code, underline, link, comments, text-style conversion,
343
+ selection fill, and excluded-node behavior.
344
+ - Existing foreground and block colors imported from Notion.
345
+ - Canonical NFM spelling and round-trip behavior.
346
+ - Collaboration, save/reconcile, Action parity, access, history, export, and
347
+ source truth boundaries.
348
+
349
+ ### Smallest compatible delta
350
+
351
+ Expose one combined palette command in `BubbleToolbar` that independently
352
+ updates or clears `notionSpan.color` and `notionSpan.bgColor` for the retained
353
+ non-empty text selection, add only the minimal theme-aware presentation and
354
+ session-local recent choice required for the existing named tokens, and prove
355
+ mark composition plus NFM and real save/reload behavior. No new persistent
356
+ document or settings primitive is warranted.
357
+
358
+ ### Deferred capabilities and reversibility
359
+
360
+ Arbitrary palettes, block color UI, keyboard/slash entry, annotation workflows,
361
+ persisted color history, and shared editor generalization are deferred. The slice
362
+ is reversible because it is a bounded TypeScript/CSS/test exposure of an
363
+ existing mark and serialization contract, with no schema, data migration,
364
+ provider, or public protocol change.
365
+
366
+ ### Evidence classification
367
+
368
+ Direct evidence:
369
+
370
+ - Alice's delegated title and stable Bowerbird ID.
371
+ - Current `BubbleToolbar` shows only for non-empty compatible selections and
372
+ already applies inline marks.
373
+ - Current `NotionSpanMark` supports foreground `color` and `bgColor`, rendering
374
+ both on the same inline mark.
375
+ - Current NFM serializer/parser encodes inline foreground colors and named `_bg`
376
+ backgrounds.
377
+ - Current `CommentHighlight` states that comment ranges are decorations and do
378
+ not enter document serialization.
379
+ - The product catalog places this work in
380
+ `content.feature.durable-foundations` / `content.author.document-editor`.
381
+
382
+ Inference frozen by this shape:
383
+
384
+ - The task title's “colored text highlighting,” reconciled with Alice's Notion
385
+ parity request, means Notion's combined named text/background color control,
386
+ not research annotations.
387
+ - The nine existing Notion-compatible hue families plus Default are the intended
388
+ first palette because they match the observed menu and already have canonical
389
+ representation; exact theme mapping remains an implementation detail so long
390
+ as token identity, contrast, and accessibility are preserved.
391
+
392
+ Unresolved product judgment:
393
+
394
+ - None that changes the first slice. Notion's palette, ordering, combined `A`
395
+ entry point, toolbar composition, and selection retention are direct evidence.
396
+ Apply/replace, mixed-state, Default, collapsed-caret, close/selection-retention,
397
+ and keyboard behavior were not directly observable, so this shape freezes the
398
+ explicit Content behavior above and does not claim exhaustive Notion parity.
399
+
400
+ ## Risk strategy
401
+
402
+ Use `system-ready`, with no feature flag and no production-validation-after-
403
+ merge plan. This is a bounded, reversible editor-formatting exposure with no
404
+ schema or remote-provider mutation. Work may not call it complete until the
405
+ exact review artifact passes focused automated checks and the frozen real-
406
+ interface save/reload story. If the existing mark cannot preserve combined
407
+ attributes or public/export rendering requires a new representation, Work
408
+ returns to Shape rather than merging an unproved or parallel model.
409
+
410
+ ## Successful-user story acceptance plan
411
+
412
+ Story `content-inline-color-v2`:
413
+
414
+ > A signed-in Content writer selects a phrase, uses one Notion-like `A` menu to
415
+ > apply and independently change or default its named text and background
416
+ > colors, combines them with ordinary inline formatting and a comment, then
417
+ > saves and reloads without losing colors, marks, link identity, comment state,
418
+ > or surrounding content.
419
+
420
+ Required assertions:
421
+
422
+ 1. Selecting ordinary inline text opens the existing bubble toolbar and exposes
423
+ one accessible `A` color control; a collapsed caret and an excluded
424
+ atom/node do not expose or apply the command.
425
+ 2. The panel presents Recently used, Text color, and Background color in the
426
+ frozen order, with Default plus the same nine named hue families and an
427
+ accessible name for every swatch.
428
+ 3. Each named text or background color applies only to selected compatible text.
429
+ Replacement and section-specific Default change only that attribute; the
430
+ existing Clear format command remains broader.
431
+ 4. The chooser retains the selection while open and after applying, identifies
432
+ both active attributes for a uniform selection, and represents mixed color
433
+ without falsely claiming one active swatch. Recently used reflects the last
434
+ session-local named choice without adding persisted settings.
435
+ 5. Bold, italic, strike, code, underline, link destination, and the color
436
+ attribute not being changed survive apply, replace, and Default operations.
437
+ 6. A selection spanning compatible text across ordinary blocks applies the mark
438
+ to the text portions without recoloring excluded inline/block atoms or whole
439
+ blocks.
440
+ 7. Canonical NFM preserves existing named foreground and background-only
441
+ spellings, and uses an additive `bg_color="<name>_bg"` attribute only when a
442
+ foreground and background coexist; apply/change/default/combined-mark
443
+ fixtures are stable through
444
+ `docToNfm(nfmToDoc(value))`.
445
+ 8. The ordinary collaborative editor update/save path persists both colors;
446
+ reload reconstructs the same color attributes, text, and other marks without a
447
+ serialization error, silent coercion, duplicate span, or lost content.
448
+ 9. A comment overlapping colored text retains its anchor and active/pending
449
+ behavior, remains visually legible, and is neither created nor resolved by
450
+ highlight changes.
451
+ 10. Existing bubble-toolbar link, comment, formatting, text-style, selection-fill,
452
+ and excluded-node tests remain green; focused editor/NFM tests and typecheck,
453
+ formatter, relevant guards, and `git diff --check` pass.
454
+ 11. A current real-interface run on a task-owned local Content runtime and
455
+ disposable Page built from the exact review artifact exercises selection,
456
+ foreground/background apply, replace, Default, mixed-state, combined
457
+ bold/link/comment formatting, save, and reload. The report states whether
458
+ its evidence is independent or
459
+ same-context.
460
+
461
+ Acceptance policy:
462
+
463
+ - Modality: `real-interface`, supported by focused automated tests.
464
+ - Independence: `preferred`.
465
+ - Custody: `same-context-allowed`.
466
+ - Interface: a fresh browser session against a task-owned local Content runtime
467
+ and disposable Page built from the exact review artifact.
468
+ - Rationale: this is a reversible formatting interaction with no production
469
+ data or destructive action. Independent evidence adds confidence when
470
+ available, while same-context custody plus exact-artifact automation and
471
+ save/reload proof is proportionate to the risk.
472
+
473
+ ## Natural Work boundary
474
+
475
+ `/work` for this exact artifact may edit the smallest Content editor, style,
476
+ i18n, focused test, and user-facing changelog surfaces required to expose the
477
+ existing mark; provision and fully clean one declared task-local runtime,
478
+ database, account, and disposable Page; run focused automated and exact-artifact
479
+ real-interface acceptance; and prepare a review-ready pull request on the
480
+ current branch. Work stops before merge or deployment.
481
+
482
+ Any change to selected-text color meaning, palette class, collapsed-caret
483
+ semantics, shipping surface, canonical representation, acceptance story, or
484
+ risk strategy invalidates implementation authority and returns to Shape.
485
+
486
+ ## Work evidence ledger
487
+
488
+ - Exact implementation revision: working tree based on
489
+ `3132ab1bd8206dabd0b5cff92a0f5c5bb56bd4e8`, ledger
490
+ `content-inline-color-work-v1-approved-dual-color`.
491
+ - Automated proof: 175 focused editor/NFM tests passed; Content typecheck exited
492
+ 0; all 55 repository guards passed; all 30 Content product-impact tests passed.
493
+ - Successful-user-story proof: real Chromium created a disposable Content Page,
494
+ selected text, used the rendered floating toolbar, and restored bold, red text,
495
+ and yellow background after reload. SQLite read-back showed `<span
496
+ color="red" bg_color="yellow_bg">**Highlighted text**</span> keeps bold and
497
+ both colors.`
498
+ - Test-resource custody: `content-color-local-acceptance-69a7e1cf` was created,
499
+ exercised, and cleaned; the declared path and port were independently absent
500
+ afterward.
501
+ - Independent technical review: Cartographer, Terra Explorer, exact manifest
502
+ above, triggered by canonical persistence/serialization risk. Initial finding:
503
+ one P2 stale-contract ambiguity in this artifact; follow-up count 1. Final
504
+ disposition: finding resolved, no blocking implementation or artifact finding.
505
+ - Repository review repair: Builder's exact-head review found that an atom-only
506
+ selection exposed an inert color control. The control now appears only when
507
+ the selection contains compatible text, with a focused regression test. Its
508
+ incremental review then found the same inert state for fenced code-block text,
509
+ whose parent schema rejects marks. The predicate now checks whether the text's
510
+ parent permits `notionSpan`, with a focused code-block regression test. The
511
+ following review found active swatch state also counted unmarkable code text;
512
+ state resolution now uses the same parent-mark eligibility boundary, with a
513
+ mixed paragraph/code-block regression test. The next review found that the
514
+ mutation callback still relied on the schema to reject unmarkable text; it now
515
+ applies the same explicit eligibility predicate, with a mixed-selection write
516
+ regression test. After rebase, review confirmed those repairs and found that
517
+ StarterKit's exclusive inline-code mark prevented the frozen code/color
518
+ composition behavior. Content now replaces that mark with an extension of the
519
+ same TipTap primitive whose exclusion set permits `notionSpan`, with a focused
520
+ coexistence regression test and an NFM serialization regression. A new
521
+ exact-head repository review and CI run are required after push.
522
+ - Changelog: the template's `agent-native changelog add` command reported that
523
+ changelog capture is disabled, so no manual entry was created.
524
+
525
+ ## Lifecycle authority envelope
526
+
527
+ ```yaml
528
+ authoritySchemaVersion: 3
529
+ stage: land
530
+ authority-source: Alice approved option 3 and invoked $work on 2026-08-18, then invoked $land on 2026-08-19 with an explicit do-not-merge constraint; Land returned internally to the matching Work envelope for review and CI repair.
531
+ authorized-scope:
532
+ repositories:
533
+ - BuilderIO/agent-native
534
+ product-surfaces:
535
+ - Content visual document editor inline formatting
536
+ outcome: Freeze a Notion-like combined named text and background color interaction for selected text in Content's visual document editor.
537
+ allowed-mutations:
538
+ - artifact-write
539
+ - branch
540
+ - commit
541
+ - push
542
+ - pull-request
543
+ - ephemeral-test-resource
544
+ write-targets:
545
+ artifacts:
546
+ - templates/content/docs/solutions/2026-08-18-colored-text-highlighting-shape.md
547
+ test-resources:
548
+ - id: content-color-local-acceptance-69a7e1cf
549
+ kind: database
550
+ surface: Local Content runtime on 127.0.0.1:4179 backed only by /tmp/codex-content-color-69a7e1cf/content.db
551
+ ownership-marker: codex-content-color-69a7e1cf
552
+ baseline: /tmp/codex-content-color-69a7e1cf was absent and TCP port 4179 had no listener at 2026-08-18T18:54:43Z
553
+ allowed-actions:
554
+ - create
555
+ - update
556
+ - exercise
557
+ - delete
558
+ cleanup-trigger: after exact-artifact real-interface acceptance
559
+ cleanup-method: Stop the task-owned server process then remove only /tmp/codex-content-color-69a7e1cf and verify the path and port are absent.
560
+ cleanup-proof: At 2026-08-18T19:06:57Z an independent check found /tmp/codex-content-color-69a7e1cf absent and no TCP listener on port 4179.
561
+ shared-impact: none
562
+ isolation: local-runtime
563
+ ownership: task-created
564
+ production-data: false
565
+ customer-data: false
566
+ cost: none
567
+ boundary-evidence:
568
+ - explicit absent path check at 2026-08-18T18:54:43Z
569
+ - explicit no-listener check for 127.0.0.1:4179 at 2026-08-18T18:54:43Z
570
+ - Chromium created a disposable Page through the rendered Content UI, selected text, applied bold plus red text and yellow background through the floating toolbar, and restored all three after reload.
571
+ - the persisted documents.content value was <span color="red" bg_color="yellow_bg">**Highlighted text**</span> keeps bold and both colors.
572
+ - explicit absent path and no-listener checks passed at 2026-08-18T19:06:57Z
573
+ max-lifetime-minutes: 240
574
+ declared-at: 2026-08-18T18:54:43Z
575
+ expires-at: 2026-08-18T22:54:43Z
576
+ status: cleaned
577
+ phase: work
578
+ governing-artifact:
579
+ path: templates/content/docs/solutions/2026-08-18-colored-text-highlighting-shape.md
580
+ revision: work-v1-approved-dual-color
581
+ architecture-fingerprint:
582
+ outcome: Match Notion's combined selected-text color interaction while persisting named foreground and background colors through Content's existing notionSpan mark.
583
+ shipping-surfaces:
584
+ - id: content-inline-color
585
+ repository: BuilderIO/agent-native
586
+ product-surface: Content visual document editor selection bubble toolbar and canonical rich-text body
587
+ constituency: signed-in Content writers
588
+ durable-destination: public Content template editor behavior in BuilderIO/agent-native
589
+ integration-action: merge
590
+ governing-architecture: The selection bubble toolbar independently updates the existing notionSpan.color and notionSpan.bgColor attributes; NFM preserves established one-color spellings and additively serializes an explicit background attribute when both colors coexist; ProseMirror selection and VisualEditor collaboration/save remain the sole owners of document formatting and durability, with no parallel mark or persisted recent-color setting.
591
+ acceptance-story:
592
+ id: content-inline-color-v2
593
+ summary: A signed-in writer uses one Notion-like A menu to independently apply change and default named text and background colors on selected text then saves and reloads without losing other marks canonical content or independent comment state.
594
+ required-assertions:
595
+ - non-empty compatible text selection exposes one accessible A color control while collapsed and excluded selections do not
596
+ - panel order is Recently used then Text color then Background color with Default plus nine named hue families in both palettes
597
+ - each named text or background color applies only to selected compatible text and replacement or section Default changes only that attribute
598
+ - selection is retained while open and after apply and uniform versus mixed color state is represented truthfully
599
+ - Recently used is session-local and adds no persisted setting
600
+ - existing inline marks link identity and the unchanged color attribute survive apply replace and Default
601
+ - cross-block compatible text works without recoloring excluded atoms or whole blocks
602
+ - canonical NFM uses existing named foreground and _bg span serialization and round-trips stably
603
+ - established foreground-only and background-only NFM fixtures remain stable while a dual-color fixture round-trips both attributes without silent loss
604
+ - collaborative save and reload preserve both color attributes text other marks and content without silent failure
605
+ - overlapping comment anchors and states remain independent and legible
606
+ - focused regressions existing toolbar tests typecheck formatter relevant guards and diff check pass
607
+ - exact-review-artifact real-interface selection panel order apply replace Default mixed state combination save and reload pass on a disposable local Page
608
+ acceptance-policy:
609
+ modality: real-interface
610
+ independence: preferred
611
+ custody: same-context-allowed
612
+ interface: Fresh browser session against a task-owned local Content runtime and disposable Page built from the exact review artifact.
613
+ rationale: Reversible editor formatting needs current interaction and durability proof; independent evidence is useful but same-context custody is proportionate when exact-artifact automated and save-reload evidence also pass.
614
+ risk-strategy:
615
+ kind: system-ready
616
+ production-validation-after-merge: false
617
+ architecture-grounding:
618
+ applicability: required
619
+ reason: The UI gesture touches the canonical rich-text mark and NFM serialization seam, so Shape must prove it reuses rather than duplicates the existing representation.
620
+ status: grounded
621
+ demonstrated-callers:
622
+ - A signed-in Content writer selects inline text and asks for Notion's combined named text and background color interaction.
623
+ existing-primitives:
624
+ - BubbleToolbar non-empty compatible selection entry point and inline mark commands
625
+ - NotionSpanMark color bgColor underline parse and render contract
626
+ - NFM named _bg inline serialization and parsing
627
+ - VisualEditor canonical collaboration save and reload path
628
+ - CommentHighlight transient decoration boundary
629
+ ownership-boundaries:
630
+ - BubbleToolbar owns the accessible human gesture
631
+ - TipTap and ProseMirror own selection and mark operations
632
+ - notionSpan owns inline color background and underline fidelity
633
+ - NFM owns canonical serialization and parsing
634
+ - VisualEditor and the collaboration stack own persistence and reconciliation
635
+ - Comments own anchor-backed overlays independently
636
+ legacy-contracts:
637
+ - existing inline marks links comments text styles selection fill and excluded-node behavior
638
+ - imported foreground and block colors
639
+ - canonical NFM spelling collaboration save Action access history export and source-truth boundaries
640
+ shared-vocabulary:
641
+ - color means the combined selected-text foreground and background interaction in this slice
642
+ - highlight means the background-color half of that interaction
643
+ - comment highlight means a transient SQL-anchor-derived decoration and remains separate
644
+ - named color means Default or one of the nine observed Notion-compatible hue families
645
+ smallest-compatible-delta: Expose independent apply replace and Default operations for existing notionSpan.color and notionSpan.bgColor in BubbleToolbar, add the observed accessible combined panel plus session-local recent choice, extend NFM additively only for simultaneous colors, and prove backward compatibility plus canonical save and reload.
646
+ deferred-capabilities:
647
+ - arbitrary custom or organization palettes
648
+ - collapsed-caret stored-mark behavior
649
+ - block color controls
650
+ - keyboard and slash command entry
651
+ - research annotation workflows
652
+ - shared editor toolkit generalization
653
+ reversibility: Bounded TypeScript CSS i18n changelog and test changes over an existing mark with no schema migration provider public protocol or data rewrite.
654
+ direct-evidence:
655
+ - Alice delegated title and Bowerbird ID in source thread 01a00f83-f02d-7b42-9a31-ff18c5a5eded
656
+ - current BubbleToolbar VisualEditor NotionSpanMark NFM and CommentHighlight source
657
+ - content.feature.durable-foundations and content.author.document-editor product records
658
+ - logged-in Notion desktop selection toolbar and combined A panel on disposable page 3c0ccf6483ce808b8198d1a8ba36e519
659
+ inferences:
660
+ - unobserved swatch transitions should follow the frozen immediate apply independent replacement section Default mixed-state and non-collapsed selection semantics
661
+ - Recently used should be session-local because no existing persistent preference primitive is needed for the demonstrated caller
662
+ unresolved-owner-questions: []
663
+ delegation-ceiling:
664
+ - artifact-write
665
+ product-boundary-gates:
666
+ agent-native-public-constituency: Any signed-in Content writer can use this public template behavior without Alice's vault machines credentials or private orchestration; it belongs in the public repository because it exposes an existing canonical public editor representation.
667
+ bowerbird-product-boundary: Bowerbird supplies only the durable private task identity for this Shape. The shipping product behavior is Content; the feature adds no Bowerbird deterministic state validation agent process retry deployment or scheduling policy.
668
+ acceptance-state:
669
+ status: pending
670
+ summary: The accepted behavior and same-context real-interface story remain satisfied, but exact-head repository review and CI are pending after the inert-control repairs; merge is explicitly prohibited in this Land invocation.
671
+ blockers:
672
+ - exact-head repository review pending after repair
673
+ - exact-head CI pending after repair
674
+ - merge explicitly prohibited by Alice for this Land invocation
675
+ last-land-packet: null
676
+ material-change:
677
+ banner: resolved by Alice approval of option 3 on 2026-08-18
678
+ changed-fields:
679
+ - governing architecture
680
+ - acceptance story
681
+ old-fingerprint: Existing notionSpan exposure with unchanged NFM serialization and simultaneous foreground/background durability.
682
+ proposed-fingerprint: Existing notionSpan exposure plus backward-compatible dual-color NFM serialization and compatibility assertions.
683
+ replacement-acceptance-story: approved; additive dual-color NFM compatibility assertions are frozen.
684
+ task-attention: autonomous
685
+ ledger-revision: content-inline-color-work-v1-approved-dual-color
686
+ status: active
687
+ ```
688
+
689
+ ## Exact handoff
690
+
691
+ Work is active for the approved option 3 replacement fingerprint. Terminal
692
+ integration remains `/land` after Work produces complete exact-artifact
693
+ evidence.