@agent-native/core-corpus 0.203.0 → 0.203.1-nightly-20261007183952

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 (96) hide show
  1. package/corpus/README.md +1 -1
  2. package/corpus/templates/analytics/.agents/skills/actions/SKILL.md +25 -0
  3. package/corpus/templates/analytics/.agents/skills/adhoc-analysis/SKILL.md +12 -0
  4. package/corpus/templates/analytics/.agents/skills/admin-surfaces/SKILL.md +1 -4
  5. package/corpus/templates/analytics/.agents/skills/analysis-workspace/SKILL.md +4 -4
  6. package/corpus/templates/analytics/.agents/skills/bigquery/SKILL.md +1 -3
  7. package/corpus/templates/analytics/.agents/skills/creative-context/SKILL.md +1 -4
  8. package/corpus/templates/analytics/.agents/skills/cross-source-analysis/SKILL.md +1 -3
  9. package/corpus/templates/analytics/.agents/skills/custom-blocks/SKILL.md +198 -0
  10. package/corpus/templates/analytics/.agents/skills/dashboard-management/SKILL.md +108 -310
  11. package/corpus/templates/analytics/.agents/skills/data-programs/SKILL.md +1 -6
  12. package/corpus/templates/analytics/.agents/skills/data-querying/SKILL.md +13 -0
  13. package/corpus/templates/analytics/.agents/skills/incident-investigation/SKILL.md +60 -0
  14. package/corpus/templates/analytics/AGENTS.md +3 -2
  15. package/corpus/templates/analytics/actions/compose-dashboard.ts +112 -36
  16. package/corpus/templates/analytics/actions/dashboard-mutation-api.ts +19 -27
  17. package/corpus/templates/analytics/actions/get-sql-dashboard.ts +19 -9
  18. package/corpus/templates/analytics/actions/inspect-dashboard-panel.ts +126 -0
  19. package/corpus/templates/analytics/actions/mutate-dashboard.ts +163 -109
  20. package/corpus/templates/analytics/actions/query-agent-native-analytics.ts +8 -4
  21. package/corpus/templates/analytics/actions/restore-dashboard-revision.ts +48 -1
  22. package/corpus/templates/analytics/actions/update-dashboard.ts +300 -106
  23. package/corpus/templates/analytics/actions/view-screen.ts +14 -7
  24. package/corpus/templates/analytics/app/components/dashboard/SqlChart.tsx +43 -218
  25. package/corpus/templates/analytics/app/components/layout/NewDashboardDialog.tsx +2 -2
  26. package/corpus/templates/analytics/app/hooks/use-dashboard-chat-context.ts +1 -1
  27. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/PanelEditorDialog.tsx +2 -2
  28. package/corpus/templates/analytics/app/pages/adhoc/sql-dashboard/types.ts +16 -13
  29. package/corpus/templates/analytics/changelog/2026-10-06-agent-dashboard-edits-are-now-checked-against-the-live-chart.md +6 -0
  30. package/corpus/templates/analytics/server/lib/agent-chat-plan-mode.ts +1 -19
  31. package/corpus/templates/analytics/server/lib/agent-readable-resource-context.ts +178 -32
  32. package/corpus/templates/analytics/server/lib/bigquery.ts +57 -4
  33. package/corpus/templates/analytics/server/lib/dashboard-agent-write.ts +164 -0
  34. package/corpus/templates/analytics/server/lib/dashboard-id.ts +13 -0
  35. package/corpus/templates/analytics/server/lib/dashboard-panel-runner.ts +168 -0
  36. package/corpus/templates/analytics/server/lib/dashboard-panel-verification.ts +1121 -0
  37. package/corpus/templates/analytics/server/lib/dashboard-report-render.ts +10 -119
  38. package/corpus/templates/analytics/server/lib/dashboard-seeds.ts +2 -0
  39. package/corpus/templates/analytics/server/lib/dashboards-store.ts +33 -10
  40. package/corpus/templates/analytics/server/lib/real-data-actions.ts +0 -23
  41. package/corpus/templates/analytics/server/plugins/agent-chat.ts +48 -92
  42. package/corpus/templates/analytics/shared/panel-render-contract.ts +749 -0
  43. package/corpus/templates/assets/.agents/skills/actions/SKILL.md +25 -0
  44. package/corpus/templates/brain/.agents/skills/actions/SKILL.md +25 -0
  45. package/corpus/templates/calendar/.agents/skills/actions/SKILL.md +25 -0
  46. package/corpus/templates/chat/.agents/skills/actions/SKILL.md +25 -0
  47. package/corpus/templates/clips/.agents/skills/actions/SKILL.md +25 -0
  48. package/corpus/templates/clips/app/components/library/library-grid.tsx +23 -13
  49. package/corpus/templates/clips/app/components/library/recording-card.tsx +3 -3
  50. package/corpus/templates/clips/app/hooks/use-library.ts +2 -1
  51. package/corpus/templates/clips/app/routes/_app.trash.tsx +23 -13
  52. package/corpus/templates/content/.agents/skills/actions/SKILL.md +25 -0
  53. package/corpus/templates/content/CHANGELOG.md +1 -1
  54. package/corpus/templates/content/actions/get-document.ts +3 -0
  55. package/corpus/templates/content/app/components/editor/DocumentEditor.tsx +13 -4
  56. package/corpus/templates/content/app/components/editor/DocumentToolbar.tsx +9 -6
  57. package/corpus/templates/content/app/components/editor/document-collaboration.ts +9 -0
  58. package/corpus/templates/content/changelog/2026-10-07-chatgpt-widget-previews-show-saved-document-bodies-without-a.md +6 -0
  59. package/corpus/templates/content/shared/api.ts +1 -0
  60. package/corpus/templates/crm/.agents/skills/actions/SKILL.md +25 -0
  61. package/corpus/templates/design/.agents/skills/actions/SKILL.md +25 -0
  62. package/corpus/templates/design/.agents/skills/design-figma-parity/SKILL.md +116 -0
  63. package/corpus/templates/design/.generated/bridge/editor-chrome.generated.ts +183 -4
  64. package/corpus/templates/design/AGENTS.md +1 -0
  65. package/corpus/templates/design/app/components/design/bridge/editor-chrome.bridge.ts +252 -3
  66. package/corpus/templates/design/app/components/design/edit-panel/position-layout-properties.tsx +150 -11
  67. package/corpus/templates/design/app/components/design/edit-panel/selection-helpers.ts +12 -0
  68. package/corpus/templates/design/app/components/design/types.ts +13 -0
  69. package/corpus/templates/design/app/lib/design-editor-route.ts +11 -0
  70. package/corpus/templates/design/app/pages/design-editor/commands/editor-paste.ts +33 -29
  71. package/corpus/templates/design/app/pages/design-editor/editor-helpers.ts +18 -5
  72. package/corpus/templates/design/app/pages/design-editor/position-coordinate-context.ts +228 -0
  73. package/corpus/templates/design/changelog/2026-10-07-design-keeps-frame-relative-positions-and-selections-stable-.md +6 -0
  74. package/corpus/templates/design/changelog/2026-10-07-position-values-stay-aligned-with-selected-layers-in-layouts.md +6 -0
  75. package/corpus/templates/design/e2e/parity-oracle.ts +144 -0
  76. package/corpus/templates/design/parity/oracle/fig.canvas.evenly-spaced-row-drag.json +45 -0
  77. package/corpus/templates/design/parity/oracle/fig.canvas.overlap-drag.json +46 -0
  78. package/corpus/templates/design/parity/oracle/fig.canvas.position-relative-to-frame.json +57 -0
  79. package/corpus/templates/design/parity/oracle/fig.inspector.align-center-within-group.json +36 -0
  80. package/corpus/templates/design/parity/oracle/fig.inspector.align-left-within-group.json +43 -0
  81. package/corpus/templates/design/parity/oracle/fig.inspector.empty-effects-title.json +42 -0
  82. package/corpus/templates/design/parity/oracle/fig.inspector.empty-fill-title.json +41 -0
  83. package/corpus/templates/design/parity/oracle/fig.inspector.empty-stroke-title.json +39 -0
  84. package/corpus/templates/design/parity/oracle/fig.inspector.populated-section-title.json +41 -0
  85. package/corpus/templates/design/scripts/runtime-budget-zoom.ts +56 -0
  86. package/corpus/templates/design/scripts/runtime-budget.ts +49 -14
  87. package/corpus/templates/dispatch/.agents/skills/actions/SKILL.md +25 -0
  88. package/corpus/templates/dispatch/DEVELOPING.md +7 -0
  89. package/corpus/templates/factory/.agents/skills/actions/SKILL.md +25 -0
  90. package/corpus/templates/factory/.agents/skills/review-latest-feedback/SKILL.md +26 -39
  91. package/corpus/templates/forms/.agents/skills/actions/SKILL.md +25 -0
  92. package/corpus/templates/mail/.agents/skills/actions/SKILL.md +25 -0
  93. package/corpus/templates/plan/.agents/skills/actions/SKILL.md +25 -0
  94. package/corpus/templates/slides/.agents/skills/actions/SKILL.md +25 -0
  95. package/corpus/templates/tasks/.agents/skills/actions/SKILL.md +25 -0
  96. 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: 11315
