experiments

$npx mdskill add microsoft/vscode/experiments

- **Experiment-controlled setting:** add `experiment: { mode: 'auto' }` to the setting's schema, or `mode: 'startup'` to only pick up changed assignments on startup. ExP then sets the setting's default through the treatment `config.<setting id>` (or `experiment.name`), and code reads the setting with `IConfigurationService` as usual. Values that users set themselves still win. Use this when users could reasonably choose the behavior themselves. - **Treatment:** read a value with `IWorkbenchAssignmentService.getTreatment<T>(name)`. It resolves to `undefined` without an assignment, so keep a fallback, and read it again on `onDidRefetchAssignments`. Use this for values that are not user preferences, such as copy or variant names.

SKILL.md

.github/skills/experimentsView on GitHub ↗
---
name: experiments
description: Use when adding, changing, or reviewing a VS Code A/B experiment, either an experiment-controlled setting or a treatment read with the assignment service, and when deciding whether and where to log an `experimentTrigger` event for a triggered ExP scorecard.
---

# Experiments

## Controlling behavior

- **Experiment-controlled setting:** add `experiment: { mode: 'auto' }` to the setting's schema, or `mode: 'startup'` to only pick up changed assignments on startup. ExP then sets the setting's default through the treatment `config.<setting id>` (or `experiment.name`), and code reads the setting with `IConfigurationService` as usual. Values that users set themselves still win. Use this when users could reasonably choose the behavior themselves.
- **Treatment:** read a value with `IWorkbenchAssignmentService.getTreatment<T>(name)`. It resolves to `undefined` without an assignment, so keep a fallback, and read it again on `onDidRefetchAssignments`. Use this for values that are not user preferences, such as copy or variant names.

To try an assignment locally, set `experiments.override.<treatment name>` in your user settings, for example `"experiments.override.config.chat.mySetting.enabled": true`.

## Trigger events for triggered scorecards

A triggered scorecard only compares users who reached the moment where control and treatment behave differently, so users that the experiment never affected don't dilute the result. Log that moment with the helpers in [experimentTrigger.ts](../../../src/vs/platform/telemetry/common/experimentTrigger.ts):

```ts
logSettingExperimentTrigger(telemetryService, MY_SETTING_ID); // experiment-controlled setting
logExperimentTrigger(telemetryService, 'myTreatment'); // treatment
```

They log the shared `experimentTrigger` event with the treatment name as `treatmentName`, at most once per window or process, so they can run on every evaluation. Base the scorecard's trigger on that event (`monacoworkbench/experimentTrigger`) and its `treatmentName`. Don't add feature-specific trigger events.

### When to use one

Use a trigger when only some assigned users are affected, at an identifiable moment: an action, a surface that only appears in some situations, or a code path that only some sessions reach. Don't use one when:

- nearly every assigned user is affected anyway, like a changed default in a common view;
- no single moment precedes every effect, like a feature switch that also changes commands or agent tools before anything is visible (`chat.agentMerge.enabled`);
- the population is already limited: onboarding experiments (`IOnboardingScenario.experiment`) only attach their assignment context to telemetry from the moment the tour would show.

Prefer no trigger over an approximate one. Dilution only costs statistical power, while a biased trigger gives wrong results.

### When to fire it

Fire it where the code decides between control and treatment behavior, before they differ, under a condition that is the same in every arm.

| The treatment… | Fire when… |
|---|---|
| changes what an action does | the action runs |
| adds UI that control lacks | the UI would render, checked in every arm |
| changes copy or an icon | that UI renders |
| changes a delay | the countdown starts, not when the delayed UI shows |
| changes a default that users can override | the default is visible and no user choice is stored |
| changes background behavior | the diverging code path runs |

```ts
// Checking the setting first would only trigger the treatment arm.
if (isBannerRelevant(context)) {
	logSettingExperimentTrigger(telemetryService, MY_SETTING_ID);
	if (configurationService.getValue<boolean>(MY_SETTING_ID)) {
		showBanner();
	}
}
```

