首页
/ graphify VS Code /graphify 技能剧本详解:九步流水线、manual-paste 派发与图构建守护机制

graphify VS Code /graphify 技能剧本详解:九步流水线、manual-paste 派发与图构建守护机制

2026-09-06 20:09:03作者:钟日瑜

graphify 把任意目录的代码、文档、论文、图片、视频编译成一张可查询的知识图谱,并在构建全程保留 EXTRACTED / INFERRED / AMBIGUOUS 三级诚实审计链。skill-vscode.md 是该工具面向 VS Code 宿主 Agent 的完整技能剧本(skill playbook):它规定了 /graphify 命令的全部用法、从解释器探测到图谱导出的九步流水线,以及查询、增量更新与提交钩子的执行细则。读完本文,你可以完整复述 graphify 的构建流程与缓存策略,理解为什么纯代码语料不需要 API key,并掌握 shrink-guard、manifest 盖章等防止图谱静默损坏的关键设计。

这是什么文件:VS Code 宿主的生成产物

skill-vscode.md 不是手写的普通文档,而是 skillgen 构建工具渲染出的提交型产物。仓库中的 platforms.toml 声明了 vscode 平台的装配方式:

  • bucket = "split":采用"精简核心 + references 侧车"的结构,核心正文渲染为 skill-vscode.md,配套参考资料渲染到 skills/vscode/references/ 目录(add-watch、exports、extraction-spec、github-and-merge、hooks、query、transcribe、update 共 8 个文件);
  • dispatch = "manual-paste":VS Code 宿主没有并行 Agent/Task API,语义抽取子代理由人手动派发并粘贴结果——这正是正文 Step B2 中那段 "No automated subagent tool" 注释的来源(对应片段 manual-paste.md);
  • extraction = "verbose":使用详细版抽取规范。

生成器 gen.py 支持 --check(字节级漂移检测)与 --bless(刷新期望产物),保证所有宿主平台的技能文件与源片段保持一致。

Usage:/graphify 命令全量参考

剧本开头的 ## Usage 块是 /graphify --help 的逐字输出内容,也是整个技能的入口契约。完整命令面如下(原文档第 12–43 行):

/graphify                                             # full pipeline on current directory (HTML viz; add --obsidian for a vault)
/graphify <path>                                      # full pipeline on specific path
/graphify https://github.com/<owner>/<repo>           # clone repo then run full pipeline on it
/graphify https://github.com/<owner>/<repo> --branch <branch>  # clone a specific branch
/graphify <url1> <url2> ...                           # clone multiple repos, build each, merge into one cross-repo graph
/graphify <path> --mode deep                          # thorough extraction, richer INFERRED edges
/graphify <path> --update                             # incremental - re-extract only new/changed files
/graphify <path> --directed                            # build directed graph (preserves edge direction: source→target)
/graphify <path> --whisper-model medium                # use a larger Whisper model for better transcription accuracy
/graphify <path> --cluster-only                       # rerun clustering on existing graph
/graphify <path> --no-viz                             # skip visualization, just report + JSON
/graphify <path> --html                               # (HTML is generated by default - this flag is a no-op)
/graphify <path> --svg                                # also export graph.svg (embeds in Notion, GitHub)
/graphify <path> --graphml                            # export graph.graphml (Gephi, yEd)
/graphify <path> --neo4j                              # generate graphify-out/cypher.txt for Neo4j
/graphify <path> --neo4j-push bolt://localhost:7687   # push directly to Neo4j
/graphify <path> --falkordb                           # generate graphify-out/cypher.txt for FalkorDB
/graphify <path> --falkordb-push falkordb://localhost:6379   # push directly to FalkorDB
/graphify <path> --mcp                                # start MCP stdio server for agent access
/graphify <path> --watch                              # watch folder, auto-rebuild on code changes (no LLM needed)
/graphify <path> --wiki                               # build agent-crawlable wiki (index.md + one article per community)
/graphify <path> --obsidian --obsidian-dir ~/vaults/my-project  # write vault to custom path (e.g. existing vault)
/graphify add <url>                                   # fetch URL, save to ./raw, update graph
/graphify add <url> --author "Name"                   # tag who wrote it
/graphify add <url> --contributor "Name"              # tag who added it to the corpus
/graphify query "<question>"                          # BFS traversal - broad context
/graphify query "<question>" --dfs                    # DFS - trace a specific path
/graphify query "<question>" --budget 1500            # cap answer at N tokens
/graphify path "AuthModule" "Database"                # shortest path between two concepts
/graphify explain "SwinTransformer"                   # plain-language explanation of a node