35
+ - template files: 11341
@@ -107,6 +107,31 @@ An action that hands control back to the user (question form, intake dialog) set
107
107
 
108
108
  Reach for `outputSchema` (validate the return), `_agentImages` (attach images the agent can see), `authorize` (gate who may call it), or `needsApproval` (require human sign-off per call) only when the action needs that guarantee — examples in `references/action-fields.md`.
109
109
 
110
+ ### Write receipts
111
+
112
+ A write action that can check its own effect returns a plain-object result with a reserved `_receipt`, so the final answer is reconciled with what the write did, not with the model's reading of a JSON string that may be truncated:
113
+
114
+ ```ts
115
+ import type { WriteReceipt } from "@agent-native/core/action";
116
+
117
+ const _receipt: WriteReceipt = {
118
+ changed: true,
119
+ verified: false,
120
+ summary: "Saved; panel 3 returned no rows.",
121
+ checks: [{ id: "panel-3", ok: false, detail: "0 rows" }],
122
+ };
123
+ return { id, _receipt };
124
+ ```
125
+
126
+ `verified` is `true` (the effect was observed), `false` (checked and did not hold), or `"unverified"` (could not be checked); `checks` and `warnings` are optional. The agent loop reads the receipt before the result is stringified and truncated (summary 200 chars, 8 checks, 5 warnings):
127
+
128
+ - `verified: false` or `changed: false` forces one honest-reconciliation retry per turn: the model must say what the receipt shows and may not call the change visible or working. If the retry is spent, the answer is prefixed with the receipt block.
129
+ - `verified: "unverified"` only prefixes that note; no retry.
130
+ - A receipt that is present but malformed counts as `unverified`, never clean. `changed: false` also records the call as `completedSideEffect: false`.
131
+ - Set `subject` (the stable target, such as a dashboard id) so a later `changed: true, verified: true` receipt for the same subject can supersede an earlier flagged one in the same turn. When the earlier receipt had failing or unverified `checks`, the later receipts (from this action or another that writes the same subject) must carry an `ok: true` check with the same `id` for each; a receipt without checks never clears one that had them. A flagged receipt with no failing checks is superseded only by the same action. Receipts without a `subject` are never superseded.
132
+
133
+ A receipt is not an error channel. A write that did not achieve the requested state throws (`fail()`); return `changed: false` only for a benign no-op, such as the record already being in the requested state.
134
+
110
135
  ## Frontend Hooks
