Skip to content

Collect AI agent skill-usage telemetry (CLI command + agent init hooks)#18009

Merged
davidfowl merged 7 commits into
mainfrom
dapine/agent-telemetry
Jul 2, 2026
Merged

Collect AI agent skill-usage telemetry (CLI command + agent init hooks)#18009
davidfowl merged 7 commits into
mainfrom
dapine/agent-telemetry

Conversation

@IEvangelist

@IEvangelist IEvangelist commented Jun 8, 2026

Copy link
Copy Markdown
Member

Description

Adds opt-out, low-cardinality usage telemetry for Aspire's own AI skills and MCP tools, mirroring the approach used by microsoft/azure-skills.

Two parts:

  1. Hidden aspire agent telemetry command — receives the parsed hook values and records a single aspire/cli/agent_telemetry reported activity through the existing CLI telemetry pipeline. It honors opt-out before creating any provider, suppresses the automatic aspire/cli/main span (so each hook event is one event, not an inflated command span), force-flushes the reported provider for reliable one-shot export, validates/normalizes every value (emitting no span when nothing valid survives), and always exits 0 so a hook can never break the agent.
  2. Auto-registration during aspire agent init — materializes the track-telemetry.{sh,ps1} scripts to ~/.aspire/hooks and writes a PostToolUse hook into each detected supported client's user-level config (GitHub Copilot CLI ~/.copilot/hooks/aspire-telemetry.json and Claude Code ~/.claude/settings.json). Hooks are always installed, for parity with azure-skills. Conservative JSON merge (never clobbers malformed/unexpected configs), idempotent, AOT-safe.

Privacy: only Aspire-owned identifiers are recorded (allowlisted skill/tool names, the skill-relative reference path, a session GUID) — never absolute paths, repo/user names, file contents, or tool arguments.

Opt-out: a single switch, ASPIRE_CLI_TELEMETRY_OPTOUT, disables all CLI telemetry including AI agent skill usage. It's checked by the hook scripts (a fast short-circuit) and honored by the command before anything is sent.

Tests include TelemetryHookScriptTests, which run the real embedded track-telemetry.{sh,ps1} scripts end-to-end and assert the resulting agent telemetry invocation.

