@agent-native/core-corpus 0.207.0-nightly-20261011124220 → 0.207.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 (144) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/secrets/SKILL.md +6 -2
  3. package/corpus/templates/analytics/CHANGELOG.md +63 -1
  4. package/corpus/templates/analytics/actions/find-data.ts +12 -1
  5. package/corpus/templates/analytics/actions/get-data-dictionary-index-status.ts +1 -1
  6. package/corpus/templates/analytics/actions/get-first-party-analytics-health.ts +1 -1
  7. package/corpus/templates/analytics/actions/import-data-dictionary-index.ts +5 -10
  8. package/corpus/templates/analytics/app/components/layout/Sidebar.tsx +2 -2
  9. package/corpus/templates/analytics/app/components/semantic-layer/IndexPanel.tsx +6 -2
  10. package/corpus/templates/analytics/app/i18n/en-US.ts +1 -0
  11. package/corpus/templates/analytics/app/pages/DataSources.tsx +1 -3
  12. package/corpus/templates/analytics/changelog/2026-10-10-analytics-now-shows-bigquery-recommendations-only-when-they-.md +6 -0
  13. package/corpus/templates/analytics/changelog/2026-10-11-analytics-finds-data-definitions-faster-and-identifies-user-.md +6 -0
  14. package/corpus/templates/analytics/evals/README.md +31 -10
  15. package/corpus/templates/analytics/evals/production-context.ts +25 -33
  16. package/corpus/templates/analytics/evals/production-source-cases-baseline.snapshot.txt +551 -0
  17. package/corpus/templates/analytics/evals/production-source-cases.eval.ts +294 -5
  18. package/corpus/templates/analytics/evals/results/analytics-smartness-before-after.csv +5 -0
  19. package/corpus/templates/analytics/scripts/build-source-index.ts +402 -28
  20. package/corpus/templates/analytics/server/lib/analytics-agent-context.ts +19 -5
  21. package/corpus/templates/analytics/server/lib/analytics-query-catalog.ts +73 -0
  22. package/corpus/templates/analytics/server/lib/data-dictionary-context.ts +14 -0
  23. package/corpus/templates/analytics/server/lib/first-party-analytics-health.ts +1 -0
  24. package/corpus/templates/analytics/server/lib/session-friction-detector.ts +11 -0
  25. package/corpus/templates/analytics/server/lib/session-friction.ts +55 -45
  26. package/corpus/templates/analytics/server/lib/session-replay.ts +23 -4
  27. package/corpus/templates/analytics/server/lib/source-index-schema.ts +1 -1
  28. package/corpus/templates/assets/.agents/skills/secrets/SKILL.md +6 -2
  29. package/corpus/templates/assets/CHANGELOG.md +6 -0
  30. package/corpus/templates/brain/.agents/skills/ingestion-and-connectors/SKILL.md +42 -24
  31. package/corpus/templates/brain/.agents/skills/secrets/SKILL.md +6 -2
  32. package/corpus/templates/brain/CHANGELOG.md +12 -0
  33. package/corpus/templates/brain/actions/_source-config.ts +33 -20
  34. package/corpus/templates/brain/actions/create-source.ts +1 -1
  35. package/corpus/templates/brain/app/i18n-data.ts +30 -60
  36. package/corpus/templates/brain/app/routes/sources.tsx +8 -28
  37. package/corpus/templates/brain/changelog/2026-10-10-zoom-imports-only-approved-meeting-series.md +6 -0
  38. package/corpus/templates/brain/server/lib/connectors.ts +26 -27
  39. package/corpus/templates/brain/server/lib/zoom.ts +16 -45
  40. package/corpus/templates/brain/shared/zoom-meeting-filter.ts +0 -6
  41. package/corpus/templates/calendar/.agents/skills/secrets/SKILL.md +6 -2
  42. package/corpus/templates/calendar/CHANGELOG.md +6 -0
  43. package/corpus/templates/chat/.agents/skills/secrets/SKILL.md +6 -2
  44. package/corpus/templates/chat/AGENTS.md +3 -3
  45. package/corpus/templates/chat/CHANGELOG.md +6 -0
  46. package/corpus/templates/chat/app/components/chat/ChatHomeRedirect.tsx +25 -0
  47. package/corpus/templates/chat/app/components/chat/ChatRouteContent.tsx +828 -15
  48. package/corpus/templates/chat/app/components/home/HomePage.tsx +332 -0
  49. package/corpus/templates/chat/app/components/layout/AgentInspector.tsx +2 -4
  50. package/corpus/templates/chat/app/components/layout/Header.tsx +1 -1
  51. package/corpus/templates/chat/app/components/layout/Layout.tsx +5 -6
  52. package/corpus/templates/chat/app/components/layout/Sidebar.tsx +35 -11
  53. package/corpus/templates/chat/app/components/ui/item.tsx +1 -0
  54. package/corpus/templates/chat/app/components/ui/separator.tsx +1 -0
  55. package/corpus/templates/chat/app/components/ui/skeleton.tsx +1 -0
  56. package/corpus/templates/chat/app/hooks/use-navigation-state.ts +16 -22
  57. package/corpus/templates/chat/app/i18n/en-US.ts +25 -0
  58. package/corpus/templates/chat/app/lib/chat-paths.ts +479 -0
  59. package/corpus/templates/chat/app/root.tsx +14 -3
  60. package/corpus/templates/chat/app/routes/chat._index.tsx +5 -0
  61. package/corpus/templates/chat/app/routes/home.tsx +3 -22
  62. package/corpus/templates/chat/changelog/2026-10-10-home-handoff-recovery-capacity.md +6 -0
  63. package/corpus/templates/clips/.agents/skills/secrets/SKILL.md +6 -2
  64. package/corpus/templates/clips/CHANGELOG.md +29 -0
  65. package/corpus/templates/clips/app/components/library/page-header.tsx +1 -1
  66. package/corpus/templates/clips/app/components/recorder/recorder-engine.ts +1 -0
  67. package/corpus/templates/clips/app/routes/import.tsx +3 -3
  68. package/corpus/templates/clips/app/routes/record.tsx +24 -4
  69. package/corpus/templates/clips/changelog/2026-10-10-camera-framing-keeps-a-consistent-size-and-position-across-d.md +6 -0
  70. package/corpus/templates/clips/changelog/2026-10-10-clips-no-longer-treats-a-temporary-storage-status-failure-as.md +6 -0
  71. package/corpus/templates/clips/changelog/2026-10-11-combo-buttons-keep-both-controls-at-the-same-height.md +6 -0
  72. package/corpus/templates/clips/changelog/2026-10-11-dedicated-agent-icon.md +6 -0
  73. package/corpus/templates/clips/changelog/2026-10-11-local-recordings-can-start-before-connecting-a-storage-provi.md +6 -0
  74. package/corpus/templates/clips/changelog/2026-10-11-recordings-waiting-for-storage-setup-remain-retryable-throug.md +6 -0
  75. package/corpus/templates/clips/desktop/src/i18n/en-US.ts +1 -0
  76. package/corpus/templates/clips/desktop/src/lib/recorder.ts +8 -2
  77. package/corpus/templates/clips/desktop/src/overlays/bubble.tsx +16 -54
  78. package/corpus/templates/clips/desktop/src-tauri/src/clips/mod.rs +780 -135
  79. package/corpus/templates/clips/server/lib/upload-lease.ts +6 -0
  80. package/corpus/templates/clips/server/lib/video-storage.ts +28 -6
  81. package/corpus/templates/clips/server/plugins/onboarding.ts +2 -1
  82. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/abort.post.ts +10 -0
  83. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/chunk.post.ts +64 -19
  84. package/corpus/templates/clips/server/routes/api/uploads/[recordingId]/interrupt.post.ts +9 -0
  85. package/corpus/templates/clips/shared/recording-core.ts +19 -1
  86. package/corpus/templates/content/.agents/skills/secrets/SKILL.md +6 -2
  87. package/corpus/templates/content/CHANGELOG.md +39 -0
  88. package/corpus/templates/content/app/components/editor/BubbleToolbar.tsx +301 -681
  89. package/corpus/templates/content/app/components/editor/CommentAiRecipient.tsx +3 -2
  90. package/corpus/templates/content/app/components/editor/CommentComposer.tsx +2 -2
  91. package/corpus/templates/content/app/components/editor/CommentsSidebar.tsx +3 -2
  92. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +0 -11
  93. package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +3 -7
  94. package/corpus/templates/content/app/components/editor/VisualEditor.tsx +102 -95
  95. package/corpus/templates/content/app/components/editor/agent-identity.tsx +3 -2
  96. package/corpus/templates/content/app/components/editor/extensions/CommentHighlight.ts +149 -21
  97. package/corpus/templates/content/app/i18n-data.ts +0 -1
  98. package/corpus/templates/content/changelog/2026-10-10-accepting-a-suggested-edit-in-a-comment-thread-no-longer-sho.md +6 -0
  99. package/corpus/templates/content/changelog/2026-10-10-the-chatgpt-and-codex-widget-no-longer-pins-a-formatting-too.md +6 -0
  100. package/corpus/templates/content/changelog/2026-10-11-dedicated-agent-icon.md +6 -0
  101. package/corpus/templates/content/changelog/2026-10-11-share-and-copy-buttons-stay-the-same-height-in-the-editor.md +6 -0
  102. package/corpus/templates/content/shared/document-intent-merge.ts +4 -2
  103. package/corpus/templates/crm/.agents/skills/secrets/SKILL.md +6 -2
  104. package/corpus/templates/crm/CHANGELOG.md +6 -0
  105. package/corpus/templates/design/.agents/skills/secrets/SKILL.md +6 -2
  106. package/corpus/templates/design/CHANGELOG.md +43 -0
  107. package/corpus/templates/design/actions/get-design.ts +1 -1
  108. package/corpus/templates/design/actions/navigate.ts +1 -1
  109. package/corpus/templates/design/actions/view-screen.ts +1 -1
  110. package/corpus/templates/design/app/components/design/editor/DesignWorkspaceRail.tsx +5 -5
  111. package/corpus/templates/design/app/components/editor/PromptDialog.tsx +2 -2
  112. package/corpus/templates/design/app/components/layout/Header.tsx +2 -2
  113. package/corpus/templates/design/app/components/layout/Sidebar.tsx +3 -3
  114. package/corpus/templates/design/app/i18n/en-US.ts +4 -4
  115. package/corpus/templates/design/app/pages/design-editor/view/left-sidebar.tsx +1 -1
  116. package/corpus/templates/design/app/pages/design-editor/view/right-sidebar-actions.tsx +21 -10
  117. package/corpus/templates/design/app/root.tsx +1 -1
  118. package/corpus/templates/design/changelog/2026-10-10-in-the-minimal-layout-the-zoom-picker-and-share-button-sit-o.md +6 -0
  119. package/corpus/templates/design/changelog/2026-10-11-dedicated-agent-icon.md +6 -0
  120. package/corpus/templates/design/changelog/2026-10-11-replay-screenshots-can-be-handed-off-to-design-boards.md +8 -0
  121. package/corpus/templates/design/changelog/2026-10-11-the-editor-s-left-rail-tab-is-now-called-layers-and-the-desi.md +6 -0
  122. package/corpus/templates/dispatch/.agents/skills/secrets/SKILL.md +6 -2
  123. package/corpus/templates/factory/.agents/skills/secrets/SKILL.md +6 -2
  124. package/corpus/templates/factory/CHANGELOG.md +6 -0
  125. package/corpus/templates/forms/.agents/skills/secrets/SKILL.md +6 -2
  126. package/corpus/templates/mail/.agents/skills/secrets/SKILL.md +6 -2
  127. package/corpus/templates/mail/CHANGELOG.md +6 -0
  128. package/corpus/templates/plan/.agents/skills/secrets/SKILL.md +6 -2
  129. package/corpus/templates/plan/CHANGELOG.md +6 -0
  130. package/corpus/templates/slides/.agents/skills/secrets/SKILL.md +6 -2
  131. package/corpus/templates/slides/CHANGELOG.md +30 -0
  132. package/corpus/templates/slides/app/components/editor/SlideEditor.tsx +48 -4
  133. package/corpus/templates/slides/app/components/editor/SlideScrollStack.tsx +307 -0
  134. package/corpus/templates/slides/app/components/editor/SlideSlashCommandMenu.tsx +1 -1
  135. package/corpus/templates/slides/app/hooks/use-compact-editor-layout.ts +26 -0
  136. package/corpus/templates/slides/app/lib/slide-scroll.ts +56 -0
  137. package/corpus/templates/slides/app/pages/DeckEditor.tsx +28 -12
  138. package/corpus/templates/slides/app/pages/Index.tsx +2 -1
  139. package/corpus/templates/slides/changelog/2026-10-10-in-a-narrow-pane-such-as-the-chatgpt-side-panel-the-editor-s.md +6 -0
  140. package/corpus/templates/slides/changelog/2026-10-11-going-back-from-a-new-slides-generation-returns-home-without.md +6 -0
  141. package/corpus/templates/slides/scripts/edit-fidelity/authoring-fuzz.ts +1 -1
  142. package/corpus/templates/tasks/.agents/skills/secrets/SKILL.md +6 -2
  143. package/corpus/templates/tasks/app/components/tasks/fields/TaskFieldsSidebar.tsx +2 -2
  144. package/package.json +1 -1
