@agent-native/core 0.147.0 → 0.148.0

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 (172) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/frontend-design/SKILL.md +115 -68
  3. package/corpus/templates/analytics/DEVELOPING.md +50 -3
  4. package/corpus/templates/analytics/actions/purge-first-party-analytics-postgres.ts +190 -0
  5. package/corpus/templates/analytics/app/i18n/index.ts +14 -29
  6. package/corpus/templates/analytics/app/i18n-data.ts +10 -10
  7. package/corpus/templates/analytics/app/pages/Settings.tsx +5 -21
  8. package/corpus/templates/analytics/app/pages/sessions/SessionsPage.tsx +1 -3
  9. package/corpus/templates/analytics/scripts/first-party-analytics-bigquery-backfill.ts +197 -18
  10. package/corpus/templates/analytics/server/db/schema.ts +23 -0
  11. package/corpus/templates/analytics/server/handlers/first-party-analytics.ts +3 -1
  12. package/corpus/templates/analytics/server/jobs/analytics-bigquery-backfill.ts +1 -1
  13. package/corpus/templates/analytics/server/lib/first-party-analytics-backend.ts +113 -13
  14. package/corpus/templates/analytics/server/lib/first-party-analytics-purge.ts +140 -0
  15. package/corpus/templates/analytics/server/lib/first-party-analytics-volume.ts +207 -0
  16. package/corpus/templates/analytics/server/lib/first-party-analytics.ts +40 -9
  17. package/corpus/templates/analytics/server/lib/gcloud.ts +148 -20
  18. package/corpus/templates/analytics/server/plugins/db.ts +42 -0
  19. package/corpus/templates/assets/.agents/skills/frontend-design/SKILL.md +115 -68
  20. package/corpus/templates/assets/app/i18n/index.ts +14 -29
  21. package/corpus/templates/brain/.agents/skills/frontend-design/SKILL.md +115 -68
  22. package/corpus/templates/brain/app/i18n/index.ts +14 -29
  23. package/corpus/templates/calendar/.agents/skills/frontend-design/SKILL.md +115 -68
  24. package/corpus/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
  25. package/corpus/templates/chat/app/i18n/index.ts +14 -29
  26. package/corpus/templates/clips/.agents/skills/frontend-design/SKILL.md +115 -68
  27. package/corpus/templates/clips/app/components/player/transcript-panel.tsx +2 -7
  28. package/corpus/templates/clips/app/components/recorder/storage-setup-card.tsx +18 -13
  29. package/corpus/templates/clips/app/components/settings/ai-setup-section.tsx +87 -370
  30. package/corpus/templates/clips/app/components/settings/slack-section.tsx +59 -101
  31. package/corpus/templates/clips/app/components/settings/video-storage-section.tsx +136 -213
  32. package/corpus/templates/clips/app/i18n/en-US.ts +11 -8
  33. package/corpus/templates/clips/desktop/src/app.tsx +1 -1
  34. package/corpus/templates/content/.agents/skills/frontend-design/SKILL.md +115 -68
  35. package/corpus/templates/content/app/i18n/index.ts +14 -29
  36. package/corpus/templates/crm/app/i18n/index.ts +14 -29
  37. package/corpus/templates/design/.agents/skills/frontend-design/SKILL.md +115 -68
  38. package/corpus/templates/design/actions/analyze-brand-assets.ts +15 -15
  39. package/corpus/templates/design/actions/import-code.ts +2 -43
  40. package/corpus/templates/design/app/i18n/index.ts +14 -29
  41. package/corpus/templates/dispatch/.agents/skills/frontend-design/SKILL.md +115 -68
  42. package/corpus/templates/dispatch/app/i18n-data.ts +1 -1
  43. package/corpus/templates/factory/.agents/skills/frontend-design/SKILL.md +115 -68
  44. package/corpus/templates/factory/AGENTS.md +40 -49
  45. package/corpus/templates/factory/actions/babysit-agent-native-pull-request.ts +66 -0
  46. package/corpus/templates/factory/actions/evaluate-triage-item.ts +37 -0
  47. package/corpus/templates/factory/actions/get-slack-feedback-context.ts +20 -0
  48. package/corpus/templates/factory/actions/get-triage-item.ts +25 -4
  49. package/corpus/templates/factory/actions/govern-agent-native-pull-request.ts +55 -0
  50. package/corpus/templates/factory/actions/ingest-github-observation.ts +21 -0
  51. package/corpus/templates/factory/actions/list-factory-audit.ts +118 -0
  52. package/corpus/templates/factory/actions/list-factory-automations.ts +2 -1
  53. package/corpus/templates/factory/actions/list-triage-items.ts +24 -2
  54. package/corpus/templates/factory/actions/poll-github-sources.ts +60 -0
  55. package/corpus/templates/factory/actions/poll-sentry-errors.ts +39 -0
  56. package/corpus/templates/factory/actions/poll-slack-channel.ts +45 -1
  57. package/corpus/templates/factory/actions/run-factory-automation.ts +1 -1
  58. package/corpus/templates/factory/actions/save-factory-automation.ts +2 -2
  59. package/corpus/templates/factory/actions/start-builder-for-item.ts +51 -0
  60. package/corpus/templates/factory/app/components/factory/FactoryAuditView.tsx +685 -0
  61. package/corpus/templates/factory/app/hooks/use-navigation-state.ts +6 -0
  62. package/corpus/templates/factory/app/i18n/en-US.ts +25 -0
  63. package/corpus/templates/factory/app/routes/factory.tsx +95 -42
  64. package/corpus/templates/factory/server/db/schema.ts +37 -0
  65. package/corpus/templates/factory/server/lib/require-factory-automation.ts +5 -1
  66. package/corpus/templates/factory/server/plugins/factory-migrations.ts +29 -0
  67. package/corpus/templates/factory/server/triage/audit.ts +79 -0
  68. package/corpus/templates/forms/.agents/skills/frontend-design/SKILL.md +115 -68
  69. package/corpus/templates/forms/app/i18n/index.ts +14 -29
  70. package/corpus/templates/macros/.agents/skills/frontend-design/SKILL.md +115 -68
  71. package/corpus/templates/macros/app/i18n/index.ts +14 -29
  72. package/corpus/templates/mail/.agents/skills/frontend-design/SKILL.md +115 -68
  73. package/corpus/templates/mail/app/i18n/index.ts +14 -29
  74. package/corpus/templates/plan/.agents/skills/frontend-design/SKILL.md +115 -68
  75. package/corpus/templates/plan/app/components/plan/wireframe/Wireframe.tsx +7 -7
  76. package/corpus/templates/plan/app/i18n/index.ts +14 -29
  77. package/corpus/templates/slides/.agents/skills/frontend-design/SKILL.md +115 -68
  78. package/corpus/templates/slides/actions/analyze-brand-assets.ts +15 -15
  79. package/corpus/templates/slides/actions/import-code.ts +2 -43
  80. package/corpus/templates/slides/app/i18n/index.ts +14 -29
  81. package/corpus/templates/slides/server/routes/api/preview-images.get.ts +4 -1
  82. package/corpus/templates/tasks/.agents/skills/frontend-design/SKILL.md +115 -68
  83. package/corpus/templates/tasks/app/components/layout/HeaderActions.tsx +1 -84
  84. package/corpus/templates/tasks/app/hooks/use-mobile.tsx +1 -21
  85. package/corpus/templates/tasks/app/i18n/index.ts +14 -29
  86. package/dist/agent/engine/ai-sdk-engine.js +2 -1
  87. package/dist/agent/engine/openai-compatible-endpoint.d.ts +2 -0
  88. package/dist/agent/engine/openai-compatible-endpoint.js +5 -1
  89. package/dist/agent/engine/provider-endpoint-validation.d.ts +9 -0
  90. package/dist/agent/engine/provider-endpoint-validation.js +26 -0
  91. package/dist/agent/engine/provider-env-vars.d.ts +1 -1
  92. package/dist/agent/engine/provider-env-vars.js +1 -1
  93. package/dist/agent/engine/registry.d.ts +8 -6
  94. package/dist/agent/engine/registry.js +37 -24
  95. package/dist/agent/tool-search.d.ts +1 -0
  96. package/dist/agent/tool-search.js +17 -1
  97. package/dist/automations/service.js +4 -10
  98. package/dist/brand-kit/brand-signals.d.ts +13 -0
  99. package/dist/brand-kit/brand-signals.js +15 -0
  100. package/dist/brand-kit/index.d.ts +2 -2
  101. package/dist/brand-kit/index.js +1 -1
  102. package/dist/cli/plan-blocks.d.ts +3 -18
  103. package/dist/cli/plan-blocks.js +2 -95
  104. package/dist/cli/plan-publish-store.d.ts +2 -61
  105. package/dist/cli/plan-publish-store.js +2 -127
  106. package/dist/cli/skills-content/connection.d.ts +1 -1
  107. package/dist/cli/skills-content/connection.js +1 -52
  108. package/dist/cli/skills-content/visual-recap-skill.d.ts +1 -1
  109. package/dist/cli/skills-content/visual-recap-skill.js +1 -553
  110. package/dist/client/agent-engine-key.d.ts +14 -4
  111. package/dist/client/agent-engine-key.js +51 -5
  112. package/dist/client/agent-provider-catalog.d.ts +20 -0
  113. package/dist/client/agent-provider-catalog.js +100 -0
  114. package/dist/client/blocks/index.d.ts +1 -0
  115. package/dist/client/blocks/index.js +1 -0
  116. package/dist/client/chat/run-recovery.js +4 -48
  117. package/dist/client/chat-first.js +4 -3
  118. package/dist/client/i18n.d.ts +14 -0
  119. package/dist/client/i18n.js +18 -0
  120. package/dist/client/settings/ProviderSetupForm.d.ts +21 -0
  121. package/dist/client/settings/ProviderSetupForm.js +145 -0
  122. package/dist/client/settings/SettingsPanel.js +52 -49
  123. package/dist/client/settings/index.d.ts +2 -0
  124. package/dist/client/settings/index.js +2 -0
  125. package/dist/coding-tools/run-code.d.ts +5 -0
  126. package/dist/coding-tools/run-code.js +196 -36
  127. package/dist/coding-tools/tool-orchestration.d.ts +10 -0
  128. package/dist/coding-tools/tool-orchestration.js +107 -0
  129. package/dist/collab/awareness.d.ts +2 -2
  130. package/dist/jobs/frontmatter.d.ts +9 -0
  131. package/dist/jobs/frontmatter.js +16 -0
  132. package/dist/jobs/scheduler.js +8 -8
  133. package/dist/jobs/tools.d.ts +1 -1
  134. package/dist/jobs/tools.js +2 -7
  135. package/dist/localization/default-messages.d.ts +20 -0
  136. package/dist/localization/default-messages.js +25 -5
  137. package/dist/observability/routes.d.ts +3 -3
  138. package/dist/onboarding/app-profile.js +1 -1
  139. package/dist/progress/routes.d.ts +1 -1
  140. package/dist/provider-api/actions/custom-provider-registration.d.ts +8 -8
  141. package/dist/provider-api/actions/provider-api.d.ts +11 -11
  142. package/dist/resources/handlers.d.ts +1 -1
  143. package/dist/scripts/agent-engines/test-agent-engine.js +34 -10
  144. package/dist/secrets/routes.d.ts +9 -9
  145. package/dist/server/agent-chat/run-code-tools.d.ts +1 -1
  146. package/dist/server/agent-chat/run-code-tools.js +3 -1
  147. package/dist/server/agent-chat-plugin.js +6 -6
  148. package/dist/server/agent-engine-api-key-route.d.ts +1 -1
  149. package/dist/server/agent-engine-api-key-route.js +43 -12
  150. package/dist/server/agents-bundle.js +2 -1
  151. package/dist/server/auth.js +21 -5
  152. package/dist/server/credential-provider.js +1 -0
  153. package/dist/server/design-token-utils.d.ts +18 -0
  154. package/dist/server/design-token-utils.js +31 -0
  155. package/dist/server/onboarding-html.js +22 -2
  156. package/dist/server/realtime-token.d.ts +1 -1
  157. package/dist/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
  158. package/dist/templates/chat/app/i18n/index.ts +14 -29
  159. package/dist/templates/default/.agents/skills/frontend-design/SKILL.md +115 -68
  160. package/dist/templates/default/app/i18n/index.ts +14 -29
  161. package/dist/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +22 -9
  162. package/dist/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +115 -68
  163. package/dist/triggers/dispatcher.js +1 -8
  164. package/docs/content/environment-variables.mdx +39 -38
  165. package/package.json +4 -4
  166. package/src/templates/chat/.agents/skills/frontend-design/SKILL.md +115 -68
  167. package/src/templates/chat/app/i18n/index.ts +14 -29
  168. package/src/templates/default/.agents/skills/frontend-design/SKILL.md +115 -68
  169. package/src/templates/default/app/i18n/index.ts +14 -29
  170. package/src/templates/workspace-core/.agents/skills/address-feedback/SKILL.md +22 -9
  171. package/src/templates/workspace-core/.agents/skills/frontend-design/SKILL.md +115 -68
  172. package/corpus/templates/plan/app/components/plan/wireframe/sanitize-html.ts +0 -343
