Skip to content
Open
Show file tree
Hide file tree
Changes from 3 commits
Commits
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
3 changes: 2 additions & 1 deletion .claude-plugin/marketplace.json
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,8 @@
{
"name": "microsoft-finops-toolkit",
"version": "15.0.0",
"source": "./plugins/microsoft-finops-toolkit",
"source": "./src/templates/agent-plugin",
Comment thread
MSBrett marked this conversation as resolved.

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

With both manifests now pointing here, the plugins/microsoft-finops-toolkit symlink has no remaining references anywhere on the branch β€” no grep hits β€” but is still committed. Worth removing it in this PR rather than leaving a dead pointer for the next reader to trip over.

Separately, strict: true on the next line is the documented default for marketplace plugin entries. Valid, but a no-op, and the new test now pins it. Fine to keep if it's deliberate belt-and-braces.

"strict": true,
"description": "Microsoft FinOps toolkit plugin for AI-powered cloud financial management.",
"category": "finops",
"homepage": "https://aka.ms/finops/toolkit"
Expand Down
37 changes: 29 additions & 8 deletions src/powershell/Tests/Unit/AgentPlugins.Tests.ps1
Original file line number Diff line number Diff line change
Expand Up @@ -34,7 +34,7 @@ Describe 'Agent plugin manifest' {
$root.agents | Should -Be './agents/'
$root.mcpServers | Should -Be '.mcp.json'
$claude.agents | Should -BeNullOrEmpty
$claude.mcpServers | Should -BeNullOrEmpty
$claude.mcpServers | Should -Be './.mcp.json'
$claude.outputStyles | Should -Be './output-styles/'
}

Expand All @@ -48,11 +48,21 @@ Describe 'Agent plugin manifest' {
$claude = Get-Content (Join-Path $script:Plugin '.claude-plugin/plugin.json') -Raw | ConvertFrom-Json

$root.mcpServers | Should -Be '.mcp.json'
$claude.mcpServers | Should -BeNullOrEmpty
$claude.agents | Should -BeNullOrEmpty
$claude.mcpServers | Should -Be './.mcp.json'
Join-Path $script:Plugin '.mcp.json' | Should -Exist
}

It 'Declares resolvable paths for every Claude component' {
$claude = Get-Content (Join-Path $script:Plugin '.claude-plugin/plugin.json') -Raw | ConvertFrom-Json
$paths = @($claude.commands) + @($claude.skills) + @($claude.mcpServers) + @($claude.outputStyles)

$paths.Count | Should -BeGreaterOrEqual 4
$paths | ForEach-Object {
$_ | Should -Not -BeNullOrEmpty
Join-Path $script:Plugin $_ | Should -Exist
}
}
Comment thread
MSBrett marked this conversation as resolved.

It 'Uses unpinned Azure MCP latest package in .mcp.json' {
$mcp = Get-Content (Join-Path $script:Plugin '.mcp.json') -Raw | ConvertFrom-Json
$args = $mcp.mcpServers.'azure-mcp-server'.args
Expand All @@ -64,13 +74,17 @@ Describe 'Agent plugin manifest' {
}

Describe 'Agent plugin components' {
It 'Ships agent definitions as NAME.agent.md files' {
$agents = Get-ChildItem (Join-Path $script:Plugin 'agents') -Filter '*.agent.md'
$agents.Count | Should -BeGreaterThan 0
It 'Ships agent definitions as Claude-compatible NAME.md files' {
$agents = Get-ChildItem (Join-Path $script:Plugin 'agents') -Filter '*.md'

$agents.Count | Should -Be 5
Comment thread
MSBrett marked this conversation as resolved.
Outdated
$agents.Name | ForEach-Object {
$_ | Should -Not -Match '\.agent\.md$'

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

This inverts the previous guard, so the .agent.md naming can no longer be restored without also editing this test β€” a follow-up PR fixing Copilot discovery would fail CI here.

If the rename is reverted, this assertion has to go with it. Worth keeping the naming change and its enforcement in the same commit either way, so CI never encodes a convention the plugin manifests contradict.

}
}

It 'Gives every agent a name and description in front matter' {
Get-ChildItem (Join-Path $script:Plugin 'agents') -Filter '*.agent.md' | ForEach-Object {
Get-ChildItem (Join-Path $script:Plugin 'agents') -Filter '*.md' | ForEach-Object {
$content = Get-Content $_.FullName -Raw
$content | Should -Match '(?ms)^---\s.*^name:\s*\S.*^description:\s*\S.*^---'
}
Expand Down Expand Up @@ -167,7 +181,7 @@ Describe 'Plugin discovery and marketplaces' {
It 'Uses repository-root-relative marketplace sources' {
$marketplaces = @{
'.github/plugin/marketplace.json' = './plugins/microsoft-finops-toolkit'
'.claude-plugin/marketplace.json' = './plugins/microsoft-finops-toolkit'
'.claude-plugin/marketplace.json' = './src/templates/agent-plugin'
Comment thread
MSBrett marked this conversation as resolved.
Outdated
}

foreach ($marketplace in $marketplaces.Keys)
Expand All @@ -177,4 +191,11 @@ Describe 'Plugin discovery and marketplaces' {
$entry.source | Should -Be $marketplaces[$marketplace]
}
}

It 'Enables strict mode explicitly for the Claude plugin' {
$json = Get-Content (Join-Path $script:RepoRoot '.claude-plugin/marketplace.json') -Raw | ConvertFrom-Json
$entry = $json.plugins | Where-Object { $_.name -eq 'microsoft-finops-toolkit' }

$entry.strict | Should -BeTrue
}
}
1 change: 1 addition & 0 deletions src/templates/agent-plugin/.claude-plugin/plugin.json
Original file line number Diff line number Diff line change
Expand Up @@ -14,5 +14,6 @@
"skills": [
"./skills/"
],
"mcpServers": "./.mcp.json",
Comment thread
MSBrett marked this conversation as resolved.
Outdated
"outputStyles": "./output-styles/"
}

Copy link
Copy Markdown
Collaborator

Choose a reason for hiding this comment

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

Blocker β€” this rename, and the other four in agents/, breaks GitHub Copilot CLI agent discovery, which requires the .agent.md extension. Full reasoning and suggested resolution in the review summary.

File renamed without changes.
Loading