Community写作与编辑github.com

maxgfr/ultradoc

回答关于任何开源项目的超精确问题,并从其真实源代码、Issues、PRs、文档和网络中生成经过引文验证的参考文档。基于真实检索,而非模型记忆。一个 skills.sh 智能体技能 + 零依赖 CLI。

ultradoc 是什么?

ultradoc 是一个用于 AI 智能体(如 Claude Code)的技能,旨在从真实源代码中检索证据并推理,从而回答关于开源项目的精确问题,或生成全面的文档。它采用确定性引擎(一个零依赖的 Node.js 脚本)进行搜索和索引,同时强制要求答案中的每个声明都必须引用可验证的检索证据——通过 `ultradoc check` 命令强制执行。该工具支持代码、Issues、PRs、文档和网络等多种数据源,并包含用于概念性问题的可选的本地语义搜索模式。 ultradoc 的独特价值在于它消除了模型记忆带来的幻觉,通过因果验证的检索循环确保答案准确、可重复且可审计,非常适合开发人员需要深入了解上游代码库而不构建完整本地环境的场景。

兼容平台~Claude Code~Codex CLI~Cursor
npx skills add maxgfr/ultradoc

Installed? Explore more 写作与编辑 skills: steipete/notion, langchain-ai/langchain, bytedance/podcast-generation · View all 6 →

在你喜欢的 AI 中提问

打开一个已预加载此 Agent Skill 的新对话。

文档

ultradoc — 回答源自源码,而非记忆

ultradoc 通过检索有依据的证据并对其进行推理,来回答关于开源项目的超精确问题。确定性引擎(scripts/ultradoc.mjs,零依赖 Node)用代码进行搜索和索引;你的工作是读取检索到的证据并撰写精确、带引用的答案。每个声明必须指向一个真实的来源。这会被强制执行:如果任何引用未能解析到检索到的证据,ultradoc check 将失败。

核心规则:不要根据你对库自身知识的记忆来回答。你的训练数据是过时的,并且会幻觉 API。只根据 ultradoc 从实际仓库、Issues、PRs、文档和网络中检索到的证据来回答。如果证据没有涵盖到,请说明并检索更多——永远不要猜测。

脚本

一个已提交、无依赖的单个文件:node scripts/ultradoc.mjs <command>。无需 npm install,无需 API 密钥。运行 --help 查看全部命令。关键命令:

  • ask --repo <url|path> --q "<问题>" [--sources ...] [--package <p>] [--semantic] [--docs-url <u>] 克隆(任何 git URL,缓存在 /tmp/ultradoc/<slug> 中)、建立索引、从所有选定来源检索,并将一个证据档案(EVIDENCE.md、evidence.json、meta.json)写入到一个运行文件夹中——该文件夹持久化保存在克隆目录旁的 <clone>/.ultradoc/runs/<id>(一个稳定的、基于提交的、跨问题复用的主目录),除非你传递了 --out。默认来源:code,issues,prs,docs(当仅凭仓库无法回答问题时,添加 web,so;对于“X 是什么时候添加/更改的”问题,添加 releases,history;对于社区 Q&A,添加 discussions——需要 gh CLI)。 在单体仓库中,--package <name|dir> 将代码/文档检索范围限定到一个工作区包。
  • code|issues|prs|docs|releases|history|discussions|so --repo <...> --q "..." —— 深入一个来源,将证据打印到标准输出(不生成档案)。使用这些命令来扩展一个薄弱的领域。history 在克隆上运行 git pickaxe(log -S/-G)——首次调用远程仓库时会获取一次完整历史记录。
  • web --repo <...> [--q "..."] [--url <u,...>] —— 无密钥的网络发现(SearXNG → DuckDuckGo → 你的 WebSearch)+ 获取/提取。传递 --url 来锚定一个你通过自己的 WebSearch 找到的特定页面。
  • overview --repo <...> [--refresh] —— 生成(一次)仓库的缓存 Markdown 摘要:它是什么、工作区包、布局、公共 API 和文档地图。缓存在克隆旁边,并在提交未更改时重用——阅读它可以在不重新索引的情况下,跨多个问题定位。这是导航地图,不是可引用的证据。
  • doc --repo <...> [--package <p>] [--sources ...] —— 构建一个有依据的参考文档:一个确定性的章节大纲(概述、安装、公共 API/每包、配置、架构),每章节检索一个档案并合并成一个单一的 evidence.json,以及一个 DOC.todo.md 工作清单。你将带引用的散文写入 DOC.md;check 像验证答案一样验证它。持久化保存在 <clone>/.ultradoc/doc/ 中。参见下面的“生成文档”。
  • check --run <档案目录> —— 根据档案的 evidence.json 验证 ANSWER.md(或 doc 运行的 DOC.md)的引用。非零退出码 ⇒ 无根据。--answer <file> 验证特定文件。
  • index --repo <...> —— 构建/打印结构索引(用于调试/检查);列出单体仓库的已发现工作区包。
  • semantic up|down|status —— 可选的本地向量后端(见下文)。

