Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
Show all changes
29 commits
Select commit Hold shift + click to select a range
9ca7e89
Adding validation subproject covering T0-T3 checks
abbinayaa May 21, 2026
1e18b78
Fixing validation errors for py and nodejs
abbinayaa May 22, 2026
c51dd5c
Fixing telemetry check and remove anonymous auth
abbinayaa May 26, 2026
4781aba
Fixing telemetry checks for python
abbinayaa May 27, 2026
1d6f56a
Update registration check
abbinayaa May 27, 2026
4bd3093
Add AgentMetricRequirementCheck
abbinayaa May 27, 2026
cacf166
MAC visibility validation via mcp tool call
IshaArora3 May 28, 2026
8c8c070
integrate mac visibility validation changes with AgentMetricRequireme…
IshaArora3 May 28, 2026
c6fd796
Remove agent metrics check for demo
abbinayaa May 28, 2026
0a7ac06
Cleaning up validate to include only local checks
abbinayaa Jun 11, 2026
01148a4
Clean up change in cli and move checks to validate
abbinayaa Jun 11, 2026
88c25e1
Removing interim message dependency
abbinayaa Jun 11, 2026
d09f622
Merge branch 'main' into users/absubram/CampAir_Validation
abbinayaa Jun 11, 2026
0b268bd
Fixing requirement check log levels
abbinayaa Jun 12, 2026
f8ef513
Adding bearer token check for tool validation
abbinayaa Jun 15, 2026
e0f7b46
fix(validate): replace Unicode checkmark with plain ASCII status markers
abbinayaa Jun 23, 2026
0e8e523
fix(blueprint): address multiple review comments on BlueprintRegistra…
abbinayaa Jun 23, 2026
e2ab473
fix(build): quote MSBuild file-logger path to handle spaces in user p…
abbinayaa Jun 23, 2026
1b8b804
fix(conversation): narrow IsErrorResponse to structural signals to re…
abbinayaa Jun 23, 2026
48a4e8f
fix(local-runtime): implement IDisposable for HttpClient ownership tr…
abbinayaa Jun 23, 2026
5e9a0c2
fix(telemetry): remove dead TelemetryContextKeywords constant and enf…
abbinayaa Jun 23, 2026
f306622
fix(callback): use case-insensitive comparison for message type in Is…
abbinayaa Jun 23, 2026
46cc28f
docs(tooling-manifest): add clarifying comment for optional manifest …
abbinayaa Jun 23, 2026
0a7ec9f
refactor(validation): reorganize types into Models/ folder with one t…
abbinayaa Jun 23, 2026
bc37d7e
fix(test): update SetsAspNetCoreUrls to use launchSettings.json inste…
abbinayaa Jun 23, 2026
ed8fe6c
fix(telemetry): restore ParentSpanPattern regex to handle JSON-quoted…
abbinayaa Jun 23, 2026
cb658bd
Address PR #456 review comments: dispose, streaming, pip
abbinayaa Jun 23, 2026
51fa6c7
Address PR #456 round 2: restore, await handler, boot log, test fixes
abbinayaa Jun 23, 2026
21c41bb
fix(tests): use double quotes for Linux shell commands in CreateFakeP…
abbinayaa Jun 23, 2026
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ Agents provisioned before this release need `Agent365.Observability.OtelWrite` g
**Option B — CLI** (`a365 setup admin`) has been removed in this release. Use Option A above, or copy the PowerShell instructions printed in the `a365 setup all` summary output.

