feat(agent): L2/L4 记忆注入——项目规范 + 全局规范文件喂进 4 处 prompt
- L2 projects.agent_rules 列(schema+迁移+类型+mapper+patchProject+API 透传) - L4 protocol.readGlobalAgentRules():worker 直接读 <data>/agent-global.md(非DB, 不读用户 ~/.claude/CLAUDE.md,避免个人习惯与受控执行冲突) - runner.rulesHeaderLines 注入 executor/planner/conflict;reviewer 同注入 - 顺序:全局规范(L4)→项目规范(L2)→任务内容→上次失败(L1)→执行约束 Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -2,7 +2,11 @@ import { test } from 'node:test';
|
||||
import assert from 'node:assert/strict';
|
||||
import { buildPrompt, buildPlannerPrompt, buildConflictPrompt } from '../src/executor/runner.js';
|
||||
import { Store } from '../src/store/index.js';
|
||||
import type { Task } from '../src/model/types.js';
|
||||
import type { Task, Project } from '../src/model/types.js';
|
||||
|
||||
function fakeProject(over: Partial<Project> = {}): Project {
|
||||
return { defaultBranch: 'main', agentRules: null, ...over } as Project;
|
||||
}
|
||||
|
||||
function fakeTask(over: Partial<Task> = {}): Task {
|
||||
return {
|
||||
@@ -43,6 +47,28 @@ test('L1: 超长错误被截断到 2000 字符', () => {
|
||||
assert.ok(!p.includes('X'.repeat(2100)));
|
||||
});
|
||||
|
||||
test('L2: project.agentRules 注入 executor/planner/conflict/,未设则不注入', () => {
|
||||
const t = fakeTask();
|
||||
const withRules = fakeProject({ agentRules: '本项目禁止改 schema.sql' });
|
||||
assert.ok(buildPrompt(t, withRules).includes('项目规范'));
|
||||
assert.ok(buildPrompt(t, withRules).includes('禁止改 schema.sql'));
|
||||
assert.ok(buildPlannerPrompt(fakeTask({ complexity: 'hard' }), 'decompose', withRules).includes('禁止改 schema.sql'));
|
||||
assert.ok(buildConflictPrompt(t, ['a.ts'], withRules).includes('禁止改 schema.sql'));
|
||||
// 未设规范 → 不出现「项目规范」标题
|
||||
assert.ok(!buildPrompt(t, fakeProject()).includes('项目规范'));
|
||||
assert.ok(!buildPrompt(t).includes('项目规范')); // 连 project 都没传
|
||||
});
|
||||
|
||||
test('L4: globalRules 注入且排在项目规范之前', () => {
|
||||
const t = fakeTask();
|
||||
const p = buildPrompt(t, fakeProject({ agentRules: 'PROJ_RULE' }), 'GLOBAL_RULE');
|
||||
assert.ok(p.includes('全局执行规范'));
|
||||
assert.ok(p.includes('GLOBAL_RULE'));
|
||||
assert.ok(p.indexOf('GLOBAL_RULE') < p.indexOf('PROJ_RULE'), '全局规范在项目规范之前');
|
||||
// 全局规范在任务内容之前(注入顺序:L4→L2→任务内容)
|
||||
assert.ok(p.indexOf('GLOBAL_RULE') < p.indexOf('任务内容'));
|
||||
});
|
||||
|
||||
test('lastRunErrorOf 取最近一次失败 run 的错误(任意 kind)', () => {
|
||||
const s = new Store(':memory:');
|
||||
const p = s.createProject({ name: 'l1', repoPath: '/tmp/l1-' + Math.random() });
|
||||
Reference in New Issue
Block a user