* Add in-editor PMF survey pane (POC)
Moves in-product surveys from notification-based flows into an editor
pane, following the same pattern as the issue reporter editor.
- EditorInput + EditorPane architecture (singleton, readonly)
- Segmented control (Q1) styled with --vscode-radio-* tokens
- List-row selection (Q2/Q3) with native radios visually hidden inside
full-width label elements, styled via :has(:checked)
- Responsive container query (collapses 2-col to 1-col at 600px)
- HC/focus-visible support for both segment and list-row patterns
- Success animation with auto-close after 3s
- Telemetry event for survey submission (survey/submit)
- Works in both workbench and sessions/agent window
- Testable via Developer: Open Survey command
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address PR feedback: accessibility, localization, design tokens
- Gate 'Open Survey' command behind IsDevelopmentContext (dev builds only)
- Localize all user-facing strings (title, description, questions, options)
- Use stable option IDs for telemetry instead of locale-dependent labels
- Replace custom submit button CSS with shared Button widget
- Add aria-hidden on decorative icons (sparkle, checkAll)
- Add role=status + aria-live=polite on success container
- Announce 'Response sent' via status() for screen readers
- Move focus to success container after submit
- Use --vscode-strokeThickness token for border widths
- Snap padding to spacing ramp (7px → 8px)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix responsive layout and accessibility
Responsive:
- Remove broken flex-wrap on segment control (caused 2x2+1 orphan grid)
- At narrow widths, segment stacks vertically (flex-direction: column)
with full-width items and proper border-radius per edge
- Segment labels get min-width: 0 + text-overflow: ellipsis so they
shrink gracefully in horizontal mode without wrapping
- Remove overflow: hidden from segment group (was clipping focus rings)
Accessibility:
- Add role=form + aria-label on the editor pane container
- Increase auto-close timeout to 5s (gives screen readers time to read)
- Add position: relative on focus-visible segments for z-index stacking
- Segment labels get explicit border-radius on first/last (no overflow
hidden needed)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix review findings: focus, URI, error handling, a11y
Engineering:
- Override focus() to move focus to first radio when survey opens
- Make resource URI dynamic (vscode-survey:/{surveyId}) to prevent
collisions across multiple survey definitions
- Guard closeEditor in auto-close timeout with .catch(onUnexpectedError)
Accessibility:
- Add aria-required=true on all radio groups
- Fix HC focus-visible vs checked outline conflict: checked uses 1px
solid contrastActiveBorder, focus-visible uses 2px dashed focusBorder
- Add completion hint ('Answer all questions to submit') with
aria-describedby on the submit button; hides once all answered
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: prevent segment control wrapping with explicit flex-wrap: nowrap
Add position: relative to contain absolutely-positioned radio inputs,
and flex-wrap: nowrap to ensure 5 segment items always stay in a single
row at widths above the 600px container-query breakpoint.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: list selection style, compact spacing, scroll visibility
- Remove one-sided border-radius + left-accent on selected list rows;
use full rectangular border matching VS Code's native list selection
- Reduce row padding (8px→6px), gap (4px→2px), question margin (24→20px)
and submit margin (28→20px) for a more compact layout
- Add 60px bottom padding to ensure the Submit button is always reachable
when scrolling
- Split container queries: segment stacks at 560px, list grid collapses
to single-column at 480px (was 600px for both — too aggressive)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address review: accessibility help, design tokens, compact styling
- Add SurveyAccessibilityHelp with AccessibleViewProviderId.Survey and
AccessibilityVerbositySettingId.Survey for screen reader discovery
- Use var(--vscode-strokeThickness) for list-option border
- Use var(--vscode-codiconFontSize) + transform: scale(2) for success icon
- Reduce list-option padding to 6px 10px (on spacing ramp)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* feat: track source signal, programmatic command, structured telemetry
- Add 'source' field to SurveyEditorInput so the triggering feature
(completions, panel.agent, agent.codeEdit) is captured with the response
- Register '_workbench.action.openCopilotSurvey' command for the Copilot
extension to open the in-editor survey instead of external URL
- Restructure telemetry: extract pmfScore, primaryBenefit, primaryFriction
as top-level fields for direct Kusto querying (keep JSON blob for
forward-compat)
- Rename question IDs: main-benefit→primary-benefit, blockers→primary-friction
- Add pmfQuestionId to ISurveyDefinition schema
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: pmfScore as numeric 0-4, update extension to open in-editor survey
- pmfScore is now a number (0=not at all, 4=extremely) with
isMeasurement:true for direct Kusto aggregation - no JSON blob
- Update Copilot SurveyService.promptSurvey() to call
'_workbench.action.openCopilotSurvey' command instead of opening
external URL - works in both main workbench and agent window
- Remove unused IAuthenticationService, IEnvService, SURVEY_URI from
SurveyService (no longer needed without external URL)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* fix: sanitize source arg, restore focus, handle singleton re-open
- Validate command source against allowlist (telemetry safety)
- Add runtime guard for dev command in stable builds
- Make SurveyEditorInput.source mutable via updateSource()
- Update existing input's source when singleton is re-opened
- Restore focus to survey pane when closing a11y help
- Await command execution in extension with error handling
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* generalize survey telemetry with telemetryKey mappings
Questions now declare their own telemetry field via telemetryKey and
asMeasurement properties. The pane iterates these at submit time
instead of hardcoding field names.
Telemetry fields:
- score (number): primary measure, option index
- primaryBenefit (string): value driver option ID
- primaryFriction (string): friction point option ID
- programmingExperience (number): experience bracket index
Added Q4: programming experience (5 brackets, 0-4 numeric measure).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The model can stream malformed JSON for tool-call arguments. The language model wrapper threw a bare Error from a fire-and-forget finished callback, producing an unhandled rejection in error telemetry without cleanly aborting the response. Align with the other tool-call consumers (langModelServer, messagesApi) by logging the diagnostic and falling back to empty parameters so the tool call is still surfaced to the consuming extension.
Co-authored-by: vs-code-engineering[bot] <122617954+vs-code-engineering[bot]@users.noreply.github.com>
Render the memory instructions and context blocks only when the memory
tool is in availableTools, so the prompt and available tools stay in sync.
Fixes#321833
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
The off-flag conversation summarization path forced `stream: false` on the
chat request. The response processor is selected by the endpoint's static
`supportsStreaming` capability, not by this flag, so for a streaming Chat
Completions model (e.g. gemini-3-flash) the single non-streamed JSON blob is
still routed through the SSE processor, which fails to parse it and reports a
spurious RESPONSE_CONTAINED_NO_CHOICES failure. Both Full and Simple modes hit
this, so /compact reported failure even though the model returned valid
summaries.
Removing `stream: false` lets the request stream (the safe default for every
endpoint type); `interceptBody` still forces `stream: false` for models that
genuinely don't support streaming.
Fixes#321085
getAvailableTools(): skip virtual-tool grouping for any tool-search-capable endpoint (not just Anthropic). Previously GPT-5.4/5.5 ran virtual-tool grouping AND responses-API client tool search simultaneously, so real MCP tools were hidden behind activate_* groups (or trimmed) and never appeared in the request's tools map - making them searchable via tool_search but not callable.
toolSearchTool: exclude always-available (non-deferred) tools from the tool_search candidate set so the limited result slots only go to tools that actually need loading.
Fixes#317998Fixes#317992
Disable process.report in copilot extension
Override process.report.getReport to return undefined, loaded as the first import in the copilot extension entrypoint. Cherry-picked from #321998 and #322036.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add GPT-5.4 and GPT-5.5 to the Responses API persistent chain-of-thought model-family gate while preserving the existing supported-family condition.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
fix: re-check cancellation after postToolUse hook to avoid closed stream write (fixes#321951)
The postToolUse hook can run for a long time because it spawns external,
user-configured commands. If the chat request is cancelled while the hook
runs, the response stream is closed by the time the hook resolves, and
writing hook progress to it throws an unhandled "Response stream has been
closed" error.
The prior fix (cdf17eb2, #319011) only checked cancellation before invoking
the hook, leaving the cancellation-during-hook window open. Re-check the
cancellation token in executePostToolUseHook after the await and skip result
processing when cancelled, since a cancelled turn never consumes the result.
Co-authored-by: vs-code-engineering[bot] <122617954+vs-code-engineering[bot]@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Edit mode is now hidden for everyone, so the chat.editMode.hidden
setting and its DeprecatedEditModeHidden policy are no longer needed.
This removes the setting registration, policy, exported policy data
entry, and the settings layout reference. The custom Edit mode file in
the built-in Copilot extension (and its provider registration) is
removed as well. The mode picker no longer special-cases a custom
`edit` mode by name for its icon or built-in grouping; the legacy
built-in Edit mode (shown when agent mode is disabled by policy) keeps
its own icon.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Allow chat-lib embedders to supply the tokenizer implementation
Embedders of @vscode/chat-lib that already have the cl100k/o200k BPE
dictionaries in memory currently load up to three copies per process
(~100 MB per encoder per copy). Open both tokenizer code paths to a
host-supplied implementation:
- INESProviderOptions gains tokenizerProvider, following the existing
optional service override pattern (languageDiagnosticsService etc.).
- The completions-core tokenizer module gains
setExternalTokenizerProvider(), checked by getTokenizer(), and
initializeTokenizers becomes a lazy thenable so the dictionary load
starts on first await (ghostText already awaits it per request)
rather than at module evaluation - giving hosts a chance to register
a provider before any load happens. Without a provider the only
change is load timing.
Fixes#321098
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address review: harden the external tokenizer provider hook
- setExternalTokenizerProvider throws on re-registration or after the
built-in load has started, freezing the load strategy.
- The initializeTokenizers gate never rejects (matching the built-in
best-effort contract); external loads are single-flight and a failed
attempt clears the memo so a later await can retry.
- getTokenizer keeps its never-throws contract: a throwing provider
falls back to the module's existing fallback chain.
- Use ?? instead of || for the tokenizerProvider option fallback.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix tokenizer tests racing the now-lazy dictionary load
The cl100k/o200k mocha suites captured getTokenizer() at suite
definition time, which only worked because the eager IIFE had loaded
the dictionaries by then; with lazy init they captured the approximate
fallback (24 failures on the Copilot test job). Fetch the tokenizer in
suiteSetup after awaiting initializeTokenizers instead. getTokenizer()
also kicks the lazy load on a miss now, so production callers that
never await still converge on exact tokenization.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Make the completions tokenizer override a factory option
Replace the process-global registration race with a factory option.
`setExternalTokenizerProvider` no longer throws (first-wins, never crashes
host init), and `createInlineCompletionsProvider` installs the provider
synchronously before any tokenization, so there is no ordering contract for
embedders to get right.
Add `IInlineCompletionsProviderOptions.tokenizerProvider` and export
`ExternalTokenizerProvider` / `Tokenizer` / `TokenizerName` from the chat-lib
public surface so embedders can actually implement and pass the option.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Replace lazy-thenable initializeTokenizers with ensureTokenizersLoaded()
The exported `initializeTokenizers` was a hand-rolled fake Promise (an object
with then/catch/finally + a `Symbol.toStringTag` spoof, cast `as Promise<void>`)
that re-invoked `loadTokenizers()` on every settle and lied to `instanceof
Promise`. Replace it with a plain `ensureTokenizersLoaded()` function that
returns the real promise from `loadTokenizers()`.
Behavior is unchanged: the load still starts lazily on first call (so an
embedding host can install an external provider first), is single-flighted, and
never rejects. Update the one prod awaiter (ghostText) and the test call sites.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Reword getTokenizer fire-and-forget comment
The comment claimed callers that never call ensureTokenizersLoaded() "still
converge on exact tokenization", which overstates the guarantee: when the
dictionary load fails, the approximate tokenizer fallback persists. Clarify
that exact tokenization is reached on a later call only once the load succeeds.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Add unit tests for the external tokenizer provider
The host-overridable tokenizer path (setExternalTokenizerProvider, the
ensureTokenizersLoaded single-flight gate, and the never-throws getTokenizer
fallback) had no coverage. Add a "Tokenizer Test Suite - external provider"
suite with a fake provider covering delegation, concurrent single-flight,
fallback-on-throw, resolve-and-retry on load failure, and first-wins
registration.
Because the completions tokenizer is process-global, add a test-only
resetTokenizersForTest() that restores the module's initial state, called in
the suite's setup and teardown so it does not leak into the other suites that
share the mocha process.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix chat-lib extraction by re-exporting tokenizer symbols locally
The chat-lib extractor (extractChatLib.ts) rewrites `import ... from` module
specifiers to point at the bundled `_internal/` tree, but it does not rewrite
`export ... from` re-export specifiers. The tokenizer re-exports in
chatLibMain.ts used `export { TokenizerName } from '...tokenization'`, whose
deep relative path was left untouched in the extracted main.ts and no longer
resolved — breaking `npm run extract-chat-lib` with TS2307 and failing the
chat-lib tests job on all three platforms.
Follow the convention already used everywhere else in this entry point (e.g.
the service re-exports just above): import the symbols at the top, where the
extractor does rewrite the path, and re-export the local bindings without a
`from` clause.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Mason Chen <jiec@microsoft.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Reduce duplicate code
* Add a second turn to the chat smoke tests
* Fix tests
* "fix" sandbox test
* Make things work
* Get tests passing
* CCR feedback
* Simplify diff
* Undo chatView.ts changes
* Missing Claude warm up
* Add SKU to enhanced/restricted GH telemetry events
The sendEnhancedGHTelemetryEvent and sendEnhancedGHTelemetryErrorEvent
methods were not enriching events with the SKU field from the copilot
token, unlike sendGHTelemetryEvent which already did this.
This caused ~90% of copilot-chat telemetry events (engine.messages,
engine.messages.length, provideInlineEdit, etc.) to have null SKU in
the restricted telemetry pipeline.
Fixesmicrosoft/vscode-internalbacklog#7962
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Refactor: extract _addSku helper, only set sku when defined
Address PR feedback:
- Extract duplicated SKU logic into private _addSku method
- Only add sku property when token SKU is present (omit when undefined)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Carl Brochu <carlbrochu@users.noreply.github.com>
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Instrument Cloud Agent backend v1/v2 rollout
Put the `chat.cloudAgentBackend.version` toggle (v1 = Jobs API, v2 = Task
API) behind an experiment so the rollout can be ramped and rolled back
remotely via ExP, and add an arm-tagged telemetry surface so the two
backends emit identical funnel and guardrail signals for apples-to-apples
monitoring.
Previously v1 was partly instrumented and v2 emitted nothing, making any
A/B comparison impossible. A shared `ICloudBackendInstrumentation` is now
injected into both backends and stamps every event with `backendVersion`,
covering session creation, activation, follow-up, and per-operation
errors, plus matching OTel metrics. v2's silent catch sites now report
through it, and `TaskApiError` carries the HTTP status for error
classification. Legacy v1 backend events are consolidated into the shared
surface and kept for dashboard continuity.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Rename "arm" to "backend version" in cloud telemetry comments
"arm" is A/B-experiment jargon not used elsewhere in the codebase. Swap it
for "backend version" in comments, docstrings, and GDPR comment text to
match the existing `backendVersion` / v1 / v2 vocabulary. Comment-only
change; no identifiers or behavior affected.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Address cloud backend rollout PR review comments
- Move backend_version attribute to the canonical github.copilot.* namespace
- Derive numeric HTTP status inside operationFailed so the status measurement is populated
- Carry HTTP status on v1 (Jobs API) invalid-job errors via JobsApiError so v1 create failures classify by status
- Only emit cloud pr_ready.count for v1 (Task API activation is a first turn, not a PR)
- Add unit tests for the new cloud metrics
- Document the new cloud operation/error metrics and backend_version attribute
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* Fix TaskApiBackend construction in fetchSessionList specs
Three fetchSessionList test cases constructed TaskApiBackend without the
required instrumentation argument, failing the CI typecheck (TS2554).
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* nes: refactor: simplify patch repsonse handler
* nes: refactor: simpler name for response handler
* nes: remove unused Log kind for duplicate additions mode
* refactor(xtab): simplify XtabPatchResponseHandler
- Convert static class to namespace for better autocomplete ergonomics
- Extract duplicate-additions policy into applyDuplicatePolicy() returning
an EditDecision discriminated union, flattening the main loop
- Remove DuplicateAdditionsMode.Log (already absent from enum)
- Remove onDuplicateRemoved callback (never used in production) along with
OnDuplicateRemovedCallback and DuplicateAdditionRemovalSummary types
- Minor cleanups: explicit boolean return on Patch.addLine, remove
redundant else/if branches in extractEdits
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* nes: patch: implement fast yield line with cursor
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Per dogfood feedback, the always-on broadcast pill in the chat input toolbar caused accidental clicks and added UI noise for a setting that is neither time-sensitive nor frequently toggled. OTel status remains discoverable via the Copilot icon chat status dashboard.
- Remove workspace+folder configurability of OTel settings (scope: application)
for both the Copilot extension settings and the agent-host OTel settings.
Settings are now user-only and policy-deliverable.
- Drop the workspace-trust capability gate, the captureContent disclosure
modal, and the yellow chat-input banner.
- Collapse the chat-input pill to a single broadcast indicator ($(broadcast))
shown whenever OTel is on; remove the statusCapturing command.
- Surface OTel state in the Copilot chat status dashboard as a single row
with the endpoint and an inline [Manage] command link.
The Anthropic Messages streaming body can return 200 with headers and then
hang mid-stream with no further chunk and no error, leaving the for-await
loop pending indefinitely. Add a 120s idle watchdog that resets on each
chunk, emits a messagesApi.streamIdleTimeout telemetry event when it trips
(so the stall is observable in the wild), rejects the iterator, and cancels
the underlying reader so the stream settles instead of hanging.
* nes: feat: migrate allowImportChanges into model configuration
Move the team-internal, experiment-based `chat.advanced.inlineEdits.allowImportChanges`
setting onto `ModelConfiguration` as an optional `allowImportChanges` field so the value
travels with the selected model config (fetched / exp-config / local / hard-coded).
XtabProvider.filterEdit now takes the value from `modelServiceConfig.allowImportChanges`
(undefined treated as None, preserving prior default) instead of reading the standalone
setting, which is removed.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* nes: patchBased02WithRecentLineNumbers and patchBased02WithoutRecentLineNumbers should hardcode allowImportChanges
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* chatSessions: scope cloud agent (v2) repo task list to the current user
The Task API (v2) repo-scoped endpoint (agents/repos/{owner}/{repo}/tasks)
returns every collaborator's tasks by default, so the cloud sessions view in a
repo workspace showed sessions not created by the current user. This mirrors how
github.com/copilot/agents only narrows to your own tasks when an author filter
is applied.
Pass the authenticated user's id as the creator_id query param on the
repo-scoped list, matching the web behavior. The scalar form is honored by the
server. The global agents/tasks path is already user-scoped, so it is left
untouched. If the current user id can't be resolved, listing falls back to
unfiltered.
- Add creator_id to ListTasksOptions
- Resolve the current user id via IOctoKitService.getCurrentAuthedUser() in
TaskApiBackend.fetchSessionList
- Add id to IOctoKitUser (already returned by GET /user)
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* comment
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Add X-VSCode-WindowKind exp filter to Copilot Chat
Mirrors the core X-VSCode-WindowKind assignment filter (added in #321572) in the Copilot Chat experimentation setup so experiments can target the editor vs. agents window. Uses the scode.workspace.isAgentSessionsWorkspace proposed API to determine the window kind.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* nes: add fetchResult to enhanced telemetry to disambiguate empty model responses
The restricted/enhanced 'copilot-nes/provideInlineEdit' event already carries 'modelResponse', but 'eventPropertiesToSimpleObject' drops falsy property values (including the empty string) before the event reaches the wire. That makes a successful but empty model response (e.g. the diff-patch model emitting "" to mean "no edit") indistinguishable from cancellations, fetch failures, and no-fetch paths in the copilot_v0_next_edit_suggestion_restricted_code_snippet table.
Add 'fetchResult' (the underlying ChatFetchResponseType, e.g. 'success' / 'canceled' / 'failed' / ...). Decode:
fetchResult = 'success' AND modelResponse IS NULL -> model responded with the empty string
fetchResult = 'canceled' / 'failed' / ... -> specific failure kind
fetchResult IS NULL -> no fetch (e.g. cache hit; check isFromCache measurement)
The field reuses the existing 'fetchResult' vocabulary already documented in the standard event's GDPR catalog, so no new naming is introduced.
Refs https://github.com/microsoft/vscode-copilot-issues/issues/443
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
* nes: address Copilot review feedback for fetchResult telemetry
Use the strongly-typed FetchResultWithStats.fetchResult value in enhanced telemetry and update tests to assert the on-wire payload via eventPropertiesToSimpleObject.
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
---------
Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Co-authored-by: Sandeep Somavarapu <sasomava@microsoft.com>
* Cloud agent: Create/Open pull request toolbar actions for settled tasks
Adds chat-input toolbar actions for v2 (Task API) cloud agent sessions:
- "Create pull request" for a settled, PR-less task; the backend resolves the
repo from the task (html_url, falling back to a GitHub repo-by-id lookup) and
creates the PR, then re-applies the toolbar gates in place.
- "Open pull request" (icon-only) once the task has a PR, opening it in the
browser; resolves both task- and PR-keyed session resources.
Also: compare-based changed files for settled PR-less tasks, reactive gate
re-evaluation on task settle / PR creation, and resolver-path telemetry.
Core: icon-only rendering for the open-PR action in the session changes toolbar.
* Address review: fix create-PR response test shape, stale wording, telemetry name
- Test FakeTaskApiClient now returns the real AgentTaskCreatePullRequestResponse
shape ({ id, number, repository_id }) instead of the stale { pull_request }.
- Reword the no-reflect warning and create-handler doc that wrongly implied a
refresh (the handler updates the toolbar gates in place).
- Rename the resolver telemetry event back to copilotcloud.pullArtifactResolve.
- Drop the 'browser-open glyph' wording now that the open-PR icon is git-pull-request.