@uptimizr/agent-core 1.1.0 → 1.2.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 (63) hide show
  1. package/AGENTS.md +238 -25
  2. package/README.md +57 -21
  3. package/dist/client.d.ts +22 -5
  4. package/dist/client.d.ts.map +1 -1
  5. package/dist/client.js +39 -10
  6. package/dist/client.js.map +1 -1
  7. package/dist/context.d.ts +93 -0
  8. package/dist/context.d.ts.map +1 -0
  9. package/dist/context.js +137 -0
  10. package/dist/context.js.map +1 -0
  11. package/dist/index.d.ts +10 -3
  12. package/dist/index.d.ts.map +1 -1
  13. package/dist/index.js +20 -2
  14. package/dist/index.js.map +1 -1
  15. package/dist/nonRegistryTools.d.ts +34 -0
  16. package/dist/nonRegistryTools.d.ts.map +1 -0
  17. package/dist/nonRegistryTools.js +70 -0
  18. package/dist/nonRegistryTools.js.map +1 -0
  19. package/dist/prompt.d.ts +33 -0
  20. package/dist/prompt.d.ts.map +1 -0
  21. package/dist/prompt.js +49 -0
  22. package/dist/prompt.js.map +1 -0
  23. package/dist/provider.d.ts +18 -0
  24. package/dist/provider.d.ts.map +1 -1
  25. package/dist/providers/anthropic.d.ts +18 -1
  26. package/dist/providers/anthropic.d.ts.map +1 -1
  27. package/dist/providers/anthropic.js +35 -3
  28. package/dist/providers/anthropic.js.map +1 -1
  29. package/dist/providers/openai.d.ts +14 -1
  30. package/dist/providers/openai.d.ts.map +1 -1
  31. package/dist/providers/openai.js +23 -1
  32. package/dist/providers/openai.js.map +1 -1
  33. package/dist/queryTool.d.ts +36 -0
  34. package/dist/queryTool.d.ts.map +1 -0
  35. package/dist/queryTool.js +123 -0
  36. package/dist/queryTool.js.map +1 -0
  37. package/dist/registryTools.d.ts +23 -1
  38. package/dist/registryTools.d.ts.map +1 -1
  39. package/dist/registryTools.js +185 -31
  40. package/dist/registryTools.js.map +1 -1
  41. package/dist/skills.d.ts +105 -0
  42. package/dist/skills.d.ts.map +1 -0
  43. package/dist/skills.generated.d.ts +44 -0
  44. package/dist/skills.generated.d.ts.map +1 -0
  45. package/dist/skills.generated.js +511 -0
  46. package/dist/skills.generated.js.map +1 -0
  47. package/dist/skills.js +144 -0
  48. package/dist/skills.js.map +1 -0
  49. package/dist/tools.d.ts +55 -8
  50. package/dist/tools.d.ts.map +1 -1
  51. package/dist/tools.js +41 -1
  52. package/dist/tools.js.map +1 -1
  53. package/dist/writeTools.d.ts +68 -0
  54. package/dist/writeTools.d.ts.map +1 -0
  55. package/dist/writeTools.js +256 -0
  56. package/dist/writeTools.js.map +1 -0
  57. package/llms.txt +164 -15
  58. package/package.json +7 -5
  59. package/skills/attention-hotspots/SKILL.md +88 -0
  60. package/skills/conversion-investigation/SKILL.md +97 -0
  61. package/skills/performance-regression-triage/SKILL.md +106 -0
  62. package/skills/weekly-scene-health/SKILL.md +105 -0
  63. package/skills/xr-comfort-audit/SKILL.md +95 -0
