01 编译器证据分层
事实从编译数据库和静态分析来,词法结果不能冒充确定调用。
过关:能区分 full / partial,并指出该看哪些文件。
掌握标准不是把两份文档背下来,而是不看稿能画出生成路径,并扛住追问。每次只学一块:读指定文件 → 在纸上画出输入/输出/失败降级 → 合上文件讲 90 秒 → 用面经追问自检。
事实从编译数据库和静态分析来,词法结果不能冒充确定调用。
过关:能区分 full / partial,并指出该看哪些文件。
信道下一层才是叶子;父级必须等叶子写完再汇聚,不能抄叶子正文。
过关:能画出 pdsch/encoder 是叶子、pdsch 是父级。
模型只看裁过的任务上下文,平台不收、不存、不读 API Key。
过关:能讲清预算怎么切、为什么走标准输入。
叶子可有限并发,父级串行;续跑要新建快照,源码或 Schema 变了必须重来。
过关:能讲清什么情况能继续、什么情况必须重来。
四路召回再融合。引用对不上本轮证据,就不展示模型原文。
过关:能举「语义像但不真」的例子,并说出怎么拦。
确定边和候选边必须分开。图不改人工模块树,更不是 LLM 流程图。
过关:不把图画成“模型猜出来的调用链”。
只能复述「用了 Clang、RAG、图谱」,但说不清为什么不能全并行、为什么候选边不能当调用链。
这是 ClangWiki 和其他“丢源码给 LLM 写文档”方案的分界。先问事实从哪来,再问模型写了什么。
完整分析:分析器跑通且读到编译数据库,直接调用可以当编译器事实。
部分分析:分析器没有或失败,词法补充可以谈文件和未解析调用,但不能写成运行时一定发生。
宏展开、函数指针、动态加载、条件编译真实分支,都不在确定性范围里。
对 src/phy/pdsch,下一层 encoder / modulation / mapping 才是最小文档单元。信道根本身是任务手册。
叶子负责源码地图、调用链、异常路径。
父级只读直接子文档,做任务路由和故障导航,质量门禁会拒绝大段复制。
生成方向自底向上;阅读方向是仓库 → 子系统 → 信道 → 叶子 → 源码。
模型不是去逛仓的。平台先按文档类型切预算,再把上下文从标准输入喂给无工具 Agent。
叶子偏源码和关系;汇聚文档偏子文档摘录;仓库首页几乎全是导航材料。
接口直接拒绝密钥类字段。认证留在本机已经登录的命令行 Agent。
证据不够必须写「无法确定」,不能靠形容词补全调用链。
快,但不能把不同版本的叶子和父级拼进同一份 Wiki。
叶子在 1–4 的上限内并行;父级和仓库级文档在叶子屏障后串行。
每完成一篇就原子写断点。继续时新建快照,并核对源码哈希、配置和 Schema。
输出先选最后一份完整稿,再按章节契约校验,失败只自动修一次。
代码问答怕的不是召不回,而是召回一段语义很像、事实不对的话。
四路:精确符号、全文、向量、图扩展,再用倒数排名融合。
精确标识符和编译器确定性会再加分。向量不可用就降级,不假装还能语义搜。
问答每轮重检索。引用必须是本轮证据编号,修一次仍不合格就拦截展示。
模块树负责稳定导航,图谱负责解释跨模块关系。社区分析不改人工边界。
确定边来自编译器、构建和显式源码。候选边可以显示,不进默认调用链,也不作为强事实进问答。
工作台是本机单用户操作面,默认只监听回环地址。删仓库注册记录不会删源码。
前端下钻和三维总览都只是观察层,不能把候选边画得更“真”。
依据仓库当前源码与文档整理。提交记录作者为
qinlianxi,远端为g18042663173-a11y/ClangWiki。你在本机的个人职责、是否独立 Owner、是否上线过生产环境,一律标为 待补,讲的时候不要先自称 0→1 Owner。
| 知识点 | 为何需要 | 在本项目中的位置 | 高频度 |
|---|---|---|---|
| CMake 只配置、导出编译数据库 | 没有真实编译参数,静态分析会漂 | clangwiki/build.py 配置 CMake,不编译目标代码 | 高 |
| libclang / 编译数据库 | 符号、直接调用、翻译单元要从编译器来 | clang-tool/src/main.cpp、clangwiki/analyzer.py | 高 |
| 编译器事实 vs 词法猜测 | 防止把函数指针、宏展开说成确定调用 | 分析模式 full / partial,关系里的候选调用 | 高 |
| 自底向上文档编排 | 父级只能读直接子文档,避免全仓塞进模型 | clangwiki/planner.py、clangwiki/pipeline.py | 高 |
| 有界上下文与章节契约 | 模型只能写指定章节,证据不够必须写无法确定 | clangwiki/context.py、clangwiki/output.py | 高 |
| 子进程调用外部 Agent,不碰密钥 | 平台不是模型网关 | clangwiki/opencode.py、clangwiki/api.py 拒收凭据字段 | 高 |
| 混合检索与 RRF | 问答不能只靠向量语义 | clangwiki/indexing.py、docs/RAG_AND_RETRIEVAL.zh-CN.md | 高 |
| 引用校验闭环 | 没有合法引用就不展示模型原文 | clangwiki/rag.py | 高 |
| 属性图:确定边 / 候选边 | 图谱不是 LLM 画的流程图 | clangwiki/graph.py、docs/CODE_KNOWLEDGE_GRAPH.zh-CN.md | 中高 |
| SQLite 任务队列与断点快照 | 长任务可恢复,且不能混版本 | clangwiki/jobs.py、clangwiki/pipeline.py 原子写断点 | 中高 |
| 本机单用户安全边界 | 源码查看不能逃出已注册仓 | clangwiki/wiki.py 源码片段、默认 127.0.0.1 | 中 |
| FastAPI + React 工作台 | 多仓、Wiki、图谱、检索、问答的人机面 | clangwiki/server.py、frontend/src/App.tsx | 中 |
| 亮点标题 | 为什么重要 | 通用技术关键词 | 先看哪些文件 | 建议学习顺序 |
|---|---|---|---|---|
| 编译器证据分层 | 这是项目和其他“丢源码给 LLM 写文档”方案的分界 | 静态分析、确定性、降级 | docs/ARCHITECTURE.zh-CN.md、clangwiki/analyzer.py、clang-tool/src/main.cpp | 1 |
| 信道下一层叶子与自底向上汇聚 | 决定文档粒度和父级能不能抄叶子正文 | 层级规划、依赖屏障 | clangwiki/knowledge.py、clangwiki/planner.py、tests/test_hierarchical_planning.py | 2 |
| 有界上下文与写作隔离 | 解释为什么模型看不到全仓、也碰不到密钥 | 上下文预算、最小权限、stdin | clangwiki/context.py、clangwiki/opencode.py、agents/clangwiki-doc.md | 3 |
| 生成可靠性:并发、断点、校验修复 | 长任务怎么失败可恢复、输出怎么不被脏数据写进去 | 受限并发、检查点、契约校验 | clangwiki/pipeline.py、clangwiki/output.py、clangwiki/jobs.py | 4 |
| 混合检索与引用闭环 | 问答为什么必须带可打开的证据 | RRF、引用校验、短会话 | clangwiki/indexing.py、clangwiki/rag.py | 5 |
| 图谱与本机工作台 | 图是观察层,不改人工模块树 | 属性图、社区分析、本机平台 | clangwiki/graph.py、frontend/src/GraphWorkbench.tsx、docs/PLATFORM_ARCHITECTURE.zh-CN.md | 6 |
| 主题 | 通用技术点 | 建议阅读位置 | 预计时间 | 读完能回答什么 |
|---|---|---|---|---|
| 产品边界与能力清单 | 本地平台、离线、多仓 | README.md | 20 分钟 | 它解决什么、不解决什么 |
| 生成主链路 | 配置、分析、规划、写作 | docs/ARCHITECTURE.zh-CN.md、clangwiki/pipeline.py | 45 分钟 | 一次生成从哪走到哪 |
| 叶子边界 | 目录树如何变成文档树 | clangwiki/knowledge.py、tests/test_hierarchical_planning.py | 30 分钟 | 为什么 encoder 是叶子、pdsch 是父级 |
| 任务规划 | 自底向上、文档类型 | clangwiki/planner.py | 20 分钟 | 叶子、信道手册、子系统、仓库首页怎么排队 |
| 上下文裁剪 | 证据预算、子文档摘录 | clangwiki/context.py | 30 分钟 | 父级为什么主要读子文档而不是全仓源码 |
| 模型适配器 | 子进程、stdin、禁工具 | clangwiki/opencode.py | 20 分钟 | 密钥为什么不进平台 |
| 输出门禁 | 章节契约、选最后一份完整稿、一次修复 | clangwiki/output.py、clangwiki/document_schema.py | 25 分钟 | 脏输出怎么被拦住 |
| 原生分析器 | AST 遍历、直接调用 | clang-tool/src/main.cpp | 40 分钟 | 编译器事实从哪来 |
| 词法降级 | 分析器失败后还能做什么 | clangwiki/analyzer.py | 25 分钟 | partial 模式能说什么、不能说什么 |
| 平台与数据根 | 快照、集合、任务 | docs/PLATFORM_ARCHITECTURE.zh-CN.md、clangwiki/platform.py | 25 分钟 | 数据放哪、当前 Wiki 怎么指 |
| 检索融合 | 四路召回、加分 | docs/RAG_AND_RETRIEVAL.zh-CN.md、clangwiki/indexing.py | 35 分钟 | 为什么不是纯向量搜索 |
| 问答校验 | 引用前缀、修复、拦截 | clangwiki/rag.py | 25 分钟 | 无效引用为什么不展示 |
| 图谱契约 | 图层、证据、社区 | docs/CODE_KNOWLEDGE_GRAPH.zh-CN.md、clangwiki/graph.py | 40 分钟 | 候选边为什么不能当调用链 |
| 任务恢复 | 双车道、断点继续 | clangwiki/jobs.py、clangwiki/api.py | 20 分钟 | 中断后怎样继续、何时必须重来 |
| 前端工作台 | 视图与人机路径 | frontend/src/App.tsx、docs/WEB_WORKSPACE.zh-CN.md | 20 分钟 | 用户点“生成 Wiki”后后台走哪 |
| 部署约束 | Windows 离线、本机监听 | docs/DEPLOYMENT_AND_USAGE.zh-CN.md | 15 分钟 | 运行时依赖什么、不依赖什么 |
若某文件或原理看不懂,请继续追问 AI;本技能负责给学习路径与题目,不提供逐行讲解。
建议你按顺序 1→6 自己讲一遍:先讲“事实从哪来”,再讲“文档怎么长出来”,最后讲“检索和图谱怎么不把猜测升级成事实”。讲卡壳的地方,把对应文件路径丢回对话即可。
交叉:后端平台 + 编译器工具 + AI 应用。
依据:核心是 Python 编排的本机知识平台;事实生产依赖 CMake/Clang;文档写作和问答通过外部命令行 Agent 完成;前端是本地 React 工作台。它服务的对象是大型 C/C++ 仓,示例和领域规则明显偏向无线基带,但框架本身按模块树工作,不是只写死 PDSCH。
1. 问题:直接把全仓源码交给模型,调用关系和职责边界会被编出来。 机制:先抽出编译器级事实,再按层级喂给模型,并规定证据不够必须写无法确定。 落点:分析产物进知识模块树,任务上下文按文档类型分配文件/符号/关系/子文档/源码预算。
2. 问题:基带仓按信道组织,叶子如果切得太大,一篇文档什么都写不透;切得太碎,父级又没有任务视角。 机制:信道根的下一层源码目录作为最小文档单元,父级只汇聚直接子文档。 落点:知识构建里解析信道根与叶子;规划器按深度从深到浅排队。
3. 问题:模型写作不稳定,stdout 可能拼多份稿,也可能缺章节或大段复制子文档。 机制:选最后一份结构完整的稿,补导航卡,按章节契约校验,失败则带原因再生成一次。 落点:输出模块的完整性选择、导航注入和综合文档反复制检查。
4. 问题:叶子文档彼此独立,但父级依赖子文档,盲目全并行会读到空子文档。 机制:叶子过屏障后再串行汇聚;叶子并发上限可配,且不改变事实和模板。 落点:流水线把叶子任务和汇聚任务拆开,线程池只覆盖叶子。
5. 问题:向量检索会把语义像的内容召回,但代码问答更怕“像但不真”。 机制:符号、全文、向量、图扩展四路召回,倒数排名融合后再给编译器确定性和精确标识符加分。 落点:索引服务的分路检索与融合;图谱块默认只扩展已确认关系。
6. 问题:本机平台一旦收密钥或能任意读盘,就从知识工具变成高风险代理。 机制:密钥字段直接拒绝;模型认证留在外部 Agent;源码路径必须落在已注册仓根下。 落点:接口层拒收凭据字段,Wiki 源码接口做路径包含检查,服务默认只绑本机回环地址。
| 决策 | 备选 | 取舍 | 风险 | 验证 |
|---|---|---|---|---|
| 事实生产与模型写作拆开 | 让模型自己扫仓写文档 | 慢一些,但调用链可追溯 | 分析器失败时文档变弱 | 看分析模式和关系确定性字段 |
| 只 configure CMake,不编译目标 | 完整编译再分析 | 文档流程只读,少破坏被分析仓 | 缺编译数据库时只能走后备/部分分析 | clangwiki/build.py 与后备编译数据库 |
| 叶子并发、父级串行 | 全串行或全并行 | 在正确性与等待时间之间折中 | 外部 Agent 额度打满、本机资源抖动 | 并发配置范围 1–4,测试与进度事件 |
| 断点继续必须新建快照并校验一致性 | 原地改同一快照 | 避免把不同源码版本混进一篇 Wiki | 配置一变就要重跑 | 断点文件原子替换;继续接口带旧运行号 |
| 候选关系永不升格为默认调用链 | 用 LLM 补全调用图 | 宁缺毋滥 | 图看起来“不完整” | 图谱规范与检索默认过滤 |
| 向量失败自动退化,不假装还能语义搜 | 向量不可用就整条问答失败 | 本地离线更稳 | 召回变短 | 检索返回告警通道 |
| 引用校验失败则拦截展示 | 先展示再人工看 | 避免未验证结论流出 | 有时用户只看到失败句 | RAG 状态 citation_validation_failed |
| 逻辑知识空间不复制源码 | 物理合成大仓 | 多仓协作但不改源仓 | 跨仓关系更多是候选 | 集合只存成员关系 |
当前仓库能从测试和代码直接验证的,主要是结构正确性,不是线上收益。
| 项 | 怎么测 | 现状 |
|---|---|---|
| 叶子/父级边界 | 跑 tests/test_hierarchical_planning.py:信道下一层是叶子,信道根是父级,根目录文件归父级 | 仓库有单测 |
| 规划顺序 | 断言叶子任务排在汇聚任务前 | 仓库有单测 |
| 分析模式 | 无分析器或分析失败时模式为 partial,诊断信息保留 | 代码路径存在,完整 Windows/libclang 环境 待测 |
| 叶子并发 | 配 2/3/4,观察同时只有受限个外部 Agent 进程,父级仍在叶子屏障后 | 待测 |
| 断点继续 | 中断一次生成,改源码后再继续,应被拒绝;不改源码应跳过已完成文档 | 待测 |
| 引用校验 | 故意让回答带不存在的引用编号,应先修复、再失败则拦截 | 待测 |
| 路径沙箱 | 请求 ../ 逃出仓根,应报超出范围 | 代码有 resolve + parents 检查,待测 |
| 生成时延、文档采纳率、问答准确率 | 选一个真实基带仓做基线:全量生成时间、校验失败率、人工抽查引用可打开率 | 待测,不要编数字 |
| 用户规模 / 上线效果 | 仓库与提交记录未给出生产指标 | 待补 |
口播按“能讲清系统设计”来写。仓库提交作者是
qinlianxi,你的个人职责、Owner 边界、是否从 0 到 1、是否上过生产,全部待确认。对外先说“我基于源码把主链路讲清楚”,不要先说“我独立主导上线”。没有测量数据的地方已经写成待测,不要补百分比。
ClangWiki 是给大型 C 和 C++ 仓用的本地知识工作流,不是通用 Agent。它先用 CMake 导出编译数据库,再用静态分析抽出模块、符号和直接调用,按信道下一层叶子自底向上写 Wiki,然后做混合检索和带引用的问答。模型认证留在本机的命令行 Agent,平台不收密钥。父级文档只读直接子文档,候选调用不会被说成确定事实。我还没有可对外报的时延和准确率数字,目前能确认的是事实生产和模型写作是拆开的。
面试官如果让我展开,我会按一条主链路讲。用户先注册本地仓,不复制源码。生成时只做 CMake 配置,拿到编译数据库,不编译被分析项目。分析器在时走完整模式,符号和直接调用可以当编译器事实;分析器没有或失败就降级,词法结果不能冒充确定调用。知识模块把信道根的下一层目录当成最小文档单元,规划器从深到浅排队。叶子可以有限并发地调外部文档 Agent,上下文从标准输入送进去,Agent 默认禁止工具,写完由平台校验章节契约,失败会带原因再修一次。叶子都完成后,父级和仓库首页再串行汇聚。每写完一篇就原子更新断点;中断后新建快照继续,源码或 Schema 变了就拒绝混版本。检索是符号、全文、向量、图扩展四路融合;问答每轮重检索,引用必须能对上本轮证据,对不上就拦截。图谱用来观察耦合和路径,不改人工模块树。个人职责和线上收益待补。
面向大型 C/C++ 代码仓的本地知识平台:用编译器事实驱动自底向上 Wiki,再提供混合检索、带引用问答和代码关系图;模型认证留在本机命令行 Agent,平台不保存密钥,也不修改源码仓。
我把它讲成一个本地代码知识工作流,不是新的通用 Agent,也不是要替代 IDE 或代码托管。大型 C 和 C++ 仓,尤其是通信基带这种按信道拆目录的仓库,人工维护 Wiki 很容易落后,直接把全仓扔给模型又会出现调用关系、职责边界被编出来的情况。所以主链路是先恢复真实编译参数,抽出模块、文件、符号和直接调用,再按叶子到父级生成文档,最后把 Wiki、源码和图关系变成可检索、可引用的上下文。模型认证留在本机命令行 Agent,平台不接收、不保存、不读取密钥。生产用户数和文档采纳率仓库里没有,我不会报数字,只讲这条边界是怎么设计的。
差别不在会不会输出 Markdown,而在事实从哪来、文档按什么粒度长出来。普通生成器通常直接读文件或让模型自己逛仓,调用链和模块边界很容易变成看起来完整的散文。这里先要求编译数据库,分析模式会区分完整和部分,叶子默认落在信道根下一层,父级只能读直接子文档,综合文档如果大段复制子文档正文会被质量门禁拒绝。问答还多了引用校验,没有对上本轮证据就不展示。所以它更像编译器辅助的知识平台,而不是一次 prompt 出一篇介绍。个人有没有从零设计这套边界,待确认。
因为它的确定性建立在编译数据库、翻译单元和 Clang 游标遍历上,这套工具链对 C 和 C++ 最完整。Python 或 JavaScript 没有同等意义的编译命令数据库,硬套会失去“确定调用”这个承诺。领域规则里也能看到物理信道、参考信号这些基带概念,说明它的观察对象是这类仓,但模块树本身按目录生长,不是把 PDSCH 写死成唯一仓库类型。如果面试官问我有没有做过其他语言适配,我如实说当前仓库没有,那是扩展方向,不是已经完成的能力。
如果这个平台收 API Key,它就从知识工具变成凭证代理,日志、配置、备份都可能泄漏。现有设计把认证完全交给本机已经登录好的命令行 Agent,ClangWiki 只拼命令、送标准输入、收标准输出。接口在写入仓库配置或任务覆盖项时,一旦字段名里出现密钥、令牌、密码这类词就直接拒绝。默认文档 Agent 还禁止全部工具,避免它去翻认证文件或改仓库。我能确认的是代码路径这样写了,没有做过专业渗透测试,也不会说“绝对不可能泄漏”。如果我的职责只是使用而不是实现这层隔离,我会把边界讲清楚,不把安全设计说成个人独有成果。
附件路径会引入“模型或 Agent 去仓库外读文件”的授权问题,也更容易和认证文件、数据根目录搅在一起。现在的做法是平台先在任务目录写好有界上下文,再把全文从标准输入喂给一次运行,工作目录保持在被分析源码仓。这样 Agent 需要源码时看的是用户已经注册的仓,需要任务说明时看的是标准输入,不需要额外的外部目录授权。并发叶子任务还会给各自一份临时配置,避免抢同一个配置文件。这个选择牺牲了一点“让模型自己探索”的灵活性,换来的是写作过程可审计。
适配器并不假设可执行文件一定叫同一个通用名字,配置里可以指向参数兼容的企业启动器。它要的是能接受运行子命令、模型参数和 Agent 参数,然后在源码仓目录里跑起来。找不到可执行文件会立刻报错并指出要安装或改路径,而不是静默跳过文档生成。超时、非零退出码和空输出都会变成明确的平台错误,日志分开存标准输出和标准错误,方便现场排障。我没有企业现场的失败率数据,只能讲故障是暴露给用户看的,不是吞掉后假装成功。
文档流程应该是只读的。完整编译可能改构建产物、耗很长时间,还可能因为缺依赖直接失败,这和“理解代码结构”不是同一件事。所以构建管理只验证仓库根目录有 CMake 清单,然后配置出编译数据库,确认里面有文件条目。拿到的是每个翻译单元真实编译参数,够静态分析用。如果配置失败,会走后备编译数据库并降级为部分分析,同时把原因写进日志和进度,不会偷偷维持“完整分析”的说法。这个取舍的代价是:没有真实编译参数时,调用关系必须降级表述。编译成功率和后备命中率待测。
仓库校验现在要求根目录存在 CMake 清单,所以不是任意目录丢进去就能完整跑。这是有意收窄:没有编译数据库,后面的编译器事实承诺就不成立。如果现场只有部分子仓能独立配置,代码里也考虑了后备路径,但会明确告诉用户已经切到部分分析。面试时我会把这说成已知限制,而不是“支持所有构建系统”。若要扩展到其他构建工具,需要先能导出等价的编译命令列表,而不是让模型猜 include 路径。
完整数据库来自 CMake 导出,带有每个文件真实的包含路径、宏和标准。后备路径是在配置失败后扫描源码拼出来的,能让流程继续,但不能保证翻译单元按项目原意被解析。因此后续分析模式会落到部分,词法补充可以给包含和未解析调用,却不能把它们升级成编译器确认的调用链。进度事件里会写明降级原因,避免工作台看起来像“已经完整分析”。我不会把后备模式说成和完整模式同等可靠,这正好是项目要避免的虚假确定。
完整分析表示本机分析器跑通了,并且读到了编译数据库,这时符号和直接调用可以按编译器事实来写。部分分析表示分析器不可用、失败,或只能做词法补充,这时我仍然可以谈文件、宏、未解析调用,但不能把它们讲成运行时一定发生的调用。架构说明写得很干脆:第一版故意不把词法结果伪装成编译器事实。宏展开、函数指针、动态加载、条件编译真实分支和跨线程数据流,都不在确定性范围里。这个分层让文档看起来可能“不完整”,但面试被追问时我能指到模式字段和关系确定性,而不是靠形容词硬撑。
因为静态游标能看到的是一次调用表达式,不一定能唯一解析到运行时目标。目标可能来自表、回调注册,或条件编译后的另一条路径。项目把无法唯一解析的调用留成候选关系,默认确定路径和检索扩展都不会把它当成已经发生的调用。领域规则也只有在多项编译器证据同时满足时才确认分类。这样做会漏掉一些真实的间接调用,但这比画出一条漂亮却无法打开源码位置的假链路更安全。如果面试官继续问我怎么补,我会说那是运行时追踪或人工确认的事,不是当前分析器该悄悄完成的事。
我不会说“证明了百分之百没有”。我能指的是几道闸:任务上下文里写明编译器证据、源码证据、推断和无法确认的使用规则;候选调用只能进待确认段落;输出校验看章节是否齐全,综合文档还检查有没有把子文档正文机械拼接上去;问答阶段再校验引用是不是本轮证据。这些是过程约束,不是最终正确率。若要量化,应该抽一批生成文档,人工标“确定 / 推断 / 编造”比例,仓库里还没有这份评测,所以我只讲机制。
每个文件一篇会碎到没有任务语义,面试和排障都用不上;整个信道一篇又会把编码、调制、映射、参考信号揉在一起,模型上下文和人的阅读都装不下。对 src/phy/pdsch 这类根,下一层 encoder、modulation、mapping 正好是实现单元,也是最小能讲清调用链和异常路径的文档单元。信道根自己变成任务手册,负责路由和故障,不再重复叶子正文。单测里也固定了这个形状:下一层是叶子,信道根是父级,根目录自己的源文件仍归父级当证据。个人有没有拍板这个粒度,待确认;我能确认的是代码和测试现在就是这样约束的。
.c 算谁的?算父级自己的直接源码,不当成又一个叶子。否则会出现“目录既是汇总节点又被自己文件拖成叶子”的混乱。知识构建会给每个文件找所属目录,信道根直接拥有的文件留在父级,子目录才形成叶子。规划父级任务时,这些文件和子文档摘录一起进上下文,但父级的章节契约更强调任务、故障和模块路由,而不是把入口文件再写成另一份工程说明书。面试时我可以用 PDSCH 根目录的入口文件当例子,先画树再讲归属,比空讲概念清楚。
生产环境更推荐反复指定信道根,让框架自动把每个根的直接子目录当叶子。只有目录真的不规则,才用叶子路径覆盖,而且不能和信道根参数同时用,避免两套边界互相打架。这是配置层的互斥,不是运行时猜。代价是使用者必须理解自己的仓长什么样,框架不会仅凭名字盲目切分。默认名字集合里虽然有一批常见信道名,但那只是未显式配置时的辅助,正式环境仍应以显式信道根为准。
因为父级的主要证据是已经写好的直接子文档,再加上本层直接源码和已确认关系。如果叶子还没落盘就写父级,上下文里的子文档要么缺失,要么读到旧快照,汇聚会变成空话或串味。所以流水线先提交全部叶子,并发只发生在叶子之间,叶子屏障过了再按规划顺序串行写信道手册、子系统导航和仓库首页。并发配置只影响同时跑多少个外部写作进程,不改变章节模板,也不单独让旧快照失效。这个“正确性屏障优先于速度”的选择,是我讲并发时一定要主动说的,否则听起来像普通线程池加速。
写作适配器给每个任务一份临时配置文件,指向各自的上下文,而不是大家抢同一个文件名。文档 Agent 默认禁止工具,工作目录是源码仓,真正写 Markdown 的是平台自己。所以并发抢的是外部模型额度和本机 CPU,不是抢平台数据库里的密钥——平台根本不存密钥。任务中心还有另一层限制:模型类任务默认单车道,同一仓库也不能同时跑两个写入任务。叶子并发是生成流水线内部的模块级并行,和平台任务车道要分开讲,否则面试官会以为整站可以无限并行打模型。
因为它的子文档是各顶层模块和架构页,必须等这些导航材料先存在,才能做仓库首读入口。规划器把仓库架构和首页放在层级任务后面,流水线也没有把它们丢进叶子线程池。首页的上下文预算里,子文档占比非常高,源码占比很低,这就是在逼模型做路由而不是再写一遍实现。如果并行写首页,最常见的失败不是慢,而是导航链接指向还不存在的篇目,或为了凑字数复制叶子。质量门禁对综合文档的反复制检查,就是在防这件事。
它不是只截几段源码,而是给整个证据包设总预算。叶子没有子文档,预算更多给符号、关系和源码摘录;信道手册和子系统导航把大头给直接子文档;仓库首页几乎把预算给子文档和少量关系。超过预算的列表会截断并写明“另有多少条未展开”,避免模型以为自己看全了。上下文开头还写死证据使用规则:编译器事实、源码事实、推断、无法确定,以及候选调用不能写成确定运行时调用。所以裁剪既是长度控制,也是表述纪律。裁完之后信息是否够用,需要用真实大仓看断章率,目前待测。
因为上层文档的职责是路由:告诉 Agent 或工程师下一步该进哪一篇,而不是再造一本合订本。如果允许大段复制,生成会变快、看起来也更“全”,但会破坏分层,检索时同一段话出现在三层文档里,引用会失去指向。实现上会给综合文档补子文档导航,并在校验里检查是否机械拼接。模型如果复制,就走一次修复,修复提示会要求精简且章节齐全。这是产品决策,不是文风偏好。我讲的时候会主动说:上层短、下层深,阅读方向和生成方向是反的。
校验会失败,不会把半成品写成当前 Wiki。流水线先尝试从标准输出里挑最后一份结构完整的稿,因为有的模型会在一次运行里吐出多段逐渐完整的结果。如果挑完仍缺节、或围栏没闭合、或看起来像报错文本,就带上失败原因再跑一次,要求只输出最终正文。第二次还失败,任务失败,断点不会把这篇标成完成。用户可以看该任务的标准输出和标准错误定位是模型跑飞还是契约过严。我没有统计过修复成功率,只能讲有一次自动修复,不是无限重试。
长生成可能跑很久,失败后如果原地改同一个快照,很容易把旧源码上的叶子和新源码上的父级拼进同一份 Wiki。所以每完成一篇就原子替换断点文件,记录已完成任务号;用户选择继续时,平台新建一个不可变运行快照,复用已经完成且仍然匹配的分析产物和文档,只跑剩余任务。继续前要核对仓库、源码哈希、生成配置和文档 Schema,不一致就拒绝,要求从头生成。原子写用临时文件再替换,避免进程被杀掉时断点截成半份 JSON。端到端续跑节省了多少时间,待测,但我可以把“为什么不能原地续”讲清楚。
源文件或叶子变化,要重生成受影响叶子和所有父级。公共头变化会按反向包含扩大范围。CMake、编译数据库或模块边界变了,分析本身就不可复用,必须完整分析。只改向量配置,则只重建向量索引。集合成员或成员当前快照变了,重建集合关系和集合 Wiki。没有 Git 时用内容哈希比。面试时我会强调:断点复用看的是“同一版事实”,不是“同一个文件夹还在”。如果我说不清哈希比的是哪些字段,就承认要对照增量规则文档,不现场编一套规则。
任务中心在启动时会把排队中和运行中的任务标成中断,并留下进度事件。它不会假装这些任务还在另一个已经消失的线程里跑。对仓库 Wiki 生成,用户可以从断点继续或重试;继续仍走新建快照那条路。同一仓库在仍有写入任务排队或运行时,不能再开第二个写入任务,避免两个生成互相覆盖当前快照指针。这是本机单用户平台的保守并发,不是分布式调度。我不会把它讲成高可用集群,它就是防把本机数据根写坏。
第一类是根本不像文档:太短、没标题、围栏没闭合、开头就是报错。第二类是结构不完整:缺少该文档类型规定的二级章节,或一次运行里拼了多份稿。第三类是综合文档把子文档当正文粘贴,失去导航职责。处理顺序是先选最后一份完整稿,再补导航卡,再校验,失败则带着原因精简重写一次。选最后一份是因为命令行 Agent 有时会把中间稿和终稿都打到标准输出。门禁不保证内容领域正确,只保证能按契约落盘。领域正确还得靠证据分层和之后的人工抽查,抽查结果待补。
无限重试会在额度、超时和坏上下文上打转,最后可能用更空的套话凑过章节名。一次修复的意义是处理“结构差一点、内容还在同一批证据上”的情况,而不是让模型自己发明缺失事实。修复提示明确要求不增删二级章节、控制篇幅、只输出正文。如果证据本身不够,正确结果应是章节还在、里面写无法确定,而不是编出调用链来过门禁。所以门禁和证据规则是配套的:一个管结构,一个管真实性声明。重试次数是产品上的刹车,不是技术做不到循环。
一级标题后的导航卡由框架确定性补齐,不把这件事交给模型自由发挥。上层文档还要自动补下钻到直接子文档的链接。这样即使用户换模型,导航结构仍稳定,Wiki 页面和导出 ZIP 才能按层级走。模型负责在契约章节里解释本层任务和证据,不负责发明一套新目录。我讲设计时会把“确定性框架 + 受限模型写作”说成同一原则在输出阶段的落点,和前面的分析模式分层是一个思路。
代码问答里用户经常带精确符号或路径,这一下用全文或符号匹配就该置顶;向量擅长的是换一种说法问同一件事。图扩展则能把调用者、被调用者和模块邻居拉进来,这是目录树看不到的。四路结果用倒数排名融合,再给精确标识符、编译器确定性、人工知识和当前范围做小幅加分。向量运行时不可用时,会告警并退化成符号、全文和图,而不是假装语义搜索还在。图侧默认只扩展已确认关系,避免把候选调用助推成高分证据。融合公式是否对所有仓最优,待测,但我能讲清每路补的是哪类失败。
融合解决的是“多路都召回到了,怎么合成一个序”,它并不理解编译器事实比词法更硬。如果只融合,一段写得很像的人工笔记可能压过精确符号定义。所以在融合分之上,对查询里识别出的标识符命中、编译器确定性、人工确认知识再做确定性加分。这是规则,不是又一个模型。加分幅度写得很小,意图是打破平局,而不是让某一路垄断。是否调过这些系数,仓库没有实验记录,我不会编一套“调参提升了多少”。
确定关系数量在大仓里可以非常多,每条边都做嵌入会重复消耗 CPU 和内存,而边的检索价值主要在扩展而不在语义近似。设计是让图块进全文和关系扩展,候选边和已拒绝边默认不进仓库索引,免得“可能调用”被搜成事实。这和图谱可视化是一致的:候选边可以显示,但不进默认确定路径。代价是语义上像的间接关系可能召不回,需要用户换精确符号或先看图。这是容量和诚实性一起做的选择。
它防的是模型写出无法打开的权威感。每轮检索后,平台给证据分配固定编号,前缀区分 Wiki、源码、图谱和人工知识。模型只能引用这些编号。答完先检查引用是否存在、来源能不能打开、有没有把候选关系说成确定调用。不合格就基于同一批证据修一次;还不合格,就返回校验失败,不展示未经验证的模型文本。没有证据时,应直接写根据当前索引无法确定。短会话最多带最近几轮摘要,但每轮都重新检索,避免把过期上下文无限续上。引用可打开率、一次修复成功率待测。
因为用户第二问常常换了符号或模块,旧证据可能已经偏了;把长对话原文续进去,看起来像多轮,其实是在用过期摘录写作。短摘要只保留问题方向,真正的事实仍从当前索引来。这会多花一次检索和一次模型调用,但引用编号始终对应本轮附件,校验才有意义。如果沿用上一轮编号,修复逻辑会和过期证据缠在一起。我把它讲成“会话是短的,证据是新的”,和文档生成里“父级只读直接子文档”是同一类限制上下文的思路。
是会显得严,但这是本机知识工具该有的失败模式。把一段无法核对的答案显示出来,工程师可能顺着错误调用去改代码,代价更高。失败文案会说明是无效引用或没引用可用证据,并拦住展示。排障时还可以看该轮的上下文文件和修复日志。如果现场经常失败,更该查索引是否建好、模型是否遵守指令,而不是把校验关掉。我不会说这套体验已经很好,只能说失败是显式的、可定位的。
模块树是权威导航,按仓库、信道、子模块、文件、符号往下走,来自目录和配置,稳定。关系图是属性图,用来解释调用、读写、类型、回调、文档和领域概念,边带状态、来源和源码位置。社区分析只观察高耦合群、桥接点、环和孤点,不自动改写人工模块边界。跨仓关系按签名一致、公共头、用户别名、名称相似这个顺序建立,最后一档只能当候选。所以图可以回答“谁在目录外还连着谁”,但不能反过来指挥文档树怎么切。把图讲成 LLM 流程图,是我会主动纠正的误解。
核心节点用综合分数找“应该先读的入口符号”,分数考虑连接度、中心性、跨社区跨度和领域权重,它是阅读入口,不是正确性证明。惊喜链接从已确认关系里筛跨模块或跨社区、名字还不像的边,用来发现目录结构之外的隐性耦合。两个视图都限制在局部子图,避免中大型仓一次渲染全部符号。前端默认先按模块或社区聚合,再下钻。如果没有测量过“工程师找到入口的时间是否缩短”,我就说这是导航设计,不作效率承诺。
会持续提示部分分析。词法调用仍在,状态是候选,不能看起来像完整调用链。构建目标和翻译单元如果来自不完整的编译数据库,覆盖率统计也会偏弱。工作台如果把这些边画成实线确定调用,就违背契约,所以规范要求编译器、构建和源码显式关系才是实线,词法和模型结果是虚线并标明候选。我讲图的时候会先说警告条,再说能点开的证据检查器,强调一条逻辑边可以对应多个源码位置,但画布上只聚合成一条边。
它是 SQLite 持久化的本地队列,不是分布式调度。模型相关任务走一条车道,分析索引走另一条 CPU 车道,同一仓库禁止两个写入任务并行。进度通过事件表和服务器推送往前端刷。重启时运行中任务变中断,生成类可以按断点继续。取消是设事件,让当前步骤安全退出,而不是立刻杀半份文件。这样设计是因为数据根就在用户机器上,并发写当前快照指针的危害大于吞吐不足。我不会把它讲成高并发后端经验,除非面试官接受“单机正确性优先”这个表述。吞吐量数字待测。
不会。删除的是注册记录,可选再清平台产物和索引。源码仓路径只是被引用,平台承诺不复制、不合并、不编辑源仓。同步到代码仓是另一条显式用户动作,而且只更新自己清单里的文件;目标目录已有但没有清单时会拒绝覆盖,避免把别人的文档冲掉。面试时我把“只读源仓”和“显式同步”分开,避免听起来像框架会随便在项目里铺文件。有没有在真实项目里执行过同步,待补。
现场常常有多个相关仓,工程师想跨仓搜接口、看候选关系,但不想也不该把源码拷到一处。集合只保存成员关系和集合级 Wiki、索引,源码仍在各自注册路径。跨仓确定关系要求签名和头文件对得上,名字像只能当候选。合成大仓会破坏各自构建系统和权限边界,也会让删除集合变成删除代码的风险操作。这个模型和“多仓 monorepo”不是一回事,我不会用 monorepo 去套。
我会举三条能指到代码的约束。第一,服务默认只监听本机回环地址,前后端同源,它不是开放到局域网的多租户服务。第二,配置和任务覆盖项拒收密钥类字段,模型认证不进数据库。第三,源码查看会把请求路径解析后,检查目标必须落在已注册仓根之下,拒绝目录逃逸。手工 Markdown 不按原始 HTML 执行。这些约束加在一起,说明它按本机单用户工具来设计。我没有做专业安全评审,不会说“已经安全”。若我的角色只是使用或局部开发,我会把实现者和讲述者分开。
即使路径合法,一次把整份大文件读进工作台也会拖垮浏览器,也增加误把整文件贴进对话的风险。接口会夹紧起止行,并给单次读取一个上限。这不是加密,是操作面收敛。和图谱默认局部加载是同一原则:先给能看完的一块,再让用户下钻。如果面试官问缓存投毒或符号链接追出仓外,我需要看解析和父目录检查是否覆盖链接情况,不能在没核对的情况下打包票。当前我能确认的是 resolve 之后做父目录包含判断。
目标环境是 Windows 离线机,运行时再依赖容器、外部图库或在线下载模型,现场会直接挂。属性图和任务状态放在本地 SQLite,向量用本机 ONNX 加本地索引文件,模型缓存只能由准备步骤放进数据根。前端构建产物打进 Python 包,生产机不必再装 Node。这是交付约束倒逼的架构,不是“SQLite 一定比专业图数据库强”。换到超大仓时,单机索引和内存会成为瓶颈,这是已知风险,需要用真实仓测量,不能用架构形容词代替。
按目前仓库证据,我只能先说:我能把生成、检索、图谱和本机工作台的主链路讲清楚,并能指到对应模块和测试。提交记录显示的作者并不是我这台机器上的名字,所以我不会主动说自己是唯一 Owner,也不会说从零带队上线。如果我实际写过其中某段,我会具体到模块:例如层级规划、断点恢复、引用校验或前端图视图,并准备对应 diff 或 PR。没有这些材料时,正确说法是“这是我用来讲编译器辅助文档和有界 Agent 写作的项目”,个人贡献待确认。这样即使被追问 Git 记录,也不会当场崩。
稳妥版是“基于源码精读,能讲清本地 C/C++ 知识平台如何把静态分析、分层 Wiki 和带引用问答串起来”。进取版只有在我能拿出提交、设计和验证记录时才升级成“负责其中某条链路的设计与实现”,并且仍要写清协作边界。进取版绝不能自动加上用户量、时延下降或“全公司采用”。目标岗位如果是 AI 应用,我突出有界上下文、引用闭环和密钥隔离;如果是后端,我突出任务车道、快照和路径沙箱;如果是编译器或基础工具,我突出分析模式和确定/候选分离。岗位变了,强调的支柱变,事实不变。
第一句是有没有真实指标,答案是没有公开测量,只有结构和单测。第二句是个人到底写了哪些模块,答案是待确认,不能用“我”把全仓领走。第三句是部分分析时还敢不敢说“我们提取了完整调用图”,答案是不敢,必须降级。能守住这三句,前面那些机制才像工程,不像包装。建议我先对着导学把主链路画出来,再用这个面经练追问;讲顺之后,再决定要不要把确认过的职责交给经历改写,做成简历条目。
工作台发一个生成任务,接口先拒收密钥字段,再把任务丢进模型车道。流水线校验仓库,配置 CMake 或走后备编译数据库,跑分析器得到符号和关系,再构建模块树并规划文档任务。每个任务先写有界上下文,再子进程调用命令行 Agent,校验通过后写入本次运行的输出目录,同时原子更新断点。叶子并行,汇聚串行。全部完成后,当前有效快照由数据库里的活动运行号指向,索引和图谱是后续独立任务,不和写作混成一次“什么都做”的大事务。我讲时会在白板上画这九步,每步只留一个职责,避免听成一团。
因为失败模式不同,重做成本也不同。生成依赖外部模型和章节契约,最贵也最容易中断;索引依赖切块和可选向量运行时;图谱依赖分析产物和社区计算。拆开后,只改嵌入配置不必重写 Wiki,图分析失败也不必把叶子文档作废。任务中心用不同车道也是这个原因:模型任务和 CPU 任务互不堵死。代价是用户要理解工作台里有多颗按钮,所以完整生成入口会把分析、叶子、父级、入库串起来,选择性维护才暴露细粒度。产品上是“一条主路径,若干补做路径”。
文档说得很清楚,选择性维护只是按文档类型或模块重跑同一套流水线,不是第二套生成器。界面默认收起,就是怕用户以为存在另一套更快但不讲证据的捷径。规划器支持按类型和模块过滤,所以可以只重做某几个叶子再汇聚父级。它仍然走同一份上下文、同一份校验和同一份断点规则。我如果把它讲成“两套系统”,面试官再看源码会对上失败。正确说法是同一引擎的过滤入口。
它是本机单用户的操作面,把多仓注册、快照 Wiki、图下钻、混合检索、带引用问答和任务进度收成中文界面。视图本身不生产编译器事实,也不存密钥。左边深色导航、中间内容、图谱右侧证据检查器,是在落实“先聚合再下钻”的加载策略。生成进度走服务器推送,是因为一次 Wiki 可能很慢,轮询会不好表达阶段。前端构建结果打进 Python 包,是为了离线机不用再装 Node。所以前端的技术点是工作台信息架构和本机交付,不是独立的互联网前端产品。视觉改动有没有提升效率,待测。
三维总览用来建立仓库级直觉,二维工作台用来做能核对证据的分析。规范写明三维是可选概览,默认仍限制局部子图,避免中大型仓一次渲染全部符号。如果只有三维,面试和排障时点不开源码位置;如果只有二维大表,用户不容易先抓住社区和桥接点。两者共用同一份确定/候选关系,不允许三维把候选边画成更“真”的效果。我没有用户研究数据,只把这讲成显示层分工。
导出是把当前有效快照按层级打成 Markdown 或压缩包,离开平台也能读。同步到代码仓是显式把当前快照写进注册仓里的平台目录,并且只更新清单管理的文件,不删除目录里其他人工文档。没有清单还已经有内容时拒绝覆盖。前者是带走,后者是回写,回写默认关闭在“自动行为”之外。这和“平台不擅自改源仓”的承诺一致。有没有项目强制要求文档必须进仓,待补。
我准备证明三件事。第一,能把编译器工具、文档系统和模型调用做成有边界的流水线,而不是“接一个大模型就结束”。第二,能在正确性和速度冲突时做可解释取舍,比如叶子并发、父级串行、候选边不升级。第三,能把检索和问答收成可核对的引用,而不是聊天记录。我不准备用它证明高并发海量用户,也不准备在指标还没测时证明业务收益。若目标岗位更偏平台,我就多讲快照、任务车道和本机安全;若偏 AI 应用,我就多讲有界上下文和校验闭环。个人模块贡献确认后,再决定进取版怎么写。
其他项目如果是业务 Agent 或中转站,强调的是调度、协议和产品功能;这个项目强调的是“事实从编译器来、模型只在有界上下文里写作”。重复的词可能都有检索、文档、Agent,但机制不同。写简历时每个项目只留两到三个支柱,这个项目我会留证据分层、分层编排、引用闭环,把密钥隔离放到追问里,避免所有项目都写“安全”和“RAG”。没有确认的职责一律不写进对外 bullet。若两个项目真用了同一套检索,就只在一个项目展开,另一个改写为业务结果。
缺三类。第一类是个人边界:哪些模块是我改的,要有提交或评审记录。第二类是一次真实仓跑通记录:分析模式、生成篇数、校验失败、断点续跑是否发生过。第三类是抽查:引用能否打开、父级有没有抄叶子、部分分析有没有被误写成完整调用图。有了这三类,才能把“待测”变成有条件的结果句。没有之前,面经只适合练表达,不适合直接变成已确认成果。这也是我建议先讲、再改简历的原因。
| 主题 | 关键路径与内部符号 | 对应正文位置 |
|---|---|---|
| 产品定位与主链路 | README.md;docs/ARCHITECTURE.zh-CN.md | 简介、主问 1、16 |
| 平台数据根与实体 | docs/PLATFORM_ARCHITECTURE.zh-CN.md;clangwiki/platform.py | 主问 13、14 |
| CMake 只配置 | clangwiki/build.py:validate_repository、configure_cmake、create_fallback_compilation_database | 主问 3 |
| 分析模式 | clangwiki/analyzer.py:ClangAnalyzer.analyze;clang-tool/src/main.cpp:Analyzer::visit | 主问 4、12 |
| 叶子边界 | clangwiki/knowledge.py:build_knowledge、_resolve_module_boundaries;tests/test_hierarchical_planning.py | 主问 5 |
| 任务规划 | clangwiki/planner.py:plan_documents、module_document_type | 主问 6、16 |
| 有界上下文 | clangwiki/context.py:build_context 中按文档类型分配 ratios | 主问 7 |
| 叶子并发与断点 | clangwiki/pipeline.py:GenerationPipeline._generate_documents、_write_checkpoint | 主问 6、8 |
| 模型适配与禁工具 | clangwiki/opencode.py:OpenCodeRunner.run_prompt、OPENCODE_CONFIG、permission: deny | 主问 2 |
| 输出门禁 | clangwiki/output.py:select_final_complete_document、validate_markdown、ensure_navigation_card | 主问 7、9 |
| 拒收密钥 | clangwiki/api.py:_reject_secrets | 主问 2、14 |
| 任务车道 | clangwiki/jobs.py:PersistentJobManager、MODEL_KINDS、resume | 主问 8、13 |
| 继续生成 | clangwiki/api.py:resume_run | 主问 8 |
| 混合检索 | clangwiki/indexing.py:IndexService.search 中四路召回与 1/(60+rank) | 主问 10 |
| 问答引用 | clangwiki/rag.py:RagService.ask、validate_citations、CITATION_RE | 主问 11 |
| 源码沙箱 | clangwiki/wiki.py:source_snippet 的 resolve 与 parents 检查 | 主问 14 |
| 图谱契约 | docs/CODE_KNOWLEDGE_GRAPH.zh-CN.md;clangwiki/graph.py、clangwiki/graph_analytics.py | 主问 12 |
| 工作台视图 | frontend/src/App.tsx;frontend/src/GraphWorkbench.tsx | 主问 17 |
| 检索/图谱规范 | docs/RAG_AND_RETRIEVAL.zh-CN.md | 主问 10、11 |
| CLI 入口 | clangwiki/cli.py:serve / generate / ask / graph | 90 秒口播、主问 16 |