111
136
 
112
137
  Import from focused `@agent-native/core/client/*` entry points; the broad
@@ -98,6 +98,18 @@ Don't just dump raw data. Synthesize findings:
98
98
  - Make the evidence trail explicit enough to audit: source(s), time window,
99
99
  filters, sample size or row count, join/match method, caveats/gaps, and
100
100
  recommended next action when useful.
101
+ - Unstructured source records (Pylon tickets, Jira issues, Gong calls and
102
+ transcripts, Slack messages) are valid evidence: code them for themes, mention
103
+ counts, sentiment, and objections, state the inspected sample size, and do not
104
+ imply unsupported statistical certainty.
105
+ - The words all, total, or exact do not by themselves call for cross-source
106
+ validation when one structured query fully covers the requested source and
107
+ filters.
108
+ - If the user challenges coverage, asks why more records were not included, or
109
+ asks for the updated answer, rerun the source query or revise from the
110
+ corrected cohort and put the updated answer in the response. Do not claim a
111
+ dashboard was revised unless the revised answer is saved with
112
+ `update-dashboard` or `mutate-dashboard`.
101
113
 
102
114
  ### Step 4: Generate Charts (when useful)
103
115
 
@@ -1,10 +1,7 @@
1
1
  ---
2
2
  name: admin-surfaces