Common pitfalls:

- **State only the treatment writes**, like dismissed or seen flags. Ignore it until the trigger has fired.
- **Data only the treatment computes**, like CI status that is only polled for an indicator. Use an arm-independent superset, or compute it in every arm until the trigger has fired.
- **Missed exposure**, like accessible labels, menus, or features that the setting suppresses. Find every place where the setting or treatment changes behavior, because a user affected before their first trigger biases the result.

Excluding users who can't be affected, such as reduced-motion users for an animation, is fine when the condition is the same in every arm. Agent host telemetry only carries the assignment context once the workbench has forwarded it, so hold earlier triggers until then (see `AgentHostGitStateService`).

Test each trigger in every arm with `TestExperimentTriggerTelemetryService`. After adding or moving a trigger, start a new experiment iteration, because earlier exposures have no trigger events.

More from microsoft/vscode

SkillDescription
accessibilityPrimary accessibility skill for VS Code. REQUIRED for new feature and contribution work, and also applies to updates of existing UI. Covers accessibility help dialogs, accessible views, verbosity settings, signals, ARIA announcements, keyboard navigation, and ARIA labels/roles.
act-on-feedbackAct on user feedback attached to the current session. Use when the user submits feedback on the session's changes via the Submit Feedback button.
agent-customization**WORKFLOW SKILL** — Create, update, review, fix, or debug VS Code agent customization files (.instructions.md, .prompt.md, .agent.md, SKILL.md, copilot-instructions.md, AGENTS.md). USE FOR: saving coding preferences; troubleshooting why instructions/skills/agents are ignored or not invoked; configuring applyTo patterns; defining tool restrictions; creating custom agent modes or specialized workflows; packaging domain knowledge; fixing YAML frontmatter syntax. DO NOT USE FOR: general coding questions (use default agent); runtime debugging or error diagnosis; MCP server configuration (use MCP docs directly); VS Code extension development. INVOKES: file system tools (read/write customization files), ask-questions tool (interview user for requirements), subagents for codebase exploration. FOR SINGLE OPERATIONS: For quick YAML frontmatter fixes or creating a single file from a known pattern, edit the file directly — no skill needed.
agent-host-chat-contributionsBuild and review cross-cutting agent-host chat behavior through lifecycle contributions. Use when adding turn lifecycle side effects, prompt or context injection, restored-history transformation, protocol-action observation, or when reviewing changes that add code to AgentSideEffects or AgentService.
agent-host-e2e-testsUse when writing, recording, updating, validating, or troubleshooting Agent Host end-to-end and real-provider integration tests under src/vs/platform/agentHost/test/node/e2e and providerIntegration. Covers adding a cross-provider test, re-recording fixtures after an SDK bump, required cross-platform Azure validation, gating non-deterministic or platform-specific tests, and diagnosing replay cache misses.
agent-host-logsAnalyze Agent Host debug log exports. Use when given an ah-logs or ahp-logs zip/folder, an Export Agent Host Debug Logs bundle, events.jsonl, AHP JSONL transport logs, Agent Host.log, remote-agenthost.log, or copilot-logs.
author-contributionsIdentify all files a specific author contributed to on a branch vs its upstream, tracing code through renames. Use when asked who edited what, what code an author contributed, or to audit authorship before a merge. This skill should be run as a subagent — it performs many git operations and returns a concise table.
auto-perf-optimizeRun agent-driven VS Code performance or memory investigations. Use when asked to launch Code OSS, automate a VS Code scenario, run the Chat memory smoke runner, capture renderer heap snapshots, take workflow screenshots, compare run summaries, or drive a repeatable scenario before heap-snapshot analysis.
azure-pipelinesUse when validating Azure DevOps pipeline changes for the VS Code build. Covers queueing builds, checking build status, viewing logs, and iterating on pipeline YAML changes without waiting for full CI runs.
build-champ-triageFind out why a build has failed