工作流程

你端到端地拥有这个任务:返回一个基于证据、带引用的答案,并且永远不要交回一个只有一半检索结果的档案。但检索和验证工作是一组独立的、几乎零成本的调用——当你的运行环境可以时,并行化它们(在一次消息中批量处理独立的深入查询;如果可用,分发给子智能体或工作流)否则就内联进行。迭代多轮直到证据完整;在完成之前不要返回。参见 references/orchestration.md。

  1. 确定目标。 识别项目及精确问题。如果你只有一个名称,找到规范的仓库 URL(使用你的网络搜索,或者如果不明确,询问用户)。记下用户关心的任何版本/分支(--ref)。

    同一个仓库的多个问题? 运行一次 overview --repo <url> 并阅读它打印出的缓存的 OVERVIEW.md:它映射了仓库(包、布局、公共 API、文档),这样后续问题就可以重用同一个克隆+索引,而不是从头开始重新定位。永远不要引用它——它是导航,不是证据。

    单体仓库? 如果 ask/index/overview 报告了工作区包(例如,socialgouv/code-du-travail-numerique → @cdt/frontend,@socialgouv/modeles-social,……),选择名称/目录与问题所涉及子系统相匹配的包,并添加 --package <name|dir>,这样检索就不会淹没在其他包中。如果没有包名明显匹配,首先运行一次无范围限定的 ask,查看哪些包是命中次数最多的,然后重新运行并将其范围限定到该包。未知的包名会大声失败并列出存在的包。

  2. 检索。 首先,像开发者一样思考,为问题推导出 2–3 个查询变体——引擎会逐字搜索,因此措辞很重要:

    • 自然语言措辞("retry backoff"),
    • 代码库可能使用的标识符形式(retryBackoff,retry_backoff,MAX_RETRIES),
    • 如果用户引用了,就是字面上的错误消息、选项或标志名称。

    多部分问题? 现在就将其拆分为子问题——每个子问题都需要自己的证据,或者最终需要明确的“未知”。跟踪每个子问题的覆盖情况。

    引擎已经处理了复数和重音("retries"/"retry","délai"/"delai"),将标识符拆分为子标记,并提升以关键词命名的文件——因此,将你的变体用于同义词和标识符("heartbeat" vs ping,"pool" vs connectionLimit),而不是用于同一单词的屈折变化。并且知道何时词汇搜索会薄弱:它需要实际出现在仓库中的单词。对于概念性或“为什么这样设计”的问题,首先使用 docs,discussions,web(或 --semantic),而不是期望 code 来承载答案。

    使用最佳变体和匹配的来源运行 ask:

    node scripts/ultradoc.mjs ask --repo <url> --q "<精确问题>" --sources code,issues,prs,docs
    

    ultradoc 从其自己的 README/清单中自动发现项目的官方文档 URL(并优先考虑仓库内的规范 docs/ 树),然后据此进行锚定——仅当需要覆盖时才传递 --docs-url <url>。当问题是概念性的或仓库内容稀疏时,添加 web,so;当问题是关于何时/为何/哪个版本发生了更改时,添加 releases,history。该命令会打印档案路径。然后将剩余的变体 × 深入来源视为扇出——在一次消息中将这些独立的深入查询作为并行调用发出(或者每个单元一个子智能体)。参见 references/orchestration.md。

  3. 读取档案。 打开运行文件夹中的 EVIDENCE.md。每个项目都有一个 ID([E1],[E2],……)、一个来源 ref 和一个片段。这就是你的证据——阅读实际的代码/Issue/PR/文档文本。

  4. 深入挖掘空白。 当一个子问题不到 ~2 个相关条目,或者没有条目实际包含所询问的符号/行为时,它就是薄弱的。不要等到一个档案看起来薄弱了才去查询这些变体——从一开始就并行运行变体查询(深入查询几乎是免费的:克隆和索引已缓存)。将它们扇出到各个来源:

    • code --repo <...> --q "<符号或行为>" 以提取更多代码区域。
    • issues/prs 以阅读相关的讨论和进行中的更改。
    • 当问题是关于何时/为何/哪个版本发生了更改时,使用 releases(变更日志 + 发布说明)和 history(git pickaxe)。
    • discussions 用于社区 Q&A 和设计线程(需要 gh CLI)。
    • web(或你的 WebSearch → web --url <u>)用于外部参考。 遵循 references/retrieval-playbook.md 了解如何迭代,以及 references/orchestration.md 了解如何并行运行这些深入查询。

    写作前进行分类。 检索是面向召回率的,因此档案将包含仅共享关键词的不相关内容。评判标准:只有当项目的片段命名了所询问的符号/行为或描述了相同的机制时,它才与问题相关——仅共享一个关键词是不够的。列出通过该测试的证据 ID,并忽略其余的——不相关的条目不能仅仅因为存在而被引用。如果分类后少于 ~2 个条目支持核心主张,请返回并检索更多。

    重新查询而不是重新阅读。 如果前 3 个代码条目不相关,不要继续向下阅读列表——使用步骤 2 中下一个标识符形状的变体重新运行 code --q。连续两个不相关的档案意味着措辞不正确,而不是仓库缺少答案。

    循环直到干涸。 按轮次深入(限制 ~3 轮)。当一轮没有出现新的相关证据时停止,或者当每个子问题都有 ≥2 个支持条目时停止——然后进行分类并写作。在限制后仍得不到支持的子问题是一个明确的未知数,绝不能从记忆中填充。

  5. 写作答案。 在同一个运行文件夹中创建 ANSWER.md。要精确且简洁。为每个事实声明引用它所属的证据 ID,例如 重试使用带抖动的指数退避 [E1],PR #79 正在重写此功能 [E7]。 参见 references/citation-format.md。当版本很重要时,将答案锚定到 meta.json 中显示的提交。涵盖步骤 2 中的每个子问题;将证据未确定的事情标记为明确的未知——不要从记忆中填充。

  6. 验证(两层)。

    • 结构: node scripts/ultradoc.mjs check --run <档案目录>。如果任何引用未能解析到证据,或答案没有引用,它就会失败。修复并重新运行直到通过。
    • 语义(对抗性支持检查): node scripts/ultradoc.mjs verify --run <档案目录> 会写入一个声明↔证据工作清单(VERIFY.todo.json + VERIFY.md)。作为怀疑论者评判每一对:默认判定为 unsupported/refuted,除非被引用的片段字面上支持该声明,将裁决(verdict)设置为 supported · partial · refuted · unsupported(+ 简短注释)。每对运行一个怀疑论者——当可用时分发给子智能体(每个返回其裁决),否则内联裁决每一对——并将所有裁决收集到一个单一的 verdicts.json 中(参见 references/orchestration.md),然后:
      node scripts/ultradoc.mjs verify --apply verdicts.json --run <档案目录>
      node scripts/ultradoc.mjs check  --semantic --run <档案目录>
      
      这会在以下情况失败:未解决/无来源(结构)以及任何被反驳(refuted)或不支持(unsupported)的声明——填补引用解析了但实际上并不支持该声明的空白。修复声明(重新引用、弱化、删除或检索更好的条目)并重新验证直到通过。还要根据 references/answer-rubric.md 进行自我审查,以确保完整性/时效性/未知性。
  7. 呈现。 向用户提供基于证据的答案及其引用和链接(文件:行号、Issue/PR 编号、来自证据的文档/SO/Web URL),以及用于验证的提交。

