@teammates/cli 0.2.3 → 0.2.5
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/dist/adapters/cli-proxy.js +3 -2
- package/dist/adapters/copilot.js +3 -2
- package/dist/cli.js +26 -12
- package/dist/onboard.d.ts +4 -7
- package/dist/onboard.js +48 -70
- package/dist/registry.d.ts +2 -0
- package/dist/registry.js +6 -1
- package/dist/registry.test.js +7 -0
- package/package.json +1 -1
|
@@ -114,8 +114,9 @@ export class CliProxyAdapter {
|
|
|
114
114
|
// Create session file inside .teammates/.tmp so sandboxed agents can access it
|
|
115
115
|
if (!this.sessionsDir) {
|
|
116
116
|
const tmpBase = join(teammate.cwd ?? process.cwd(), ".teammates", ".tmp");
|
|
117
|
-
|
|
118
|
-
await mkdir(
|
|
117
|
+
const dir = join(tmpBase, "sessions");
|
|
118
|
+
await mkdir(dir, { recursive: true });
|
|
119
|
+
this.sessionsDir = dir;
|
|
119
120
|
// Ensure .tmp is gitignored
|
|
120
121
|
const gitignorePath = join(tmpBase, "..", ".gitignore");
|
|
121
122
|
const existing = await readFile(gitignorePath, "utf-8").catch(() => "");
|
package/dist/adapters/copilot.js
CHANGED
|
@@ -39,8 +39,9 @@ export class CopilotAdapter {
|
|
|
39
39
|
// Create session file inside .teammates/.tmp so the agent can access it
|
|
40
40
|
if (!this.sessionsDir) {
|
|
41
41
|
const tmpBase = join(teammate.cwd ?? process.cwd(), ".teammates", ".tmp");
|
|
42
|
-
|
|
43
|
-
await mkdir(
|
|
42
|
+
const dir = join(tmpBase, "sessions");
|
|
43
|
+
await mkdir(dir, { recursive: true });
|
|
44
|
+
this.sessionsDir = dir;
|
|
44
45
|
const gitignorePath = join(tmpBase, "..", ".gitignore");
|
|
45
46
|
const existing = await readFile(gitignorePath, "utf-8").catch(() => "");
|
|
46
47
|
if (!existing.includes(".tmp/")) {
|
package/dist/cli.js
CHANGED
|
@@ -11,7 +11,7 @@ import { spawn as cpSpawn, exec as execCb, execSync, } from "node:child_process"
|
|
|
11
11
|
import { appendFileSync, readFileSync, writeFileSync } from "node:fs";
|
|
12
12
|
import { mkdir, readdir, rm, stat, unlink } from "node:fs/promises";
|
|
13
13
|
import { tmpdir } from "node:os";
|
|
14
|
-
import { join, resolve } from "node:path";
|
|
14
|
+
import { dirname, join, resolve } from "node:path";
|
|
15
15
|
import { createInterface } from "node:readline";
|
|
16
16
|
import { promisify } from "node:util";
|
|
17
17
|
const execAsync = promisify(execCb);
|
|
@@ -1431,16 +1431,22 @@ Do NOT modify any other teammate's files. Only edit your own SOUL.md and daily l
|
|
|
1431
1431
|
const teammatesDir = join(projectDir, ".teammates");
|
|
1432
1432
|
console.log();
|
|
1433
1433
|
try {
|
|
1434
|
-
const { teammates, files } = await importTeammates(sourceDir, teammatesDir);
|
|
1435
|
-
|
|
1434
|
+
const { teammates, skipped, files } = await importTeammates(sourceDir, teammatesDir);
|
|
1435
|
+
const allTeammates = [...teammates, ...skipped];
|
|
1436
|
+
if (allTeammates.length === 0) {
|
|
1436
1437
|
console.log(chalk.yellow(" No teammates found at ") + chalk.white(sourceDir));
|
|
1437
1438
|
console.log(chalk.gray(" The directory should contain teammate folders (each with a SOUL.md)."));
|
|
1438
1439
|
return;
|
|
1439
1440
|
}
|
|
1440
|
-
|
|
1441
|
-
chalk.
|
|
1442
|
-
|
|
1443
|
-
|
|
1441
|
+
if (teammates.length > 0) {
|
|
1442
|
+
console.log(chalk.green(" ✔") +
|
|
1443
|
+
chalk.white(` Imported ${teammates.length} teammate${teammates.length > 1 ? "s" : ""}: `) +
|
|
1444
|
+
chalk.cyan(teammates.join(", ")));
|
|
1445
|
+
console.log(chalk.gray(` (${files.length} files copied)`));
|
|
1446
|
+
}
|
|
1447
|
+
if (skipped.length > 0) {
|
|
1448
|
+
console.log(chalk.gray(` ${skipped.length} already present: ${skipped.join(", ")} (will re-adapt)`));
|
|
1449
|
+
}
|
|
1444
1450
|
console.log();
|
|
1445
1451
|
// Copy framework files so the agent has TEMPLATE.md etc. available
|
|
1446
1452
|
await copyTemplateFiles(teammatesDir);
|
|
@@ -1452,7 +1458,7 @@ Do NOT modify any other teammate's files. Only edit your own SOUL.md and daily l
|
|
|
1452
1458
|
console.log();
|
|
1453
1459
|
const adapt = await this.askChoice("Adapt now? (y/n): ", ["y", "n"]);
|
|
1454
1460
|
if (adapt === "y") {
|
|
1455
|
-
await this.runAdaptationAgent(this.adapter, projectDir,
|
|
1461
|
+
await this.runAdaptationAgent(this.adapter, projectDir, allTeammates, sourceDir);
|
|
1456
1462
|
}
|
|
1457
1463
|
else {
|
|
1458
1464
|
console.log(chalk.gray(" Skipped adaptation. Run /init to adapt later."));
|
|
@@ -1974,6 +1980,7 @@ Do NOT modify any other teammate's files. Only edit your own SOUL.md and daily l
|
|
|
1974
1980
|
weeklyLogs: [],
|
|
1975
1981
|
ownership: { primary: [], secondary: [] },
|
|
1976
1982
|
routingKeywords: [],
|
|
1983
|
+
cwd: dirname(this.teammatesDir),
|
|
1977
1984
|
});
|
|
1978
1985
|
// Add status entry (init() already ran, so we add it manually)
|
|
1979
1986
|
this.orchestrator.getAllStatuses().set(this.adapterName, { state: "idle" });
|
|
@@ -3010,18 +3017,25 @@ Do NOT modify any other teammate's files. Only edit your own SOUL.md and daily l
|
|
|
3010
3017
|
sourceDir = resolved;
|
|
3011
3018
|
}
|
|
3012
3019
|
try {
|
|
3013
|
-
const { teammates, files } = await importTeammates(sourceDir, teammatesDir);
|
|
3014
|
-
|
|
3020
|
+
const { teammates, skipped, files } = await importTeammates(sourceDir, teammatesDir);
|
|
3021
|
+
// Combine newly imported + already existing for adaptation
|
|
3022
|
+
const allTeammates = [...teammates, ...skipped];
|
|
3023
|
+
if (allTeammates.length === 0) {
|
|
3015
3024
|
this.feedLine(tp.warning(` No teammates found at ${sourceDir}`));
|
|
3016
3025
|
this.refreshView();
|
|
3017
3026
|
return;
|
|
3018
3027
|
}
|
|
3019
|
-
|
|
3028
|
+
if (teammates.length > 0) {
|
|
3029
|
+
this.feedLine(tp.success(` Imported ${teammates.length} teammate${teammates.length > 1 ? "s" : ""}: ${teammates.join(", ")} (${files.length} files)`));
|
|
3030
|
+
}
|
|
3031
|
+
if (skipped.length > 0) {
|
|
3032
|
+
this.feedLine(tp.muted(` ${skipped.length} already present: ${skipped.join(", ")} (will re-adapt)`));
|
|
3033
|
+
}
|
|
3020
3034
|
// Copy framework files so the agent has TEMPLATE.md etc. available
|
|
3021
3035
|
await copyTemplateFiles(teammatesDir);
|
|
3022
3036
|
// Queue a single adaptation task that handles all teammates
|
|
3023
3037
|
this.feedLine(tp.muted(` Queuing ${this.adapterName} to scan this project and adapt the team...`));
|
|
3024
|
-
const prompt = await buildImportAdaptationPrompt(teammatesDir,
|
|
3038
|
+
const prompt = await buildImportAdaptationPrompt(teammatesDir, allTeammates, sourceDir);
|
|
3025
3039
|
this.taskQueue.push({
|
|
3026
3040
|
type: "agent",
|
|
3027
3041
|
teammate: this.adapterName,
|
package/dist/onboard.d.ts
CHANGED
|
@@ -25,16 +25,13 @@ export declare function copyTemplateFiles(teammatesDir: string): Promise<string[
|
|
|
25
25
|
*/
|
|
26
26
|
export declare function importTeammates(sourceDir: string, targetDir: string): Promise<{
|
|
27
27
|
teammates: string[];
|
|
28
|
+
skipped: string[];
|
|
28
29
|
files: string[];
|
|
29
30
|
}>;
|
|
30
31
|
/**
|
|
31
|
-
* Build
|
|
32
|
-
* The agent
|
|
33
|
-
*
|
|
34
|
-
* 2. Evaluate which imported teammates are needed
|
|
35
|
-
* 3. Adapt kept teammates (add Previous Projects section + rewrite for new project)
|
|
36
|
-
* 4. Create any new teammates the project needs
|
|
37
|
-
* 5. Remove teammates that don't apply
|
|
32
|
+
* Build an import-adaptation prompt that runs as a single non-interactive agent session.
|
|
33
|
+
* The agent scans the target project and adapts all imported teammates in one pass.
|
|
34
|
+
* No pauses or approval gates — the agent must complete all work autonomously.
|
|
38
35
|
*
|
|
39
36
|
* @param teammatesDir - The .teammates/ directory in the target project
|
|
40
37
|
* @param teammateNames - Names of all imported teammates
|
package/dist/onboard.js
CHANGED
|
@@ -129,6 +129,7 @@ export async function importTeammates(sourceDir, targetDir) {
|
|
|
129
129
|
}
|
|
130
130
|
await mkdir(targetDir, { recursive: true });
|
|
131
131
|
const teammates = [];
|
|
132
|
+
const skipped = [];
|
|
132
133
|
const files = [];
|
|
133
134
|
const entries = await readdir(sourceDir, { withFileTypes: true });
|
|
134
135
|
for (const entry of entries) {
|
|
@@ -140,6 +141,7 @@ export async function importTeammates(sourceDir, targetDir) {
|
|
|
140
141
|
// Skip if teammate already exists in target
|
|
141
142
|
try {
|
|
142
143
|
await stat(destPath);
|
|
144
|
+
skipped.push(entry.name);
|
|
143
145
|
continue;
|
|
144
146
|
}
|
|
145
147
|
catch {
|
|
@@ -185,16 +187,12 @@ export async function importTeammates(sourceDir, targetDir) {
|
|
|
185
187
|
await writeFile(gitignoreDest, "USER.md\n.*/\n", "utf-8");
|
|
186
188
|
files.push(".gitignore");
|
|
187
189
|
}
|
|
188
|
-
return { teammates, files };
|
|
190
|
+
return { teammates, skipped, files };
|
|
189
191
|
}
|
|
190
192
|
/**
|
|
191
|
-
* Build
|
|
192
|
-
* The agent
|
|
193
|
-
*
|
|
194
|
-
* 2. Evaluate which imported teammates are needed
|
|
195
|
-
* 3. Adapt kept teammates (add Previous Projects section + rewrite for new project)
|
|
196
|
-
* 4. Create any new teammates the project needs
|
|
197
|
-
* 5. Remove teammates that don't apply
|
|
193
|
+
* Build an import-adaptation prompt that runs as a single non-interactive agent session.
|
|
194
|
+
* The agent scans the target project and adapts all imported teammates in one pass.
|
|
195
|
+
* No pauses or approval gates — the agent must complete all work autonomously.
|
|
198
196
|
*
|
|
199
197
|
* @param teammatesDir - The .teammates/ directory in the target project
|
|
200
198
|
* @param teammateNames - Names of all imported teammates
|
|
@@ -227,101 +225,83 @@ export async function buildImportAdaptationPrompt(teammatesDir, teammateNames, s
|
|
|
227
225
|
teammateSections.push(`### @${name}\n${soulBlock}${wisdomBlock}`);
|
|
228
226
|
}
|
|
229
227
|
const projectDir = dirname(teammatesDir);
|
|
230
|
-
return `You are adapting an imported team to a new project.
|
|
228
|
+
return `You are adapting an imported team to a new project. This is a non-interactive session — complete ALL work without pausing. Do not ask for confirmation or wait for user input.
|
|
231
229
|
|
|
232
230
|
**Source project:** \`${sourceProjectPath}\`
|
|
233
231
|
**Target project:** \`${projectDir}\`
|
|
234
232
|
**Target .teammates/ directory:** \`${teammatesDir}\`
|
|
235
233
|
**Imported teammates:** ${teammateNames.map((n) => `@${n}`).join(", ")}
|
|
236
234
|
|
|
235
|
+
> **IMPORTANT:** The \`example/\` directory inside \`.teammates/\` is a **template reference**, NOT a teammate. Do not adapt it, rename it, or treat it as a teammate. When creating new teammates, never use "example" as a folder name.
|
|
236
|
+
|
|
237
237
|
## Imported Teammates (from source project)
|
|
238
238
|
|
|
239
239
|
${teammateSections.join("\n\n---\n\n")}
|
|
240
240
|
|
|
241
241
|
## Instructions
|
|
242
242
|
|
|
243
|
-
|
|
244
|
-
|
|
245
|
-
### Phase 1: Scan This Project
|
|
246
|
-
|
|
247
|
-
Analyze the current project to understand its structure:
|
|
248
|
-
- Read the project root: package manifest, README, config files
|
|
249
|
-
- Identify major subsystems, languages, frameworks, file patterns
|
|
250
|
-
- Understand the dependency flow and architecture
|
|
251
|
-
|
|
252
|
-
**Present your analysis to the user and wait for confirmation.**
|
|
243
|
+
Complete these steps in order. Do NOT pause, ask questions, or wait for approval. Make all changes directly.
|
|
253
244
|
|
|
254
|
-
###
|
|
245
|
+
### Step 1: Scan This Project
|
|
255
246
|
|
|
256
|
-
|
|
257
|
-
-
|
|
258
|
-
-
|
|
247
|
+
Read the project root to understand its structure:
|
|
248
|
+
- Package manifest, README, config files
|
|
249
|
+
- Major subsystems, languages, frameworks, file patterns
|
|
250
|
+
- Dependency flow and architecture
|
|
259
251
|
|
|
260
|
-
|
|
252
|
+
### Step 2: Adapt EVERY Imported Teammate
|
|
261
253
|
|
|
262
|
-
|
|
263
|
-
\`\`\`
|
|
264
|
-
KEEP: @name1, @name2
|
|
265
|
-
DROP: @name3
|
|
266
|
-
CREATE: @newname (role description)
|
|
267
|
-
\`\`\`
|
|
254
|
+
This is the most important step. For EACH imported teammate listed above, you MUST edit their SOUL.md and WISDOM.md to reflect THIS project, not the source project.
|
|
268
255
|
|
|
269
|
-
|
|
256
|
+
For each teammate's **SOUL.md**:
|
|
270
257
|
|
|
271
|
-
|
|
272
|
-
|
|
273
|
-
1. **Add a "Previous Projects" section** to SOUL.md (place it after Ethics, before any appendix). Compress what the teammate did in the source project into a portable summary:
|
|
258
|
+
1. **Add a "Previous Projects" section** (place it after Ethics). Compress what the teammate did in the source project:
|
|
274
259
|
\`\`\`markdown
|
|
275
260
|
## Previous Projects
|
|
276
261
|
|
|
277
|
-
### <project-name>
|
|
262
|
+
### <source-project-name>
|
|
278
263
|
- **Role**: <one-line summary of what they did>
|
|
279
264
|
- **Stack**: <key technologies they worked with>
|
|
280
265
|
- **Domains**: <what they owned — file patterns or subsystem names>
|
|
281
266
|
- **Key learnings**: <1-3 bullets of notable patterns, decisions, or lessons>
|
|
282
267
|
\`\`\`
|
|
283
268
|
|
|
284
|
-
2. **Rewrite
|
|
269
|
+
2. **Rewrite project-specific sections** for THIS project:
|
|
285
270
|
- **Preserve**: Identity (name, personality), Core Principles, Ethics
|
|
286
|
-
- **Rewrite**: Ownership (primary/secondary file globs for THIS project), Boundaries, Capabilities (commands, file patterns, technologies), Routing keywords, Quality Bar
|
|
287
|
-
- **Update**:
|
|
288
|
-
|
|
289
|
-
3. **Update WISDOM.md**:
|
|
290
|
-
- **Add** a "Previous Projects" section at the top with a compressed note:
|
|
291
|
-
\`\`\`markdown
|
|
292
|
-
## Previous Projects
|
|
293
|
-
|
|
294
|
-
### <project-name>
|
|
295
|
-
- Carried over universal wisdom entries from the source project
|
|
296
|
-
- Project-specific entries removed or adapted
|
|
297
|
-
\`\`\`
|
|
298
|
-
- **Keep** wisdom entries that are universal (general principles, patterns, lessons)
|
|
299
|
-
- **Remove** entries that reference source project paths, architecture, or tools not used here
|
|
300
|
-
- **Adapt** entries with transferable knowledge but old-project-specific details
|
|
301
|
-
|
|
302
|
-
### Phase 4: Handle Dropped Teammates
|
|
271
|
+
- **Rewrite completely**: Ownership (primary/secondary file globs for THIS project's actual files), Boundaries, Capabilities (commands, file patterns, technologies for THIS project), Routing keywords, Quality Bar
|
|
272
|
+
- **Update**: All codebase-specific references — paths, package names, tools, teammate names must reference THIS project
|
|
303
273
|
|
|
304
|
-
For each
|
|
274
|
+
For each teammate's **WISDOM.md**:
|
|
275
|
+
- Add a "Previous Projects" note at the top
|
|
276
|
+
- Keep universal wisdom entries (general principles, patterns)
|
|
277
|
+
- Remove entries that reference source project paths, architecture, or tools not used here
|
|
278
|
+
- Adapt entries with transferable knowledge but old-project-specific details
|
|
305
279
|
|
|
306
|
-
###
|
|
280
|
+
### Step 3: Evaluate Gaps and Create New Teammates
|
|
307
281
|
|
|
308
|
-
|
|
282
|
+
After adapting all existing teammates, check if THIS project has major subsystems that no teammate covers. If so, create new teammates:
|
|
309
283
|
- Create \`${teammatesDir}/<name>/\` with SOUL.md, WISDOM.md, and \`memory/\`
|
|
310
284
|
- Use the template at \`${teammatesDir}/TEMPLATE.md\` for structure
|
|
311
285
|
- WISDOM.md starts with one creation entry
|
|
312
286
|
|
|
313
|
-
|
|
287
|
+
If a teammate's domain doesn't exist at all in this project and their skills aren't transferable, delete their directory under \`${teammatesDir}\`.
|
|
288
|
+
|
|
289
|
+
### Step 4: Update Framework Files
|
|
314
290
|
|
|
315
291
|
- Update \`${teammatesDir}/README.md\` with the final roster
|
|
316
292
|
- Update \`${teammatesDir}/CROSS-TEAM.md\` ownership table
|
|
317
293
|
|
|
318
|
-
###
|
|
294
|
+
### Step 5: Verify
|
|
319
295
|
|
|
320
|
-
- Every
|
|
321
|
-
- Ownership globs
|
|
322
|
-
- Boundaries reference
|
|
296
|
+
- Every teammate has SOUL.md and WISDOM.md adapted to THIS project
|
|
297
|
+
- Ownership globs reference actual files in THIS project
|
|
298
|
+
- Boundaries reference correct teammate names
|
|
323
299
|
- Previous Projects sections are present for all imported teammates
|
|
324
|
-
- CROSS-TEAM.md has one row per teammate
|
|
300
|
+
- CROSS-TEAM.md has one row per teammate
|
|
301
|
+
|
|
302
|
+
## Critical Reminder
|
|
303
|
+
|
|
304
|
+
The PRIMARY goal is adapting the imported teammates. Every SOUL.md must be rewritten so the teammate understands THIS project's codebase, not the source project's. If you only have time for one thing, adapt the existing teammates — that is more important than creating new ones.`;
|
|
325
305
|
}
|
|
326
306
|
/**
|
|
327
307
|
* Load ONBOARDING.md from the project dir, package root, or built-in fallback.
|
|
@@ -368,7 +348,9 @@ function wrapPrompt(onboardingContent, projectDir) {
|
|
|
368
348
|
|
|
369
349
|
You do NOT need to create the framework files listed above — they're already there.
|
|
370
350
|
|
|
371
|
-
|
|
351
|
+
> **IMPORTANT:** The \`example/\` directory is a **template reference**, NOT a teammate. Do not modify it or treat it as a teammate. Never name a new teammate "example".
|
|
352
|
+
|
|
353
|
+
Follow the onboarding instructions below. This is a non-interactive session — complete ALL work without pausing. Do not ask for confirmation or wait for user input. Work through each step and make all changes directly.
|
|
372
354
|
|
|
373
355
|
---
|
|
374
356
|
|
|
@@ -392,26 +374,22 @@ Identify:
|
|
|
392
374
|
3. **Key technologies** — languages, frameworks, tools per area
|
|
393
375
|
4. **File patterns** — glob patterns for each domain
|
|
394
376
|
|
|
395
|
-
**Present your analysis to the user and get confirmation before proceeding.**
|
|
396
|
-
|
|
397
377
|
## Step 2: Design the Team
|
|
398
378
|
|
|
399
|
-
|
|
379
|
+
Based on your analysis, design a roster of teammates:
|
|
400
380
|
- **Aim for 3–7 teammates.** Fewer for small projects, more for monorepos.
|
|
401
381
|
- **Each teammate owns a distinct domain** with minimal overlap.
|
|
402
382
|
- **Pick short, memorable names** — one word, evocative of the domain.
|
|
403
383
|
|
|
404
|
-
For each
|
|
384
|
+
For each teammate, define:
|
|
405
385
|
- Name and one-line persona
|
|
406
386
|
- Primary ownership (file patterns)
|
|
407
387
|
- Key technologies
|
|
408
388
|
- Boundaries (what they do NOT own)
|
|
409
389
|
|
|
410
|
-
**Present the proposed roster to the user for approval.**
|
|
411
|
-
|
|
412
390
|
## Step 3: Create the Directory Structure
|
|
413
391
|
|
|
414
|
-
|
|
392
|
+
Create teammate folders under \`.teammates/\`:
|
|
415
393
|
|
|
416
394
|
### Teammate folders
|
|
417
395
|
For each teammate, create \`.teammates/<name>/\` with:
|
package/dist/registry.d.ts
CHANGED
|
@@ -9,6 +9,8 @@ export declare class Registry {
|
|
|
9
9
|
private teammatesDir;
|
|
10
10
|
private teammates;
|
|
11
11
|
constructor(teammatesDir: string);
|
|
12
|
+
/** Names that are never teammates (template references, config files) */
|
|
13
|
+
private static NON_TEAMMATE_NAMES;
|
|
12
14
|
/** Discover and load all teammates from .teammates/ */
|
|
13
15
|
loadAll(): Promise<Map<string, TeammateConfig>>;
|
|
14
16
|
/** Load a single teammate by name */
|
package/dist/registry.js
CHANGED
|
@@ -12,10 +12,15 @@ export class Registry {
|
|
|
12
12
|
constructor(teammatesDir) {
|
|
13
13
|
this.teammatesDir = teammatesDir;
|
|
14
14
|
}
|
|
15
|
+
/** Names that are never teammates (template references, config files) */
|
|
16
|
+
static NON_TEAMMATE_NAMES = new Set(["example"]);
|
|
15
17
|
/** Discover and load all teammates from .teammates/ */
|
|
16
18
|
async loadAll() {
|
|
17
19
|
const entries = await readdir(this.teammatesDir, { withFileTypes: true });
|
|
18
|
-
const dirs = entries.filter((e) => e.isDirectory() &&
|
|
20
|
+
const dirs = entries.filter((e) => e.isDirectory() &&
|
|
21
|
+
!e.name.startsWith(".") &&
|
|
22
|
+
!e.name.startsWith("_") &&
|
|
23
|
+
!Registry.NON_TEAMMATE_NAMES.has(e.name));
|
|
19
24
|
for (const dir of dirs) {
|
|
20
25
|
const config = await this.loadTeammate(dir.name);
|
|
21
26
|
if (config) {
|
package/dist/registry.test.js
CHANGED
|
@@ -56,6 +56,13 @@ describe("Registry.loadAll", () => {
|
|
|
56
56
|
await registry.loadAll();
|
|
57
57
|
expect(registry.list()).toEqual(["beacon"]);
|
|
58
58
|
});
|
|
59
|
+
it("skips the example directory even if it has SOUL.md", async () => {
|
|
60
|
+
await createTeammate("beacon", "# Beacon\n\nPlatform engineer.");
|
|
61
|
+
await createTeammate("example", "# Example\n\nTemplate reference.");
|
|
62
|
+
const registry = new Registry(tempDir);
|
|
63
|
+
await registry.loadAll();
|
|
64
|
+
expect(registry.list()).toEqual(["beacon"]);
|
|
65
|
+
});
|
|
59
66
|
});
|
|
60
67
|
describe("Registry.loadTeammate", () => {
|
|
61
68
|
it("loads soul content", async () => {
|
package/package.json
CHANGED