package/corpus/README.md CHANGED
@@ -32,4 +32,4 @@ rg -n "defineAction|useActionQuery" node_modules/@agent-native/core-corpus/corpu
32
32
 
33
33
  ## Generated Counts
34
34
 
35
- - template files: 11961
35
+ - template files: 11993
@@ -25,8 +25,12 @@ never copy a value into app code or client-visible state.
25
25
  3. If the app truly needs its own API key, register it with the shared secrets
26
26
  surface. Do not build a parallel key form or storage table.
27
27
  4. Use deployment configuration only for a secret owned by the deployed app,
28
- such as a webhook verification secret. A deployment key must not stand in
29
- for a user's or customer's provider credential.
28
+ such as a webhook verification secret. LLM inference keys are an app-owned
29
+ exception: self-hosted apps may use provider keys from deployment env as a
30
+ shared fallback, while scoped user or organization keys take precedence.
31
+ Hosted-workspace deployments backed by a shared database must not share
32
+ those env keys across apps or tenants. This exception does not authorize
33
+ using env credentials to access user-owned provider data.
30
34
 
31
35
  ## Register an app-local API key
32
36
 
@@ -3,16 +3,73 @@
3
3
  All notable user-facing changes to Agent-Native Analytics are documented here. Open it any
4
4
  time from the command menu (Cmd+K → "What's new") or from Settings.