@@ -2,16 +2,19 @@
2
2
  name: frontend-design
3
3
  description: >-
4
4
  Sets the visual direction for a new or redesigned surface, with production
5
- quality that avoids generic AI aesthetics. Use when building a new page,
6
- app, or marketing surface, defining visual identity, or doing a design pass
7
- ("make this look good"). Do not load it for routine UI edits: adding a field
8
- to an existing form, fixing spacing, wiring a button, or changing copy.
5
+ quality that avoids generic AI aesthetics. Use when building, redesigning, or
6
+ cleaning up any user-facing UI, including screenshot-driven feedback, copy or
7
+ density reduction, settings, control placement, or a design pass ("make this
8
+ look good"). Do not load it only for purely mechanical wiring or formatting.
9
9
  scope: dev
10
10
  license: Complete terms in LICENSE.txt
11
11
  source: https://github.com/anthropics/skills/blob/main/skills/frontend-design/SKILL.md
12
12
  local-changes: >-
13
- Description narrowed and Verification rescoped deliberately; an upstream sync
14
- must not restore the broad auto-load triggers or screenshot-everything step.
13
+ Description deliberately widened on 2026-08-09 because the previous narrow
14
+ trigger excluded routine UI edits, including screenshot-driven cleanup, copy
15
+ and density changes, settings, and control placement. An upstream sync must
16
+ not re-narrow it. Verification remains deliberately rescoped; an upstream
17
+ sync must not restore screenshot-everything or broad browser-automation steps.
15
18
  metadata:
16
19
  internal: true
17
20
  ---
@@ -26,10 +29,12 @@ The user may ask for a component, page, full app, dashboard, marketing surface,
26
29
 
27
30
  Before coding, decide:
28
31
 
29
- - **Purpose**: What workflow does this surface make easier? What is the primary action?
32
+ - **Purpose**: What workflow does this surface make easier? What does the user
33
+ need to understand, decide, or do next?
30
34
  - **Audience**: Who will use it repeatedly, and what should feel fast, calm, playful, premium, editorial, technical, or utilitarian?
31
35
  - **Tone**: Choose a concrete aesthetic direction: refined minimal, dense operations console, editorial, playful, industrial, warm handmade, high-contrast data tool, etc.
32
- - **Information hierarchy**: What must be visible in the first five seconds, and what should be progressively disclosed?
36
+ - **Information hierarchy**: What must be visible to orient and act, and what
37
+ can wait until context or intent makes it relevant?
33
38
  - **Differentiation**: What makes this feel designed for this exact domain?
34
39
 
35
40
  Then implement working code that is cohesive, accessible, responsive, and polished in small details: typography, spacing, copy, motion, empty states, loading states, focus states, and error states.
@@ -50,46 +55,80 @@ before selecting its accent family. Shared behavior and semantic token names
50
55
  should stay consistent; palette, density, composition, type contrast, and
51
56
  shape language should not be identical by default.
52
57
 
53
- ## Minimalism And Progressive Disclosure
54
-
55
- Default to Apple/Linear-level restraint: make the primary workflow obvious, then remove everything that does not help that workflow right now. A polished UI often has fewer visible controls, fewer borders, fewer labels, and fewer explanatory surfaces than the first reasonable implementation.
56
-
57
- ### Progressive Disclosure Is A Design Requirement
58
-
59
- Treat an all-at-once interface as a defect to fix during design, not as a
60
- styling preference. Before coding, inventory every piece of content and action
61
- on the surface, then assign each one to the smallest useful visibility level:
62
-
63
- 1. **Immediate** — the page title, current state, one primary action, and the
64
- compact context needed to choose what to do next.
65
- 2. **Expanded** — the details needed for the selected item or active workflow.
66
- 3. **On demand** — advanced settings, diagnostics, credentials, metadata,
67
- destructive actions, documentation, and rarely used tools.
68
-
69
- Use single-select accordions or simple disclosure rows for sibling panels when
70
- the user is choosing one item at a time. Inside an expanded panel, keep another
71
- layer for independent concerns instead of dumping every form, explanation, and
72
- secondary action into the first reveal. Prefer one flat panel with alignment,
73
- dividers, and whitespace over nested cards; provider or product icons should
74
- not receive decorative borders or containers unless the container communicates
75
- state or interaction. A collapsed row should still show the item name, status,
76
- and a concise summary so the user can scan the whole surface without opening
77
- everything.
78
-
79
- Before shipping, ask: “What can disappear until the user asks for it?” Then
80
- verify collapsed, expanded, loading, empty, error, and narrow-width states.
81
- If the first viewport contains multiple forms, repeated explanatory copy,
82
- documentation links, and controls for unrelated tasks, the surface has not
83
- passed this requirement yet.
84
-
85
- - **Start by subtracting**: Before adding a visible control, banner, toolbar row, card, or explanatory block, ask what can be removed, merged, renamed, or moved into an existing affordance.
86
- - **One primary action**: Each surface should have one dominant next action. Secondary actions belong in menus, popovers, command palettes, disclosure rows, or contextual hover/focus states unless they are used constantly.
87
- - **Progressively disclose rare work**: Advanced options, diagnostics, metadata, settings, import/export, destructive actions, and inspection tools should stay tucked away until requested. Prefer small icon triggers with tooltips, popovers, drawers, or detail panels over permanent chrome.
88
- - **Keep chrome quiet**: Avoid new always-visible bars, badges, callouts, helper text, and counters unless they prevent mistakes or are central to repeated use. Status can often be a dot, ring, muted count, or tooltip.
89
- - **Favor content over containers**: Do not wrap every section in a card. Use whitespace, alignment, typography, dividers, and full-width bands before adding boxes.
90
- - **Design for repeated use**: Production app UI should feel calm after the hundredth use. If a control shouts, animates, explains itself, or occupies a full row for an occasional action, hide or compress it.
91
- - **Make absence intentional**: Empty states should be sparse and action-oriented. Do not fill blank space with marketing copy, decorative art, or lists of features just because the screen feels empty.
92
- - **Use familiar primitives**: Icon buttons need clear tooltips. Menus, popovers, tabs, switches, and segmented controls should carry complexity instead of exposing every option at once.
58
+ ## High-Signal Minimalism And Progressive Disclosure
59
+
60
+ Minimalism means fewer competing kinds of UI, not less useful information. Keep
61
+ surfaces dense and scannable: reduce redundant prose, decorative containers,
62
+ borders, badges, accent colors, and persistent controls before removing content
63
+ that helps the user orient, compare, decide, or recover. The reference class is
64
+ calm productivity software such as ChatGPT/Codex, Linear, and Vercel, not empty
65
+ whitespace.
66
+
67
+ ### Product UX Philosophy
68
+
69
+ Apply these principles as binding decision rules:
70
+
71
+ - **Purpose over presence**: Every visible element must support orientation,
72
+ state comprehension, a decision, an action, or recovery. Before adding one,
73
+ name which; if it supports none or duplicates another element, remove or
74
+ defer it.
75
+ - **Clarity over cleverness**: Use plain language, familiar patterns, explicit
76
+ hierarchy, and visible state. Do not make decoration or invented terminology
77
+ carry meaning. Preserve the labels, hit targets, focus states, and recovery
78
+ paths required for accessible use.
79
+ - **Simple first, powerful on demand**: Keep the current task and state in the
80
+ default presentation. Put advanced, rare, diagnostic, and secondary work
81
+ behind contextual disclosure, menus, or Settings. Do not turn a discoverability
82
+ concern into permanent chrome, and do not hide information needed for the
83
+ current decision.
84
+ - **Hierarchy over chrome**: Use typography, spacing, alignment, and restrained
85
+ emphasis to organize information. Treat prose, controls, borders, cards,
86
+ badges, and accent colors as a competition budget: reduce competing kinds of
87
+ elements before reducing useful information. When a surface has one clear
88
+ next decision, give it dominant emphasis and move secondary actions out of
89
+ the default path. Do not wrap every section in a card or add borders for
90
+ grouping alone; use spacing, alignment, typography, or dividers first. A
91
+ container must communicate grouping, state, or interaction.
92
+ - **Coherence over novelty**: Reuse the product's primitives, interaction
93
+ patterns, and language. When given a screenshot or reference product, match
94
+ its underlying hierarchy, density, and behavior; do not copy decoration or
95
+ introduce a second visual language without a product reason.
96
+ - **Quiet continuity**: Feedback must be immediate, contextual, and honest.
97
+ Preserve the user's place and layout, make loading, empty, and error states
98
+ understandable, and use motion only to explain a change.
99
+ - **Respect repeated use**: Optimize for the hundredth use, not the first
100
+ impression. If a control repeats an explanation, occupies persistent space
101
+ for an occasional task, or turns routine work into ceremony, remove it or
102
+ move it to the contextual surface that owns it.
103
+
104
+ ### Progressive Disclosure And Information Timing
105
+
106
+ Expose information and controls according to relevance, frequency, and
107
+ consequence. Before coding, inventory the content and actions and assign them to
108
+ the smallest useful visibility layer:
109
+
110
+ 1. **Orient and act**: location, current state, and context needed for the next
111
+ meaningful choice.
112
+ 2. **Support active work**: details and controls for the selected item or
113
+ current workflow.
114
+ 3. **Available on demand**: advanced settings, diagnostics, credentials,
115
+ metadata, destructive actions, documentation, and rare tools.
116
+
117
+ Use a disclosure pattern that matches the task. Keep independent concerns easy
118
+ to scan inside an expanded area instead of dumping every form, explanation,
119
+ and secondary action into the first reveal. A collapsed row must retain its
120
+ label and essential state; remove explanatory subtext unless it changes the
121
+ next decision. For configuration with a known current state, show that state
122
+ first and expose editing contextually instead of defaulting to a full form.
123
+
124
+ Before shipping, verify collapsed, expanded, loading, empty, error, and
125
+ narrow-width states. The default state fails review when its first viewport
126
+ contains multiple unrelated forms, repeated explanatory copy, documentation
127
+ links, or controls for unrelated tasks. It also fails when useful information
128
+ has been replaced with empty whitespace or extra clicks solely to look minimal.
129
+ The default state passes when users can identify their location, current state,
130
+ current task, and relevant next choice without reading documentation, while
131
+ the useful information remains dense and scannable.
93
132
 
94
133
  ## Aesthetic Guidelines
95
134
 
@@ -166,26 +205,28 @@ passed this requirement yet.
166
205
 
167
206
  ### Product Surface Review
168
207
 
169
- Before shipping a new app or a substantial redesign, review the first viewport
170
- as an operator would use it repeatedly:
171
-
172
- - Show one clear job title, the current state, and one primary next action.
173
- - Put optional inputs, provider choices, diagnostics, long explanations, and
174
- secondary actions behind a disclosure, a later step, a menu, or the agent
175
- sidebar. Do not put multiple unrelated forms side by side by default.
176
- - Prefer a short step flow or a focused page per domain job over one giant
177
- dashboard. A route can have several states, but it should reveal one state
178
- at a time and preserve the user's progress.
208
+ Before shipping a new app or a substantial redesign, review the surface as an
209
+ operator would use it repeatedly:
210
+
211
+ - Can users identify where they are, what state they are in, and what
212
+ meaningful choices or next steps are available?
213
+ - Remove competing or redundant elements, then place optional inputs, provider
214
+ choices, diagnostics, long explanations, and secondary actions where they
215
+ remain discoverable without crowding the current task.
216
+ - Match the composition to the workflow. Use a focused page or step flow when
217
+ the work is sequential; use an overview when comparing or monitoring several
218
+ things is genuinely the job. Preserve the user's progress in either case.
179
219
  - Remove generic hero copy, feature tours, repeated helper text, nested cards,
180
220
  status-chip soup, and decorative AI treatment before adding more styling.
181
- - For review flows, stack the source/original first and the generated or safe
182
- result second by default. Use side-by-side comparison only when the content
183
- is short enough to scan without excessive horizontal reading.
221
+ - For review flows, choose stacking, side-by-side comparison, or another
222
+ composition based on content length, scanability, and the user's comparison
223
+ task.
184
224
  - Compare the result with sibling apps. Shared toolkit behavior should feel
185
225
  consistent, but a repeated palette, hero composition, type pairing, and
186
226
  radius language without a product reason is visual drift, not consistency.
187
- - Check the result at the target desktop width and a narrow width. If the first
188
- viewport feels like documentation instead of a tool, subtract again.
227
+ - Check the result with realistic content at the target desktop width and a
228
+ narrow width. If it feels like documentation instead of a tool, reduce noise
229
+ or clarify the hierarchy.
189
230
 
190
231
  ## shadcn/ui Design Rules
191
232
 
@@ -203,18 +244,24 @@ as an operator would use it repeatedly:
203
244
  not show generic "Loading..." text for content loads; reserve `Spinner` for
204
245
  brief mutations, uploads, and progress actions. Use the app's existing
205
246
  loading primitive when it is a genuine design-system adapter. Empty states
206
- should have one clear next action.
247
+ should communicate the state and offer the appropriate next step or small set
248
+ of choices.
207
249
 
208
250
  ## Anti-Patterns
209
251
 
210
- Avoid:
252
+ Avoid patterns that add visual noise, obscure state, or compete with the user's
253
+ task without a clear product reason:
211
254
 
212
255
  - Generic AI aesthetics: purple gradients, glassy cards everywhere, vague sparkle language, decorative blobs, and context-free hero sections.
213
256
  - Custom reimplementations of shadcn primitives.
214
257
  - Raw color overrides on shared components when semantic tokens or variants would work.
215
- - New always-visible controls for rare actions. Prefer menus, popovers, sheets, tabs, collapsibles, or advanced sections.
216
- - Full-width banners, persistent helper rows, decorative cards, or explanatory chrome for status that could be a compact affordance.
217
- - Treating progressive disclosure as optional. If a control is not part of the main daily workflow, hide it until context, hover, focus, or explicit user intent makes it relevant.
258
+ - New always-visible controls for rare actions when a contextual surface would
259
+ preserve discoverability and reduce noise.
260
+ - Full-width banners, persistent helper rows, decorative cards, or explanatory
261
+ chrome for status that could be communicated more clearly with less weight.
262
+ - Hiding essential meaning or operability behind progressive disclosure. Defer
263
+ complexity when it is contextual or infrequent, but preserve labels, focus,
264
+ hit targets, accessibility, and recovery paths.
218
265
  - UI cards nested inside other cards.
219
266
  - Text or icons that resize or shift fixed-format UI on hover/loading.
220
267
 
@@ -11,42 +11,38 @@ ladder.
11
11
 
12
12
  ## Core rules
13
13
 
14
- - Keep app state in SQL via Drizzle and scope every read/write by org and
15
- member. Use actions as the UI, agent, CLI, MCP, and A2A surface.
16
- - Keep migrations additive and portable. These tables intentionally use explicit
17
- `ownerEmail`/`orgId` columns for org-visible data, not `ownableColumns()`;
18
- do not call `accessFilter` on them without adding deliberate visibility data.
19
- - Resolve Slack through `server/connectors/credentials.ts`, passing caller
20
- identity at the entrypoint. The dependency guard does not inspect nested
21
- connector code, so a new direct `process.env.SLACK_BOT_TOKEN` read is a bug.
14
+ - Keep app state in SQL via Drizzle, scope reads/writes by org and member, and
15
+ use actions as the UI, agent, CLI, MCP, and A2A surface.
16
+ - Keep migrations additive and portable. These org-visible tables use explicit
17
+ `ownerEmail`/`orgId`, not `ownableColumns()`; add deliberate visibility data
18
+ before using `accessFilter`.
19
+ - Resolve Slack through `server/connectors/credentials.ts` with caller identity
20
+ supplied at the entrypoint; never read `SLACK_BOT_TOKEN` directly.
22
21
  - A missing callback, partial thread, unreadable provider response, or missed
23
- reconciliation is not success. Preserve typed failure or
22
+ reconciliation is not success; preserve typed failure or
24
23
  `reconciliation_required` state.
25
- - Hard guards are code, not prompt text: auth, session, identity,
26
- credentials/vault, migrations, payments, security, and publishable
27
- `packages/*` changes always require human review.
28
- - All work is deduped by Factory item and rule/run identity. Provider comment IDs
29
- are not the idempotency boundary.
30
- - Slack interaction uses the generic Agent-Native Slack adapter. Clear-bug Slack
31
- automations add 👀 and tag `@builderio` in the source thread; GitHub and Sentry
32
- clear bugs use the Builder run API. Clips, Design, and Content are always
33
- owner-managed and never enter autonomous dispatch or PR governance.
34
- - PR governance requires verified BuilderIO membership, a clear bug, passing
35
- CI, and handled review feedback. Product or UX implications stay
36
- manual. Auto-merge additionally requires a verified Factory Builder run.
37
- - Reuse the existing ai-services GitHub read and Builder execution APIs. Do not
38
- duplicate GitHub installation/webhook infrastructure in this template.
24
+ - Auth, identity, credentials/vault, migrations, payments, security, and
25
+ publishable `packages/*` changes are code-level guards requiring human review.
26
+ - Deduplicate by Factory item and rule/run identity, not provider comment ID.
27
+ - Use the generic Slack adapter: clear-bug automations add 👀 and tag
28
+ `@builderio`; GitHub/Sentry clear bugs use the Builder run API. Clips, Design,
29
+ and Content stay owner-managed outside autonomous dispatch and PR governance.
30
+ - PR governance requires verified BuilderIO membership, a clear bug, passing CI,
31
+ and handled review feedback; product/UX implications stay manual. Auto-merge
32
+ also requires a verified Factory Builder run.
33
+ - Reuse the ai-services GitHub read and Builder execution APIs; do not duplicate
34
+ GitHub installation/webhook infrastructure here.
39
35
  - Do not add CRUD routes under `server/routes/api/`; actions are the domain
40
- surface. Provider callbacks are the only exception and must verify signatures.
41
- - Factory graph edits create immutable blueprint versions. AI proposes a graph
42
- with `source=ai`; a person reviews and publishes it through
43
- the same action surface as manual edits.
36
+ surface. Provider callbacks must verify signatures.
37
+ - Graph edits create immutable blueprint versions. AI proposes with `source=ai`;
38
+ a person reviews and publishes through the same action surface.
44
39
 
45
40
  ## Application state
46
41
 
47
42
  - `navigation.view`: `factory` when the workspace is open.
48
43
  - `navigation.factoryId`: selected Factory id when present.
49
- - `navigation.factoryTab`: `map` | `inbox` | `rules` | `automations` | `settings`.
44
+ - `navigation.factoryTab`: `map` | `inbox` | `rules` | `automations` | `audit` | `settings`.
45
+ - `navigation.factoryAuditRunId`: selected automation run in the audit view when present.
50
46
  - `navigation.factoryNodeId` / `navigation.factoryEdgeId`: selected graph item.
51
47
  - A selected graph node or edge is part of `navigation` context. Read
52
48
  `view-screen` before answering why a route exists or changing the selected
@@ -65,37 +61,32 @@ ladder.
65
61
  | `evaluate-triage-item` | Append a decision. |
66
62
  | `record-triage-feedback` | Capture human correction for learning. |
67
63
  | `approve-factory-item` | Explicitly authorize one bounded run. |
68
- | `start-builder-for-item` | Govern clear-bug dispatch; Slack tags Builder in-thread, other sources use Builder API. |
69
- | `govern-agent-native-pull-request` | Apply CI, review, internal-author, product, and owner gates to PR approval/merge. |
70
- | `list-factory-automations` / `save-factory-automation` / `run-factory-automation` | Inspect and edit org-owned Factory prompts, models, schedules, and runs. |
71
- | `get-factory-automation-health` | Inspect the durable scheduler heartbeat and last scheduler error when runs appear stale. |
64
+ | `start-builder-for-item` | Govern clear-bug dispatch through Slack or Builder API. |
65
+ | `govern-agent-native-pull-request` | Apply CI, review, author, product, and owner gates. |
66
+ | `list-factory-automations` / `save-factory-automation` / `run-factory-automation` | Inspect or edit org-owned prompts, schedules, and runs. |
67
+ | `list-factory-audit` | Inspect automation runs, evidence, decisions, and provider actions. |
68
+ | `get-factory-automation-health` | Inspect scheduler heartbeat and last error. |
72
69
  | `suggest-factory-rules` | Mine feedback and fast approvals into proposals. |
73
70
  | `reconcile-triage-run` | Persist callback/provider reconciliation. |
74
71
  | `list-factories` / `get-factory-graph` | Inspect Factory definitions, graph versions, and live evidence metrics. |
75
72
  | `save-factory-graph` | Create or version a complete visual graph; never starts provider work. |
76
73
  | `list-factory-comments` / `add-factory-comment` | Read or attach comments to a canvas, node, or edge. |
77
74
 
78
- Rules start in shadow mode; hard guards always apply. Editable organization
79
- automations execute stored prompts; every external mutation needs a durable run,
80
- idempotency key, and provider confirmation. The legacy observer is disabled
81
- once organization automations are seeded.
82
-
83
- Use the visual editor for direct blueprint changes. Use the agent chat for
84
- natural language design, explanations, and proposals; it must preserve a
85
- complete graph and use `save-factory-graph` rather than describing an
86
- unpersisted change. Rule or guard changes must go through the triage rule
87
- actions, never through graph JSON.
75
+ Rules start in shadow mode; hard guards always apply. Organization automations
76
+ execute stored prompts, and every external mutation needs a durable run,
77
+ idempotency key, and provider confirmation. The legacy observer ends once org
78
+ automations are seeded. Use the visual editor for graph changes and agent chat
79
+ for proposals; persist complete graphs with `save-factory-graph`. Change rules
80
+ through triage rule actions, never graph JSON.
88
81
 
89
82
  ## Scheduler identity
90
83
 
91
- `WORKSPACE_OWNER_EMAIL` is read only at startup to find the deployment org and
92
- stamp seeded automation `createdBy`; it is never caller identity and must not
93
- enter request authorization or credential resolution.
84
+ `WORKSPACE_OWNER_EMAIL` is startup-only deployment-org and seed identity; never
85
+ use it for request authorization or credential resolution.
94
86
 
95
87
  ## Hosting
96
88
 
97
89
  Production needs `DATABASE_URL`, `WORKSPACE_OWNER_EMAIL`, and
98
- `FACTORY_PUBLIC_URL`. Builder execution additionally needs the service URL,
99
- project ID, and workspace-resolved Builder credentials. GitHub and Sentry
100
- polling use workspace-resolved provider credentials. Provider callbacks and
101
- external writes must remain auditable and fail closed when evidence is partial.
90
+ `FACTORY_PUBLIC_URL`; Builder execution also needs its service URL, project ID,
91
+ and workspace credentials. GitHub/Sentry use workspace credentials. Callbacks
92
+ and external writes stay auditable and fail closed on partial evidence.
@@ -11,6 +11,7 @@ import {
11
11
  workspaceMemberIdentityFromContext,
12
12
  } from "../server/lib/require-workspace-member.js";
13
13
  import { createAiServicesGitReadClient } from "../server/triage/ai-services-git.js";
14
+ import { recordFactoryAudit } from "../server/triage/audit.js";
14
15
  import { createGitHubClient } from "../server/triage/github-client.js";
15
16
  import {
16
17
  metadataString,
@@ -140,6 +141,20 @@ export default defineAction({
140
141
  prBabysitState: "closed-or-draft",
141
142
  prBabysitLastCheckedAt: new Date().toISOString(),
142
143
  });
144
+ await recordFactoryAudit(
145
+ context,
146
+ { userEmail, orgId },
147
+ {
148
+ action: "babysit-agent-native-pull-request",
149
+ kind: "governance",
150
+ status: "skipped",
151
+ itemId,
152
+ source: "github",
153
+ sourceUrl: item.sourceUrl,
154
+ summary: "Skipped because the pull request is closed or a draft.",
155
+ details: { state: pullRequest.state, draft: pullRequest.draft },
156
+ },
157
+ );
143
158
  return { ok: true, action: "skipped", reason: "PR is closed or draft." };
144
159
  }
145
160
 
@@ -154,6 +169,20 @@ export default defineAction({
154
169
  prBabysitOwnerArea: ownerOwnedArea,
155
170
  prBabysitLastCheckedAt: new Date().toISOString(),
156
171
  });
172
+ await recordFactoryAudit(
173
+ context,
174
+ { userEmail, orgId },
175
+ {
176
+ action: "babysit-agent-native-pull-request",
177
+ kind: "governance",
178
+ status: "skipped",
179
+ itemId,
180
+ source: "github",
181
+ sourceUrl: item.sourceUrl,
182
+ summary: `${ownerOwnedArea} is owner-managed; no bot feedback was posted.`,
183
+ details: { ownerOwnedArea },
184
+ },
185
+ );
157
186
  return {
158
187
  ok: true,
159
188
  action: "skipped",
@@ -205,6 +234,30 @@ export default defineAction({
205
234
  mergeableState: pullRequest.mergeableState,
206
235
  snapshot: signal,
207
236
  });
237
+ await recordFactoryAudit(
238
+ context,
239
+ { userEmail, orgId },
240
+ {
241
+ action: "babysit-agent-native-pull-request",
242
+ kind: "governance",
243
+ status: needsBabysit ? "success" : "skipped",
244
+ itemId,
245
+ source: "github",
246
+ sourceUrl: item.sourceUrl,
247
+ summary: needsBabysit
248
+ ? "Review feedback, CI, or mergeability needs Builder attention."
249
+ : "The pull request is clean and needs no Builder feedback request.",
250
+ details: {
251
+ headSha: snapshot.headSha,
252
+ checks: snapshot.checks.length,
253
+ comments: snapshot.comments.length,
254
+ unresolvedReviewState,
255
+ mergeable: pullRequest.mergeable,
256
+ mergeableState: pullRequest.mergeableState,
257
+ reviewFeedbackClean: signal.isClean,
258
+ },
259
+ },
260
+ );
208
261
  const now = new Date();
209
262
  const nowIso = now.toISOString();
210
263
  const metadata = parseTriageMetadata(item.metadataJson);
@@ -261,6 +314,19 @@ export default defineAction({
261
314
  item.pullRequestNumber,
262
315
  BUILDER_BOT_REQUEST,
263
316
  );
317
+ await recordFactoryAudit(
318
+ context,
319
+ { userEmail, orgId },
320
+ {
321
+ action: "babysit-agent-native-pull-request",
322
+ kind: "external_action",
323
+ itemId,
324
+ source: "github",
325
+ sourceUrl: comment.htmlUrl,
326
+ summary: "Posted the bounded feedback-fix request to builder-io-bot.",
327
+ details: { commentUrl: comment.htmlUrl, quietForMinutes: 0 },
328
+ },
329
+ );
264
330
  await updateBabysitMetadata(itemId, orgId, {
265
331
  prBabysitState: "active",
266
332
  prBabysitFingerprint: fingerprint,
@@ -15,6 +15,7 @@ import {
15
15
  requireWorkspaceMember,
16
16
  workspaceMemberIdentityFromContext,
17
17
  } from "../server/lib/require-workspace-member.js";
18
+ import { recordFactoryAudit } from "../server/triage/audit.js";
18
19
  import {
19
20
  normalizeTriagePolicyGuards,
20
21
  triageGuardCodeSchema,
@@ -70,6 +71,20 @@ export default defineAction({
70
71
  : `Observed failure taxonomy: ${failureTaxonomy.label} (${failureTaxonomy.code}; ${failureTaxonomy.regime}). `;
71
72
 
72
73
  if (rules.length === 0) {
74
+ await recordFactoryAudit(
75
+ context,
76
+ { userEmail, orgId },
77
+ {
78
+ action: "evaluate-triage-item",
79
+ kind: "decision",
80
+ status: "skipped",
81
+ itemId,
82
+ source: item.source,
83
+ sourceUrl: item.sourceUrl,
84
+ summary: "No enabled shadow rules were available for this item.",
85
+ details: { evaluated: 0 },
86
+ },
87
+ );
73
88
  return {
74
89
  ok: true,
75
90
  itemId,
@@ -119,6 +134,28 @@ export default defineAction({
119
134
  .where(and(eq(triageItems.id, itemId), eq(triageItems.orgId, orgId)));
120
135
  });
121
136
 
137
+ for (const decision of decisions) {
138
+ await recordFactoryAudit(
139
+ context,
140
+ { userEmail, orgId },
141
+ {
142
+ action: "evaluate-triage-item",
143
+ kind: "decision",
144
+ itemId,
145
+ source: item.source,
146
+ sourceUrl: item.sourceUrl,
147
+ summary: decision.reason,
148
+ details: {
149
+ decisionId: decision.id,
150
+ outcome: decision.outcome,
151
+ ruleId: decision.ruleId,
152
+ mode: decision.mode,
153
+ promptVersion: decision.promptVersion,
154
+ },
155
+ },
156
+ );
157
+ }
158
+
122
159
  return {
123
160
  ok: true,
124
161
  itemId,
@@ -9,6 +9,7 @@ import {
9
9
  requireWorkspaceMember,
10
10
  workspaceMemberIdentityFromContext,
11
11
  } from "../server/lib/require-workspace-member.js";
12
+ import { recordFactoryAudit } from "../server/triage/audit.js";
12
13
  import { createSlackReader } from "../server/triage/slack-client.js";
13
14
 
14
15
  const MAX_THREAD_PAGES = 5;
@@ -71,6 +72,25 @@ export default defineAction({
71
72
  cursor = result.next_cursor;
72
73
  }
73
74
 
75
+ await recordFactoryAudit(
76
+ context,
77
+ { userEmail, orgId },
78
+ {
79
+ action: "get-slack-feedback-context",
80
+ kind: "read",
81
+ itemId,
82
+ source: "slack",
83
+ sourceUrl: item.sourceUrl,
84
+ summary: `Read the Slack thread (${messages.length} message${messages.length === 1 ? "" : "s"}).`,
85
+ details: {
86
+ channelId: item.channelId,
87
+ threadTs: item.threadTs,
88
+ coverage: hasMore ? "partial" : "complete",
89
+ messageCount: messages.length,
90
+ },
91
+ },
92
+ );
93
+
74
94
  return {
75
95
  ok: true,
76
96
  itemId,
@@ -13,6 +13,7 @@ import {
13
13
  requireWorkspaceMember,
14
14
  workspaceMemberIdentityFromContext,
15
15
  } from "../server/lib/require-workspace-member.js";
16
+ import { recordFactoryAudit } from "../server/triage/audit.js";
16
17
 
17
18
  export default defineAction({
18
19
  description:
@@ -21,7 +22,7 @@ export default defineAction({
21
22
  http: { method: "GET" },
22
23
  readOnly: true,
23
24
  run: async ({ itemId }, context) => {
24
- const { orgId } = await requireWorkspaceMember(
25
+ const { userEmail, orgId } = await requireWorkspaceMember(
25
26
  workspaceMemberIdentityFromContext(context),
26
27
  );
27
28
  const db = getDb();
@@ -55,6 +56,28 @@ export default defineAction({
55
56
  .where(and(eq(triageRuns.itemId, itemId), eq(triageRuns.orgId, orgId)))
56
57
  .orderBy(asc(triageRuns.startedAt));
57
58
 
59
+ const matchingFeedback = feedback.filter((entry) =>
60
+ decisions.some((decision) => decision.id === entry.decisionId),
61
+ );
62
+ await recordFactoryAudit(
63
+ context,
64
+ { userEmail, orgId },
65
+ {
66
+ action: "get-triage-item",
67
+ kind: "read",
68
+ itemId,
69
+ source: item.source,
70
+ sourceUrl: item.sourceUrl,
71
+ summary: `Inspected ${item.title}`,
72
+ details: {
73
+ decisionCount: decisions.length,
74
+ feedbackCount: matchingFeedback.length,
75
+ runCount: runs.length,
76
+ coverage: item.coverage,
77
+ },
78
+ },
79
+ );
80
+
58
81
  return {
59
82
  ...item,
60
83
  decisions: decisions.map((decision) => ({
@@ -65,9 +88,7 @@ export default defineAction({
65
88
  mode: decision.mode,
66
89
  createdAt: decision.createdAt,
67
90
  })),
68
- feedback: feedback.filter((entry) =>
69
- decisions.some((decision) => decision.id === entry.decisionId),
70
- ),
91
+ feedback: matchingFeedback,
71
92
  runs,
72
93
  };
73
94
  },