base-skeleton-complete.test.js
2.85 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
/**
* Unit Test — `_base` 骨架必须齐全(28 号设计 验收 6、二轮修复 问题 2)
*
* 锁的是一条**只有真跑一次招聘才会显形**的静默失效:
* `hire()` 雇一个仓库里没有的角色时,从 `_base` 复制骨架毕业出一份新本体,随即用
* `missingBodyDefinition()`(agent-locator)判它齐不齐全 —— 缺一份就停在 status='draft',
* 不许被任何公司雇走。而 `_base` 一度只带 agent.md + config.json,于是**每一个**新本体
* 出生即 draft,补齐只能靠 agent-creator 那次 fire-and-forget 的自调用(已知缺陷:单会话锁,
* 连招时只有第一个被填充)。症状是「招聘成功了,人却永远上不了岗」,一处报错都没有。
*
* 两条断言分工:
* ① 逐份查字节数 —— 三份定义都得真有内容,缺一份新本体就少一条提示词到达路径;
* 200 字节是「写了点东西」的下限,不是质量标准;
* ② 拿**闸门本人**(missingBodyDefinition)判 `_base`:它必须判**三份全缺**。
*
* ⚠️ ② 的方向是二轮修复反过来的(原来断言 `[]`)。补齐 `_base` 与「非空即齐全」的旧判据
* 凑在一起会把闸门整个抵消:骨架一拷完就转正,新角色拿着通用 Base Agent 文本直接上岗,
* 第二家公司还会把它当可复用本体雇走。所以 `_base` 的三份定义里都埋了
* `BASE_SKELETON_SENTINEL`,「齐全」的判据变成「有内容 **且** 不再是骨架」——
* `_base` 自己**永远**是骨架,也就永远不该被判成齐全。详见 base-graduation-gate.test.js。
*/
import { describe, it, expect } from 'vitest';
import fs from 'fs';
import path from 'path';
import { missingBodyDefinition, BASE_SKELETON_SENTINEL } from '../../services/agent-locator.js';
const BASE_DIR = path.resolve(__dirname, '../../../system/agents/_base');
const DEFINITION_FILES = [
'agent.md',
'soul.md',
path.join('.claude', 'skills', 'main_skill', 'SKILL.md'),
];
describe('_base 元 agent 骨架(新本体的出生起点)', () => {
it.each(DEFINITION_FILES)('_base/%s 存在且不是占位(去空白后 > 200 字节)', (rel) => {
const p = path.join(BASE_DIR, rel);
expect(fs.existsSync(p), `${p} 不存在`).toBe(true);
expect(fs.readFileSync(p, 'utf-8').trim().length).toBeGreaterThan(200);
});
it.each(DEFINITION_FILES)('_base/%s 带着骨架哨兵(人一眼看得见「这份还没填」)', (rel) => {
expect(fs.readFileSync(path.join(BASE_DIR, rel), 'utf-8')).toContain(BASE_SKELETON_SENTINEL);
});
it('闸门直接判 _base:三份**全部**算缺 —— 骨架不是定义', () => {
// 文件全在、内容也不少(上一条断言过),旧的「非空即齐全」判据会把它们全部放行。
expect(missingBodyDefinition('_base')).toEqual(DEFINITION_FILES);
});
});