5
5
 
6
- ## 2026-10-09
6
+ ## 2026-10-11
7
+
8
+ ### Improved
9
+
10
+ - Analytics finds data definitions faster and identifies user-organization relationships more clearly.
11
+
12
+ ## 2026-10-10
7
13
 
8
14
  ### Improved
9
15
 
16
+ - Long session recordings start playback while remaining chunks load.
17
+ - Read only the event fields needed for onboarding journeys.
18
+ - The source index reports tracking calls with event names it cannot resolve, making event coverage gaps easier to spot.
19
+ - The data index preserves dbt's declared primary entity separately from its row grain.
20
+
21
+ ### Fixed
22
+
23
+ - Analytics discovery preserves source and freshness details when saved dictionary entries contain blank fields.
24
+ - Analytics now shows BigQuery recommendations only when they apply and marks unavailable index counts clearly.
25
+ - Onboarding journey queries reuse a single event read while preserving exact output attribution
26
+ - Reduce duplicate reads when loading organization onboarding journeys
27
+ - Replay friction scores now count rage clicks that span recording uploads.
28
+ - Session summaries count replay errors and failed requests across uploads without double-counting retries
29
+ - Storyboard export failures now report bounded handoff diagnostics without exposing raw exceptions.
30
+
31
+ ### Changed
32
+
33
+ - Definitions and the source index now live on one Semantic layer page, which replaces the Source Status and Data Dictionary pages.
34
+
35
+ ## 2026-10-09
36
+
37
+ ### Added
38
+
39
+ - Analytics can query owner-defined dbt metrics through a workspace connection
40
+ - Compare later onboarding activity across first-party sessions and apps, with unknown identities and incomplete observation windows called out.
41
+ - Dashboard folders can now sync with a GitHub repo folder: pull only the panels that changed in GitHub, or export app changes as a pull request, without overwriting edits made elsewhere in the app.
42
+ - Dashboards can filter by several values at once with multi-select filters.
43
+ - Journey capture can render recorded media in Chromium and save visible prompt provenance locally.
44
+ - Review source connections and export the data dictionary from one status page
45
+
46
+ ### Improved
47
+
48
+ - Analytics prioritizes reviewed definitions over broad generated matches, keeps exact runnable panels discoverable, reports source-index quality accurately, and continues BigQuery searches without repeating metadata reads.
49
+ - Ask chats now open on their own shareable URL at /ask/<id>, and /ask always starts a blank chat.
50
+ - Dashboard filters support searching, selecting all values, or keeping only one value.
51
+ - Data Sources now lists integrations in the same rows as Settings, with connected sources first and setup in a side sheet.
52
+ - Approved metric definitions rank ahead of dashboard examples for exact name searches.
53
+ - Generated source entries now appear in data dictionary browsing, and new entries remain unapproved until reviewed.
54
+ - Journey captures can check replay media and optionally save a private, bounded copy of visible user messages.
55
+ - Onboarding journey event reads avoid an unused identity scan, cap query cost, and mark follow-up coverage incomplete when results are too large
56
+ - Onboarding journeys now honor the selected date range when reading events.
57
+ - Onboarding summaries return journey counts without waiting for replay metadata.
10
58
  - Onboarding journeys include Builder connection and custom-key outcomes through deeper paths
