mirror of
https://github.com/claude-code-best/claude-code.git
synced 2026-06-15 12:55:51 +00:00
fix: 限制 skill-learning evidence 无限增长导致全局 skill 文件膨胀
evidence 数组和追加块缺少大小限制,导致 skill 文件(如 sdd-brainstorming)在短时间内膨胀至 21K+ 行/78 个 evidence 块。 三处修复: - instinctParser: evidence 数组 cap 10 条, observationIds cap 20 条 - skillGenerator: 追加块每次最多 20 行, 文件总大小上限 50KB, 生成 skill 的 evidence 段限制 20 行 - agentGenerator: 生成 agent 的 evidence 段限制 20 行 Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -122,6 +122,7 @@ function buildAgentContent(params: {
|
||||
'',
|
||||
instincts
|
||||
.flatMap(instinct => instinct.evidence.map(evidence => `- ${evidence}`))
|
||||
.slice(0, 20)
|
||||
.join('\n'),
|
||||
'',
|
||||
].join('\n')
|
||||
|
||||
@@ -35,15 +35,18 @@ export function createInstinct(
|
||||
})
|
||||
}
|
||||
|
||||
const MAX_EVIDENCE_ENTRIES = 10
|
||||
|
||||
export function normalizeInstinct(instinct: StoredInstinct): StoredInstinct {
|
||||
const uniqueEvidence = Array.from(new Set(instinct.evidence.filter(Boolean)))
|
||||
return {
|
||||
...instinct,
|
||||
id: instinct.id || buildInstinctId(instinct.trigger, instinct.action),
|
||||
confidence: clampConfidence(instinct.confidence),
|
||||
evidence: Array.from(new Set(instinct.evidence.filter(Boolean))),
|
||||
evidence: uniqueEvidence.slice(-MAX_EVIDENCE_ENTRIES),
|
||||
evidenceOutcome: instinct.evidenceOutcome,
|
||||
observationIds: instinct.observationIds
|
||||
? Array.from(new Set(instinct.observationIds))
|
||||
? Array.from(new Set(instinct.observationIds)).slice(-20)
|
||||
: undefined,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,6 +12,9 @@ import {
|
||||
import type { LearnedSkillDraft, SkillLearningScope } from './types.js'
|
||||
|
||||
export const DUPLICATE_SKILL_OVERLAP_THRESHOLD = 0.8
|
||||
const MAX_EVIDENCE_LINES_PER_APPEND = 20
|
||||
const MAX_EVIDENCE_LINES_IN_SKILL = 20
|
||||
const MAX_SKILL_FILE_BYTES = 50_000
|
||||
|
||||
export type SkillGeneratorOptions = {
|
||||
cwd?: string
|
||||
@@ -101,20 +104,41 @@ export async function appendInstinctEvidenceToSkill(
|
||||
const existing = await readFile(target.path, 'utf8').catch(
|
||||
() => target.content,
|
||||
)
|
||||
|
||||
// Skip if the file already exceeds the size cap
|
||||
if (Buffer.byteLength(existing, 'utf8') >= MAX_SKILL_FILE_BYTES) {
|
||||
return target.path
|
||||
}
|
||||
|
||||
const allEvidence = instincts.flatMap(instinct =>
|
||||
instinct.evidence.map(evidence => `- ${evidence}`),
|
||||
)
|
||||
const evidenceLines = allEvidence.slice(0, MAX_EVIDENCE_LINES_PER_APPEND)
|
||||
if (evidenceLines.length < allEvidence.length) {
|
||||
evidenceLines.push(
|
||||
`- [... ${allEvidence.length - evidenceLines.length} more evidence entries omitted]`,
|
||||
)
|
||||
}
|
||||
|
||||
const now = new Date().toISOString()
|
||||
const block = [
|
||||
'',
|
||||
`## Learned evidence (${now})`,
|
||||
'',
|
||||
...instincts.flatMap(instinct =>
|
||||
instinct.evidence.map(evidence => `- ${evidence}`),
|
||||
),
|
||||
...evidenceLines,
|
||||
'',
|
||||
].join('\n')
|
||||
const merged = existing.endsWith('\n')
|
||||
? existing + block
|
||||
: `${existing}\n${block}`
|
||||
await writeFile(target.path, merged, 'utf8')
|
||||
|
||||
// Final guard: truncate if merged exceeds size cap
|
||||
const finalContent =
|
||||
Buffer.byteLength(merged, 'utf8') > MAX_SKILL_FILE_BYTES
|
||||
? merged.slice(0, MAX_SKILL_FILE_BYTES)
|
||||
: merged
|
||||
|
||||
await writeFile(target.path, finalContent, 'utf8')
|
||||
clearSkillIndexCache()
|
||||
return target.path
|
||||
}
|
||||
@@ -191,6 +215,7 @@ function buildSkillContent(params: {
|
||||
'',
|
||||
instincts
|
||||
.flatMap(instinct => instinct.evidence.map(evidence => `- ${evidence}`))
|
||||
.slice(0, MAX_EVIDENCE_LINES_IN_SKILL)
|
||||
.join('\n'),
|
||||
'',
|
||||
]
|
||||
|
||||
Reference in New Issue
Block a user