新技能为什么装好了却还看不到?GoWork 的技能发现缓存、刷新与重扫
GoWork 新技能明明已经放到目录里却看不到,通常不是技能坏了,而是技能发现缓存、刷新入口和全局重扫时机共同作用的结果。本文解释缓存 TTL、刷新按钮、junction 限制与正确排查顺序。
如果你刚把一个新 skill 放进目录,却发现 GoWork 里就是不显示,先看结论:大多数情况下,问题不在 skill 本身,而在“发现结果还没刷新”。 也就是说,加载器此刻看到的仍然是上一次扫描留下的缓存;只要等缓存 TTL 到期、手动点一次刷新,或触发一次全局重扫,技能通常就会出现。另一类常见原因,是目录接入方式不对:例如旧版 GoWork 的技能发现器不会跟随 junction 或 symlink,这时你把 skill 目录“挂接”进去,扫描器看见的是入口路径,却没有真的走到目标目录里。
这类问题看起来像“安装失败”,其实更接近“索引还没更新”。而这正是执行型助手和普通聊天机器人不同的地方:它不是只回答一句“可能是缓存问题”,而是应该知道先查缓存、再查路径、最后再查技能本体。在 GoWork 的内容流水线里,content-pipeline skill 也明确写过一个经验结论:共享状态必须固定读写 D:/omnigoai/.claude/skills/content-pipeline/ 下的那一份,不能因为 agent 从别的副本读到说明,就假设状态文件也会自动同步。技能发现本质上也是同一件事——入口路径、实际目录和缓存快照必须对得上。
如果你已经读过 GoWork 助手:真正会动手做事的本地 AI、多步任务为什么不能只在当轮写计划 和 失败后别重来:让 AI 助理从上次进度继续,这篇文章继续回答一个更具体、但很常见的问题:为什么一个新技能明明已经装好了,GoWork 却暂时“看不见”它?
先说最常见的原因:技能发现不是每次打开界面都全盘重扫
很多桌面应用为了避免每次打开都去深扫整个技能目录,都会把“上次发现到了哪些 skill、它们的元数据是什么”缓存下来。GoWork 这么做的原因并不神秘:技能目录可能很多、磁盘扫描有成本、还要兼顾首屏速度。
所以当你新增一个 skill 时,系统通常不会在每一次界面重绘时都立刻发现它,而是会遵循一套更保守的机制:
- 先读已有缓存;
- 在缓存 TTL 内直接复用;
- TTL 到期后,或用户显式触发刷新时,再重扫技能目录;
- 若某些入口路径需要更深层的全局扫描,只有在“重扫”阶段才会重新纳入索引。
这意味着一个看似矛盾、其实完全正常的现象:文件已经在磁盘上,但 UI 里暂时还没有。 问题不在文件不存在,而在发现索引还停留在上一次快照。
为什么缓存 TTL 不是“偷懒”,而是技能系统的稳定性设计?
很多人一看到“缓存”就觉得是多余层,仿佛只要删掉缓存、每次都现扫就行。但技能发现和普通配置项不一样,它往往涉及:
- 遍历多个目录;
- 读取每个 skill 的
SKILL.md或元数据; - 解析 frontmatter、名称、描述和适用场景;
- 处理重复项、损坏项和不可读目录;
- 在界面层生成可展示的技能列表。
如果每次打开技能面板都全量做一遍,用户得到的往往不是“更实时”,而是更慢、更抖的体验。TTL 的作用,是在“发现足够新”和“界面足够快”之间取一个平衡。
所以缓存 TTL 不应被理解为 bug,而应被理解为技能发现系统的节流器。真正的问题不在于系统用了缓存,而在于用户是否有清晰的刷新路径,以及当缓存尚未失效时,界面有没有足够直白地告诉你:现在看到的是旧索引,不是实时磁盘视图。
为什么“点刷新”与“等 TTL 过期”不是一回事?
它们看起来都能让技能出现,但语义不同。
- 等 TTL 过期:属于被动刷新。系统认为旧缓存已经不再可靠,于是下一次访问时触发重新扫描。
- 手动点刷新:属于主动失效。用户明确告诉系统:“我刚做了变更,请立刻丢弃旧索引并重扫。”
- 全局重扫:比普通刷新更重,适合入口路径发生变化、目录挂接方式变化,或者你怀疑上一轮扫描范围就不完整的时候。
这三者解决的不是同一级别的问题。普通新增 skill,往往刷新一次就够;但如果问题出在目录结构或挂接方式,仅靠“等一会儿”可能永远等不出来,因为扫描器从一开始就没走到真正的目标目录。
一个真实坑点:旧版 GoWork 的技能发现器不跟随 junction / symlink
这是这类问题里最容易误判的一种。
在 content-pipeline 的跨 agent README 里,有一句非常关键的话:某些 agent 的技能目录不跟随 junction/symlink,如 GoWork ≤1.3.x 的加载器,已在源码修复待发版。 这句话说明了两层事实:
- skill 本身可能完全没问题;
- 问题发生在“发现器如何遍历目录”,不是“技能内容怎么写”。
这意味着,如果你把 skill 目录通过 junction、symlink 或类似方式“映射”进 GoWork 的技能目录,旧版加载器可能只看到那个入口壳子,而不会继续走进真实目录。结果就是:
- 文件管理器里你明明能看到;
- 终端里路径也能访问;
- 但 GoWork 的技能列表就是没有它。
此时刷新再多次也没用,因为缓存刷新的前提是扫描范围正确。如果扫描器根本不跟随该入口,缓存里永远不会出现这条技能。
为什么“复制目录”有时比“优雅挂接”更可靠?
理论上,junction/symlink 很优雅:一份源目录,多处复用,不必重复维护。但前提是消费方真的支持这种目录语义。
如果发现器暂时不支持,你继续坚持“只用挂接不复制”,得到的不是优雅,而是持续不可见。也正因为此,content-pipeline 的 README 给出的临时建议非常务实:若某些 agent 不跟随 junction/symlink,就把本目录复制到它的技能目录即可。
这不是说复制比引用更先进,而是说在当前实现边界下,复制是更稳定的交付方式。对于技能发现系统来说,最重要的不是路径看起来多优雅,而是扫描器能真实读到 SKILL.md、解析出元数据并纳入索引。
一个更稳的排查顺序:先看“发现链路”,不要一上来怀疑 skill 写坏了
当新技能看不到时,最浪费时间的做法,是立刻回头重写 skill 内容。更好的顺序是:
1. 先确认文件是否真的落在扫描目录里
不是“你以为的目录”,而是 GoWork 当前版本实际会扫的目录。若用了映射路径,还要确认扫描器是否支持跟随。
2. 再判断是不是缓存尚未失效
如果路径正确,但只是刚新增不久,优先尝试刷新或等待 TTL 到期,而不是直接断言“加载失败”。
3. 必要时触发全局重扫
当你改动了目录入口、迁移了 skill 根目录、或从副本切回绝对路径时,普通刷新未必足够,全局重扫更保险。
4. 最后才回头查 skill 本体
例如 SKILL.md 是否损坏、frontmatter 是否异常、标题和 description 是否缺失。只有前面三层都排除后,才值得怀疑技能文件本身。
这个顺序的本质,是先检查“发现链路”是否通,再检查“内容解析”是否对。因为对技能系统来说,看不见和读不懂是两类完全不同的问题。
为什么共享状态和绝对路径在这里也重要?
技能发现不只是“能不能列出来”,还关系到后续执行会不会读错状态。
content-pipeline 明确要求,topics.md 和 content-log.md 必须始终读写 D:/omnigoai/.claude/skills/content-pipeline/ 下的共享状态,而不是某个副本里的同名文件。原因很简单:指令副本可以有多个,状态真相只能有一份。
技能发现也一样。如果某个 skill 因为复制、挂接或缓存问题被识别成多个来源,或者 UI 指向的是旧副本,接下来就可能出现两类更麻烦的问题:
- 你以为自己更新了 skill,实际上运行的还是旧副本;
- 你以为系统“没记住”,其实它读写的是另一份状态文件。
所以“刷新技能列表”从来不只是一个界面小动作,它影响的是整个执行链路里的入口一致性。
为什么刷新按钮很重要?
因为缓存 TTL 解决的是性能,刷新按钮解决的是可控性。
没有刷新按钮时,用户只能猜:
- 现在是不是还在缓存窗口里?
- 我刚才的改动有没有被看见?
- 要不要重启应用?
- 还是要等几分钟再看?
而一个明确的刷新入口,至少能把这种不确定性缩小到可验证的动作:我刚改完,现在主动请求重新扫描。
它的价值不在“帮系统做了本来不会做的事”,而在于把“等缓存自己过期”的被动等待,变成“由用户控制重建索引”的主动操作。对于经常新增、调试和迭代技能的人来说,这种确定性非常重要。
从产品设计看,技能发现为什么最好同时有 TTL、刷新和重扫三层?
因为三者分别处理三种不同场景:
- TTL:保证常规使用时快而稳;
- 刷新:处理“我刚改过”的即时反馈;
- 全局重扫:处理目录结构变化、映射方式变化和历史索引失真。
缺任何一层,体验都会出问题:
- 只有 TTL,没有刷新:用户会一直等,不知道系统是否看见改动;
- 只有刷新,没有 TTL:技能列表每次都重扫,界面响应会变差;
- 没有全局重扫:当目录入口层级发生变化时,普通刷新也可能永远修不回来。
这也是为什么“缓存 TTL、刷新按钮与全局重扫”最好被视作同一个发现系统的三件套,而不是三个互相替代的开关。
常见问题
FAQ 1:新技能看不到,第一步该做什么?
先不要重写 skill。先确认它是否真的在 GoWork 当前会扫描到的目录里,再手动刷新一次;如果你用了 junction 或 symlink,还要先确认当前版本是否支持跟随。
FAQ 2:等一会儿和点刷新有什么本质区别?
等一会儿依赖缓存 TTL 自然过期;点刷新是主动让系统丢弃旧索引并重扫。前者是被动更新,后者是立即请求重新发现。
FAQ 3:为什么我明明能在文件管理器里看到 skill,GoWork 却看不到?
因为“文件存在”只说明磁盘上有它,不说明技能发现器已经扫描到它。最常见原因是缓存还没失效,或旧版加载器不跟随 junction/symlink。
FAQ 4:为什么复制 skill 目录反而更稳?
因为在不支持映射目录的加载器里,复制意味着扫描器能直接读到真实文件。它不够优雅,但在当前实现边界下更可靠。
如果你遇到的是“新技能明明装好了却暂时不可见”,先别把它当成 skill 本体损坏。多数时候,真正要排查的是:发现缓存是否还有效、刷新是否已触发、扫描器是否真的走到了目标目录。 这类问题的关键不是多懂一点提示词,而是把技能系统当成一个有索引、有路径边界、也有一致性要求的执行入口来看。想继续了解 GoWork 如何把长期任务、记忆和执行状态串起来,可以再看 GoWork 助手:真正会动手做事的本地 AI、多步任务为什么不能只在当轮写计划 和 GoWork 下载页。