ai-team 1.2.0 → 1.3.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
package/CHANGELOG.md CHANGED
@@ -1,3 +1,11 @@
1
+ # [1.3.0](https://github.com/seanwuapps/ai-team/compare/v1.2.0...v1.3.0) (2026-02-23)
2
+
3
+
4
+ ### Features
5
+
6
+ * ensure mandatory agents are included in profiles and templates ([f48c99c](https://github.com/seanwuapps/ai-team/commit/f48c99c3953303dfee9e552c56dffe36979a692c))
7
+ * update mandatory agents to include product-team-orchestrator ([16bbc8e](https://github.com/seanwuapps/ai-team/commit/16bbc8e5a1292f6c68a00e01be68d14073817741))
8
+
1
9
  # [1.2.0](https://github.com/seanwuapps/ai-team/compare/v1.1.0...v1.2.0) (2026-02-23)
2
10
 
3
11
 
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "ai-team",
3
- "version": "1.2.0",
3
+ "version": "1.3.0",
4
4
  "description": "AI agent team management CLI tool",
5
5
  "type": "module",
6
6
  "main": "src/cli.js",
@@ -4,6 +4,10 @@ import { fileURLToPath } from "node:url";
4
4
  import { readdir, readFile } from "node:fs/promises";
5
5
  import { confirm, select, checkbox } from "@inquirer/prompts";
6
6
  import YAML from "yaml";
7
+ import {
8
+ MANDATORY_AGENTS,
9
+ ensureMandatoryAgents,
10
+ } from "./template-registry.js";
7
11
 
8
12
  const __dirname = path.dirname(fileURLToPath(import.meta.url));
9
13
  const definitionsDir = path.resolve(__dirname, "../agents/definitions");
@@ -47,7 +51,7 @@ export async function collectInteractiveProfile({
47
51
  ide: ide ?? "vscode",
48
52
  team: team ?? "web-product",
49
53
  includeMcp: includeMcp ?? true,
50
- agents: agents ?? null,
54
+ agents: ensureMandatoryAgents(agents),
51
55
  };
52
56
  }
53
57
 
@@ -80,6 +84,7 @@ export async function collectInteractiveProfile({
80
84
  name: def.emoji ? `${def.emoji} ${def.name}` : def.name,
81
85
  value: def.name,
82
86
  checked: true,
87
+ disabled: MANDATORY_AGENTS.includes(def.name) ? "required" : undefined,
83
88
  description: def.description,
84
89
  })),
85
90
  });
@@ -87,6 +92,8 @@ export async function collectInteractiveProfile({
87
92
  selected.length > 0 ? selected : definitions.map((d) => d.name);
88
93
  }
89
94
 
95
+ agentsAnswer = ensureMandatoryAgents(agentsAnswer);
96
+
90
97
  let includeMcpAnswer = includeMcp;
91
98
  if (includeMcpAnswer === undefined) {
92
99
  includeMcpAnswer = await confirm({
@@ -7,6 +7,7 @@ import {
7
7
  createManifest,
8
8
  bumpManifest,
9
9
  } from "./manifest.js";
10
+ import { ensureMandatoryAgents } from "./template-registry.js";
10
11
  import { readTextIfExists, writeText } from "./fs-utils.js";
11
12
  import { hashText } from "./hash.js";
12
13
  import { detectLegacyLayout, applyLegacyMigration } from "./migration.js";
@@ -102,11 +103,16 @@ export async function planSync({
102
103
  force = false,
103
104
  command = "plan",
104
105
  }) {
106
+ const normalizedProfile = {
107
+ ...profile,
108
+ agents: ensureMandatoryAgents(profile.agents),
109
+ };
110
+
105
111
  const { templateVersion, schemaVersion, entries } =
106
112
  await collectTemplateEntries({
107
- ide: profile.ide,
108
- includeMcp: profile.includeMcp,
109
- agents: profile.agents ?? null,
113
+ ide: normalizedProfile.ide,
114
+ includeMcp: normalizedProfile.includeMcp,
115
+ agents: normalizedProfile.agents,
110
116
  });
111
117
 
112
118
  const installedManifest = await loadInstalledManifest(targetDir);
@@ -176,7 +182,7 @@ export async function planSync({
176
182
  return {
177
183
  command,
178
184
  targetDir,
179
- profile,
185
+ profile: normalizedProfile,
180
186
  schemaVersion,
181
187
  templateVersion,
182
188
  hasManifest: Boolean(installedManifest),
@@ -8,6 +8,26 @@ import { generateAgentEntriesForIde } from "../agents/generate.js";
8
8
 
9
9
  const dirname = path.dirname(fileURLToPath(import.meta.url));
10
10
  export const TEMPLATE_ROOT = path.resolve(dirname, "../../templates/bootstrap");
11
+ export const MANDATORY_AGENTS = ["agent-manager", "product-team-orchestrator"];
12
+
13
+ export function ensureMandatoryAgents(agents) {
14
+ if (!Array.isArray(agents) || agents.length === 0) {
15
+ return null;
16
+ }
17
+
18
+ const normalized = new Set(
19
+ agents
20
+ .filter((value) => typeof value === "string")
21
+ .map((value) => value.trim())
22
+ .filter(Boolean),
23
+ );
24
+
25
+ for (const mandatoryAgent of MANDATORY_AGENTS) {
26
+ normalized.add(mandatoryAgent);
27
+ }
28
+
29
+ return Array.from(normalized);
30
+ }
11
31
 
12
32
  export async function loadTemplateManifest() {
13
33
  const filePath = path.join(TEMPLATE_ROOT, "manifest.json");
@@ -87,8 +107,8 @@ export async function collectTemplateEntries({ ide, includeMcp, agents }) {
87
107
  const entries = [];
88
108
 
89
109
  // Normalise agent filter to a Set for fast lookup (null/undefined = include all)
90
- const agentFilter =
91
- Array.isArray(agents) && agents.length > 0 ? new Set(agents) : null;
110
+ const normalizedAgents = ensureMandatoryAgents(agents);
111
+ const agentFilter = normalizedAgents ? new Set(normalizedAgents) : null;
92
112
 
93
113
  for (const absolutePath of baseFiles) {
94
114
  const relative = path.relative(baseRoot, absolutePath);
@@ -105,3 +105,26 @@ test("json merge keeps local MCP servers in safe mode", async () => {
105
105
  const updated = JSON.parse(await fs.readFile(mcpPath, "utf8"));
106
106
  assert.ok(updated.servers["custom-local"]);
107
107
  });
108
+
109
+ test("applySync persists mandatory agent-manager in manifest profile", async () => {
110
+ const targetDir = await makeTempDir();
111
+ const profile = {
112
+ ide: "vscode",
113
+ team: "web-product",
114
+ includeMcp: true,
115
+ agents: ["planning-agent"],
116
+ };
117
+
118
+ const plan = await planSync({ targetDir, profile });
119
+ const result = await applySync(plan);
120
+
121
+ assert.deepEqual(result.manifest.profile.agents, [
122
+ "planning-agent",
123
+ "agent-manager",
124
+ ]);
125
+ assert.ok(
126
+ plan.actions.some(
127
+ (action) => action.targetPath === ".github/agents/agent-manager.agent.md",
128
+ ),
129
+ );
130
+ });
@@ -30,6 +30,21 @@ test("collectTemplateEntries omits MCP output when includeMcp is false", async (
30
30
  assert.ok(result.entries.every((entry) => entry.targetPath !== ".mcp.json"));
31
31
  });
32
32
 
33
+ test("collectTemplateEntries always includes agent-manager", async () => {
34
+ const result = await collectTemplateEntries({
35
+ ide: "vscode",
36
+ includeMcp: false,
37
+ agents: ["planning-agent"],
38
+ });
39
+
40
+ const generatedAgents = result.entries
41
+ .filter((entry) => entry.targetPath.startsWith(".github/agents/"))
42
+ .map((entry) => entry.targetPath);
43
+
44
+ assert.ok(generatedAgents.includes(".github/agents/planning-agent.agent.md"));
45
+ assert.ok(generatedAgents.includes(".github/agents/agent-manager.agent.md"));
46
+ });
47
+
33
48
  test("getIdePack supports legacy packs.overlays manifest shape", () => {
34
49
  const legacyManifest = {
35
50
  packs: {