fix: stabilize compound-engineering component counts (#299)

This commit is contained in:
Trevin Chow
2026-03-17 23:46:27 -07:00
committed by GitHub
parent 51f906c9ff
commit 754c2a893b
7 changed files with 70 additions and 22 deletions

View File

@@ -11,7 +11,7 @@
"plugins": [ "plugins": [
{ {
"name": "compound-engineering", "name": "compound-engineering",
"description": "AI-powered development tools that get smarter with every use. Make each unit of engineering work easier than the last. Includes 29 specialized agents and 44 skills.", "description": "AI-powered development tools that get smarter with every use. Make each unit of engineering work easier than the last.",
"version": "2.42.0", "version": "2.42.0",
"author": { "author": {
"name": "Kieran Klaassen", "name": "Kieran Klaassen",

View File

@@ -1,7 +1,7 @@
{ {
"name": "compound-engineering", "name": "compound-engineering",
"version": "2.42.0", "version": "2.42.0",
"description": "AI-powered development tools. 29 agents, 44 skills, 1 MCP server for code review, research, design, and workflow automation.", "description": "AI-powered development tools for code review, research, design, and workflow automation.",
"author": { "author": {
"name": "Kieran Klaassen", "name": "Kieran Klaassen",
"email": "kieran@every.to", "email": "kieran@every.to",

View File

@@ -2,7 +2,7 @@
"name": "compound-engineering", "name": "compound-engineering",
"displayName": "Compound Engineering", "displayName": "Compound Engineering",
"version": "2.42.0", "version": "2.42.0",
"description": "AI-powered development tools. 29 agents, 44 skills, 1 MCP server for code review, research, design, and workflow automation.", "description": "AI-powered development tools for code review, research, design, and workflow automation.",
"author": { "author": {
"name": "Kieran Klaassen", "name": "Kieran Klaassen",
"email": "kieran@every.to", "email": "kieran@every.to",

View File

@@ -6,15 +6,15 @@ AI-powered development tools that get smarter with every use. Make each unit of
| Component | Count | | Component | Count |
|-----------|-------| |-----------|-------|
| Agents | 29 | | Agents | 25+ |
| Skills | 44 | | Skills | 40+ |
| MCP Servers | 1 | | MCP Servers | 1 |
## Agents ## Agents
Agents are organized into categories for easier discovery. Agents are organized into categories for easier discovery.
### Review (15) ### Review
| Agent | Description | | Agent | Description |
|-------|-------------| |-------|-------------|
@@ -34,7 +34,7 @@ Agents are organized into categories for easier discovery.
| `schema-drift-detector` | Detect unrelated schema.rb changes in PRs | | `schema-drift-detector` | Detect unrelated schema.rb changes in PRs |
| `security-sentinel` | Security audits and vulnerability assessments | | `security-sentinel` | Security audits and vulnerability assessments |
### Research (6) ### Research
| Agent | Description | | Agent | Description |
|-------|-------------| |-------|-------------|
@@ -45,7 +45,7 @@ Agents are organized into categories for easier discovery.
| `learnings-researcher` | Search institutional learnings for relevant past solutions | | `learnings-researcher` | Search institutional learnings for relevant past solutions |
| `repo-research-analyst` | Research repository structure and conventions | | `repo-research-analyst` | Research repository structure and conventions |
### Design (3) ### Design
| Agent | Description | | Agent | Description |
|-------|-------------| |-------|-------------|
@@ -53,7 +53,7 @@ Agents are organized into categories for easier discovery.
| `design-iterator` | Iteratively refine UI through systematic design iterations | | `design-iterator` | Iteratively refine UI through systematic design iterations |
| `figma-design-sync` | Synchronize web implementations with Figma designs | | `figma-design-sync` | Synchronize web implementations with Figma designs |
### Workflow (4) ### Workflow
| Agent | Description | | Agent | Description |
|-------|-------------| |-------|-------------|
@@ -62,7 +62,7 @@ Agents are organized into categories for easier discovery.
| `pr-comment-resolver` | Address PR comments and implement fixes | | `pr-comment-resolver` | Address PR comments and implement fixes |
| `spec-flow-analyzer` | Analyze user flows and identify gaps in specifications | | `spec-flow-analyzer` | Analyze user flows and identify gaps in specifications |
### Docs (1) ### Docs
| Agent | Description | | Agent | Description |
|-------|-------------| |-------|-------------|

View File

@@ -1,18 +1,21 @@
#!/usr/bin/env bun #!/usr/bin/env bun
import path from "path" import path from "path"
import { validateReleasePleaseConfig } from "../../src/release/config" import { validateReleasePleaseConfig } from "../../src/release/config"
import { syncReleaseMetadata } from "../../src/release/metadata" import { getCompoundEngineeringCounts, syncReleaseMetadata } from "../../src/release/metadata"
import { readJson } from "../../src/utils/files" import { readJson } from "../../src/utils/files"
const releasePleaseConfig = await readJson<{ packages: Record<string, unknown> }>( const releasePleaseConfig = await readJson<{ packages: Record<string, unknown> }>(
path.join(process.cwd(), ".github", "release-please-config.json"), path.join(process.cwd(), ".github", "release-please-config.json"),
) )
const configErrors = validateReleasePleaseConfig(releasePleaseConfig) const configErrors = validateReleasePleaseConfig(releasePleaseConfig)
const counts = await getCompoundEngineeringCounts(process.cwd())
const result = await syncReleaseMetadata({ write: false }) const result = await syncReleaseMetadata({ write: false })
const changed = result.updates.filter((update) => update.changed) const changed = result.updates.filter((update) => update.changed)
if (configErrors.length === 0 && changed.length === 0) { if (configErrors.length === 0 && changed.length === 0) {
console.log("Release metadata is in sync.") console.log(
`Release metadata is in sync. compound-engineering currently has ${counts.agents} agents, ${counts.skills} skills, and ${counts.mcpServers} MCP server${counts.mcpServers === 1 ? "" : "s"}.`,
)
process.exit(0) process.exit(0)
} }
@@ -28,5 +31,8 @@ if (changed.length > 0) {
for (const update of changed) { for (const update of changed) {
console.error(`- ${update.path}`) console.error(`- ${update.path}`)
} }
console.error(
`Current compound-engineering counts: ${counts.agents} agents, ${counts.skills} skills, ${counts.mcpServers} MCP server${counts.mcpServers === 1 ? "" : "s"}.`,
)
} }
process.exit(1) process.exit(1)

View File

@@ -41,6 +41,18 @@ export type MetadataSyncResult = {
updates: FileUpdate[] updates: FileUpdate[]
} }
export type CompoundEngineeringCounts = {
agents: number
skills: number
mcpServers: number
}
const COMPOUND_ENGINEERING_DESCRIPTION =
"AI-powered development tools for code review, research, design, and workflow automation."
const COMPOUND_ENGINEERING_MARKETPLACE_DESCRIPTION =
"AI-powered development tools that get smarter with every use. Make each unit of engineering work easier than the last."
function resolveExpectedVersion( function resolveExpectedVersion(
explicitVersion: string | undefined, explicitVersion: string | undefined,
fallbackVersion: string, fallbackVersion: string,
@@ -90,12 +102,23 @@ export async function countMcpServers(pluginRoot: string): Promise<number> {
return Object.keys(manifest.mcpServers ?? {}).length return Object.keys(manifest.mcpServers ?? {}).length
} }
export async function buildCompoundEngineeringDescription(root: string): Promise<string> { export async function getCompoundEngineeringCounts(root: string): Promise<CompoundEngineeringCounts> {
const pluginRoot = path.join(root, "plugins", "compound-engineering") const pluginRoot = path.join(root, "plugins", "compound-engineering")
const agents = await countMarkdownFiles(path.join(pluginRoot, "agents")) const [agents, skills, mcpServers] = await Promise.all([
const skills = await countSkillDirectories(path.join(pluginRoot, "skills")) countMarkdownFiles(path.join(pluginRoot, "agents")),
const mcpServers = await countMcpServers(pluginRoot) countSkillDirectories(path.join(pluginRoot, "skills")),
return `AI-powered development tools. ${agents} agents, ${skills} skills, ${mcpServers} MCP server${mcpServers === 1 ? "" : "s"} for code review, research, design, and workflow automation.` countMcpServers(pluginRoot),
])
return { agents, skills, mcpServers }
}
export async function buildCompoundEngineeringDescription(_root: string): Promise<string> {
return COMPOUND_ENGINEERING_DESCRIPTION
}
export async function buildCompoundEngineeringMarketplaceDescription(_root: string): Promise<string> {
return COMPOUND_ENGINEERING_MARKETPLACE_DESCRIPTION
} }
export async function syncReleaseMetadata(options: SyncOptions = {}): Promise<MetadataSyncResult> { export async function syncReleaseMetadata(options: SyncOptions = {}): Promise<MetadataSyncResult> {
@@ -105,6 +128,7 @@ export async function syncReleaseMetadata(options: SyncOptions = {}): Promise<Me
const updates: FileUpdate[] = [] const updates: FileUpdate[] = []
const compoundDescription = await buildCompoundEngineeringDescription(root) const compoundDescription = await buildCompoundEngineeringDescription(root)
const compoundMarketplaceDescription = await buildCompoundEngineeringMarketplaceDescription(root)
const compoundClaudePath = path.join(root, "plugins", "compound-engineering", ".claude-plugin", "plugin.json") const compoundClaudePath = path.join(root, "plugins", "compound-engineering", ".claude-plugin", "plugin.json")
const compoundCursorPath = path.join(root, "plugins", "compound-engineering", ".cursor-plugin", "plugin.json") const compoundCursorPath = path.join(root, "plugins", "compound-engineering", ".cursor-plugin", "plugin.json")
@@ -178,8 +202,8 @@ export async function syncReleaseMetadata(options: SyncOptions = {}): Promise<Me
plugin.version = expectedCompoundVersion plugin.version = expectedCompoundVersion
changed = true changed = true
} }
if (plugin.description !== `AI-powered development tools that get smarter with every use. Make each unit of engineering work easier than the last. Includes ${await countMarkdownFiles(path.join(root, "plugins", "compound-engineering", "agents"))} specialized agents and ${await countSkillDirectories(path.join(root, "plugins", "compound-engineering", "skills"))} skills.`) { if (plugin.description !== compoundMarketplaceDescription) {
plugin.description = `AI-powered development tools that get smarter with every use. Make each unit of engineering work easier than the last. Includes ${await countMarkdownFiles(path.join(root, "plugins", "compound-engineering", "agents"))} specialized agents and ${await countSkillDirectories(path.join(root, "plugins", "compound-engineering", "skills"))} skills.` plugin.description = compoundMarketplaceDescription
changed = true changed = true
} }
} }

View File

@@ -2,7 +2,11 @@ import { mkdtemp, mkdir, writeFile } from "fs/promises"
import os from "os" import os from "os"
import path from "path" import path from "path"
import { afterEach, describe, expect, test } from "bun:test" import { afterEach, describe, expect, test } from "bun:test"
import { buildCompoundEngineeringDescription, syncReleaseMetadata } from "../src/release/metadata" import {
buildCompoundEngineeringDescription,
getCompoundEngineeringCounts,
syncReleaseMetadata,
} from "../src/release/metadata"
const tempRoots: string[] = [] const tempRoots: string[] = []
@@ -83,10 +87,24 @@ async function makeFixtureRoot(): Promise<string> {
} }
describe("release metadata", () => { describe("release metadata", () => {
test("builds the current compound-engineering manifest description from repo counts", async () => { test("reports current compound-engineering counts from the repo", async () => {
const counts = await getCompoundEngineeringCounts(process.cwd())
expect(counts).toEqual({
agents: expect.any(Number),
skills: expect.any(Number),
mcpServers: expect.any(Number),
})
expect(counts.agents).toBeGreaterThan(0)
expect(counts.skills).toBeGreaterThan(0)
expect(counts.mcpServers).toBeGreaterThanOrEqual(0)
})
test("builds a stable compound-engineering manifest description", async () => {
const description = await buildCompoundEngineeringDescription(process.cwd()) const description = await buildCompoundEngineeringDescription(process.cwd())
expect(description).toBe( expect(description).toBe(
"AI-powered development tools. 29 agents, 44 skills, 1 MCP server for code review, research, design, and workflow automation.", "AI-powered development tools for code review, research, design, and workflow automation.",
) )
}) })