3
3
  description: >-
4
- The /agents admin home for Analytics: fleet feature-flag control plane,
5
- dashboard usage audit, and connected-app database admin. Use when an admin
6
- asks about feature flags/rollouts, dashboard usage stats, or connecting
7
- another agent-native app's database.
4
+ Use when an admin asks about feature flags and rollouts, dashboard usage stats, or connecting another app's database (the /agents admin home for Analytics).
8
5
  ---
9
6
 
10
7
  # Admin Surfaces (`/agents`)
@@ -1,10 +1,7 @@
1
1
  ---
2
2
  name: analysis-workspace
3
3
  description: >-
4
- How to use Resources-backed workspace files for large-scale multi-source
5
- analyses: scratch/ temporary staging, chunked batch processing with per-item
6
- memos, run-code aggregation, saveToFile for big API pulls, and synthesizing
7
- across files that exceed one context window.
4
+ Large analyses and file delivery: scratch staging, chunked batches, run-code aggregation, CSV/XLSX exports. Use when work exceeds one context window or the user wants a file.
8
5
  ---
9
6
 
10
7
  # Analysis Workspace
@@ -98,6 +95,9 @@ Inside `run-code`, use the workspace helper functions:
98
95
  CSV control. For a durable CSV, use `run-code` with `workspaceWrite` in a
99
96
  normal Resources folder, then call `show-workspace-file` with that path. If
100
97
  `run-code` is not available, discover it once with tool search.
98
+ - Deliver a requested CSV, Markdown, or other file in the same chat turn. Write
99
+ only verified successful data to a non-scratch workspace path, never an error
100
+ or failed response, and never finish with only a path or filename.
101
101
  - For an explicit `.xlsx` request, call `docs-search` once for `xlsx export`
102
102
  and follow the returned workflow. The QuickJS `run-code` sandbox has no Node
103
103
  imports; do not try to load `xlsx` or `exceljs` there.
@@ -1,9 +1,7 @@
1
1
  ---
2
2
  name: bigquery
3
3
  description: >-
4
- Query the configured BigQuery warehouse for analytics data. Use when the user
5
- asks for warehouse SQL, BigQuery tables, Amplitude-in-BigQuery events, or a
6
- metric/table that the data dictionary says lives in BigQuery.
4
+ Query the BigQuery warehouse. Use for warehouse SQL, BigQuery tables, Amplitude-in-BigQuery events, or a metric the data dictionary says lives in BigQuery.
7
5
  ---
8
6
 
9
7
  # BigQuery
@@ -1,10 +1,7 @@
1
1
  ---
2
2
  name: creative-context
3
3
  description: >-
4
- Reuse approved dashboards and creative context while respecting named
5
- contexts, immutable packs, provenance, and opt-out state. Use when building
6
- or refining a dashboard, or when the user references saved or approved
7
- context.
4
+ Reuse approved dashboards and creative context (named contexts, packs, provenance, opt-out). Use when building or refining a dashboard or citing saved context.
8
5
  scope: both
9
6
  requires-lab: creative-context.library