### Added
- `a365 validate` — validates the local agent project configuration and readiness. Runs structural checks (config, manifest, bearer token), builds the project (which may install dependencies such as npm packages or Python packages), boots the agent locally, sends test conversation turns, verifies telemetry spans, and checks blueprint registration. Reports results as a tiered JSON report (`a365.validate.json`).
- New `Microsoft.Agents.A365.DevTools.Validation` subproject for reusable validation contracts and helpers.
- Log separator written at the start of each CLI invocation now redacts values for secret-bearing options (e.g. `--idp-client-secret`) so they are not written to the log file in plain text.
- Authentication context (tenant and user) is now logged at the `Information` level whenever the resolved sign-in identity changes, giving operators a clear audit trail in the log file of who the CLI is acting as, without exposing credentials.
- `a365 develop-mcp evaluate` command for evaluating MCP server tool schema quality — runs deterministic and semantic checks (via GitHub Copilot or Claude Code CLIs), computes maturity scoring, and generates an interactive HTML report
Expand Down
12 changes: 12 additions & 0 deletions src/Microsoft.Agents.A365.DevTools.Cli.sln
Original file line number Diff line number Diff line change
Expand Up @@ -5,8 +5,12 @@ VisualStudioVersion = 17.0.31903.59
MinimumVisualStudioVersion = 10.0.40219.1
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Agents.A365.DevTools.Cli", "Microsoft.Agents.A365.DevTools.Cli\Microsoft.Agents.A365.DevTools.Cli.csproj", "{B46A53DE-09FD-8E1D-83E8-F1DC1DB32397}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Agents.A365.DevTools.Validation", "Microsoft.Agents.A365.DevTools.Validation\Microsoft.Agents.A365.DevTools.Validation.csproj", "{A1A5F7A7-1F3A-4D32-8B28-A2B95B2F1F11}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Agents.A365.DevTools.Cli.Tests", "Tests\Microsoft.Agents.A365.DevTools.Cli.Tests\Microsoft.Agents.A365.DevTools.Cli.Tests.csproj", "{ACDAF3A6-DD04-9652-7C37-1C5EC3FA9FB5}"
EndProject
Project("{FAE04EC0-301F-11D3-BF4B-00C04F79EFBC}") = "Microsoft.Agents.A365.DevTools.Validation.Tests", "Tests\Microsoft.Agents.A365.DevTools.Validation.Tests\Microsoft.Agents.A365.DevTools.Validation.Tests.csproj", "{DAD2B4B5-2E68-46EA-97FC-30A0A1E0FE91}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Any CPU = Debug|Any CPU
Expand All @@ -17,10 +21,18 @@ Global
{B46A53DE-09FD-8E1D-83E8-F1DC1DB32397}.Debug|Any CPU.Build.0 = Debug|Any CPU
{B46A53DE-09FD-8E1D-83E8-F1DC1DB32397}.Release|Any CPU.ActiveCfg = Release|Any CPU
{B46A53DE-09FD-8E1D-83E8-F1DC1DB32397}.Release|Any CPU.Build.0 = Release|Any CPU
{A1A5F7A7-1F3A-4D32-8B28-A2B95B2F1F11}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{A1A5F7A7-1F3A-4D32-8B28-A2B95B2F1F11}.Debug|Any CPU.Build.0 = Debug|Any CPU
{A1A5F7A7-1F3A-4D32-8B28-A2B95B2F1F11}.Release|Any CPU.ActiveCfg = Release|Any CPU
{A1A5F7A7-1F3A-4D32-8B28-A2B95B2F1F11}.Release|Any CPU.Build.0 = Release|Any CPU
{ACDAF3A6-DD04-9652-7C37-1C5EC3FA9FB5}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{ACDAF3A6-DD04-9652-7C37-1C5EC3FA9FB5}.Debug|Any CPU.Build.0 = Debug|Any CPU
{ACDAF3A6-DD04-9652-7C37-1C5EC3FA9FB5}.Release|Any CPU.ActiveCfg = Release|Any CPU
{ACDAF3A6-DD04-9652-7C37-1C5EC3FA9FB5}.Release|Any CPU.Build.0 = Release|Any CPU
{DAD2B4B5-2E68-46EA-97FC-30A0A1E0FE91}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
{DAD2B4B5-2E68-46EA-97FC-30A0A1E0FE91}.Debug|Any CPU.Build.0 = Debug|Any CPU
{DAD2B4B5-2E68-46EA-97FC-30A0A1E0FE91}.Release|Any CPU.ActiveCfg = Release|Any CPU
{DAD2B4B5-2E68-46EA-97FC-30A0A1E0FE91}.Release|Any CPU.Build.0 = Release|Any CPU
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
Expand Down
876 changes: 876 additions & 0 deletions src/Microsoft.Agents.A365.DevTools.Cli/Commands/ValidateCommand.cs