11
59
  - Onboarding journeys now show later activity within a chosen window, mark no-later results as right-censored, and identify when follow-up counts are incomplete.
12
60
  - You can add app origins to a public key's replay allowlist without replacing its existing origins.
13
61
 
14
62
  ### Fixed
15
63
 
64
+ - First-party BigQuery dashboards use date-bounded weekly activity queries on both saved dashboard versions
65
+ - GitHub source connections use dedicated OAuth app credentials, separate from sign-in.
66
+ - Journey screenshots account for legacy clipping when checking embedded replay content.
67
+ - Journey trees remain available when a matching recording is not visible
68
+ - Onboarding journey queries avoid redundant event reads
69
+ - Onboarding journeys can find recordings from exact replay links even when session IDs differ
70
+ - Onboarding journey summaries load reliably for organizations using Builder Analytics.
71
+ - Replay screenshots finish loading fonts before capture.
72
+ - Replay screenshots support modern CSS colors.
16
73
  - Existing chat threads keep the composer anchored at the bottom while their messages load.
17
74
  - Journey captures now flag visible previews missing from the recording instead of saving blank screenshots
18
75
  - Journey recordings flag iframe content when clipping, masks, or filters make its visibility uncertain.
@@ -20,6 +77,10 @@ time from the command menu (Cmd+K → "What's new") or from Settings.
20
77
  - Session recordings keep their full history and performance insights across browser session changes and large replays.