按功能分组理解:

类别 命令/参数 说明
构建范围 无参 / <path> / GitHub URL / 多 URL 默认对当前目录做完整流水线;URL 触发 Step 0 克隆(多 URL 会合并为一张跨仓库图)
抽取模式 --mode deep--whisper-model 深度抽取产生更丰富的 INFERRED 边;更大的 Whisper 模型提升转写准确率
增量 --update--cluster-only 只重抽新增/变更文件;仅在已有图上重跑社区发现
图形态 --directed 构建 DiGraph 保留 source→target 方向,否则默认无向 Graph
导出 --svg --graphml --neo4j(-push) --falkordb(-push) --wiki --mcp 对应 cli.py 中的 export 子命令 html/callflow-html/obsidian/wiki/svg/graphml/neo4j/falkordb;push 变体直接写入图数据库
可视化 --no-viz--html--obsidian [--obsidian-dir <path>] HTML 默认生成(--html 是 no-op);--obsidian 显式开启才逐节点生成 vault 文件
运维 --watchadd 监听目录自动重建(无需 LLM);抓取 URL 进语料并更新图
查询 query--dfs--budget N)、pathexplain BFS 广域上下文 / DFS 路径追踪 / 节点白话解释

快速路径:先查已有图,而不是重建

剧本在"必须执行的动作"里定义了一条快速路径:执行任何检测之前,先检查 graphify-out/graph.json(相对于当前工作目录,即项目根)是否存在。若存在、且用户请求是关于代码库的自然语言问题("How does X work?"、"What calls Y?"),而不是显式重建命令(--update--cluster-only 或裸路径/URL):

  1. 跳过 Step 1–5,直接进入查询流程;
  2. 立即执行 graphify query "<question>"
  3. 不跑 detect、不检查语料规模、不要求用户缩小范围——"The graph is already built — use it."

未给路径时默认用 .,不得反问用户;路径若以 https://github.com/ 开头则先走 Step 0 克隆再解析为本地路径。查询侧要求先把问题对图谱自身词表做展开(vocab expansion),避免措辞不匹配导致答案退化成噪声;回答只能基于图输出,引用具体事实时要引用 source_location。遍历模式、--budget 上限、NetworkX 内联兜底、save-result 反馈与 path/explain 流程,完整定义在 query.md 中。

Step 0–2:GitHub 克隆、解释器自举与语料检测

Step 0 仅对 URL / 多路径生效

只有当输入是一个或多个 https://github.com/... URL,或需要合并的多个本地子目录时才执行克隆与跨仓库合并,细则见 github-and-merge.md;纯本地路径直接跳过。

Step 1 解释器探测与安装

这是整份剧本里最长的一段 shell 逻辑,目的是在 uv tool、pipx、venv、系统安装四种安装形态下找到能 import graphify 的解释器,并按优先级尝试:uv tool run --from graphifyy → 读 graphify 二进制的 shebang(带字符集校验)→ 回退 python3。导入失败则 uv tool install --upgrade graphifyypip install graphifyy(必要时 --break-system-packages)。最后写两个持久化侧车:

  • graphify-out/.graphify_python:解释器绝对路径,后续所有 bash 块都必须用 $(cat graphify-out/.graphify_python) 替换 python3
  • graphify-out/.graphify_root:扫描根绝对路径,供无参 graphify update 定位上次扫描目录。