Draft pending coordinated review with the companion PRs (hook scripts in microsoft/aspire-skills#30, docs in microsoft/aspire.dev#1229). Clients shipped now: Copilot CLI + Claude Code; VS Code / OpenCode hook schemas are deferred. See the tracking issue for known edge cases.

Part of #18008

Checklist

  • Is this feature complete?
    • Yes. Ready to ship.
    • No. Follow-up changes expected.
  • Are you including unit tests for the changes and scenario tests if relevant?
    • Yes
    • No
  • Did you add public API?
    • Yes
    • No
  • Does the change make any security assumptions or guarantees?
    • Yes
    • No

@github-actions

github-actions Bot commented Jun 8, 2026

Copy link
Copy Markdown
Contributor

🚀 Dogfood this PR with:

⚠️ WARNING: Do not do this without first carefully reviewing the code of this PR to satisfy yourself it is safe.

curl -fsSL https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.sh | bash -s -- 18009

Or

  • Run remotely in PowerShell:
iex "& { $(irm https://raw.githubusercontent.com/microsoft/aspire/main/eng/scripts/get-aspire-cli-pr.ps1) } 18009"

IEvangelist

This comment was marked as low quality.

@github-actions

github-actions Bot commented Jun 9, 2026

Copy link
Copy Markdown
Contributor

CLI E2E Tests unknown — 113 passed, 0 failed, 2 unknown (commit d35e9c6)

View all recordings
- Test Detail
AddPackageInteractiveWhileAppHostRunningDetached Recording · Job · CLI logs
AddPackageWhileAppHostRunningDetached Recording · Job · CLI logs
AgentCommands_AllHelpOutputs_AreCorrect Recording · Job · CLI logs
AgentInitCommand_DefaultSelection_InstallsDefaultSkills Recording · Job · CLI logs
AgentInitCommand_MigratesDeprecatedConfig Recording · Job · CLI logs
AgentInit_NonInteractive_BundleOnlySkillsNotInCatalog Recording · Job · CLI logs
AgentMcpListStructuredLogsReturnsLogsFromStarterApp Recording · Job · CLI logs
AgentMcpListStructuredLogsReturnsLogsFromStarterApp_DevLocalhost Recording · Job · CLI logs
AgentMcpListStructuredLogsReturnsLogsFromStarterApp_Isolated Recording · Job · CLI logs
AllPublishMethodsBuildDockerImages Recording · Job · CLI logs
AspireAddAndStartWorkAgainstLegacyAppHostTs Recording · Job · CLI logs
AspireAddPackageVersionToDirectoryPackagesProps Recording · Job · CLI logs
AspireInitSingleFileAppHostRunsViaDotnetRunAppHost Recording · Job · CLI logs
AspireInit_ExistingAppHostDir_RecreatesNuGetConfigKeepsFiles Recording · Job · CLI logs
AspireInit_SolutionFile_BuildsAgainstChannelHive Recording · Job · CLI logs
AspireStartUpdatesStaleTypeScriptAppHostPath Recording · Job · CLI logs
AspireUpdateRemovesAppHostPackageVersionFromDirectoryPackagesProps Recording · Job · CLI logs
AspireUpdateRemovesOrphanAppHostPackageVersionWhenSdkAlreadyCurrent Recording · Job · CLI logs
Banner_DisplayedOnFirstRun Recording · Job · CLI logs
Banner_DisplayedWithExplicitFlag Recording · Job · CLI logs
Banner_NotDisplayedWithNoLogoFlag Recording · Job · CLI logs
CertificatesClean_RemovesCertificates Recording · Job · CLI logs
CertificatesTrust_WithNoCert_CreatesAndTrustsCertificate Recording · Job · CLI logs
CertificatesTrust_WithUntrustedCert_TrustsCertificate Recording · Job · CLI logs
ConfigSetGet_CreatesNestedJsonFormat Recording · Job · CLI logs
CreateAndRunAspireStarterProject Recording · Job · CLI logs
CreateAndRunAspireStarterProjectWithBundle Recording · Job · CLI logs
CreateAndRunEmptyAppHostProject Recording · Job · CLI logs
CreateAndRunJavaEmptyAppHostProject Recording · Job · CLI logs
CreateAndRunJsReactProject Recording · Job · CLI logs
CreateAndRunPolyglotAppHostWithDevLocalhostUrls Recording · Job · CLI logs
CreateAndRunPythonReactProject Recording · Job · CLI logs
CreateAndRunTypeScriptEmptyAppHostProject Recording · Job · CLI logs
CreateAndRunTypeScriptStarterProject Recording · Job · CLI logs
CreateJavaAppHostWithViteApp Recording · Job · CLI logs
CreateTypeScriptAppHostWithViteApp_UsesConfiguredToolchain Recording · Job · CLI logs
DashboardRunWithAgentMcpListTracesReturnsNoTraces Recording · Job · CLI logs
DashboardRunWithAgentMcpListTracesReturnsNoTraces_DevLocalhost Recording · Job · CLI logs
DashboardRunWithOtelTracesReturnsNoTraces Recording · Job · CLI logs
DashboardRunWithOtelTracesReturnsNoTraces_DevLocalhost Recording · Job · CLI logs
DeployK8sBasicApiService Recording · Job · CLI logs
DeployK8sWithExternalHelmChart Recording · Job · CLI logs
DeployK8sWithGarnet Recording · Job · CLI logs
DeployK8sWithMongoDB Recording · Job · CLI logs
DeployK8sWithMySql Recording · Job · CLI logs
DeployK8sWithPostgres Recording · Job · CLI logs
DeployK8sWithRabbitMQ Recording · Job · CLI logs
DeployK8sWithRedis Recording · Job · CLI logs
DeployK8sWithSqlServer Recording · Job · CLI logs
DeployK8sWithValkey Recording · Job · CLI logs
DeployTypeScriptAppToKubernetes Recording · Job · CLI logs
DescribeCommandResolvesReplicaNames Recording · Job · CLI logs
DescribeCommandShowsRunningResources Recording · Job · CLI logs
DetachFormatJsonProducesValidJson Recording · Job · CLI logs
DetachFormatJsonProducesValidJsonWhenRestartingExistingInstance Recording · Job · CLI logs
DoPublishAndDeployListStepsWork Recording · Job · CLI logs
DocsCommand_RendersInteractiveMarkdownFromLocalSource Recording · Job · CLI logs
DoctorCommand_DetectsDeprecatedAgentConfig Recording · Job · CLI logs
DoctorCommand_TypeScriptAppHostReportsMissingConfiguredToolchain Recording · Job · CLI logs
DoctorCommand_WithSslCertDir_ShowsTrusted Recording · Job · CLI logs
DoctorCommand_WithoutSslCertDir_ShowsPartiallyTrusted Recording · Job · CLI logs
DotNetRunFileBasedAppHostUsesAspireCliBundle Recording · Job · CLI logs
DotNetRunProjectAppHostUsesAspireCliBundle Recording · Job · CLI logs
GatewayWithoutExternalEndpoint_FailsPublishWithGuidance Recording · Job · CLI logs
GeneratedAspireDevScript_StartsWatchMode_WithConfiguredToolchain Recording · Job · CLI logs
GlobalMigration_HandlesCommentsAndTrailingCommas Recording · Job · CLI logs
GlobalMigration_HandlesMalformedLegacyJson Recording · Job · CLI logs
GlobalMigration_PreservesAllValueTypes Recording · Job · CLI logs
GlobalMigration_SkipsWhenNewConfigExists Recording · Job · CLI logs
GlobalSettings_MigratedFromLegacyFormat Recording · Job · CLI logs
IngressWithoutExternalEndpoint_FailsPublishWithGuidance Recording · Job · CLI logs
InitTypeScriptAppHost_AugmentsExistingViteRepoInWorkspaceSubdirectory Recording · Job · CLI logs
InteractiveCSharpInitCreatesExpectedFiles Recording · Job · CLI logs
InvalidAppHostPathWithComments_IsHealedOnRun Recording · Job · CLI logs
JavaScriptHostingApisRunFromTypeScriptAppHost Recording · Job · CLI logs
LatestCliCanStartStableChannelAppHost Recording · Job · CLI logs
LatestCliCanStartStableChannelTypeScriptAppHost Recording · Job · CLI logs
LegacySettingsMigration_AdjustsRelativeAppHostPath Recording · Job · CLI logs
LogsCommandShowsResourceLogs Recording · Job · CLI logs
OtelLogsReturnsStructuredLogsFromStarterApp Recording · Job · CLI logs
OtelLogsReturnsStructuredLogsFromStarterAppIsolated Recording · Job · CLI logs
ProcessCommandCallbackReceivesCliArguments Recording · Job · CLI logs
PsCommandListsRunningAppHost Recording · Job · CLI logs
PsFormatJsonOutputsOnlyJsonToStdout Recording · Job · CLI logs
PublishJavaScriptPatternsGeneratesExpectedDockerComposeArtifacts Recording · Job · CLI logs
PublishWithConfigureEnvFileUpdatesEnvOutput Recording · Job · CLI logs
PublishWithDockerComposeServiceCallbackSucceeds Recording · Job · CLI logs
PublishWithoutOutputPathUsesAppHostDirectoryDefault Recording · Job · CLI logs
ResourceCommand_FailedExec_ShowsLogPathAndLogHasEntries Recording · Job · CLI logs
ResourceCommand_SetAndDeleteParameterUpdatesDescribeOutput Recording · Job · CLI logs
RestoreGeneratesSdkFiles Recording · Job · CLI logs
RestoreGeneratesSdkFiles_WithConfiguredToolchain Recording · Job · CLI logs
RestoreRefreshesGeneratedSdkAfterAddingIntegration Recording · Job · CLI logs
RestoreSupportsConfigOnlyHelperPackageAndCrossPackageTypes Recording · Job · CLI logs
RunFromParentDirectory_UsesExistingConfigNearAppHost Recording · Job · CLI logs
RunReportsSyntaxErrorsForDotNetAppHost Recording · Job · CLI logs
RunReportsSyntaxErrorsForTypeScriptAppHost Recording · Job · CLI logs
SecretCrudOnDotNetAppHost Recording · Job · CLI logs
SecretCrudOnTypeScriptAppHost Recording · Job · CLI logs
StagingChannel_ConfigureAndVerifySettings_ThenSwitchChannels Recording · Job · CLI logs
StartAndWaitForTypeScriptSqlServerAppHostWithNativeAssets Recording · Job · CLI logs
StartReportsSyntaxErrorsForDotNetAppHost Recording · Job · CLI logs
StartReportsSyntaxErrorsForTypeScriptAppHost Recording · Job · CLI logs
StopAllAppHostsFromAppHostDirectory Recording · Job · CLI logs
StopJavaPolyglotAppHostUsingApphostDirectory Recording · Job · CLI logs
StopNonInteractiveSingleAppHost Recording · Job · CLI logs
StopTypeScriptPolyglotAppHostUsingApphostDirectory Recording · Job · CLI logs
StopWithNoRunningAppHostExitsSuccessfully Recording · Job · CLI logs
TypeScriptAppHostRunDoesNotDeadlockWhenLazyOptionsInvokeAsyncCallback Recording · Job · CLI logs
TypeScriptAppHostWithVite_AllowsDifferentGuestPkgManager Recording · Job · CLI logs
UnAwaitedChainsCompileWithAutoResolvePromises Recording · Job · CLI logs
UpdateToStable_CSharpEmptyAppHost_KeepsConfigChannel Recording · Job · CLI logs
UpdateToStable_CSharpSingleFileInit_KeepsConfigChannel Recording · Job · CLI logs
UpdateToStable_TypeScriptSingleFileInit_KeepsConfigChannel Recording · Job · CLI logs
UpdateToStable_TypeScript_PreviewsStablePkgsAndKeepsChannel Recording · Job · CLI logs

📹 Recordings uploaded automatically from CI run #27236204071

Copilot AI review requested due to automatic review settings June 25, 2026 13:58

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

This PR adds opt-out, low-cardinality usage telemetry for Aspire's own AI skills and MCP tools (part of #18008), mirroring microsoft/azure-skills. It introduces a hidden aspire agent telemetry CLI command that records a single reported activity per agent PostToolUse event, and auto-registers PostToolUse hooks during aspire agent init for detected GitHub Copilot CLI and Claude Code clients. Privacy is enforced by recording only allowlisted, Aspire-owned identifiers (skill/tool names, skill-relative reference path, session GUID); the single ASPIRE_CLI_TELEMETRY_OPTOUT switch gates everything, re-checked by both the hook scripts and the command.

Changes:

  • New hidden aspire agent telemetry command that validates/normalizes hook values, drops anything invalid (emitting no span when nothing survives), suppresses the generic aspire/cli/main span, force-flushes the reported (Azure Monitor) provider, and always exits 0 so a hook can never break the agent.
  • aspire agent init Phase 6 materializes track-telemetry.{sh,ps1} to ~/.aspire/hooks and writes user-level PostToolUse hooks via a conservative, idempotent JSON merge that never clobbers malformed/unexpected configs.
  • Embedded hook scripts + bundle sync/verify tooling, new localized strings, and comprehensive unit/script tests.

Reviewed changes

Copilot reviewed 50 out of 51 changed files in this pull request and generated no comments.

Show a summary per file
File Description
src/Aspire.Cli/Commands/AgentTelemetryCommand.cs New hidden command; validates/drops values, emits one reported span, always exits 0.
src/Aspire.Cli/Telemetry/AgentTelemetryInvocation.cs Null-safe leading-token matcher for agent telemetry used to suppress the main span.
src/Aspire.Cli/Telemetry/TelemetryManager.cs Adds ForceFlushReportedAsync + bounded flush constant for reliable one-shot export.
src/Aspire.Cli/Program.cs Wires opt-out, main-span suppression, reported-flush, and DI registrations.
src/Aspire.Cli/Commands/AgentInitCommand.cs Phase 6 best-effort telemetry hook configuration; surfaces configured/skipped clients.
src/Aspire.Cli/Commands/McpInitCommand.cs Threads the new configurator through the legacy delegating command.
src/Aspire.Cli/Agents/Hooks/TelemetryHookConfigurator.cs Writes Copilot/Claude user-level hooks; conservative idempotent JSON merge + atomic write.
src/Aspire.Cli/Agents/Hooks/TelemetryHookInstaller.cs Materializes embedded scripts with LF/no-BOM, atomic write, executable bit.
src/Aspire.Cli/Agents/Hooks/HookCommandFormatter.cs + interfaces/records Quoting helpers and DI contracts for hook wiring.
src/Aspire.Cli/Agents/Hooks/track-telemetry.{sh,ps1} Embedded hook scripts: classify events, honor opt-out, always emit {"continue":true}.
src/Aspire.Cli/Aspire.Cli.csproj Embeds the hook scripts with matching LogicalNames.
src/Aspire.Cli/Resources/AgentCommandStrings.{resx,Designer.cs} + xlf/* Adds 8 localized strings (command/option descriptions, hook install/skip messages).
eng/scripts/aspire-skills-bundle.common.ps1 + update/verify scripts Bundle sync/verify of embedded hooks with SHA-256 integrity against a pinned commit.
tests/Aspire.Cli.Tests/Commands/AgentTelemetryCommandTests.cs Verifies tag emission, value dropping, unsafe-path rejection, exit-0 behavior.
tests/Aspire.Cli.Tests/Telemetry/AgentTelemetryInvocationTests.cs Verifies the leading-token matcher across positive/negative/null cases.
tests/Aspire.Cli.Tests/Telemetry/TelemetryConfigurationTests.cs Verifies opt-out gating of Azure Monitor for the agent telemetry path.
tests/Aspire.Cli.Tests/Commands/AgentInitCommandTests.cs Verifies hook installation for a detected client; adds FakeDetectingDetector.
tests/Aspire.Cli.Tests/Utils/CliTestHelper.cs Registers the new hook services and AgentTelemetryCommand for tests.
Files not reviewed (1)
  • src/Aspire.Cli/Resources/AgentCommandStrings.Designer.cs: Generated file

@IEvangelist IEvangelist force-pushed the dapine/agent-telemetry branch from 4299a9b to 9a213e4 Compare June 25, 2026 14:57
@github-actions

This comment has been minimized.

@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@IEvangelist IEvangelist force-pushed the dapine/agent-telemetry branch from 9a213e4 to 6857fad Compare June 25, 2026 20:51
Copilot AI review requested due to automatic review settings June 25, 2026 20:51
@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 51 out of 52 changed files in this pull request and generated 1 comment.

Files not reviewed (1)
  • src/Aspire.Cli/Resources/AgentCommandStrings.Designer.cs: Generated file

Comment thread src/Aspire.Cli/Agents/Hooks/TelemetryHookConfigurator.cs Outdated
@IEvangelist IEvangelist force-pushed the dapine/agent-telemetry branch from 6857fad to 78c5732 Compare June 26, 2026 13:01
@github-actions

This comment has been minimized.

Copilot AI review requested due to automatic review settings June 26, 2026 19:39
@IEvangelist IEvangelist force-pushed the dapine/agent-telemetry branch from 78c5732 to e2489fa Compare June 26, 2026 19:39
@github-actions

This comment has been minimized.

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 51 out of 52 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • src/Aspire.Cli/Resources/AgentCommandStrings.Designer.cs: Generated file

@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@IEvangelist IEvangelist force-pushed the dapine/agent-telemetry branch from e2489fa to 0891f58 Compare June 29, 2026 12:48
@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

IEvangelist and others added 7 commits June 29, 2026 13:51
…lemetry

Introduces a hidden 'aspire agent telemetry' subcommand that receives parsed
agent PostToolUse values (event type, client, session, skill/tool name, file
reference, timestamp) and writes them into Aspire's reported telemetry pipeline.

- AgentTelemetryInvocation detector suppresses the main CLI usage span and the
  first-run notice so each hook event emits only one agent_telemetry span.
- Per-field validation/sanitization drops unsafe or overlong values (absolute
  paths, traversal, unknown event types) so only low-cardinality Aspire-owned
  identifiers are recorded. The command never throws and always exits 0.
- Multi-level opt-out: global ASPIRE_CLI_TELEMETRY_OPTOUT and new AI-only
  ASPIRE_CLI_AGENT_TELEMETRY_OPTOUT, honored before any provider is created.
- Bounded reported-provider force-flush for the one-shot fire-and-forget path.
- Localized command/option strings + unit tests (41 passing).

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
…init'

Materialize the track-telemetry.{sh,ps1} hook scripts to ~/.aspire/hooks and
register a PostToolUse hook into each detected client's user-level config
(GitHub Copilot CLI ~/.copilot/hooks/aspire-telemetry.json and Claude Code
~/.claude/settings.json). Default-on for parity with azure-skills, with a
--no-telemetry-hooks opt-out; transmission stays gated by the telemetry
opt-out env vars that both the scripts and the 'agent telemetry' command
re-check.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Simplify the AI agent skill-usage telemetry to honor only the existing
ASPIRE_CLI_TELEMETRY_OPTOUT switch. Remove the AI-specific
ASPIRE_CLI_AGENT_TELEMETRY_OPTOUT environment variable and the
'aspire agent init --no-telemetry-hooks' option; hooks are always installed
during 'agent init' and whether telemetry is sent stays gated by the single
opt-out, re-checked at runtime by both the hook scripts and the CLI command.

Also address code-review findings:
- Emit no reported span when no value survives validation (was a tagless span).
- Add TelemetryHookScriptTests that run the real embedded track-telemetry.{sh,ps1}
  scripts end-to-end and assert the resulting 'agent telemetry' invocation.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
JsonNode.Parse(content)?.AsObject() only guarded against JsonException, but
AsObject() throws InvalidOperationException when the settings.json root is valid
JSON that isn't an object (e.g. [1,2,3], "str", 42). That escaped both the
configurator and the best-effort callers and would crash 'aspire agent init'.
Parse first, then pattern-match: null starts a fresh object, a JsonObject is
used as-is, and any other root is skipped as UnexpectedConfigShape. Adds a
regression test covering a non-object (array) root.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Close the remaining test gaps for the telemetry hook scripts and make the
aspire-skills bundle CI responsible for the embedded hook scripts too.

Tests (tests/Aspire.Cli.Tests/Agents/TelemetryHookScriptTests.cs):
- Add 3 bash + 4 pwsh cases covering previously untested branches:
  SKILL.md read -> skill_invocation, reference_file_read relative-path
  forwarding, Claude `aspire:` skill-name prefix stripping, and VS Code
  `mcp_aspire_` MCP client detection.

Bundle CI (Option C, commit-pinned source sync):
- eng/scripts/aspire-skills-bundle.common.ps1: new shared helper used by
  both update and verify so their hook logic cannot drift. Fetches hooks
  from microsoft/aspire-skills at the release's immutable commit and hashes
  over LF-normalized UTF-8 (no BOM) so .ps1 (text=auto) and .sh (eol=lf)
  hash consistently regardless of checkout line endings.
- update-aspire-skills-bundle.ps1: pin to the release commit, sync
  hooks/scripts/track-telemetry.{sh,ps1} into src/Aspire.Cli/Agents/Hooks,
  and record { commitSha, files: { name: sha256 } } in the bundle metadata.
  Releases that predate the hooks warn and skip (transition-friendly).
- verify-aspire-skills-bundle.ps1: when metadata records hooks, cross-check
  that each embedded file matches the recorded hash AND that the recorded
  hash matches the canonical source at the pinned commit.
- verify-aspire-skills-bundle.yml: trigger on the embedded hook scripts and
  the new shared helper so hand-edits are verified.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Configure the PostToolUse hooks per the GitHub Copilot CLI and Claude Code hooks references:

- Copilot keeps shell form; the powershell value invokes pwsh (PowerShell 7+), the documented Windows prerequisite, instead of Windows PowerShell 5.1.

- Claude moves to exec form (command + args) as the docs recommend for path-referencing hooks, avoiding the Git Bash shell hop and PowerShell-style quoting mismatch on Windows. Uses pwsh on Windows and bash on Unix.

- IsAspireHook matches the script name in either command (legacy shell form) or args (exec form) so re-init stays idempotent across the format change.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
Make the PostToolUse hook scripts fail-safe by construction rather than
relying on every code path remembering to print the response:

- bash: a single EXIT trap is now the one guaranteed emit point for the
  continue response; all paths just exit 0. A final explicit exit 0 stops
  the CLI's exit code (e.g. timeout's 124) leaking through as the hook's
  exit code.
- pwsh: a top-level trap is the last-resort net for any unhandled
  terminating error, so the redundant per-call try/catch around stdin
  read, JSON parse, and CLI invoke are removed.
- Both: a fast pre-filter returns immediately when the raw payload
  contains no skill/aspire token, skipping all sed/grep (bash) and JSON
  parsing (pwsh) on the common non-Aspire event.

Validated: existing pwsh script tests pass; the bash script and both
fail-safe paths (missing CLI, malformed payload) verified to emit exactly
one response and exit 0.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@IEvangelist IEvangelist force-pushed the dapine/agent-telemetry branch from 7b1ee7c to aecbb0b Compare June 29, 2026 18:51
@github-actions

Copy link
Copy Markdown
Contributor

Tests selector (audit mode)

The full test matrix and all jobs still run in audit mode. The tests and jobs below are what selective CI would run under enforcement.

Runs the full test matrix + all jobs (ALL) — run-all fallback: 'eng/scripts/aspire-skills-bundle.common.ps1' is neither Layer-1-owned nor matched by a Layer 2 rule


Selection computed for commit aecbb0b.

@github-actions

Copy link
Copy Markdown
Contributor

Retrying the failed CI jobs for this pull request from the CI run attempt. The rerun is being tracked in the rerun attempt.

IEvangelist added a commit to microsoft/aspire-skills that referenced this pull request Jun 29, 2026
Re-syncs hooks/scripts/track-telemetry.{sh,ps1} byte-for-byte (LF-normalized)
with the canonical embedded copies in microsoft/aspire#18009 after a round of
hardening:

- Parse Copilot CLI's JSON-encoded-string toolArgs (not just nested objects) so
  skill and reference-file detection actually fires for the Copilot client.
- Guaranteed single hook response via an EXIT trap (sh) / top-level trap (ps1).
- Bound the Aspire CLI call (sh: timeout 10; ps1: child process WaitForExit) so a
  hung or slow CLI can't stall the agent's tool loop.
- Case-insensitive opt-out parity between the two scripts.
- Fast-path early return for the common non-Aspire PostToolUse event.

Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com>
@IEvangelist IEvangelist marked this pull request as ready for review June 29, 2026 20:48
Copilot AI review requested due to automatic review settings June 29, 2026 20:48

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Copilot reviewed 51 out of 52 changed files in this pull request and generated no new comments.

Files not reviewed (1)
  • src/Aspire.Cli/Resources/AgentCommandStrings.Designer.cs: Generated file

@github-actions

Copy link
Copy Markdown
Contributor

CI Failure Analysis: Code Issue Detected

The CI build failed due to compile errors caused by changes in this PR. The failing file is tests/Aspire.Cli.Tests/Telemetry/TelemetryConfigurationTests.cs, which is modified by the PR, and the same errors appear across the stabilization and CLI test builds.

Failure details:

  • Job: Stabilization Check
  • Failed Step: Build + pack with StabilizePackageVersion=true
  • Error: TelemetryConfigurationTests.cs(292,50): error CS1503: Argument 1: cannot convert from 'Microsoft.Extensions.Configuration.IConfigurationRoot' to 'Aspire.Cli.Telemetry.TelemetryConfiguration'
  • Error: TelemetryConfigurationTests.cs(292,65): error CS9174: Cannot initialize type 'TelemetryTagsSource' with a collection expression because the type is not constructible.
  • Also failed: Tests / Cli / Cli on Ubuntu, Windows, and macOS with the same CS1503 / CS9174 errors; Tests / Final Test Results and Final Results failed because dependent jobs failed.
  • Likely cause: The tests still construct TelemetryTagsSource with the old shape/signature after the telemetry-related CLI changes in this PR.

The CI will not be automatically rerun. Please fix the compile errors and push an updated commit.

Generated by Analyze CI Failure · 192.7 AIC · ⌖ 11.1 AIC · ⊞ 33.4K ·

@github-actions

Copy link
Copy Markdown
Contributor

CI Failure Analysis: Code Issue Detected

The CI build failed due to compilation errors caused by changes in this PR.

Failure details:

  • Job: Stabilization Check, Tests / Cli / Cli (ubuntu-latest), Tests / Cli / Cli (windows-latest), Tests / Cli / Cli (macos-latest)
  • Failed Step: Build test project / Build + pack with StabilizePackageVersion=true
  • Error:
    tests/Aspire.Cli.Tests/Telemetry/TelemetryConfigurationTests.cs(292,50): error CS1503: Argument 1: cannot convert from 'Microsoft.Extensions.Configuration.IConfigurationRoot' to 'Aspire.Cli.Telemetry.TelemetryConfiguration'
    tests/Aspire.Cli.Tests/Telemetry/TelemetryConfigurationTests.cs(292,65): error CS9174: Cannot initialize type 'TelemetryTagsSource' with a collection expression because the type is not constructible.
    tests/Aspire.Cli.Tests/Telemetry/TelemetryConfigurationTests.cs(302,50): error CS1503: Argument 1: cannot convert from 'Microsoft.Extensions.Configuration.IConfigurationRoot' to 'Aspire.Cli.Telemetry.TelemetryConfiguration'
    tests/Aspire.Cli.Tests/Telemetry/TelemetryConfigurationTests.cs(302,65): error CS9174: Cannot initialize type 'TelemetryTagsSource' with a collection expression because the type is not constructible.
    
  • Likely cause: This PR modified src/Aspire.Cli/Telemetry/TelemetryConstants.cs, TelemetryManager.cs, and added AgentTelemetryInvocation.cs, which changed the constructor signature of TelemetryConfiguration (it no longer accepts IConfigurationRoot as its first argument) and changed TelemetryTagsSource so it is no longer constructible via a collection expression. The file tests/Aspire.Cli.Tests/Telemetry/TelemetryConfigurationTests.cs was updated by this PR (+29 lines) but lines 292 and 302 still use the old API.

The CI will not be automatically rerun. Please fix the compilation errors in TelemetryConfigurationTests.cs lines 292 and 302 to use the updated TelemetryConfiguration and TelemetryTagsSource API shapes, then push an updated commit.

Generated by Analyze CI Failure · 176.6 AIC · ⌖ 13.7 AIC · ⊞ 39.6K ·

@github-actions

Copy link
Copy Markdown
Contributor

CI Failure Analysis: Code Issue Detected

The CI build failed due to compilation errors caused by changes in this PR.

Failure details:

  • Jobs: Stabilization Check, Tests / Cli / Cli (ubuntu-latest), Tests / Cli / Cli (windows-latest), Tests / Cli / Cli (macos-latest)
  • Failed Step: Build test project / Build + pack with StabilizePackageVersion=true
  • File: tests/Aspire.Cli.Tests/Telemetry/TelemetryConfigurationTests.cs (lines 292, 302)

Errors:

error CS1503: Argument 1: cannot convert from 'Microsoft.Extensions.Configuration.IConfigurationRoot' to 'Aspire.Cli.Telemetry.TelemetryConfiguration'

error CS9174: Cannot initialize type 'TelemetryTagsSource' with a collection expression because the type is not constructible.

Likely cause: The PR modifies src/Aspire.Cli/Telemetry/TelemetryManager.cs and related telemetry source files, which appear to have changed the TelemetryConfiguration type's constructor — it no longer accepts IConfigurationRoot as an argument. The tests in TelemetryConfigurationTests.cs (also modified by this PR, +29 lines) still reference the old API at lines 292 and 302. The TelemetryTagsSource type also appears to have changed such that it no longer supports collection expression initialization.

The CI will not be automatically rerun. Please fix the compilation errors and push an updated commit.

View the workflow run

Generated by Analyze CI Failure · 135 AIC · ⌖ 12.6 AIC · ⊞ 39.6K ·

@github-actions

Copy link
Copy Markdown
Contributor

CI Failure Analysis: Code Issue Detected

The CI build failed due to compilation errors caused by changes in this PR.

Failure details:

  • Jobs: Stabilization Check, Tests / Cli / Cli (ubuntu-latest), Tests / Cli / Cli (windows-latest), Tests / Cli / Cli (macos-latest)

  • Failed Step: Build test project

  • Errors:

    tests/Aspire.Cli.Tests/Telemetry/TelemetryConfigurationTests.cs(292,50): error CS1503: Argument 1: cannot convert from 'Microsoft.Extensions.Configuration.IConfigurationRoot' to 'Aspire.Cli.Telemetry.TelemetryConfiguration'
    tests/Aspire.Cli.Tests/Telemetry/TelemetryConfigurationTests.cs(292,65): error CS9174: Cannot initialize type 'TelemetryTagsSource' with a collection expression because the type is not constructible.
    tests/Aspire.Cli.Tests/Telemetry/TelemetryConfigurationTests.cs(302,50): error CS1503: Argument 1: cannot convert from 'Microsoft.Extensions.Configuration.IConfigurationRoot' to 'Aspire.Cli.Telemetry.TelemetryConfiguration'
    tests/Aspire.Cli.Tests/Telemetry/TelemetryConfigurationTests.cs(302,65): error CS9174: Cannot initialize type 'TelemetryTagsSource' with a collection expression because the type is not constructible.
    
  • Likely cause: This PR modified both src/Aspire.Cli/Telemetry/TelemetryManager.cs (+36) and tests/Aspire.Cli.Tests/Telemetry/TelemetryConfigurationTests.cs (+29). The test file at lines 292 and 302 passes an IConfigurationRoot where a TelemetryConfiguration is now expected, and attempts to use a collection expression to initialize TelemetryTagsSource which is no longer constructible that way. It appears the production API changed (the constructor/factory for TelemetryConfiguration no longer accepts IConfigurationRoot directly, and TelemetryTagsSource is no longer constructible via collection initializer) but the test file was not fully updated to match.

The CI will not be automatically rerun. Please fix the type mismatches in TelemetryConfigurationTests.cs and push an updated commit.

Generated by Analyze CI Failure · 135.8 AIC · ⌖ 12.7 AIC · ⊞ 39.9K ·

@github-actions

Copy link
Copy Markdown
Contributor

CI Failure Analysis: Code Issue Detected

The CI build failed due to compilation errors caused by changes in this PR.

Failure details:

  • Jobs: Stabilization Check, Tests / Cli / Cli (ubuntu-latest), Tests / Cli / Cli (windows-latest), Tests / Cli / Cli (macos-latest)
  • Failed Step: Build test project / Build + pack with StabilizePackageVersion=true
  • Failing file: tests/Aspire.Cli.Tests/Telemetry/TelemetryConfigurationTests.cs (modified by this PR, +29/-0)

Compilation errors:

TelemetryConfigurationTests.cs(292,50): error CS1503: Argument 1: cannot convert from
  'Microsoft.Extensions.Configuration.IConfigurationRoot' to 'Aspire.Cli.Telemetry.TelemetryConfiguration'

TelemetryConfigurationTests.cs(292,65): error CS9174: Cannot initialize type 'TelemetryTagsSource'
  with a collection expression because the type is not constructible.

TelemetryConfigurationTests.cs(302,50): error CS1503: Argument 1: cannot convert from
  'Microsoft.Extensions.Configuration.IConfigurationRoot' to 'Aspire.Cli.Telemetry.TelemetryConfiguration'

TelemetryConfigurationTests.cs(302,65): error CS9174: Cannot initialize type 'TelemetryTagsSource'
  with a collection expression because the type is not constructible.

Likely cause: The PR modified src/Aspire.Cli/Telemetry/TelemetryConfiguration and/or TelemetryTagsSource (via changes to TelemetryManager.cs, TelemetryConstants.cs, and related files), but TelemetryConfigurationTests.cs at lines 292 and 302 still passes IConfigurationRoot as argument 1 to TelemetryConfiguration and uses a collection expression initializer for TelemetryTagsSource, which are no longer compatible with the updated source type signatures.

The CI will not be automatically rerun. Please fix the type mismatches in TelemetryConfigurationTests.cs and push an updated commit.

View the workflow run

Generated by Analyze CI Failure · 95.3 AIC · ⌖ 22.3 AIC · ⊞ 39.4K ·

@davidfowl davidfowl left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Please test this well after the merge

@davidfowl davidfowl merged commit 3d27046 into main Jul 2, 2026
654 of 657 checks passed
@github-actions github-actions Bot added this to the 13.5 milestone Jul 2, 2026
@davidfowl davidfowl deleted the dapine/agent-telemetry branch July 2, 2026 05:38
@aspire-repo-bot

Copy link
Copy Markdown
Contributor

⚠️ Documentation was required for this change, but a docs PR could not be drafted automatically.

Documentation changes were written and committed to branch docs/agent-telemetry-hooks-18009 (commit 2cebce8), but the create_pull_request safe-output tool failed twice with "Pinned SHA failed to generate patch: ERR_SYSTEM: Git command failed with status 1" — the workspace is a shallow/grafted clone and the tool cannot resolve the diff between the base and the new commit.

Triggered signals (5): cli_command_added, cli_command_file_changed, cli_option_added, cli_resource_strings_changed, defaults_or_constants_file_changed. Evidence: AgentTelemetryCommand.cs adds a new (hidden) aspire agent telemetry command with --event-type option; AgentInitCommand.cs adds a Phase 6 that installs PostToolUse hook scripts; AgentCommandStrings.resx adds InitCommand_TelemetryHooksInstalled and related strings.

Intended docs changes (needed but not merged):

  • reference/cli/commands/aspire-agent-init.mdx — add Step 4 (telemetry hooks) to the description, add a full Telemetry hooks section (what gets installed, data collected, opt-out via ASPIRE_CLI_TELEMETRY_OPTOUT).
  • reference/cli/microsoft-collected-cli-telemetry.mdx — add Aspire 13.5 AI agent skill/tool usage row to the data-points table.

See the workflow run for details: https://github.com/microsoft/aspire/actions/runs/28602209839

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

3 participants