21
78
  - Large onboarding journeys keep their step counts when follow-up coverage exceeds query limits
22
79
 
80
+ ### Removed
81
+
82
+ - Removed the default HTTP 5xx spike alert, since server responses are no longer recorded as analytics events
83
+
23
84
  ## 2026-10-08
24
85
 
25
86
  ### Added
@@ -85,6 +146,7 @@ time from the command menu (Cmd+K → "What's new") or from Settings.
85
146
 
86
147
  ### Improved
87
148
 
149
+ - Session replays now show the date and time the session started, and the Sessions list shows start times in a shorter, easier-to-scan format.
88
150
  - Agent dashboard edits are now checked against the live chart before they save, so the agent no longer reports a chart change that did not happen.
89
151
 
90
152
  ### Fixed
@@ -37,13 +37,24 @@ export default defineAction({
37
37
  orgId: getRequestOrgId() || null,
38
38
  });
39
39
  const { candidates, ...paginationAndCoverage } = result;
40
+ const sourceIndexGuidance =
41
+ result.sourceIndexStatus === "not-configured"
42
+ ? "The generated source index is not configured, so absence from these references is not evidence that a warehouse relation does not exist. Use search-bigquery-schema for connected BigQuery schemas."
43
+ : result.sourceIndexStatus === "invalid" ||
44
+ result.sourceIndexStatus === "unavailable"
45
+ ? "The generated source index could not be read, so treat these references as incomplete and verify with search-bigquery-schema."
46
+ : "";
40
47
  return {
41
48
  question,
42
49
  results: candidates,
43
50
  ...paginationAndCoverage,
44
51
  resultType: "reference-metadata",
45
- guidance:
52
+ guidance: [
46
53
  "Treat saved SQL and source-index entries as examples or unapproved metadata. Verify source scope, live schema, partitions, and current values before answering. If truncated is true and nextPage is present, continue with that cursor; if truncated is true and nextPage is null, refine the search or use an explicit dashboard/schema search because a source cap was reached.",
54
+ sourceIndexGuidance,
55
+ ]
56
+ .filter(Boolean)
57
+ .join(" "),
47
58
  };
48
59
  },
49
60
  });