@@ -0,0 +1,511 @@
1
+ /**
2
+ * GENERATED FILE — do not edit.
3
+ *
4
+ * Compiled from `oss/packages/agent-core/skills/<name>/SKILL.md` by
5
+ * `scripts/gen-agent-skills.mjs`. Edit the SKILL.md file and run
6
+ * `pnpm gen:skills`; `pnpm gen:skills:check` is the CI gate.
7
+ *
8
+ * This module is data only. `skills.ts` turns it into the renderable
9
+ * {@link ./skills.js#AGENT_SKILLS} every consumer uses, which is why nothing
10
+ * here touches `node:fs` — `@uptimizr/agent-core` stays browser-safe.
11
+ */
12
+ /** Every packaged skill, in catalog (directory-name) order. */
13
+ export const GENERATED_AGENT_SKILLS = [
14
+ {
15
+ id: "attention-hotspots",
16
+ name: "attention_hotspots",
17
+ title: "Attention hot-spots for a scene",
18
+ description: "Find where visitors look and click in a scene: view-direction concentration, gaze→mesh flow, the objects that draw the most interaction, and the ones nobody ever notices. USE FOR: deciding where to put a call to action, finding ignored or invisible content, explaining why an object gets no clicks, laying out a scene around what people actually look at. Trigger phrases: what do people look at, attention hotspots, where do visitors click, which meshes get ignored, blind spots, gaze heatmap, is anyone seeing this object.",
19
+ tools: [
20
+ "camera_heatmap",
21
+ "flow_links",
22
+ "click_rays",
23
+ "top_meshes",
24
+ "mesh_dwell",
25
+ "mesh_blind_spots",
26
+ "query",
27
+ ],
28
+ capabilities: ["query"],
29
+ args: [
30
+ {
31
+ name: "scene",
32
+ description: "The scene id to analyse (see the uptimizr://scenes resource).",
33
+ required: true,
34
+ },
35
+ {
36
+ name: "range",
37
+ description: 'The window to analyse, in words — e.g. "the last 7 days", "since launch".',
38
+ required: false,
39
+ default: "the last 7 days",
40
+ },
41
+ ],
42
+ body: [
43
+ 'Where does attention concentrate in scene "{{scene}}" over {{range}}?',
44
+ "",
45
+ "Work through the method below with the read-only tools it names — all of them scoped with",
46
+ '`scene="{{scene}}"` — and synthesise one answer.',
47
+ "",
48
+ "1. **Orient before you ask anything.** Read the `uptimizr://context` resource first: it gives the",
49
+ " real scene ids, the scene's **named regions** and the custom-event names this project emits, and",
50
+ " it tells you which metrics are empty because their capture channel is off. Name regions the way",
51
+ ' the project names them — "the checkout counter", not "the cluster at x≈3".',
52
+ "",
53
+ '2. **Where do they look?** `camera_heatmap` (`scene="{{scene}}"`) gives the view-direction',
54
+ " distribution — what people point the camera at, whether or not they ever click it. Ask for",
55
+ ' `format: "summary"`: the digest merges neighbouring cells into a handful of clusters with a',
56
+ " share each and a plain-language `reading`, which is what you want here; the raw grid is",
57
+ " thousands of cells you cannot describe.",
58
+ "",
59
+ '3. **Does looking turn into touching?** `flow_links` (`scene="{{scene}}"`) links where the gaze was',
60
+ " to the mesh that was then clicked. A strong link is a working call to action; a heavy look with",
61
+ " no outgoing link is content that draws the eye and then disappoints.",
62
+ "",
63
+ '4. **Where do the clicks land?** `click_rays` (`scene="{{scene}}"`) gives view-gated clicks per',
64
+ " voxel and mesh — clicks attributed to what the visitor could actually see, not to whatever the",
65
+ " ray happened to pass through.",
66
+ "",
67
+ '5. **Rank the objects.** `top_meshes` (`scene="{{scene}}"`) for the most-interacted meshes, and',
68
+ ' `mesh_dwell` (`scene="{{scene}}"`) for how long attention rests on each one. Dwell without',
69
+ " interaction is hesitation, and it usually means the object looks clickable and is not, or is",
70
+ " clickable and does not look it.",
71
+ "",
72
+ '6. **Name the cold half.** `mesh_blind_spots` (`scene="{{scene}}"`) lists the meshes that are',
73
+ " present and essentially never noticed. A hot-spot report that only names hot spots tells you",
74
+ " nothing about the content you paid to build.",
75
+ "",
76
+ "7. **Narrow it with the DSL.** For anything the canned tools do not expose, use the single `query`",
77
+ ' tool: pick the `metric`, bound it with `range`, filter it, and set `format: "summary"` for a',
78
+ " bounded digest — each summary row carries a `drillQuery` you can send straight back instead of",
79
+ " rebuilding the filter. Set `compare: { range: <previous window> }` to see whether a hot spot is",
80
+ " new, and `explain: true` when a result looks wrong or empty: the plan names the capture channel,",
81
+ " the sample size and the row cap behind it.",
82
+ "",
83
+ "## What to report",
84
+ "",
85
+ "- The two or three real hot-spots, named with the project's own region and mesh names, each with",
86
+ " its share of attention.",
87
+ "- The cold areas and the meshes nobody notices.",
88
+ "- Where gaze fails to convert into interaction, and what that implies for layout and",
89
+ " call-to-action placement.",
90
+ "",
91
+ "Carry the caveats: heatmaps are gated on the view/pointer capture channels and are sampled",
92
+ "(ADR 0012), so a share is a share _of the sampled events_; say so, and say when a result was",
93
+ "truncated (`meta.truncated`) or sits below the metric's own minimum sample. Do not turn a voxel",
94
+ "cluster into a claim about one object unless `click_rays` or `flow_links` attributes it to that",
95
+ "mesh.",
96
+ "",
97
+ "End with 2–3 concrete layout or content recommendations. If an `annotate` tool is available, leave",
98
+ "a note on the region you want revisited — a region-scoped annotation is what makes the next report",
99
+ "open where this one ended. If a `pin_panel` tool is available, pin the heatmap panel you reasoned",
100
+ "from.",
101
+ ].join("\n"),
102
+ },
103
+ {
104
+ id: "conversion-investigation",
105
+ name: "conversion_investigation",
106
+ title: "Conversion investigation",
107
+ description: 'Find out where a funnel loses people and whether the loss is real: step-by-step drop-off, the bounce that happens before the funnel even starts, scene-to-scene retention, variant performance, and the interaction failures (dead clicks, rage clicks, unreachable meshes) that explain a stalled step. USE FOR: a funnel that converts worse than expected, an A/B variant comparison, "where do people drop off", diagnosing a step nobody completes. Trigger phrases: conversion, funnel, drop-off, why are people leaving, which variant wins, bounce rate, retention, people get stuck.',
108
+ tools: [
109
+ "funnel",
110
+ "load_bounce_funnel",
111
+ "scene_retention",
112
+ "variant_leaderboard",
113
+ "dead_clicks",
114
+ "rage_clicks",
115
+ "mesh_reachability",
116
+ "flow_links",
117
+ "insight_significance",
118
+ "insight_movers",
119
+ "query",
120
+ ],
121
+ capabilities: ["query"],
122
+ args: [
123
+ {
124
+ name: "scene",
125
+ description: "Optional scene id to scope the investigation to (see the uptimizr://scenes resource).",
126
+ required: false,
127
+ },
128
+ {
129
+ name: "range",
130
+ description: 'The window to investigate, in words — e.g. "the last 7 days", "since the release".',
131
+ required: false,
132
+ default: "the last 7 days",
133
+ },
134
+ ],
135
+ body: [
136
+ "Investigate conversion for {{scope}} over {{range}}: where do people drop off, and is the drop real?",
137
+ "",
138
+ "Work through the method below with the read-only tools it names, then answer.",
139
+ "",
140
+ "1. **Orient before you ask anything.** Read the `uptimizr://context` resource first. A funnel is",
141
+ " built out of **this project's own event types and custom-event names** — invent one and every",
142
+ " step reads zero. The context document lists the vocabulary the application actually emits, the",
143
+ " real scene ids, and which metrics are empty because their capture channel is off.",
144
+ "",
145
+ '2. **Check the step before the first step.** `load_bounce_funnel`{{#scene}} (`scene="{{scene}}"`){{/scene}}',
146
+ " measures load → first interaction → stay. If people leave before the funnel starts, nothing",
147
+ ' inside it will explain the number, and a "conversion problem" is really a load or a first-impression',
148
+ " problem.",
149
+ "",
150
+ '3. **Run the funnel itself.** `funnel`{{#scene}} (`scene="{{scene}}"`){{/scene}} with the `steps`',
151
+ " built from the context document's vocabulary. Read it as the _transition_ rates, not the totals:",
152
+ " the step with the worst step-to-step rate is the one to investigate, even when a later step has",
153
+ " fewer people in absolute terms.",
154
+ "",
155
+ '4. **Follow them out of the scene.** `scene_retention`{{#scene}} (`scene="{{scene}}"`){{/scene}}',
156
+ ' shows where a visitor goes next. A step that "loses" people to the next scene is not a loss at',
157
+ " all; one that loses them to nothing is.",
158
+ "",
159
+ "5. **Explain the stalled step.** At the worst step, look for interaction failure rather than",
160
+ " intent: `dead_clicks` (clicks that hit nothing actionable), `rage_clicks` (repeated clicking in",
161
+ " one spot — frustration you can locate), `mesh_reachability` (the target is too far away or",
162
+ " behind something to be clicked at all) and `flow_links` (people look at the target and never",
163
+ " click it). One of these usually _is_ the drop-off.",
164
+ "",
165
+ "6. **Compare variants honestly.** `variant_leaderboard` ranks variants by conversion. A leaderboard",
166
+ " is not a verdict: check each variant's sample size before repeating its rate, and say plainly",
167
+ " when two variants are too close or too small to separate. `insight_significance` can test a",
168
+ " metric with a portable bucket series across two **windows**; it does not test one segment against",
169
+ " another, and if you ask it to it will say so — report that limitation rather than inventing a",
170
+ " p-value.",
171
+ "",
172
+ '7. **See whether this is new.** `insight_movers`{{#scene}} (`scene="{{scene}}"`){{/scene}} ranks',
173
+ ' what changed against the previous equal window, so you can tell "this funnel has always been bad"',
174
+ ' from "this funnel broke last Tuesday". Ignore any row with `aboveMinSample: false`.',
175
+ "",
176
+ "8. **Use the DSL for the cuts the canned tools do not expose.** The single `query` tool takes a",
177
+ " `metric`, a `range`, that metric's filters, and `compare: { range: <previous window> }` to return",
178
+ " `{ current, previous, delta, deltaPct }` already joined — do not subtract two runs by hand. Use",
179
+ " `dimensions` to regroup a portable count (by device class, source or scene) and",
180
+ ' `format: "summary"` for a bounded digest with a `reading` and a `drillQuery` per row. When a step',
181
+ " reads zero, re-send it with `explain: true` before reporting it: the plan will tell you whether",
182
+ " the number is real or whether the channel behind it is switched off.",
183
+ "",
184
+ "## What to report",
185
+ "",
186
+ "- The step that actually loses people, with its entry and exit counts and its transition rate.",
187
+ "- The mechanism, named: dead clicks on a specific mesh, an unreachable target, a bounce before the",
188
+ " first interaction, or a genuine loss of interest.",
189
+ "- What each variant did, with sample sizes, and whether the difference can be told apart from noise.",
190
+ "",
191
+ "Carry the caveats into the text: funnel steps are only as good as the event vocabulary they were",
192
+ "built from, a rate over a handful of sessions is not a rate, `meta.truncated` means you are looking",
193
+ 'at a cut-off list, and a disabled capture channel produces a zero that means "not measured".',
194
+ "",
195
+ "End with 2–3 concrete recommendations tied to the step and the mesh they apply to. If an `annotate`",
196
+ "tool is available, leave a note on the failing step so the next investigation starts there, and use",
197
+ "`save_analysis` to store the funnel definition you settled on — the next run should not have to",
198
+ "guess the steps again. If a `pin_panel` tool is available, pin the funnel panel.",
199
+ ].join("\n"),
200
+ },
201
+ {
202
+ id: "performance-regression-triage",
203
+ name: "performance_regression_triage",
204
+ title: "Performance regression triage",
205
+ description: 'Triage a frame-rate or stability regression: confirm it moved, date it, locate it (which scene, device class, place in the scene), and name the mechanism — jank, shader compile stalls, memory pressure, a render-scale change or a rendering-technology shift. USE FOR: "the app got slower", a FPS drop after a release, stutter reports, deciding whether a regression is real or noise. Trigger phrases: performance regression, FPS dropped, why is it slow, stutter, jank, frame drops, did the last release slow things down, triage performance.',
206
+ tools: [
207
+ "insight_movers",
208
+ "insight_anomalies",
209
+ "insight_significance",
210
+ "insight_baseline",
211
+ "perf_summary",
212
+ "perf_distribution",
213
+ "frame_time_percentiles",
214
+ "jank_rate",
215
+ "perf_by_device",
216
+ "perf_by_scene",
217
+ "perf_heatmap",
218
+ "compile_stalls",
219
+ "resource_percentiles",
220
+ "render_scale_truth",
221
+ "rendering_technology",
222
+ "query",
223
+ ],
224
+ capabilities: ["query"],
225
+ args: [
226
+ {
227
+ name: "scene",
228
+ description: "Optional scene id to scope the triage to (see the uptimizr://scenes resource).",
229
+ required: false,
230
+ },
231
+ {
232
+ name: "range",
233
+ description: 'The window to triage, in words — e.g. "the last 14 days", "since the release".',
234
+ required: false,
235
+ default: "the last 14 days",
236
+ },
237
+ ],
238
+ body: [
239
+ "Triage the performance regression in {{scope}} over {{range}}: is it real, when did it start, who",
240
+ "does it hit, and what is causing it?",
241
+ "",
242
+ "Work through the method below with the read-only tools it names, then answer.",
243
+ "",
244
+ "1. **Orient before you ask anything.** Read the `uptimizr://context` resource first: the real scene",
245
+ " ids, the data freshness, and which metrics are empty because their capture channel is off. A",
246
+ " performance channel that was never enabled looks exactly like a scene with no problem.",
247
+ "",
248
+ '2. **Confirm something moved.** `insight_movers`{{#scene}} (`scene="{{scene}}"`){{/scene}} ranks',
249
+ " every comparable metric against the previous equal window by how unusual the change is. Read",
250
+ " `direction` with the sign of `delta` — a _rise_ in jank or errors is a regression — and drop any",
251
+ " row with `aboveMinSample: false`.",
252
+ "",
253
+ "3. **Ask whether the new level is outside normal.** `insight_baseline` on `perf_summary` gives the",
254
+ " project's own median and spread; compare the new reading with `median` give or take a few `mad`,",
255
+ ' or with the p10..p90 band. Frame rates are noisy, and "down 6 FPS" is routine in some projects',
256
+ " and an incident in others.",
257
+ "",
258
+ "4. **Prove it rather than asserting it.** `insight_significance` on the metric that moved reports",
259
+ " the effect, a 95 % interval and a p-value across the two windows. An interval straddling 0 means",
260
+ ' you cannot tell yet; `powerNote` says what this much data could have detected at all. Say "not',
261
+ ' yet distinguishable from noise" when that is the truth — it is a finding.',
262
+ "",
263
+ "5. **Put a date on it.** `insight_anomalies` (`metric=perf_summary`, `window=28`{{#scene}},",
264
+ ' `scene="{{scene}}"`{{/scene}}) separates a one-day `spike`/`drop` from a `shift` — a level that',
265
+ " changed and stayed changed, which is what a release looks like. Quote the `bucketStart` and the",
266
+ " `contributor`. For the day-by-day shape around that date, ask the `query` tool for",
267
+ ' `metric: "perf_daily"` — it is a registry metric with no canned tool of its own.',
268
+ "",
269
+ "6. **Locate it.** `perf_by_scene` (which scene), `perf_by_device` (which device class — a",
270
+ " regression that only hits low-end hardware is a different bug from one that hits everyone), and",
271
+ ' `perf_heatmap`{{#scene}} (`scene="{{scene}}"`){{/scene}} for _where in the scene_ the frames are',
272
+ ' being lost. Ask for `format: "summary"` on the heatmap: merged clusters with shares, not a grid.',
273
+ "",
274
+ '7. **Name the mechanism.** `frame_time_percentiles` and `jank_rate` separate "uniformly slower"',
275
+ ' from "occasionally catastrophic" — the second is what users report and the average hides.',
276
+ " `perf_distribution` shows whether the whole population shifted or a tail got worse.",
277
+ " `compile_stalls` finds shader/pipeline compilation blocking the first seconds.",
278
+ " `resource_percentiles` finds GPU/memory pressure. `render_scale_truth` catches a resolution",
279
+ " change quietly doing the work the frame rate is getting credit for, and `rendering_technology`",
280
+ ' catches a shift in the engine/renderer mix between the two windows — a "regression" that is',
281
+ " really a change in who is measuring.",
282
+ "",
283
+ "8. **Cut it any way you need with the DSL.** The single `query` tool takes a `metric`, a `range`,",
284
+ " that metric's filters and `compare: { range: <the window before the shift> }`, returning",
285
+ " `{ current, previous, delta, deltaPct }` already joined — never subtract two runs yourself. Use",
286
+ ' `dimensions` to regroup a portable count, `format: "summary"` for a bounded digest with a',
287
+ " `reading` and a per-row `drillQuery`, and `explain: true` whenever a number looks impossible:",
288
+ " the plan names the sample size, the row cap and every capture channel that could make it lie.",
289
+ "",
290
+ "## What to report",
291
+ "",
292
+ "- Whether the regression is real, with the effect, the interval and the honest verdict when it is",
293
+ " not yet distinguishable from noise.",
294
+ "- The date it started and whether it is a spike or a sustained shift.",
295
+ "- Who it hits: scene, device class, and where in the scene.",
296
+ "- The mechanism, named, with the metric that shows it.",
297
+ "",
298
+ "Carry the caveats: percentiles below the metric's minimum sample, a session count too small to",
299
+ "generalise, sampled capture (ADR 0012), truncated results, and any device class whose share of",
300
+ "traffic changed between the windows — a mix shift moves the average without anything getting slower.",
301
+ "",
302
+ "End with 2–3 concrete recommendations naming the scene, the device class or the asset they apply",
303
+ "to. If an `annotate` tool is available, leave a dated note on the shift so the next report can see",
304
+ "what happened; `save_analysis` keeps the triage for the post-mortem. If a `pin_panel` tool is",
305
+ "available, pin the panel that shows the regression.",
306
+ ].join("\n"),
307
+ },
308
+ {
309
+ id: "weekly-scene-health",
310
+ name: "weekly_scene_health",
311
+ title: "Weekly scene health",
312
+ description: 'A weekly health check for a scene (or the whole project): a weighted health score with every factor traced back to the metric behind it, what changed against last week, traffic, event mix, performance, and the most-interacted meshes. USE FOR: the recurring "how is the scene doing?" review, a scheduled weekly or monthly report, a first look at a project you do not know yet, deciding which scene to investigate next. Trigger phrases: weekly report, scene health, how is my scene doing, what changed this week, health check, monthly review, status report.',
313
+ tools: [
314
+ "insight_scene_health",
315
+ "insight_movers",
316
+ "insight_baseline",
317
+ "insight_significance",
318
+ "insight_anomalies",
319
+ "event_counts",
320
+ "timeseries",
321
+ "perf_summary",
322
+ "top_meshes",
323
+ "list_sessions",
324
+ "query",
325
+ ],
326
+ capabilities: ["query"],
327
+ args: [
328
+ {
329
+ name: "scene",
330
+ description: "Optional scene id to scope the analysis to (see the uptimizr://scenes resource).",
331
+ required: false,
332
+ },
333
+ {
334
+ name: "range",
335
+ description: 'The window to report on, in words — e.g. "the last 7 days", "June".',
336
+ required: false,
337
+ default: "the last 7 days",
338
+ },
339
+ ],
340
+ body: [
341
+ "Give me a weekly health report for {{scope}} covering {{range}}.",
342
+ "",
343
+ "Work through the method below with the read-only tools it names, then summarise the findings.",
344
+ "",
345
+ "1. **Orient before you ask anything.** Read the `uptimizr://context` resource first: it gives the",
346
+ " real scene ids, region ids and custom-event names for this project, and tells you which metrics",
347
+ " are empty because their capture channel is off. Use its ids instead of inventing your own, and",
348
+ " never report a switched-off channel's zero as a finding.",
349
+ "",
350
+ "2. **Start from the score, not the numbers.** Call `insight_scene_health`{{#scene}} with",
351
+ ' `scene="{{scene}}"`{{/scene}}: it scores each scene 0–100 over six weighted factors — perf',
352
+ " stability, jank, errors, dead clicks, coverage and XR abandonment — so you start from _which_",
353
+ " scene to look at. Open the lowest-scoring scene first, then the factor whose own score is",
354
+ " furthest below 50. Every factor names the `metric` behind it, its `raw` value and the project",
355
+ " `baseline` it was compared with, so the sentence you write is already in the row. 50 is the",
356
+ " project norm, not a pass mark, and a factor with `score: null` was not counted — its `note`",
357
+ " says why.",
358
+ "",
359
+ '3. **Find out what moved.** Call `insight_movers`{{#scene}} (`scene="{{scene}}"`){{/scene}}: it',
360
+ " compares every comparable metric with the previous equal window and ranks the changes by how",
361
+ " unusual each one is, so start from what actually moved instead of re-deriving it. Read",
362
+ " `direction` together with the sign of `delta` — a rise in a `down` metric (errors, dead clicks,",
363
+ " jank) is a regression — and do not report any row with `aboveMinSample: false`: its delta is",
364
+ " real arithmetic but not evidence.",
365
+ "",
366
+ "4. **Ask whether the new level is even unusual.** For each metric that moved, call",
367
+ " `insight_baseline` and compare the new value with `median` give or take a few `mad`, or with",
368
+ ' the p10..p90 band. "Down 12 %" means nothing until you know the week-to-week spread.',
369
+ "",
370
+ "5. **Before calling any single change real, test it.** `insight_significance` reports the effect,",
371
+ " a 95 % interval and a p-value for one metric across the two windows. An interval that straddles",
372
+ " 0 means you cannot tell yet, whatever the p-value says, and `powerNote` states what this much",
373
+ " data could have detected at all.",
374
+ "",
375
+ "6. **Put a date on it.** Call `insight_anomalies` (`metric=perf_summary`, then `error_heatmap`{{#scene}},",
376
+ ' `scene="{{scene}}"`{{/scene}}, `window=28`): it returns the individual days that were out of line',
377
+ " (`spike` / `drop`) and the day a level changed and stayed changed (`shift`), with `contributor`",
378
+ " naming the mesh, channel or source holding most of the excess. Quote the `bucketStart` and the",
379
+ ' `contributor` rather than saying "recently".',
380
+ "",
381
+ '7. **Fill in the picture.** `event_counts` for the per-event-type mix{{#scene}} (`scene="{{scene}}"`){{/scene}};',
382
+ " `timeseries` (`interval` ≈ 86400 s) for day-by-day volume and the average-FPS trend;",
383
+ " `perf_summary` for avg/min/p50 FPS; `top_meshes` for the most-interacted meshes; `list_sessions`",
384
+ " for how many sessions were recorded.",
385
+ "",
386
+ "8. **Drill with the DSL, not with arithmetic.** When a canned tool does not expose the filter you",
387
+ " need, use the single `query` tool: pick the `metric`, bound it with `range`, and set",
388
+ " `compare: { range: <previous week> }` so the collector returns",
389
+ " `{ current, previous, delta, deltaPct }` already joined — never run two queries and subtract",
390
+ " them yourself. `dimensions` regroups a portable count (event, mesh, input-source and gesture",
391
+ ' tallies) without a new tool. Ask for `format: "summary"` on anything long or spatial: it comes',
392
+ " back as a bounded digest with shares, a plain-language `reading`, and a `drillQuery` per row you",
393
+ " can send straight back. If a result is surprising or empty, re-send it with `explain: true` and",
394
+ " read the plan before you report the number.",
395
+ "",
396
+ "## What to report",
397
+ "",
398
+ "- The score and the two or three factors that drag it down, each with the metric id behind it.",
399
+ "- What moved, by how much, and whether it is outside the baseline — with the date the anomaly",
400
+ " scan put on it.",
401
+ "- Traffic, event mix, FPS trend and the meshes people actually touch.",
402
+ "",
403
+ "Always carry the caveats into the text rather than dropping them: a row below its minimum sample",
404
+ "(`aboveMinSample: false`), a metric whose capture channel the context document says is off, and any",
405
+ '`meta.truncated` or `caveats` entry on a result you quoted. Say "not enough data to tell" when that',
406
+ "is the honest answer.",
407
+ "",
408
+ "End with 2–3 concrete recommendations — each naming the scene, the mesh or the day it applies to.",
409
+ "If an `annotate` tool is available, leave a dated note on the finding you want the next reader to",
410
+ "see, and if `save_analysis` is available, store the report so next week's run has something to",
411
+ "compare against. If a `pin_panel` tool is available, pin the panel behind the headline factor.",
412
+ ].join("\n"),
413
+ },
414
+ {
415
+ id: "xr-comfort-audit",
416
+ name: "xr_comfort_audit",
417
+ title: "XR comfort & drop-off audit",
418
+ description: "Audit VR/AR comfort for a scene (or the whole project): rapid head rotation, locomotion style, tracking quality, guardian/boundary contacts, input-source mix, and the short sessions that mean someone took the headset off. USE FOR: motion-sickness complaints, immersive sessions that end early, choosing a locomotion scheme, checking whether a play space is big enough. Trigger phrases: XR comfort, VR motion sickness, why do people quit VR, headset drop-off, teleport vs smooth locomotion, guardian boundary, hand tracking vs controllers.",
419
+ tools: [
420
+ "xr_rotation",
421
+ "xr_locomotion",
422
+ "xr_abandonment",
423
+ "xr_sources",
424
+ "xr_tracking_quality",
425
+ "xr_boundary_contacts",
426
+ "boundary_heatmap_stats",
427
+ "insight_scene_health",
428
+ "insight_movers",
429
+ "query",
430
+ ],
431
+ capabilities: ["query"],
432
+ args: [
433
+ {
434
+ name: "scene",
435
+ description: "Optional scene id to scope the audit to (see the uptimizr://scenes resource).",
436
+ required: false,
437
+ },
438
+ {
439
+ name: "range",
440
+ description: 'The window to audit, in words — e.g. "the last 7 days", "since the XR release".',
441
+ required: false,
442
+ default: "the last 7 days",
443
+ },
444
+ ],
445
+ body: [
446
+ "Audit XR/immersive comfort and drop-off for {{scope}} over {{range}}.",
447
+ "",
448
+ "Work through the method below with the read-only tools it names{{#scene}}, all scoped with",
449
+ '`scene="{{scene}}"`{{/scene}}, and correlate the signals — no single one of them is a verdict.',
450
+ "",
451
+ "1. **Orient before you ask anything.** Read the `uptimizr://context` resource first. Every metric",
452
+ " below is gated on the **XR capture channel**: if the context document says it is off, these",
453
+ ' tools return empty by design and the honest answer is "XR capture is not enabled here", not',
454
+ ' "there is no comfort problem".',
455
+ "",
456
+ '2. **Rapid head rotation — the motion-sickness proxy.** `xr_rotation`{{#scene}} (`scene="{{scene}}"`){{/scene}}',
457
+ " gives the rate of fast head/view turns. High rates are a proxy, not a diagnosis: they can mean",
458
+ " discomfort-inducing camera work, or simply a scene that rewards looking around. Read it against",
459
+ " the next two signals before calling it.",
460
+ "",
461
+ '3. **Locomotion style and session span.** `xr_locomotion`{{#scene}} (`scene="{{scene}}"`){{/scene}}',
462
+ " gives the fly / navigate / teleport mix and how long each session lasted. Continuous (smooth)",
463
+ " locomotion paired with heavy rapid rotation is the classic uncomfortable combination; teleport",
464
+ " is the usual mitigation.",
465
+ "",
466
+ '4. **Did they take the headset off?** `xr_abandonment`{{#scene}} (`scene="{{scene}}"`){{/scene}}',
467
+ " finds immersive sessions that ended early. Early exits _plus_ one of the two signals above is",
468
+ " the finding; early exits on their own may just be a short demo.",
469
+ "",
470
+ "5. **Rule out the boring explanations first.** `xr_tracking_quality` catches tracking loss — an",
471
+ " exit caused by the headset losing its pose is not a comfort problem.",
472
+ " `xr_boundary_contacts` and `boundary_heatmap_stats` catch a play space that is too small or a",
473
+ " scene that pushes people into the guardian; that is a layout problem with a layout fix.",
474
+ "",
475
+ '6. **Who is playing.** `xr_sources`{{#scene}} (`scene="{{scene}}"`){{/scene}} gives the hand vs.',
476
+ " controller vs. gaze input split. Comfort conclusions differ by input source, and a shift in the",
477
+ " mix between two windows can move every other number without anything getting worse.",
478
+ "",
479
+ "7. **Put it in context.** `insight_scene_health` scores XR abandonment as one of its six weighted",
480
+ " factors, so it tells you whether this scene is unusual _for this project_;",
481
+ ' `insight_movers`{{#scene}} (`scene="{{scene}}"`){{/scene}} tells you whether the comfort signals',
482
+ " moved against the previous equal window. Drop any row with `aboveMinSample: false`.",
483
+ "",
484
+ "8. **Cut it further with the DSL.** The single `query` tool takes a `metric`, a `range`, that",
485
+ " metric's filters, `dimensions` to regroup a portable count, and `compare: { range: <previous",
486
+ 'window> }` for `{ current, previous, delta, deltaPct }` already joined. `format: "summary"`',
487
+ " returns a bounded digest with a plain-language `reading`; `explain: true` returns the plan",
488
+ " instead of the rows and names every reason the answer might mislead — worth one call before",
489
+ " reporting a zero on a channel-gated metric.",
490
+ "",
491
+ "## What to report",
492
+ "",
493
+ "- The uncomfortable patterns you can actually evidence: heavy rapid rotation or continuous",
494
+ " locomotion paired with early exits, named per scene and per input source.",
495
+ "- The alternatives you ruled out: tracking loss, boundary contacts, a short-by-design experience.",
496
+ "- Comfort mitigations: teleport or snap-turn options, vignetting during movement, slower or",
497
+ " user-controlled camera motion, a larger required play space, or moving interactive content",
498
+ " inside the guardian.",
499
+ "",
500
+ "Carry the caveats: XR sessions are a small fraction of most projects' traffic, so say the session",
501
+ "count next to every rate; the rotation and locomotion metrics are sampled (ADR 0012); and a metric",
502
+ "whose channel is off is not a zero. Never turn one uncomfortable session into a trend.",
503
+ "",
504
+ "End with 2–3 concrete comfort changes, each tied to the scene and the locomotion or input mode it",
505
+ "applies to. If an `annotate` tool is available, leave a note on the scene so the next audit can see",
506
+ "what was tried; `save_analysis` keeps the before-picture to compare the fix against. If a",
507
+ "`pin_panel` tool is available, pin the locomotion-comfort panel.",
508
+ ].join("\n"),
509
+ },
510
+ ];
511
+ //# sourceMappingURL=skills.generated.js.map
@@ -0,0 +1 @@
1
+ {"version":3,"file":"skills.generated.js","sourceRoot":"","sources":["../src/skills.generated.ts"],"names":[],"mappings":"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"}