Large diffs are not rendered by default.

Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ public static class CommandNames
{
// Main commands
public const string Setup = "setup";
public const string Validate = "validate";
public const string Deploy = "deploy";
public const string Config = "config";
public const string Publish = "publish";
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -22,6 +22,10 @@
<InternalsVisibleTo Include="Microsoft.Agents.A365.DevTools.Cli.Tests" />
</ItemGroup>

<ItemGroup>
<ProjectReference Include="..\Microsoft.Agents.A365.DevTools.Validation\Microsoft.Agents.A365.DevTools.Validation.csproj" />
</ItemGroup>

<ItemGroup>
<!-- CLI Framework -->
<PackageReference Include="Microsoft.Identity.Client" />
Expand Down
2 changes: 2 additions & 0 deletions src/Microsoft.Agents.A365.DevTools.Cli/Program.cs
Original file line number Diff line number Diff line change
Expand Up @@ -150,6 +150,7 @@ await Task.WhenAll(
var queryEntraLogger = serviceProvider.GetRequiredService<ILogger<QueryEntraCommand>>();
var cleanupLogger = serviceProvider.GetRequiredService<ILogger<CleanupCommand>>();
var publishLogger = serviceProvider.GetRequiredService<ILogger<PublishCommand>>();
var validateLogger = serviceProvider.GetRequiredService<ILogger<ValidateCommand>>();
var developLogger = serviceProvider.GetRequiredService<Microsoft.Extensions.Logging.ILogger<Program>>();
var configService = serviceProvider.GetRequiredService<IConfigService>();
var executor = serviceProvider.GetRequiredService<CommandExecutor>();
Expand Down Expand Up @@ -178,6 +179,7 @@ await Task.WhenAll(
var confirmationProvider = serviceProvider.GetRequiredService<IConfirmationProvider>();
rootCommand.AddCommand(SetupCommand.CreateCommand(setupLogger, configService, executor,
backendConfigurator, azureAuthValidator, platformDetector, graphApiService, agentBlueprintService, blueprintLookupService, federatedCredentialService, clientAppValidator, confirmationProvider, armApiService, resolver: bootstrapResolver));
rootCommand.AddCommand(ValidateCommand.CreateCommand(validateLogger, configService, platformDetector, executor, processService, authService, graphApiService, agentBlueprintService));
var manifestTemplateService = serviceProvider.GetRequiredService<ManifestTemplateService>();
rootCommand.AddCommand(QueryEntraCommand.CreateCommand(queryEntraLogger, configService, executor, graphApiService, agentBlueprintService, resolver: bootstrapResolver));
rootCommand.AddCommand(CleanupCommand.CreateCommand(cleanupLogger, configService, backendConfigurator, executor, agentBlueprintService, confirmationProvider, federatedCredentialService, azureAuthValidator, graphApiService, resolver: bootstrapResolver));
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -78,7 +78,20 @@ public virtual async Task<CommandResult> ExecuteAsync(
};
}

process.Start();
try
{
process.Start();
}
catch (System.ComponentModel.Win32Exception ex)
{
_logger.LogDebug(ex, "Process '{Command}' not found", command);
return new CommandResult
{
ExitCode = -1,
StandardOutput = string.Empty,
StandardError = $"'{command}' not found: {ex.Message}"
};
}

if (captureOutput)
{
Expand Down
Original file line number Diff line number Diff line change
@@ -1,77 +1,83 @@
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

namespace Microsoft.Agents.A365.DevTools.Cli.Services.Requirements;

/// <summary>
/// Result of a requirement check execution
/// </summary>
public class RequirementCheckResult
{
/// <summary>
/// Whether the requirement check passed
/// </summary>
public bool Passed { get; set; }

/// <summary>
/// Whether this is a warning (informational, doesn't block setup)
/// </summary>
public bool IsWarning { get; set; }

/// <summary>
/// Error message if the check failed
/// </summary>
public string? ErrorMessage { get; set; }

/// <summary>
/// Guidance on how to resolve the issue if the check failed
/// </summary>
public string? ResolutionGuidance { get; set; }

/// <summary>
/// Additional details about the check result
/// </summary>
public string? Details { get; set; }

/// <summary>
/// Creates a successful result
/// </summary>
public static RequirementCheckResult Success(string? details = null)
{
return new RequirementCheckResult
{
Passed = true,
IsWarning = false,
Details = details
};
}

/// <summary>
/// Creates a warning result (informational, doesn't block setup)
/// </summary>
public static RequirementCheckResult Warning(string message, string? details = null)
{
return new RequirementCheckResult
{
Passed = true,
IsWarning = true,
ErrorMessage = message,
Details = details
};
}

/// <summary>
/// Creates a failed result
/// </summary>
public static RequirementCheckResult Failure(string errorMessage, string resolutionGuidance, string? details = null)
{
return new RequirementCheckResult
{
Passed = false,
IsWarning = false,
ErrorMessage = errorMessage,
ResolutionGuidance = resolutionGuidance,
Details = details
};
}
}
// Copyright (c) Microsoft Corporation.
// Licensed under the MIT License.

namespace Microsoft.Agents.A365.DevTools.Cli.Services.Requirements;

/// <summary>
/// Result of a requirement check execution
/// </summary>
public class RequirementCheckResult
{
/// <summary>
/// Whether the requirement check passed
/// </summary>
public bool Passed { get; set; }

/// <summary>
/// Whether this is a warning (informational, doesn't block setup)
/// </summary>
public bool IsWarning { get; set; }

/// <summary>
/// Error message if the check failed
/// </summary>
public string? ErrorMessage { get; set; }

/// <summary>
/// Guidance on how to resolve the issue if the check failed
/// </summary>
public string? ResolutionGuidance { get; set; }

/// <summary>
/// Additional details about the check result
/// </summary>
public string? Details { get; set; }

/// <summary>
/// Optional metadata for structured report output (validate-specific).
/// Consumers should cast to the appropriate metadata type.
/// </summary>
public object? Metadata { get; set; }

/// <summary>
/// Creates a successful result
/// </summary>
public static RequirementCheckResult Success(string? details = null)
{
return new RequirementCheckResult
{
Passed = true,
IsWarning = false,
Details = details
};
}

/// <summary>
/// Creates a warning result (informational, doesn't block setup)
/// </summary>
public static RequirementCheckResult Warning(string message, string? details = null)
{
return new RequirementCheckResult
{
Passed = true,
IsWarning = true,
ErrorMessage = message,
Details = details
};
}

/// <summary>
/// Creates a failed result
/// </summary>
public static RequirementCheckResult Failure(string errorMessage, string resolutionGuidance, string? details = null)
{
return new RequirementCheckResult
{
Passed = false,
IsWarning = false,
ErrorMessage = errorMessage,
ResolutionGuidance = resolutionGuidance,
Details = details
};
}
}
Loading
Loading