@@ -39,7 +39,7 @@ export default defineAction({
39
39
  generatedAt: result.bundle.generatedAt,
40
40
  entryCount: result.bundle.entries.length,
41
41
  unresolvedTrackingCallSites:
42
- result.bundle.scanSummary?.unresolvedTrackingCallSites ?? 0,
42
+ result.bundle.scanSummary?.unresolvedTrackingCallSites ?? null,
43
43
  sources: result.bundle.sources,
44
44
  sourceCounts: result.bundle.sources.map(({ id }) => ({
45
45
  source: id,
@@ -74,7 +74,7 @@ const healthSchema = z.object({
74
74
 
75
75
  export default defineAction({
76
76
  description:
77
- "Check whether the built-in first-party Analytics source is still a good fit for Neon/Postgres. Use this before a large or historical query. It reads compact daily rollups and the small slow-query pressure ledger, never the raw event table. For BigQuery cutovers, it also reports pending delivery count, age, and the last delivery error so a warehouse outage is visible before dashboards go quiet. A pending delivery-queue migration is reported as degraded delivery health instead of hiding the existing health result. `healthy` means Neon is fine, `monitor` means keep Neon but watch growth or delivery lag, and `recommend_bigquery` means use a configured external analytics backend for high-volume or historical queries. The result reports the two supported external options with safe setup links: BigQuery for warehouse SQL and history, and Amplitude for product analytics, funnels, and retention. A recommendation is based on 1M+ observed events, three or more slow queries in 24 hours, or any query timeout/30-second query. Connecting a backend does not silently reroute `/track` events or backfill existing Neon events.",
77
+ "Check whether the built-in first-party Analytics source is still a good fit for Neon/Postgres. Use this before a large or historical query. It reads compact daily rollups and the small slow-query pressure ledger, never the raw event table. For BigQuery cutovers, it also reports pending delivery count, age, and the last delivery error so a warehouse outage is visible before dashboards go quiet. A pending delivery-queue migration is reported as degraded delivery health instead of hiding the existing health result. `healthy` means Neon is fine, `monitor` means keep Neon but watch query pressure or delivery lag, and `recommend_bigquery` means move high-volume or historical queries to a configured external analytics backend. Event volume, three or more slow queries in 24 hours, or any query timeout/30-second query can trigger that recommendation while the first-party sink is Neon/Postgres. When BigQuery is already the first-party sink, event volume is not a migration reason; query pressure and delivery lag can still produce `monitor`. The result reports the two supported external options with safe setup links: BigQuery for warehouse SQL and history, and Amplitude for product analytics, funnels, and retention. Connecting a backend does not silently reroute `/track` events or backfill existing Neon events.",
78
78
  schema: z.object({}),
79
79
  outputSchema: healthSchema,
80
80
  http: { method: "GET" },
@@ -29,22 +29,17 @@ export default defineAction({
29
29
  const index = bundle as SourceIndexBundle;
30
30
  await putOrgSetting(admin.orgId, SOURCE_INDEX_SETTING_KEY, index);
31
31
  invalidateSourceIndexCache(admin.orgId);
32
- const scanSummary = index.scanSummary
33
- ? {
34
- ...index.scanSummary,
35
- unresolvedTrackingCallSites:
36
- index.scanSummary.unresolvedTrackingCallSites ?? 0,
37
- }
38
- : null;
32
+ const scanSummary = index.scanSummary ?? null;
33
+ const unresolvedTrackingCallSites =
34
+ scanSummary?.unresolvedTrackingCallSites ?? null;
39
35
  return {
40
36
  entryCount: index.entries.length,
41
37
  generatedAt: index.generatedAt,
42
38
  sources: index.sources.map((source) => source.id),
43
39
  scanSummary,
44
- unresolvedTrackingCallSites:
45
- scanSummary?.unresolvedTrackingCallSites ?? 0,
40
+ unresolvedTrackingCallSites,
46
41
  message: scanSummary
47
- ? `Replaced the source index with ${index.entries.length} unapproved entries; omitted ${scanSummary.unsafeEntriesOmitted} unsafe entries and ${scanSummary.unsafeFieldsOmitted} unsafe fields, marked ${scanSummary.truncatedFields} truncated fields, and found ${scanSummary.unresolvedTrackingCallSites} tracking call sites with unresolved event names.`
42
+ ? `Replaced the source index with ${index.entries.length} unapproved entries; omitted ${scanSummary.unsafeEntriesOmitted} unsafe entries and ${scanSummary.unsafeFieldsOmitted} unsafe fields, marked ${scanSummary.truncatedFields} truncated fields, and ${unresolvedTrackingCallSites === null ? "could not determine the unresolved tracking call count" : `found ${unresolvedTrackingCallSites} tracking call sites with unresolved event names`}.`
48
43
  : `Replaced the source index with ${index.entries.length} unapproved entries. Scan quality counts are unavailable for this bundle.`,
49
44
  };
50
45
  },
@@ -2635,12 +2635,12 @@ export function Sidebar({ mobile }: { mobile?: boolean } = {}) {
2635
2635
  </div>
2636
2636
  </nav>
2637
2637
 
2638
- <div className="mt-3 shrink-0 min-w-0 space-y-1 border-t border-border/70">
2638
+ <div className="mt-3 shrink-0 min-w-0">
2639
2639
  <AppSidebarFooter
2640
2640
  collapsed={false}
2641
2641
  collapsible={false}
2642
2642
  feedback={footerFeedback}
2643
- className="space-y-1 border-t-0 px-2"
2643
+ className="border-border/70 px-2"
2644
2644
  orgSwitcher={
2645
2645
  <OrgSwitcher className="min-w-0 flex-1 !px-2 !bg-transparent !text-primary hover:!bg-accent/60 hover:!text-primary" />
2646
2646
  }
@@ -116,7 +116,7 @@ type IndexStatusAvailable = {
116
116
  status: "available";
117
117
  generatedAt: string;
118
118
  entryCount: number;
119
- unresolvedTrackingCallSites: number;
119
+ unresolvedTrackingCallSites: number | null;
120
120
  sources: Array<{ id: string; revision?: string }>;
121
121
  sourceCounts?: Array<{ source: string; entryCount: number }>;
122
122
  ageDays: number;
@@ -393,7 +393,11 @@ function StatusSection() {
393
393
  {available ? (
394
394
  <SettingRow label={t("indexPanel.unresolvedTrackingCallSites")}>
395
395
  <span className="text-sm tabular-nums text-muted-foreground">
396
- {formatters.formatNumber(available.unresolvedTrackingCallSites)}
396
+ {available.unresolvedTrackingCallSites === null
397
+ ? t("indexPanel.unresolvedTrackingCallSitesUnavailable")
398
+ : formatters.formatNumber(
399
+ available.unresolvedTrackingCallSites,
400
+ )}
397
401
  </span>
398
402
  </SettingRow>
399
403
  ) : null}
@@ -1869,6 +1869,7 @@ export default {
1869
1869
  presetWeekly: "Weekly on Monday at 06:00",
1870
1870
  status: "Status",
1871
1871
  unresolvedTrackingCallSites: "Unresolved tracking calls",
1872
+ unresolvedTrackingCallSitesUnavailable: "Unavailable",
1872
1873
  dynamicTrackingCoverageCaveat:
1873
1874
  "Calls with runtime-computed event names are excluded; aliases or other tracking APIs may be missed.",
1874
1875
  overviewFailed: "Build state could not be loaded.",
@@ -1588,9 +1588,7 @@ function useFirstPartyAnalyticsData() {
1588
1588
  | undefined;
1589
1589
  const healthStatus = healthQuery.isError ? "unavailable" : health?.status;
1590
1590
  const externalBackends = health?.externalBackends ?? [];
1591
- const externalBackendConfigured = externalBackends.some(
1592
- (backend) => backend.configured === true,
1593
- );
1591
+ const externalBackendConfigured = health?.bigQuery.configured === true;
1594
1592
  const recommendsExternalBackend = healthStatus === "recommend_bigquery";
1595
1593
  const healthTitleKey = recommendsExternalBackend
1596
1594
  ? externalBackendConfigured
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: fixed
3
+ date: 2026-10-10
4
+ ---
5
+
6
+ Analytics now shows BigQuery recommendations only when they apply and marks unavailable index counts clearly.
@@ -0,0 +1,6 @@
1
+ ---
2
+ type: improved
3
+ date: 2026-10-11
4
+ ---
5
+
6
+ Analytics finds data definitions faster and identifies user-organization relationships more clearly.
@@ -10,8 +10,10 @@ The Analytics adapter assembles the production framework prompt, Analytics
10
10
  instructions, initial tools, read-only action registry, and request-time catalog
11
11
  prefetch. It invokes the shared production `runAgentLoop` with the real Analytics
12
12
  final-response guard, caller email, organization id, abort signal, and usage
13
- capture. The runner checks a bounded receipt for those conditions and rejects
14
- failed or timed-out prefetch, missing guard/usage, skipped cases, or cancellation.
13
+ capture. The runner checks a bounded receipt for those conditions. A failed or
14
+ timed-out catalog prefetch is reported to the model as a context note, as in
15
+ production; the agent can still search with its tools. Aborted runs, missing
16
+ guard/usage, skipped cases, and incorrect answers fail the eval.
15
17
 
16
18
  This exercises the shared production agent-loop boundary; it does not dispatch
17
19
  through the mounted HTTP chat handler or its thread/run persistence path. The
@@ -22,22 +24,41 @@ read from environment variables or app configuration.
22
24
  If either identity value or the production adapter is missing, the command
23
25
  exits with an error before running or scoring any case.
24
26
 
27
+ ## Production path before and after
28
+
29
+ `results/analytics-smartness-before-after.csv` contains two runs per phase for
30
+ the same redacted synthetic case based on the reported Builder.io user and
31
+ organization question. It is not a replay of Brent's historical chat. The CSV
32
+ contains only run timing, token and tool counts, credits, and scorer outcomes;
33
+ it has no prompts, transcripts, emails, identifiers, row values, or secrets.
34
+
35
+ Both phases completed through the production agent loop, but both failed the
36
+ source-contract scorer because the production organization had no generated
37
+ source index configured at evaluation time. Mean latency fell from 101.4s to
38
+ 83.7s (17.4%), mean LLM calls from 14.5 to 12 (17.2%), and mean input tokens
39
+ from 908k to 855k (5.8%). This establishes a faster lookup path, not an
40
+ accuracy improvement. The generated index now includes the missing membership
41
+ grains; rerun the same cases after the index is imported to measure the
42
+ accuracy gain. No production index or data rows were written for this eval.
43
+
25
44
  ## Synthetic source and grain cases
26
45
 
27
- `production-source-cases.eval.ts` adds six synthetic questions. They ask for
28
- model selection and declared grain only; they do not use captured prompts,
29
- people, identifiers, event rows, or production result values. Their scorer
30
- rejects failed or aborted runs, email-shaped output, and calls outside the
31
- metadata-only tool set. The CLI still runs each case through this directory's
32
- production adapter and the shared production agent loop.
46
+ `production-source-cases.eval.ts` adds seven synthetic questions. They ask for
47
+ source selection, declared grain, and relation or field attribution; they do
48
+ not use captured prompts, people, identifiers, event rows, or production result
49
+ values. Their scorer rejects failed or aborted runs, email-shaped output, and
50
+ calls outside the metadata-only tool set. The CLI still runs each case through
51
+ this directory's production adapter and the shared production agent loop.
33
52
 
34
53
  The expected source contracts are:
35
54
 
36
55
  - Builder.io user roster: `dbt_mart.dim_users_core` at user grain,
37
56
  `dbt_mart.dim_organizations` at organization grain, joined through
38
57
  `dbt_intermediate.user_organization_role` at user-organization membership
39
- grain. The nonexistent `dbt_mapping.user_id_to_org_id` is not an accepted
40
- alternative.
58
+ grain. `dbt_mapping.user_id_to_org_id` is also a real one-row-per-membership
59
+ map with `user_id`, `organization_id`, and `is_root_org`; it does not carry
60
+ `organization_role`, so it cannot replace the role bridge for role-aware
61
+ rosters.
41
62
  - Builder.io current and historical counts: `dbt_mart.organization_user_count`
42
63
  is one row per organization per date; `dbt_mart.aggregate_monthly_users_per_org`
43
64
  is one row per organization per month.
@@ -51,20 +51,32 @@ function toMessages(
51
51
  return messages;
52
52
  }
53
53
 
54
- function appendReferences(
54
+ export function buildAnalyticsPromptContext(
55
55
  systemPrompt: string,
56
- candidates: Awaited<
57
- ReturnType<typeof retrieveAnalyticsPromptReferences>
58
- >["jevPromptCandidates"],
56
+ references: Awaited<ReturnType<typeof retrieveAnalyticsPromptReferences>>,
59
57
  ): string {
60
- if (candidates.length === 0) return systemPrompt;
61
- const references = candidates
62
- .map(
63
- (candidate) =>
64
- `### ${candidate.name}\n${candidate.description}\n${candidate.content}`,
65
- )
66
- .join("\n\n");
67
- return `${systemPrompt}\n\n<resource scope="analytics-catalog">\n${references}\n</resource>`;
58
+ const candidates = references.jevPromptCandidates;
59
+ let prompt = systemPrompt;
60
+ if (candidates.length > 0) {
61
+ const resource = candidates
62
+ .map(
63
+ (candidate) =>
64
+ `### ${candidate.name}\n${candidate.description}\n${candidate.content}`,
65
+ )
66
+ .join("\n\n");
67
+ prompt += `\n\n<resource scope="analytics-catalog">\n${resource}\n</resource>`;
68
+ }
69
+ if (
70
+ references.prefetchStatus === "timed_out" ||
71
+ references.prefetchStatus === "failed"
72
+ ) {
73
+ const reason =
74
+ references.prefetchStatus === "timed_out" ? "timed out" : "failed";
75
+ const subject =
76
+ candidates.length > 0 ? "Some preloaded context" : "Preloaded context";
77
+ prompt += `\n\n<context-note>${subject} was unavailable this turn (${reason}); search for anything relevant with the available tools before answering.</context-note>`;
78
+ }
79
+ return prompt;
68
80
  }
69
81
 
70
82
  export function filterAnalyticsEvalActions(
@@ -123,10 +135,7 @@ async function runAnalyticsProductionPath(args: {
123
135
  deadlineAt: Date.now() + 1_300,
124
136
  });
125
137
  const runId = `eval:${crypto.randomUUID()}`;
126
- const prompt = appendReferences(
127
- args.systemPrompt,
128
- references.jevPromptCandidates,
129
- );
138
+ const prompt = buildAnalyticsPromptContext(args.systemPrompt, references);
130
139
  const availableTools = actionsToEngineTools(args.actions);
131
140
  const initialNames = new Set(args.initialToolNames);
132
141
  const tools = availableTools.filter((tool) => initialNames.has(tool.name));
@@ -195,23 +204,6 @@ async function runAnalyticsProductionPath(args: {
195
204
  availableActionNames,
196
205
  readOnlyActionNames,
197
206
  };
198
- if (
199
- references.prefetchStatus !== "ok" &&
200
- references.prefetchStatus !== "empty"
201
- ) {
202
- return {
203
- output: {
204
- text: "",
205
- toolCalls: [],
206
- ok: false,
207
- error: `Analytics request preparation ${references.prefetchStatus}.`,
208
- runId,
209
- durationMs: 0,
210
- },
211
- receipt,
212
- };
213
- }
214
-
215
207
  const started = Date.now();
216
208
  let ok = true;
217
209
  try {