关于 timeless-docs
Timeless Docs 是用于改写文档和代码注释的技能,强调清晰、简洁地描述系统当前状态。它按变更内容或指定路径开展检查,并保留重要约束及需要保留历史的文档。
主要功能
- 01直接说明当前行为
- 02删去琐碎或重复内容
- 03适用于注释和文档
- 04检查变更文件或指定路径
- 05保留重要约束及例外
适用场景
- 01修改当前代码差异中的注释
- 02检查指定的文档文件
- 03清晰描述现状而不叙述变迁
安装
复制下面的命令,在终端中运行。
npx skills add https:/ / github.com/ bonkey/ skills --skill timeless-docs安装后在 Claude Code 中输入/timeless-docs确认已加载。
详细介绍
永恒文档
重写文档和代码注释,说明系统是什么,而不是它如何演变至此。直接陈述当前设计。不要提及历史、变迁或缺失。聚焦于有实质意义的信息——信息过多本身也是坏信息。
理由:描述变迁的文档会在变迁被遗忘时立即失效。不了解旧状态的读者从中得不到任何好处。说明现状即可;历史属于 git。
这条原则同样适用于代码注释和正文。注释解释某行代码为何存在时,很容易不经意间写出对比句式。
规则
- 直接描述当前状态。 不谈历史、变迁或缺失。
- 只保留有实质意义的信息。 删除复述显而易见内容或没有提供有效信息的内容。
- 让文字易于阅读。 使用浅白的语言,简短明了——但不要简短到晦涩难懂。
可读性
文档的价值在于有人阅读。确保段落使用现在时态,且只包含有实质意义的事实后,还要让内容易于理解:
- 语言浅白。 优先使用常见词,而非华丽辞藻;句子简短、主动。读者首次需要了解某个术语时,将其解释清楚;删去没有帮助的行话。
- 简短,但不晦涩。 删除填充语、模糊措辞和铺垫,但不要删掉读者理解句子所需的上下文。若一条注释必须通过逆向分析代码才能读懂,那就删得太过了。
- 具体,而非抽象。 写出实际对象(
Config/Base.xcconfig、/session),不要写“相关配置”。 - 每句只表达一个意思。 一句话表达了两个意思,就拆开写。
禁止的句式
重写或删除以下内容:
- 时间对比——“现在是 X”/“目前是 X”,且暗示过去的状态
- 变更叙述——“从 X 改为 Y”/“从 X 迁移”/“不再是 X”/“过去会 X”
- 过去状态标记——“以前是 X”/“原先是 X”/“从 X 重命名而来”
- 对被舍弃方案的对比——“而不是 X”/“取代 X”/“不是 Y”,且用于与其他方案或已舍弃的做法对比;只陈述代码实际执行的操作
- 否定式罗列——“这里没有 X、没有 Y、没有 Z”;说明实际存在的内容,而非不存在的内容
- 新旧标签——“旧的 X”/“新的 X”
重写示例
正文:
❌ The config loader was migrated from YAML and now parses config.toml.
✅ The config loader parses config.toml.
❌ Previously this used a global cache; it now uses a per-request cache.
✅ Each request gets its own cache.
❌ This endpoint returns JSON rather than the old XML format.
✅ This endpoint returns JSON.
❌ The new auth flow replaces the deprecated token endpoint.
✅ Auth uses the /session endpoint.
❌ Tenant values live in Swift, not xcconfig — we moved them out of build settings.
✅ Tenant values live in Swift.
❌ No Redis, no Kafka, no external queues — everything runs in-process.
✅ Jobs run in-process via a bounded worker pool.
❌ No checked-in Info.plist. All keys are in xcconfig now.
✅ All Info.plist keys are declared as INFOPLIST_KEY_* in Config/Base.xcconfig.
最后一组示例展示了处理否定式罗列的一般方法:将“没有什么”改为实际采用的具体机制——这通常比原句更具体、更有用,而不只是更短。
代码注释:
❌ // changed to 30s from 10s to avoid flaky timeouts
✅ // 30s: shorter values flake under CI load
❌ // formerly returned nil; now returns an empty array
✅ // returns an empty array when there are no matches
❌ // MainActor isolation is now the default
✅ // MainActor isolation is the default
❌ // use a set instead of a list for dedupe
✅ // set: callers rely on uniqueness
❌ // run the action in a Task rather than driving a .task off state
✅ // run the async action in a Task the button owns
唯一重要的区别
并非所有否定句都禁止。要区分真实的当前属性和对被舍弃方案的对比。
- 保留读者需要了解的真实当前约束:
- “批次之间不保证顺序。”
- “不同分片中的 ID 不唯一。”
- “此调用不是线程安全的。”
- 删除仅用于指向已舍弃方案的对比:
- “使用集合而非列表。” → “将 ID 存储在集合中。”
- “返回 JSON,而非 XML。” → “返回 JSON。”
判断标准:不了解另一种方案的读者仍需要这句话吗?如果需要,就保留(作为对事实的直接陈述)。如果这句话只有对照旧方案或其他方案才说得通,就删掉对比。
同样,保留原因,删掉历史。 “改为 30s,因为 10s 不稳定”表达了一个真实约束(较短的超时时间容易导致不稳定),但裹上了变迁叙述。保留约束,删掉“改为”:“30s 能承受 CI 负载尖峰。”
历史就是内容的地方——不要删改
有些文档的用途就是记录变更。请勿改动这些文档;如需修改,请先征求同意:
CHANGELOG.md、发行说明、版本历史- 迁移指南和升级指南
- 架构决策记录/决策日志(参见
captains-log技能) - 带有移除时间线的弃用通知——这些通知警示当前和不久的将来,仍然具有重要作用
如果用户选定的范围包含其中任何一项,请标记出来,并在编辑前确认,而不要抹去其历史记录。
范围:两种模式
每次运行都属于变更模式或路径模式。根据请求选择模式;参数为路径时使用路径模式,参数为 changes、diff、session(或没有参数)时使用变更模式。
变更模式 — 当前工作触及的文档
当用户指向近期工作,而非某个位置时使用此模式,例如:“这些变更”“这个差异”“我们刚编辑的内容”“提交之前”,或者用户没有指定目标但当前有正在进行的工作。
按以下来源构建文件列表,采用第一个非空来源:
- 会话编辑 — 本次对话中先前创建或编辑的文件。
- 未提交的工作 —
git status --porcelain:已修改、已暂存和未跟踪的文件。 - 分支差异 — 如果工作区干净,则运行
git diff <default-branch>...HEAD --name-only。
如果这三项都为空,请说明情况并询问要处理的路径——不要转而检查整个代码库。
在每个文件中,只编辑本次变更触及的文案:
- 差异块中新增或修改的注释/文档行;
- 与变更块相邻,且因该变更而过时或带有历史意味的注释——代码变更正是“现在使用 X”这类注释出现的时机,也是旧注释开始描述已不存在状态的原因;
- 变更集中的文档文件(
README、docs/*.md等)里的已变更章节。
变更模式是有针对性的处理,不是文件审查。不要重写已变更文件中未触及的部分;如果注意到范围外存在禁止模式,请在报告中将其列为候选项,而不要编辑。
路径模式 — 指定文件或文件夹
当用户指定文件或目录时使用此模式。只处理指定范围,并递归检查目录:文档文件,以及源文件中的注释和文档字符串。
- 如果指定的是整个项目(“这个项目”、仓库根目录),请枚举候选内容(
README、docs/、模块/头文件注释、文档字符串);如果范围较大,请先提出简短计划,再进行批量编辑。 - 如果指定的路径不存在,或目标确实不明确,请询问要处理哪些文件或目录。
工作流程
1. 确定范围
根据范围:两种模式中的说明选择模式并构建文件列表。编辑前说明模式和文件列表,以便用户及时调整。
2. 检查例外项
找出历史记录本身具有重要意义的文件(见上文)。将其单独列出,并在编辑前向用户确认。
3. 扫描禁止模式
阅读每个目标文件并收集候选编辑项。以下搜索提示可用于查找机械性案例:
# path mode — scan the named files/folders
grep -rniE "no longer|used to|previously|formerly|renamed from|migrated from|instead of|rather than|the old |the new |now (uses|returns|is|it)" <path>
# changes mode — scan only added lines in the diff
git diff -U0 HEAD | grep -iE "^\+.*(no longer|used to|previously|formerly|renamed from|migrated from|instead of|rather than|the old |the new |now (uses|returns|is|it))"
Grep 只能找出明显案例——时间对比和否定式清单模式通常需要人工判断。不要只依赖 Grep。在变更模式下,还要结合上下文阅读差异块:变更代码上方未修改的注释,现在可能已经无法准确描述现有行为。
4. 改写为描述当前状态
对每个候选项:
- 直接陈述当前行为,同时保留所有重要事实——限制、约定、不变量、注意事项,以及选择背后的实际原因。
- 如果一句话只描述过渡过程,且没有需要保留的当前状态信息,就删除它。
- 与周围内容的语气、时态和格式保持一致。尽量少改——不要重写已经清晰且不过时的段落。
5. 精简与可读性检查
删除那些只是复述代码显而易见行为的语句、形式化的注释和冗余句子。保留关键信息:任何称职的读者都无法一眼推断出的内容。然后应用可读性规则——用词通俗、句子简短主动、使用具体名词、每句只表达一个想法;但不要删减过度,以免语句变得晦涩难懂。
6. 验证
- 没有丢失重要信息。
- 每项陈述仍与代码一致。
- 文本读起来自然,脱离此前状态也能独立理解。
- 不再包含任何禁止模式。
注意事项
- 优先保留原意。切勿仅因真实的约束、原因或警告采用否定或对比的表述方式,就将其删除——应将其改写为对当前状态的直接陈述。
- 不要编造无法从代码中验证的当前状态信息。如果文档中的说法看起来已过时,应标记出来,而不是猜测。
- 如果不确定某行描述的是真实属性还是用于否定某个替代方案的对比,应保留该行并告知用户,而不是删除。
- 修改应精简且便于审查;不要借口清理文本而对整个文件重新排版或调整结构。
输出
按文件分组,报告模式和改动内容:
- 文件和位置
- 模式(时间对比、变更叙述、否定清单、琐碎细节等)
- 修改前 → 修改后,或删除的文本及其不包含当前状态关键信息的原因
另行列出需要用户决定的事项:
- 未作修改的例外文件和含义模糊的否定表述
- 在更改模式下,于已修改文本以外发现的禁止模式(可作为后续路径模式处理的候选项)