What happened?
Claude Code adapter inject模式实现Bug报告
问题概述
类型: Bug - 设计缺陷
组件: src/adapters/claude-code.ts
影响: inject模式不是真正的skill注入,而是文本追加
严重程度: 高 - inject模式本质设计错误
Bug描述
当前inject实现
// src/adapters/claude-code.ts:576-580
if (skillMode === "inject") {
appendSystemPrompt = injectedSystemPrompt(task.skillContent)
}
// 实际命令: claude --append-system-prompt "<skvm-skill-injected/>\n\n{skillContent}"
问题本质
inject模式使用--append-system-prompt参数追加文本到system prompt,这不是Claude Code的skill系统。
关键问题:
--append-system-prompt只是追加一段文本,不是skill机制
- skill不会出现在init事件的skills列表中
- 无法通过
/skill命令调用
- Claude Code不将其识别为skill
- 模型只是一段额外instruction,不知道这是skill
Bug后果
1. skillLoaded检测失败
由于inject模式使用--append-system-prompt而非skill系统:
- skill不会出现在init事件的skills列表中
detectSkillInject依赖模型回显sentinel(thinking mode不回显)
- 最终
skillLoaded=false
// src/adapters/claude-code.ts:649-656
if (task.skillContent && skillLoaded === false) {
if (skillMode === "inject") {
skillLoaded = detectSkillInject(events, snippet) // 返回false
}
}
2. Evidence记录skill未加载
// src/adapters/claude-code.ts:659-661
if (skillLoaded !== undefined) {
result.skillLoaded = skillLoaded // false
}
Evidence的runMeta.skillLoaded=false被写入agent logs。
3. Optimizer生成WARNING警告
// src/jit-optimize/workspace.ts:536
if (ev.runMeta.skillLoaded === false) {
parts.push(`- WARNING: skill was not loaded`)
}
Optimizer在生成evidence摘要时,看到"WARNING: skill was not loaded"。
4. Optimizer误判放弃优化
Optimizer认为"无法基于skill分析问题",因为skill"未加载":
Round 1: optimizer abstained (infraBlocked).
Reason: Run with Evidence Index 0 (runStatus=ok) shows
'WARNING: skill was not loaded', meaning the agent operated
without the skvm-general skill's guidance. No skill-level
diagnosis is possible from this evidence.
5. jit-optimize流程中断
=== Round 0 (baseline): train=0.700 test=0.613 ===
=== Round 1/3 ===
optimizer abstained (infraBlocked)
Proposal finalized as infra-blocked
- Round 0 baseline评估完成(有分数)
- Round 1 optimizer启动但立即放弃
- 后续round全部跳过
- 无法进入skill修改流程
6. 最终结果:无法完成skill迭代
status: infra-blocked
best round: 0
total rounds: 2 (但实际只有round-0有效)
关键后果:
- 没有产生skill修改建议
- 没有优化后的skill版本(round-1/round-2)
- 没有验证skill提升效果
- jit-optimize核心功能完全失效
7. 受影响范围
受影响的模型:
- GLM系列(DashScope,thinking mode)
- DeepSeek thinking mode
- 其他不会回显system prompt内容的模型
不受影响的模型:
- 可能某些Anthropic模型会回显(但行为不确定)
8. 实际测试证据
# 测试日志 ~/.skvm/proposals/.../run.log
[10:38:52.381] Round 0 (baseline): train=0.700 test=0.613
[10:38:52.387] === Round 1/3 ===
[10:44:40.716] optimizer abstained (infraBlocked)
Reason: WARNING: skill was not loaded
# proposal状态
status: infra-blocked
bestRoundReason: infra-blocked at round-1: skill was not loaded
对比分析
inject模式(当前实现)
claude --append-system-prompt "<skvm-skill-injected/>\n\n{skill内容}"
- 追加文本到system prompt末尾
- Claude Code视为普通文本
- 不在skill系统中
- 检测依赖模型回显(不可靠)
discover模式(正确实现)
# skill文件: .claude/skills/skvm-general/SKILL.md
claude -p "prompt"
- 使用官方skill目录
- Claude Code自动加载识别
- 在init事件skills列表中
- 模型可通过
/skill调用
- 检测基于init事件(可靠)
应该如何实现inject模式
建议方案:skill文件 + prompt触发
inject模式应该写入skill文件并在prompt中触发调用:
if (skillMode === "inject") {
// 1. 写入skill文件(同discover)
const skillDir = path.join(task.workDir, ".claude", "skills", skillName)
await mkdir(skillDir, { recursive: true })
const frontmatter = `---\nname: ${skillName}\ndescription: ${skillDesc}\n---\n\n`
await Bun.write(path.join(skillDir, "SKILL.md"), frontmatter + task.skillContent)
// 2. 在prompt中触发skill调用
prompt = `/skill ${skillName}\n\n${task.prompt}`
}
效果:
- skill通过官方机制加载
- 模型主动响应
/skill命令加载skill
- skill出现在init事件skills列表中
- 检测可以基于Skill tool调用或init事件
模式语义重新定义
| 模式 |
行为 |
含义 |
| discover |
写入skill文件 |
skill静默存在,模型可能自动发现 |
| inject |
写入skill文件 + prompt触发 /skill |
skill存在 + 主动调用,模型必加载 |
核心区别:
- discover:skill存在,等待模型自动识别(基于description触发)
- inject:skill存在 + 强制调用,模型一定会加载使用
当前inject模式的额外问题
检测逻辑依赖模型回显
// src/adapters/claude-code.ts:430
if (text.includes(SKILL_INJECT_SENTINEL)) return true
假设模型会在输出中回显<skvm-skill-injected/>sentinel:
- thinking mode模型不回显system prompt内容
- 导致误判skill未加载
- 即使修复检测,inject本身仍是错误设计
建议修复方案
步骤1:重新实现inject模式
// src/adapters/claude-code.ts:576-589
if (task.skillContent) {
skillLoaded = false
// 无论inject还是discover,都写入skill文件
const skillDir = path.join(task.workDir, ".claude", "skills", skillName)
await mkdir(skillDir, { recursive: true })
const frontmatter = `---\nname: ${skillName}\ndescription: ${skillDesc}\n---\n\n`
await Bun.write(path.join(skillDir, "SKILL.md"), frontmatter + task.skillContent)
if (skillMode === "inject") {
// inject模式:在prompt中触发skill调用
prompt = `/skill ${skillName}\n\n${task.prompt}`
}
}
步骤2:更新检测逻辑
// inject模式检测:模型是否执行了Skill tool调用
if (skillMode === "inject") {
skillLoaded = detectSkillInvoke(events, skillName) // 检测Skill tool调用
} else {
skillLoaded = detectSkillDiscover(events, skillName) // 检测init事件skills列表
}
新增检测函数
function detectSkillInvoke(events: ClaudeCodeEvent[], skillName: string): boolean {
const matchesName = (s: unknown): boolean =>
typeof s === "string" && (s === skillName || s.endsWith(`:${skillName}`))
for (const ev of events) {
if (ev.type !== "assistant" || !ev.message) continue
const content = Array.isArray(ev.message.content) ? ev.message.content : []
for (const c of content) {
if (!c || (c as { type?: string }).type !== "tool_use") continue
const tu = c as ClaudeCodeContentToolUse
if (tu.name === "Skill" || tu.name === "skill") {
const inputName = (tu.input as { name?: string; skill?: string })?.name
?? (tu.input as { name?: string; skill?: string })?.skill
if (matchesName(inputName)) return true
}
}
}
return false
}
相关文件
| 文件 |
位置 |
问题 |
src/adapters/claude-code.ts:576-580 |
inject模式实现 |
使用--append-system-prompt而非skill系统 |
src/adapters/claude-code.ts:417-435 |
detectSkillInject |
检测依赖模型回显 |
测试验证
验证修复后inject模式
预期行为:
- skill文件写入
.claude/skills/<name>/SKILL.md
- prompt以
/skill <name>开头
- 模型执行Skill tool调用
- init事件显示skill已加载
- 检测返回
skillLoaded=true
报告人: yang_zixin
日期: 2026-05-13
状态: 待修复
建议优先级: 高 - 需要重新实现inject模式逻辑
Reproduction
Logs / output
SkVM version / commit
.
Runtime
.
Additional context
No response
Checks
What happened?
Claude Code adapter inject模式实现Bug报告
问题概述
类型: Bug - 设计缺陷
组件:
src/adapters/claude-code.ts影响: inject模式不是真正的skill注入,而是文本追加
严重程度: 高 - inject模式本质设计错误
Bug描述
当前inject实现
问题本质
inject模式使用
--append-system-prompt参数追加文本到system prompt,这不是Claude Code的skill系统。关键问题:
--append-system-prompt只是追加一段文本,不是skill机制/skill命令调用Bug后果
1. skillLoaded检测失败
由于inject模式使用
--append-system-prompt而非skill系统:detectSkillInject依赖模型回显sentinel(thinking mode不回显)skillLoaded=false2. Evidence记录skill未加载
Evidence的
runMeta.skillLoaded=false被写入agent logs。3. Optimizer生成WARNING警告
Optimizer在生成evidence摘要时,看到"WARNING: skill was not loaded"。
4. Optimizer误判放弃优化
Optimizer认为"无法基于skill分析问题",因为skill"未加载":
5. jit-optimize流程中断
6. 最终结果:无法完成skill迭代
关键后果:
7. 受影响范围
受影响的模型:
不受影响的模型:
8. 实际测试证据
对比分析
inject模式(当前实现)
claude --append-system-prompt "<skvm-skill-injected/>\n\n{skill内容}"discover模式(正确实现)
/skill调用应该如何实现inject模式
建议方案:skill文件 + prompt触发
inject模式应该写入skill文件并在prompt中触发调用:
效果:
/skill命令加载skill模式语义重新定义
/skill核心区别:
当前inject模式的额外问题
检测逻辑依赖模型回显
假设模型会在输出中回显
<skvm-skill-injected/>sentinel:建议修复方案
步骤1:重新实现inject模式
步骤2:更新检测逻辑
新增检测函数
相关文件
src/adapters/claude-code.ts:576-580--append-system-prompt而非skill系统src/adapters/claude-code.ts:417-435测试验证
验证修复后inject模式
预期行为:
.claude/skills/<name>/SKILL.md/skill <name>开头skillLoaded=true报告人: yang_zixin
日期: 2026-05-13
状态: 待修复
建议优先级: 高 - 需要重新实现inject模式逻辑
Reproduction
.Logs / output
SkVM version / commit
.
Runtime
.
Additional context
No response
Checks
CONTRIBUTING.md.