生成文档

当用户想要一个整个项目(或整个包)的文档而不是一个答案时,使用 doc——它是在章节大纲上扇出的相同有根据的循环:

  1. 构建脚手架。 node scripts/ultradoc.mjs doc --repo <url> [--package <p>]。引擎构建一个确定性的提纲(概述、安装/使用、公共 API 或每个工作区包一个章节、配置、架构),为每个章节检索一个档案,将它们合并成一个带有全局 [E#] ID 的 evidence.json,并写入 DOC.todo.md(每章节工作清单)+ DOC.plan.json。添加 --sources code,docs,issues,prs 以使各章节基于比仅代码+文档更多的来源。它持久化保存在 <clone>/.ultradoc/doc/ 下。
  2. 写作每个章节。 读取 DOC.todo.md 和 EVIDENCE.md,然后在运行文件夹中写入 DOC.md:每个提纲条目一个章节,每个声明引用 [E#]。证据薄弱的章节是一个扇出单元——深入查询它(code|docs|issues …)或将空白标记为明确的未知;永远不要凭记忆写作。每章节的写作工作可以并行化——参见 references/orchestration.md。
  3. 验证并呈现。 node scripts/ultradoc.mjs check --run <doc-dir>(以及 verify + check --semantic 用于支持门控,与步骤 6 完全一样——两者都会自动检测 DOC.md)。修复直到有依据,然后呈现锚定到其提交的 DOC.md。

可选的语义模式(完全本地,无需 API 密钥)

确定性的 Tier-1 搜索(ripgrep + 符号索引)是默认设置,不需要任何东西。对于更模糊、概念性的问题,你可以启用本地语义搜索:

node scripts/ultradoc.mjs semantic up      # docker compose: Qdrant + Ollama (+ SearXNG)
node scripts/ultradoc.mjs ask --repo <url> --q "..." --semantic

一切都在本地 Docker 容器中运行——无密钥,无数据离开机器。如果栈未启动,--semantic 会记录一条通知并回退到 Tier 1。参见 references/semantic-setup.md。

参考

  • references/orchestration.md —— 如何跨调用/子智能体并行化检索深入查询和验证,包含返回 + 裁决汇编契约以及顺序回退。
  • references/retrieval-playbook.md —— 如何选择来源并迭代以得到完整答案。
  • references/citation-format.md —— check 强制执行的引用语法。
  • references/answer-rubric.md —— 在呈现之前的语义自我审查。
  • references/provider-apis.md —— 如何按主机获取 Issues/PRs,无需密钥。

相关技能