10
7
  metadata:
@@ -1,9 +1,7 @@
1
1
  ---
2
2
  name: cross-source-analysis
3
3
  description: >-
4
- Use when an analytics question spans multiple data sources (e.g. warehouse
5
- events + CRM + support + first-party) and you must stitch identities, remove
6
- duplicates, and produce one consolidated answer with per-source provenance.
4
+ Use when a question spans multiple sources (warehouse + CRM + support + first-party): stitch identities, remove duplicates, give one answer with per-source provenance.
7
5
  ---
8
6
 
9
7
  # Cross-Source Analysis
@@ -0,0 +1,198 @@
1
+ ---
2
+ name: custom-blocks
3
+ description: >-
4
+ Create, embed, clone, or repair a Custom Block (extension panel). Use for a bespoke visualization native panels cannot draw, or to fix or copy an extension-backed dashboard.
5
+ ---
6
+
7
+ # Custom Blocks
8
+
9
+ Analytics has one user-facing artifact type: dashboards. Build with native
10
+ dashboard panels and Data Programs first. A sandboxed extension embedded in a
11
+ dashboard is presented to users as a Custom Block, not as a separate Analytics
12
+ artifact.
13
+
14
+ Use native chart, table, metric, section, funnel, heatmap, callout, filter, and
15
+ layout capabilities whenever they can represent the request faithfully.
16
+ Reusable ROI, engagement, cross-sell, and win/loss dashboards compose these
17
+ native panels around real SQL or Data Program results. Use a Data Program when
18
+ the durable need is reusable fetching, transformation, or computed data that
19
+ native panels can render. Dual-axis charts are native (`config.rightYKeys`),
20
+ never an extension. Do not create a Custom Block merely because a request says
21
+ custom, asks for a dashboard, or would take more effort with native components.
22
+
23
+ ## When To Create One
24
+
25
+ Create a Custom Block only when the user explicitly asks for a genuinely
26
+ bespoke or one-off visualization or interaction, the native dashboard model
27
+ cannot represent it faithfully, and its intended scope is this dashboard.
28
+
29
+ - Create it with `create-extension`, immediately embed it as a
30
+ `chartType: "extension"` panel with `config.extensionId`, and set
31
+ `config.customBlock` to `{ authoredBy: "agent", intent: "one-off", scope: "dashboard", nativeGapReason: "custom-visualization" | "custom-interaction" | "custom-layout" | "other" }`.
32
+ Choose the narrow categorical reason; never put prompt text, customer data, or
33
+ other free text in this metadata.
34
+ - Use the host theme CSS variables and match the dashboard typography, card
35
+ spacing, and density so the sandboxed content reads as an agent-authored patch
36
+ to Analytics instead of a foreign mini-app. Describe it as a sandboxed,
37
+ agent-authored dashboard patch.
38
+ - Never leave it standalone or direct the user to an Extensions page.
39
+ - A Custom Block is a fast runtime patch, not the durable destination for
40
+ reusable product behavior. If the request should work across dashboards or
41
+ users, changes app chrome or business logic, adds a reusable chart type, needs
42
+ native accessibility/export/governance, or explicitly asks for app code, a PR,
43
+ or a native feature, call `connect-builder` with the request verbatim instead
44
+ of creating a Custom Block. If scope is ambiguous, ask whether the user wants a
45
+ one-off block for this dashboard or a reusable app feature.
46
+ - When the user chooses Promote to app code, preserve the existing Custom Block
47
+ and pass its dashboard id, panel id, extension id, and requested native
48
+ placement through `connect-builder`; do not delete or replace the block until
49
+ the native implementation is reviewed and deployed.
50
+ - Legacy analyses and existing extension-backed dashboards remain readable and
51
+ editable for compatibility.
52
+
53
+ An explicit request to build one authorizes every non-destructive step in the
54
+ same turn: query or scaffold, seed extension data (`extension-data-set`), save,
55
+ embed, and `navigate`. Do not leave an empty shell or ask whether to proceed.
56
+
57
+ ## Extension Data Boundary
58
+
59
+ Code inside a Custom Block runs in an iframe and may call only actions that are
60
+ HTTP-mounted and intended for `appAction`. Use the canonical `bigquery` action
61
+ for warehouse SQL; never call `query-agent-native-analytics`,
62
+ `bigquery-table-info`, or another `http: false` agent-only action from extension
63
+ code. For first-party Analytics data, prefer a native `source: "first-party"`
64
+ panel, or query it as the agent and seed the extension data store.
65
+
66
+ ## Embedding An Extension As A Panel
67
+
68
+ Use `chartType: "extension"` to add an extension box alongside normal SQL
69
+ charts. The panel skips `source` and `sql`. For ordinary requests such as "put
70
+ X in this dashboard," save the author-selected extension id in
71
+ `config.extensionId`. This makes the selection part of the shared dashboard and
72
+ keeps the widget present in scheduled report captures:
73
+
74
+ ```jsonc
75
+ {
76
+ "id": "pipeline-widget",
77
+ "title": "Pipeline Widget",
78
+ "chartType": "extension",
79
+ "width": 3,
80
+ "config": { "extensionId": "extension-123" },
81
+ }
82
+ ```
83
+
84
+ Direct embeds receive the dashboard id, name, description, current filters, and
85
+ panel context. Embedding does not grant extension access, so share the
86
+ extension with the dashboard audience (`share-resource --resourceType
87
+ extension ...`); otherwise viewers see an "extension unavailable" placeholder.
88
+
89
+ Use a stable `config.extensionSlotId` only when the user explicitly wants each
90
+ viewer to choose or install their own widget:
91
+
92
+ ```text
93
+ analytics.dashboard.<dashboard-id>.panel.<panel-id>
94
+ ```
95
+
96
+ Create or choose the extension, call `add-extension-slot-target` with the
97
+ extension id and slot id, then call `install-extension` with the same values.
98
+ The dashboard panel is shared, while the installed extension is per-user. Empty
99
+ slots show the normal install affordance instead of a broken iframe.
100
+
101
+ ```jsonc
102
+ {
103
+ "id": "pipeline-widget",
104
+ "title": "Pipeline Widget",
105
+ "chartType": "extension",
106
+ "width": 3,
107
+ "config": {
108
+ "extensionSlotId": "analytics.dashboard.weekly-metrics.panel.pipeline-widget",
109
+ },
110
+ }
111
+ ```
112
+
113
+ - Both direct and slot-backed extensions receive dashboard and panel context.
114
+ - Installs and extension access are per viewer. Slot installs are per-user
115
+ preferences, so different viewers can see different widgets and scheduled
116
+ reports running as a service identity may show an empty slot. This is why
117
+ slots are opt-in rather than the default.
118
+ - Inspect an existing Custom Block through the `get-sql-dashboard` panel
119
+ summaries (`extensionId`, `extensionSlotId`).
120
+
121
+ ## Cloning A Direct-Extension Dashboard (e.g. per-customer copies)
122
+
123
+ When the user asks for a copy of an existing extension-backed dashboard for a
124
+ different customer/org (for example "make an Intuit version of the Roku usage
125
+ dashboard"), follow this playbook. Extension bodies are frequently tens of
126
+ thousands of characters. The reliable path is to read+transform+write the body
127
+ INSIDE `run-code` (where `workspaceRead` returns the full file) and then create
128
+ from that written file — never by pulling the body into chat context first or
129
+ re-typing it as a `content` argument.
130
+
131
+ 1. `get-sql-dashboard` on the source dashboard (pass the extension panel's id in
132
+ `panelIds`) and confirm the target panel is a `chartType: "extension"` panel
133
+ with `config.extensionId`; grab that extension id. For a slot-backed panel,
134
+ clone the dashboard panel with a new stable `extensionSlotId`, then target
135
+ and install the desired extension into that slot instead of using this
136
+ body-copy playbook.
137
+ 2. `get-extension` for that id with `forceContent: true` **exactly once**. Reuse
138
+ that body for the rest of the turn — a second same-run read intentionally
139
+ omits `content` and returns `contentOmitted` instead. That is not the content
140
+ disappearing; use the copy you already have. Do NOT try to re-fetch the body
141
+ with `run-code` (`appAction('get-extension')`) to page past a display
142
+ truncation — the same-run omit makes it return empty `content`, wasting turns.
143
+ If you need the full body again, read the workspace resource file (step 5) or
144
+ set `forceContent: true` on a single native `get-extension`.
145
+ 3. Change ONLY the small customer-specific static config (e.g. the
146
+ `ACCOUNT_USAGE_STATIC` block: company name, title, org-discovery filters,
147
+ messaging). Prefer a focused `update-extension` edit/patch over regenerating
148
+ the entire HTML.
149
+ 4. **Call `create-extension` / `update-extension` as native tools.** They are
150
+ mutating actions and are NOT callable from `run-code` / `appAction` (the
151
+ sandbox bridge only exposes read-only actions). Do not try to create or update
152
+ an extension from inside `run-code`.
153
+ 5. **If the source body already exists as a workspace/shared resource file**
154
+ (e.g. a pre-built `intuit-analytics-extension.html`), do the read AND the
155
+ customer swap in ONE `run-code` call, then create from the written file:
156
+ - Inside `run-code`: `const src = await workspaceRead('<source>.html')`
157
+ returns the WHOLE file (it auto-pages; there is no 50k cap here), do the
158
+ small string-replace on the static config block, then
159
+ `await workspaceWrite('<target>.html', modified)`.
160
+ - Then call `create-extension` (native) with
161
+ `contentFromWorkspaceFile: '<target>.html'` and leave `content` empty — the
162
+ server reads the full file verbatim.
163
+ Do NOT read the source body with the `resources` read tool (or `get-extension`)
164
+ first just to transform it: that display is capped and wastes a turn. And do
165
+ NOT re-emit an 80k+ char body as the `content` argument — it gets cut off
166
+ mid-stream. `contentFromAttachment` only sees files the user pasted into chat,
167
+ not workspace resources. `create-extension`/`update-extension` are mutating and
168
+ cannot run from `run-code`, so only the read+write+transform happens there.
169
+ 6. Finally save a new dashboard embedding the new extension panel
170
+ (`chartType: "extension"`, `config.extensionId`) with `update-dashboard`, then
171
+ `navigate` to it.
172
+
173
+ ## Repairing An Existing Extension-Backed Dashboard
174
+
175
+ When the user asks to fix data loading in an existing or migrated
176
+ extension-backed dashboard, treat the current extension body as user-authored
177
+ design. Read the dashboard config and extension once, identify the smallest
178
+ data-loading seam, and call `update-extension` with exactly `id`,
179
+ `operation="edit"`, and a `payloadJson` string containing focused
180
+ `patches`/`edits` that change only that seam. Never send empty placeholder
181
+ fields. Preserve the existing layout, CSS, copy, and interactions. Do not send a
182
+ reconstructed full `content` body for a data-only repair.
183
+
184
+ A request that combines a visual rewrite (compacting, removing sections,
185
+ renaming, changing padding) with a data repair is a broad rewrite: after
186
+ inspecting the current extension, use `operation="replace"` with the complete
187
+ replacement in `payloadJson`. If a focused edit fails, inspect the current body
188
+ and change the target rather than retrying the same arguments.
189
+
190
+ ### Display truncation is cosmetic — do not chase the "missing" tail
191
+
192
+ A tool result ending in `...[truncated — full result was N chars; only first
193
+ 50,000 shown]` (from the `resources` read tool or `get-extension`) means only the
194
+ DISPLAYED text was capped. The file is intact. `run-code`'s `workspaceRead`
195
+ returns the full N chars, and `contentFromWorkspaceFile` hosts the full file.
196
+ Never read the same file twice or try to "page the rest" to recover the tail —
197
+ that is the single biggest source of wasted turns on clone requests. Decide to
198
+ clone, then go straight to the `run-code` read+transform+write path in step 5.