Step 2 用 detect() 生成检测 JSON,并执行三道规模闸门

$(cat graphify-out/.graphify_python) -c "
import json
from graphify.detect import detect
from pathlib import Path
result = detect(Path('INPUT_PATH'))
# Write the sidecar from Python, not a shell redirect, so the same block renders
# on PowerShell hosts without console-encoding drift (#2528).
Path('graphify-out/.graphify_detect.json').write_text(json.dumps(result, ensure_ascii=False), encoding=\"utf-8\")
print(f'Detected {result[\"total_files\"]} files')
"

实现落点在 detect.pydetect()(支持 gitignore 感知、符号链接策略、Google Workspace 等参数)。检测 JSON 由 Python 写入而非 shell 重定向,是为 PowerShell 宿主避免控制台编码漂移(#2528)。

脚本要求静默读取 JSON 并呈现干净摘要(0 文件类别省略):

Corpus: X files · ~Y words
  code:     N files (.py .ts .go ...)
  docs:     N files (.md .txt ...)
  papers:   N files (.pdf ...)
  images:   N files
  video:    N files (.mp4 .mp3 ...)

随后按结果行动,这里有三道闸门:

  • total_files == 0:停止,输出 "No supported files found in [path].";
  • skipped_sensitive 非空:报告数量与文件名,让被误判为敏感(凭据)的源文件可见、可改名(#2106);
  • total_words > 2,000,000total_files > 500:展示警告,然后按 detect JSON 中的 scan_root(解析后 INPUT_PATH 的绝对路径),把 code/document/paper/image/video 全部文件列表拼接、剔除 scan_root + "/graphify-out/" 前缀的转换产物,按第一级子目录计数排序,展示 top 5 并等待用户选择再继续;若全部文件都在 (root) 无子目录,则改为建议 --no-cluster 跳过昂贵的聚类步骤。

测试覆盖见 test_detect.py

Step 2.5 音视频转写

仅当 detect 返回的 video 数量大于 0 时执行:按 transcribe.md 先把音视频转写成文本,再当作 document 进入 Step 3。零视频文件则整步跳过。

Step 3:AST 与语义抽取并行,代码语料零 API key

这一步分为结构化抽取(确定性、免费)与语义抽取(LLM、耗 token)两部分,剧本明确要求二者并行派发(可省 5–15 秒),在 Part C 汇合。

零 API key 原则

这是剧本中反复强调的契约:graphify 不需要 API key,绝不允许 Agent 向用户索要或被 key 阻塞。代码走 AST 抽取,完全不需要 LLM;纯代码语料(最常见的 /graphify .)会整体跳过 Part B。语义抽取仅在已设置 GEMINI_API_KEY/GOOGLE_API_KEY 时使用 Gemini(graphify.llm.extract_corpus_parallel(files, backend="gemini"),默认模型 gemini-3-flash-preview,可用 GRAPHIFY_GEMINI_MODEL--model 覆盖,扩展安装为 pip install 'graphifyy[gemini]');否则宿主 Agent 本身就是 LLM。graphify 明确不读取 ANTHROPIC_API_KEYOPENAI_API_KEY 或其他供应商 key——脚本原文直言:如果你发现自己正要为缺失的 API key 而提示或停下,"that is a misread of this skill"。

Part A:AST 结构化抽取

$(cat graphify-out/.graphify_python) -c "
import sys, json
from graphify.extract import collect_files, extract
from pathlib import Path
import json

code_files = []
detect = json.loads(Path('graphify-out/.graphify_detect.json').read_text(encoding=\"utf-8\"))
for f in detect.get('files', {}).get('code', []):
    code_files.extend(collect_files(Path(f)) if Path(f).is_dir() else [Path(f)])

if code_files:
    result = extract(code_files, cache_root=Path('INPUT_PATH'))
    Path('graphify-out/.graphify_ast.json').write_text(json.dumps(result, indent=2, ensure_ascii=False), encoding=\"utf-8\")
    print(f'AST: {len(result[\"nodes\"])} nodes, {len(result[\"edges\"])} edges')
else:
    Path('graphify-out/.graphify_ast.json').write_text(json.dumps({'nodes':[],'edges':[],'input_tokens':0,'output_tokens':0}, ensure_ascii=False), encoding=\"utf-8\")
    print('No code files - skipping AST extraction')
"

实现落点为 extract.pyextract()extract.pycollect_files()cache_root 指定后抽取结果参与文件级缓存。

Part B:语义抽取(缓存 → 分块 → 派发 → 收集)

快速路径:若 document/paper/image 均为 0(纯代码语料),必须先写出空语义文件再进 Part C——因为 Part C 无条件读取 .graphify_semantic.json,缺文件会 FileNotFoundError

$(cat graphify-out/.graphify_python) -c "
import json
from pathlib import Path
Path('graphify-out/.graphify_semantic.json').write_text(json.dumps({'nodes':[],'edges':[],'hyperedges':[],'input_tokens':0,'output_tokens':0}), encoding='utf-8')
"

Step B0 先查抽取缓存。只有内容文件进入语义通道——代码已被 Part A 的 AST 覆盖,把每类文件都扁平化进语义通道会让子代理重读所有源码(#1392);视频则已在 Step 2.5 转写为文档:

$(cat graphify-out/.graphify_python) -c "
import json
from graphify.cache import check_semantic_cache
from pathlib import Path

detect = json.loads(Path('graphify-out/.graphify_detect.json').read_text(encoding=\"utf-8\"))
all_files = [f for cat in ('document', 'paper', 'image') for f in detect['files'].get(cat, [])]

cached_nodes, cached_edges, cached_hyperedges, uncached = check_semantic_cache(all_files, root='INPUT_PATH', prompt_file='SPEC_PATH')

if cached_nodes or cached_edges or cached_hyperedges:
    Path('graphify-out/.graphify_cached.json').write_text(json.dumps({'nodes': cached_nodes, 'edges': cached_edges, 'hyperedges': cached_hyperedges}, ensure_ascii=False), encoding=\"utf-8\")
else:
    Path('graphify-out/.graphify_cached.json').unlink(missing_ok=True)
Path('graphify-out/.graphify_uncached.txt').write_text('\n'.join(uncached), encoding=\"utf-8\")
print(f'Cache: {len(all_files)-len(uncached)} files hit, {len(uncached)} files need extraction')
"

关键细节:SPEC_PATHextraction-spec.md绝对路径,它既是子代理的抽取提示词,也是缓存条目的归属标记——graphify 升级若改动提示词,旧条目会被重新抽取而非重放(#1939)。B0 与 B3 必须传入同一个 SPEC_PATH。缓存实现见 cache.pycheck_semantic_cache()cache.pysave_semantic_cache(),行为由 test_cache.py 覆盖。

Step B1 分块:读取 .graphify_uncached.txt,每块 20–25 个文件;图片单独成块(视觉需要独立上下文);同目录文件尽量聚到同一块以提升跨文件关系命中率。派发前先打印时间估算:ceil(uncached_non_code_files / 22) 个代理、每批约 45 秒,输出 "Semantic extraction: ~N files → X agents, estimated ~Ys"。

Step B2 派发与粘贴(VS Code 特化):剧本对 Claude Code 类宿主要求"必须使用 Agent 工具,逐文件自读慢 5–10 倍";而 VS Code 变体的措辞是——宿主没有并行 Agent/Task API,按宿主允许的方式(新会话、并行分屏)逐块派发,然后把每个响应粘贴回块文件:

# After pasting a subagent's JSON for chunk N, save it (replace N and PASTED_JSON):
PROJECT_ROOT=$(pwd)  # cwd — where Part C globs graphify-out/ (NOT .graphify_root/scan dir, #1392)
cat > "${PROJECT_ROOT}/graphify-out/.graphify_chunk_0N.json" <<'CHUNK_JSON'
PASTED_JSON
CHUNK_JSON

块 JSON 一律落在当前工作目录graphify-out/ 下(Part C 在这里做 glob,而非扫描目录,#1392)。子代理提示词本体(JSON schema、节点 ID 规则、置信度评级、hyperedge 与视觉规则)在 extraction-spec.md,仅在至少一个块含 doc/paper/image 时才加载,并需替换 FILE_LIST、CHUNK_NUM、TOTAL_CHUNKS、DEEP_MODE 四个占位符——--mode deep 必须一路透传,不得丢失。

Step B3 收集、缓存与合并:以块文件存在且含合法 nodes/edges JSON 作为成功信号;文件缺失大概率是子代理被以只读(Explore 类型)派发,必须打印警告并要求改用 general-purpose 代理,禁止静默跳过;失败或非法 JSON 的块打印警告后跳过,但超过半数块失败就停止并让用户重跑。合并前还要把 Agent 工具结果 usage 字段里的真实 token 数写回块 JSON(块文件本身恒为占位 0)。随后依次:

  1. glob graphify-out/.graphify_chunk_*.json 合并出 .graphify_semantic_new.json
  2. save_semantic_cache(..., prompt_file='SPEC_PATH') 把新结果写入缓存(读旧条目用什么提示词、写新条目就必须用什么提示词,#1939);
  3. 缓存 + 新结果按节点 id 去重合并进 .graphify_semantic.json,打印 Extraction complete - N nodes, M edges (X from cache, Y new)
  4. 清理 .graphify_cached.json.graphify_uncached.txt.graphify_semantic_new.json

Part C:AST + 语义合并

# AST nodes first, semantic nodes deduplicated by id
ast = json.loads(Path('graphify-out/.graphify_ast.json').read_text(encoding=\"utf-8\"))
sem = json.loads(Path('graphify-out/.graphify_semantic.json').read_text(encoding=\"utf-8\"))
seen = {n['id'] for n in ast['nodes']}
merged_nodes = list(ast['nodes'])
for n in sem['nodes']:
    if n['id'] not in seen:
        merged_nodes.append(n)
        seen.add(n['id'])
merged_edges = ast['edges'] + sem['edges']
merged_hyperedges = sem.get('hyperedges', [])
# → graphify-out/.graphify_extract.json

合并顺序体现"确定性优先":AST 节点在前,语义节点按 id 去重补齐;边直接拼接;hyperedges 全部来自语义侧;token 计数继承自语义侧。

Step 4:建图、聚类、分析,以及 shrink-guard

Step 4 之前要替换 IS_DIRECTED--directedTrue 构建 DiGraph,否则默认无向 Graph)——和 INPUT_PATH 一样是占位符,不能留字面量进代码。核心块:

G = build_from_json(extraction, root='INPUT_PATH', directed=IS_DIRECTED)
# Guard BEFORE any write: an empty extraction must not clobber a good graph.json /
# GRAPH_REPORT.md / analysis sidecar. Check immediately after build (#1392).
if G.number_of_nodes() == 0:
    print('ERROR: Graph is empty - extraction produced no nodes.')
    print('Possible causes: all files were skipped, binary-only corpus, or extraction failed.')
    raise SystemExit(1)
communities = cluster(G)
cohesion = score_all(G, communities)
gods = god_nodes(G)
surprises = surprising_connections(G, communities)
questions = suggest_questions(G, communities, labels)

wrote = to_json(G, communities, 'graphify-out/graph.json')
if not wrote:
    print('ERROR: refused to shrink graphify-out/graph.json (existing graph has more nodes; #479).')
    print('If this shrink is intentional (you deleted files), re-run a full build with --force.')
    raise SystemExit(1)
report = generate(G, communities, cohesion, labels, gods, surprises, detection, tokens, 'INPUT_PATH', suggested_questions=questions)
Path('graphify-out/GRAPH_REPORT.md').write_text(report, encoding=\"utf-8\")
# + graphify-out/.graphify_analysis.json (communities/cohesion/gods/surprises/questions)

这段代码链上每个函数都能在仓库中逐一找到实现与测试:

  • build_from_json()build.pyroot= 参数把 source_file 相对化到与 --update 相同的基准,保证全量构建与增量更新在重抽时节点 key 不漂移(#1361);
  • cluster() / score_all()cluster.pycluster.py,分别做社区发现与内聚度打分,test_cluster.py 覆盖;
  • god_nodes() / surprising_connections() / suggest_questions()analyze.pyanalyze.pyanalyze.py,由 test_analyze.py 覆盖;
  • generate()report.py 生成 GRAPH_REPORT.md;
  • to_json()export.py返回 bool 实现 #479 shrink-guard——新图节点数小于既有 graph.json 时返回 False 且不写盘。剧本要求"先导出、再写报告":只有图真正写入成功,才允许写 GRAPH_REPORT.md 与分析侧车,确保报告永远不会描述一份 graph.json 里没有的图(#1392)。守护行为另有专项测试 test_build_merge_shrink_guard.py

空图守卫放在任何写盘之前:0 节点直接退出,不污染既有产物。此步打印 ERROR: Graph is empty 时,必须停下并告知用户,禁止继续进入标注或可视化。

Step 4.5–5:只读健康检查与社区标注

Step 4.5 图谱健康检查

一个非破坏性的完整性门,在标注前诊断三类静默损坏——边坍缩、悬空/缺失端点、自环(正是增量更新与 AST/LLM id 失配的典型病灶):

from graphify.diagnostics import diagnose_extraction, format_diagnostic_report
summary = diagnose_extraction(extraction, directed=IS_DIRECTED, root='INPUT_PATH')
print(format_diagnostic_report(summary))
# 汇总 dangling / missing / self-loop / collapsed 边数,打印 GRAPH HEALTH WARNING 或 OK

实现见 diagnostics.pydiagnose_extraction()diagnostics.pyformat_diagnostic_report()。健康检查只读、从不中止:出现 GRAPH HEALTH WARNING 时图仍可用,但依据 Honesty Rules 必须把完整性问题暴露在最终摘要里。

Step 5 为社区写人类可读标签

读取 .graphify_analysis.json,对每个社区的节点标签归纳出 2–5 词的白话名(如 "Attention Mechanism"、"Training Pipeline"),然后重建图、用真实标签重新生成建议问题(标签影响问题措辞)、重写报告、把标签写入 .graphify_labels.json 供可视化器使用,并带 community_labels=labels 重新导出,让 graph.json 的节点携带策展后的 community_name(#2490)。由于与 Step 4 使用同一份 extraction,shrink-guard 按节点数必然通过;若仍被拒绝,把 guard 消息原样呈现,不得 --force 强推。

Step 6 及后续:HTML 恒开、其余导出按需

  • HTML 恒开(除非 --no-viz):graphify export html,图超过 5000 节点时自动聚合到社区视图;
  • Obsidian 仅限显式 --obsidiangraphify export obsidian,可用 --dir ~/vaults/my-project 写入自定义 vault,因为每节点生成一个文件;
  • Steps 6b–8(wiki、Neo4j/FalkorDB 生成与 push、SVG、GraphML、MCP、token 压缩基准——后者在 total_words > 5000 时触发)仅在其 flag 出现时执行;默认运行全部跳过。逐项说明在 exports.md。注意:--wiki 要在 Step 9 清理之前导出,那时 .graphify_labels.json 尚在。

CLI 侧对应 cli.py 的 export 子命令分派(html、callflow-html、obsidian、wiki、svg、graphml、neo4j、falkordb,neo4j/falkordb 支持 push 与口令环境变量)。

Step 9:manifest 盖章、成本追踪与收尾

收尾步骤完成三件事,核心是 manifest 的选择性盖章

from graphify.detect import save_manifest
from graphify.cli import _stamped_manifest_files

_corpus = detect.get('all_files') or detect['files']
_manifest_files = _stamped_manifest_files(_corpus, extract, Path('INPUT_PATH'))
# 只给“实际产出了输出”的语义文件盖章;失败/遗漏的块保持未盖,下次 --update 会重新排队(#2015)
# 本运行已派发但未盖章的语义文件清掉旧 semantic_hash,避免被当作未变更(#1948)
save_manifest(_manifest_files, root='INPUT_PATH', scan_corpus=_scan, clear_semantic=_cleared or None)
# → 更新 graphify-out/cost.json 累计 token 成本;打印本次/历史用量

规则要点:

  • 代码文件恒盖章(AST 确定性),文档/论文/图片只有真正产出才盖章——被检测到但块失败的文件必须保持未盖章,否则下次 --update 会把它当完成态、内容永久丢失(#2015);
  • root= 把 manifest key 相对化到扫描根,使磁盘上的 manifest 可跨克隆/机器移植,--update 才能命中缓存文件而非全部未命中(#1417);
  • scan_corpus 传原始全量语料(而非盖章过滤子集),让根目录内新被排除的文件被正常丢弃而不是伪装成删除,未触碰文件的历史行保留(#1908);
  • cost.json 按运行追加 {date, input_tokens, output_tokens, files} 并累计总量。

最后删除 .graphify_detect/extract/ast/semantic/analysis.json 与所有 .graphify_chunk_*.json.needs_update,向用户报告产物清单:

Graph complete. Outputs in PATH_TO_DIR/graphify-out/

  graph.html            - interactive graph, open in browser
  GRAPH_REPORT.md       - audit report
  graph.json            - raw graph data
  obsidian/             - Obsidian vault (only if --obsidian was given)

随后只粘贴报告中的 God Nodes、Surprising Connections、Suggested Questions 三节(不粘全报告),并主动挑出跨越最多社区边界或桥接节点最出人意味的建议问题,以 "The most interesting question this graph can answer: [question]. Want me to trace it?" 邀请探索。剧本的收束语是:"The graph is the map. Your job after the pipeline is to be the guide."——回答要沿着图结构展开(哪些节点相连、跨越了哪些社区边界、路径揭示了什么),每轮以自然的追问结尾,让会话像导航而非一次性报告。

子命令护栏与增量/查询/追加/监听

解释器护栏:执行 --update--cluster-onlyquerypathexplainadd 任何子命令前,先检查 graphify-out/.graphify_python 是否存在;缺失(例如用户删了 graphify-out/)时按 shebang → python3 的顺序重新解析解释器并回写,再运行子命令。

  • --update / --cluster-only:均为非默认子命令——前者只重抽新增/变更文件,后者在既有图上重跑聚类;两条流程的完整 runbook 在 update.md。增量更新的设计与去重策略另有专项文档 incremental-updates-dedup 设计实施计划,测试见 test_incremental.py
  • /graphify query:图存在时从图回答而不是重建;CLI 不可用时回退到对 graph.json 的内联 NetworkX 遍历。参数与流程详见 query.mdtest_query_cli.py
  • /graphify add--watch:不属于默认构建;URL 抓取与目录监听的完整流程在 add-watch.md
  • 提交钩子与 CLAUDE.md 集成:安装 post-commit 自动重建钩子、把 graphify 接入项目 CLAUDE.md 的说明在 hooks.md

Honesty Rules:五条不可妥协的输出纪律

剧本末尾的 Honesty Rules 是整份技能的行为底线,也是 graphify 差异化定位的浓缩:

  • Never invent an edge. 不确定就用 AMBIGUOUS——边必须可审计;
  • Never skip the corpus check warning. 超大语料警告不可省略;
  • Always show token cost in the report. 语义抽取成本必须显式呈现;
  • Never hide cohesion scores behind symbols. 内聚度给原始数字,不用符号替代;
  • Never run HTML viz on a graph with more than 5,000 nodes without warning. 大图可视化必须先行警告。

源码级索引:文档声明到实现的对应关系

剧本声明 实现位置 测试/佐证
detect() 语料检测与 manifest detect.pydetect.py save_manifest test_detect.py
collect_files / extract AST 抽取 extract.pyextract.py test_extract.py
语义缓存读写(prompt 归属) cache.pycache.py test_cache.py
build_from_json(root, directed) build.py test_build_merge_shrink_guard.py
cluster / score_all cluster.pycluster.py test_cluster.py
god_nodes / surprising_connections / suggest_questions analyze.py 起三函数 test_analyze.py
to_json shrink-guard(返回 bool) export.py test_build_merge_shrink_guard.py
diagnose_extraction / format_diagnostic_report diagnostics.pydiagnostics.py test_multigraph_diagnostics.py
report.generate report.py test_report.py
_stamped_manifest_files 选择性盖章 cli.py test_incremental.py
VS Code 平台装配(manual-paste、verbose) platforms.tomlgen.py manual-paste.md

一句话总结这份剧本的设计哲学:把"LLM 参与的部分"压缩到不可压缩的最小(仅内容文件的语义抽取),把其余一切(解释器、检测、AST、缓存、建图、守护、审计、成本)都写成确定性步骤与可重放文件——而 VS Code 变体与通用版的唯一实质差异,就是 B2 从"Agent 工具派发"退化为"手动派发 + 粘贴",其余九步完全一致。

登录后查看全文
热门项目推荐
相关项目推荐

项目优选

收起
kernelkernel
deepin linux kernel
C
33
18
ops-transformerops-transformer
本项目是CANN提供的transformer类大模型算子库,实现网络在NPU上加速计算。
C++
1.13 K
2.75 K
pytorchpytorch
作为 Ascend for PyTorch 社区的核心组件,TorchNPU 是昇腾专为 PyTorch 打造的深度学习适配插件,使 PyTorch 框架能够直接调用昇腾 NPU,为开发者提供昇腾 AI 处理器的超强算力。
Python
857
1.35 K
docsdocs
暂无描述
Markdown
897
5.8 K
kernelkernel
openEuler内核是openEuler操作系统的核心,既是系统性能与稳定性的基石,也是连接处理器、设备与服务的桥梁。
C
529
593
ops-nnops-nn
本项目是CANN提供的神经网络类计算算子库,实现网络在NPU上加速计算。
C++
915
1.83 K
jiuwenswarmjiuwenswarm
JiuwenSwarm 是一款基于openJiuwen开发的智能AI Agent,它能够将大语言模型的强大能力,通过你日常使用的各类通讯应用,直接延伸至你的指尖。
Python
3.58 K
1.01 K
ops-mathops-math
本项目是CANN提供的数学类基础计算算子库,实现网络在NPU上加速计算。
C++
1.35 K
1.46 K
cann-learning-hubcann-learning-hub
CANN 学习中心仓,支持在线互动运行、边学边练,提供教程、示例与优化方案,一站式助力昇腾开发者快速上手。
Jupyter Notebook
1.01 K
515
AscendNPU-IRAscendNPU-IR
AscendNPU-IR是基于MLIR(Multi-Level Intermediate Representation)构建的,面向昇腾亲和算子编译时使用的中间表示,提供昇腾完备表达能力,通过编译优化提升昇腾AI处理器计算效率,支持通过生态框架使能昇腾AI处理器与深度调优
C++
547
388