# Changelog All notable changes to this project are documented in this file. ## [Unreleased] ## [3.0.0] — 2026-10-13 ### Major — Token-First Surgical Engine (Pillars 1–4) - **Pillar 1: Precise Context Slicer & AST Skeleton Folding (`gf_read`)**: - `src/v3/slicer.ts` & `ast-engine.ts`: Folds non-target function bodies (`/* ... N lines folded ... */`) while preserving 100% of imports, types, interfaces, and exact 1-based line numbers. - Type-Closed Symbol Slicing: Automatically extracts target symbols + referenced `interface`/`type`/`enum` definitions from local or imported files into a compact, zero-noise plain-text block. - **Pillar 2: Blast-Radius Call-Site Slicing & Instant Static Guard (`gf_edit`)**: - `src/v3/blast-radius.ts`: Automatically attaches cross-repo 3-line call-site micro-snippets (`[Blast Radius]`) around target symbols so callers can be updated in a single turn. - `src/v3/surgical-edit.ts`: In-place symbol or line-range replacement with instant zero-LLM AST syntax checking (automatic rollback on syntax error) and caller arity verification. - **Pillar 3: Deterministic Execution & Stdout Dehydration (`gf_exec`)**: - `src/v3/dehydrator.ts`: Fast 2-hop reverse import Diff-to-Test Impact Router locates affected test files from git diff in <15ms. - Output Dehydrator: Compresses passing builds/test suites to a 1-line `PASS` receipt (-99% tokens) and extracts focused assertion failures + inlined 5-line failure source context for failing runs. - **Pillar 4: Auto-Compiled Executable Trajectory Macros (`gf_macro`)**: - `src/v3/macro-engine.ts`: Records tool trajectories; automatically compiles recurring multi-target reads (`context-bundle`) and verification command sequences (`command-pipeline`) into standalone `.graphflow/macros/*.mjs` scripts and 1-step executable macros. - **MCP Schema Overhead Slashed by 92%**: - Replaced 10 bulky legacy MCP tool definitions (5,897 tokens/turn) with 4 surgical tools (444 tokens/turn). - Slimmed down all 10 agent surface rules and `SKILL.md` by 82%–91% and removed toxic `assistantReply` echo loops. ## [2.3.0] — 2026-10-12 ### Added — retrieval quality (community/paper-informed wave) - **BM25 hybrid ranking**: `src/graph/bm25.ts` (BM25F field weights symbol×3 / path×2 / summary×1, k1=1.2, b=0.75). `searchGraphNodes` / `querySymbolGraph` / `computeAnchorRelevance` now score with corpus IDF (generic tokens like `utils`/`index` demoted automatically); lexical + vector channels fuse via RRF (`rrfFuse`). Without a corpus index the anchor-relevance scorer is byte-identical to the previous one. - **Personalized PageRank expansion**: `src/graph/pagerank.ts` (power iteration, relation-kind edge weights, LRU cache). `expandSubgraph` accepts `expansionStrategy: "ppr"` to admit neighbors by PPR mass instead of fixed-depth BFS (default `"bfs"` unchanged). - **Single-file flood guard**: keyword candidates are diversified per source file (cap 20) before compression, and same-file/import expansion stops adding from a file that already owns ≥50% (or 6) of the L1 anchor channel — one hub file can no longer wall off the true target. - **Query-intent routing**: `src/graph/query-router.ts` classifies symbol / module-overview / impact / general (confidence ≥0.6 gates); impact queries auto-select PPR expansion, module-overview raises the L2 quota floor. Explicit caller options always win. - **Optional embedding rerank**: `src/graph/rerank.ts` reorders the top-40 fused hits by query/text cosine behind `LayeredPackageOptions.enableRerank` (default off; hash/fnv providers auto-skip). - **Refill cost ladder**: `ContextRefillManager` escalates per hint lexical (cost 1) → vector (2) → file node (4), cumulative spend never exceeding the budget; stage choice exposed via `lastStages`. ### Added — indexing (speed + coverage) - **Parallel full-rebuild pipeline**: `src/graph/index-pipeline.ts` — async sliding-window file pipeline (the previous `Promise.all` over `readFileSync` serialized on the event loop). Measured 1.71× on this repository (1842ms → 1076ms, 315 files); output byte-identical at any concurrency. Config `graphPolicy.parallelIndex = { enabled: true, concurrency: 4 }`; `enabled: false` restores the sequential path exactly. Unreadable files now skip (logged) instead of aborting the run. - **Recursive L2 module summaries (RAPTOR-lite)**: modules above 4000 chars / 40 children roll up compactly with per-subdirectory child nodes; deterministic, idempotent, no LLM. - **PHP, C#, Scala indexers**: tree-sitter coverage 10 → 13 languages (classes/interfaces/traits/methods/properties/imports/calls/inheritance; verified against live AST dumps). `.php`/`.cs`/`.scala` route automatically. - **SCIP ingestion (precise code intelligence)**: `src/graph/scip/` — zero-dependency protobuf reader + `graphflow scip [--limit N] [--json]` CLI. Definition/reference occurrences from any SCIP emitter (scip-typescript, scip-java, …) become exact `defines`/`references` edges (`scip:` symbol nodes, external stubs, per-file caps, per-document failure isolation). ### Added — skill flywheel (evidence-ranked, self-maintaining) - **Wilson lower-bound ranking**: skills order by the confidence lower bound of their success evidence (46/50 outranks 2/2), existing score as tie-break; composites and atomics compete on the same basis. - **Lazy scheduled consolidation**: skill-library maintenance runs when >7 days or >50 new episodes since the last pass (persisted on a `skill-library-meta` node), triggered from the recall read path, fully failure-safe. - **Lesson dedup**: episode lessons collapse exact and near-duplicates (token-set Jaccard ≥0.8) at every playbook append point. - **Semantic drift detection**: `src/learning/skill-drift.ts` — cosine distance between a skill's text and the centroid of its grounded symbols' current summaries; ≥0.35 flips staleness to the new `semantic-drift` reason (unrecallable). Hash/missing embedding providers skip entirely. - **Lexical skill recall**: BM25 over skill name + playbook bullets lets content-matched skills enter hints as low-confidence candidates (`lexicalScore`, floor 0.5) without displacing Wilson-ordered symbolic matches. ### Added — planning (case-based + verifiable) - **Similar-episode retrieval**: `src/agents/episode-retrieval.ts` — past episodes/dialogue turns ranked by token Jaccard + bigram Dice (pending/superseded excluded); `graphflow_plan` returns `episodeContext` and injects past lessons into the LLM planner prompt. - **Task-profile plan templates**: research tasks plan 分析与综合 → 验证与引用核对 (no 实现 node); bugfix tasks plan 复现与定位 → 修复实现 → 回归验证; default keeps the 4-node pipeline. - **Acceptance criteria**: `TaskNode.acceptance` (test command or graph-assertion) attached per template; `validateAcceptance`/`validatePlan` enforce safe runner prefixes, reject shell metacharacters, and verify graph assertions against the real symbol graph. Absence stays valid (warnings only). - **Query-translate auto-retry**: CJK low-recall queries are translated locally on the economy tier (15s timeout, one retry max) and the context rebuilds with `englishQuery`; the host bridge work item now appears only when no LLM is configured. Result carries a `queryTranslation` receipt. ### Fixed — test portability - `tests/m-fileread-cache.test.ts`: oversized-store test used `truncateSync` with a file descriptor (TypeError on Linux); now `ftruncateSync`. ### Docs — benchmark numbers re-measured (2026-10-11, post-merge of #62/#63) - Token ratio (8 queries): realistic top-K arm **92.2%** (103,135 → 8,092 tokens), naive-grep arm **98.8%**. Previously 95.6% / 98.5%; the repository grew, so the baselines moved. - Memory A/B (31 held-out tasks, synthetic): ON 58.1% vs OFF 58.1% (rescued 1, hurt 1); previously 51.6% vs 61.3%. Still no net transfer. - Retrieval golden set (132 queries, in-sample): Hit@5 97.7%, MRR 0.735, NDCG@5 0.466 (previously 100% / 0.779 / 0.638). CI gate (≥80% recall / ≥90% top-K) still passes. ### Fixed — production `npm audit --omit=dev` (GHSA-6qxp-vccf-f47h, GHSA-jqcg-44mw-7w3h) - Direct `@modelcontextprotocol/sdk` (root and `packages/efficiency-agent`) moved from `^1.30.0` to `^1.32.1`. The advisory range was `<1.31.0` (OAuth client could send credentials to an authorization server chosen by the MCP server). - `overrides.proxy-addr` is `^2.0.8`. express still declares `^2.0.7`, which resolved to the vulnerable `2.0.7` (IPv4-mapped IPv6 trust spoofing). ### Fixed — skill markdown graph clients stay open (Windows sqlite EBUSY) - `importSkillsFromMarkdownRuntime`, `exportSkillsToMarkdownRuntime`, and `extractDialogueKnowledgeRuntime` now `close()` the graph client in `finally`. Default `auto` transport opens better-sqlite3; leaving that handle open makes a later `rmSync` of `graphflow-graph.sqlite` fail with `EBUSY` on Windows. ### Fixed — large workspaces no longer have to be fully indexed, and dialogue record no longer materializes a huge file graph - `graphPolicy.excludeGlobs` and `graphPolicy.maxFileSizeBytes` are honored by workspace index, single-file index, and the pending-index check. `/.graphflowignore` uses the same rules (`name/` at any depth, anchored `path/to/dir/`, basename globs, path globs). Negation and nested ignore files are not supported. Markdown stays on the 200KB source cap; the 5MB document cap applies to office/PDF only. - `dialogue record` on a file store larger than 512MB streams just the dialogue nodes and appends a delta line. It does not `JSON.parse` the code graph. SQLite `listDialogueNodes()` returns the same rows with a SQL filter instead of `readSnapshot()`. ### Fixed — 中文查询零召回与多跳排序错位(对照测试复现三故障) - **混合中英分词丢词**:`tokenizeForIndex` 含 CJK 的整段直接跳过标识符切分——`providerPriority自定义` 中英文词全部消失,混合查询只能靠 CJK bigram 命中。现在切出其中的 Latin runs 正常索引,CJK 短语路径不变;纯中文/纯英文行为零变化(英文 golden 零影响)。 - **确定性中英术语表**:新增 `src/graph/cjk-glossary.ts` 种子表(约80词,代码实证的高精度词),`expandSearchQueries` 在 CJK 查询上自动追加英文扩展,零 LLM、无 agent 往返;覆盖不到的词仍走 `query-translate-en` 回退(诚实边界)。 - **通用开发路径 RRF 稀释**:`users/desktop/tmp/code` 等目录名此前等权参与 RRF 融合,9 路垃圾排序淹没真相(T4:framework-routes 压过 schema.ts)。通用段进 stop 表,剩余路径提示降权至 0.25(`expandSearchQueriesWeighted`,原签名兼容)。 - **覆盖率修正(T2)**:单稀有词 sense 碰撞曾压过多词真相 owner。`rankNodesForContextQuery` 新增 distinct-term 加分(>=3 不同词才触发,1.5/词),纯加法,单 token 查询分数逐字不变。 - **relevance 按长度加权 + 交付按 relevance 排序**:生产实测发现排序后真相仍被交付裁掉——`computeAnchorRelevance` 按 token 个数平权,bigram 巧合与 distinctive 命中同分。改长度加权(无新魔法数)后真相显著分离;低相关裁剪改取 relevance 降序 Top5(稳定排序,pack 序兜底 ties),backfill 湍流下交付集稳定。`m109` 字节界限重校为全量形(新交付正确覆盖全部 3 个 guard 夹具文件,0.75 系数编码的是旧 partial-delivery;防膨胀本质(数百 vs 339K 级)与全部安全断言 unchanged)。 - **注释卫生**:实现注释曾逐字引用触发查询的 distinctive 词,自匹配冲进交付(computeAnchorRelevance 0.203)。改中性措辞;术语表/测试夹具的命中是词典与测试本分(与仓库既有行为一致),保留。 - **生产四题终验**(真实链路,本仓库):T1 定义 0.658 首位;T2 真 owner 0.451 断层第一、免委托;T3 `module:src/learning/cost-ledger` 首轮交付(仍附带诚实委托);T4 loader+health+专项测试一次交付、免委托。4/4 有效。 - 测试锁定:新增 `m-cjk-glossary`(11 用例)+ `m109` 界限重校。回归:检索/排序/压缩/锚点/向量 20 文件 290 用例绿;全量 **302 文件 / 2816 用例零失败**,tsc/eslint 干净。 - **语义兜底(表外中文通用修复)**:关键词零命中 + 非 hash 后端时,`fuseVectorRecallIfEnabled` 自动放宽到全图向量候选(此前只重排关键词命中,空输入恒空)。hash 后端明确不兜底(FNV 向量无语义,兜底即注噪,测试锁定);无向量节点时行为与此前一致,随 deferred backfill 渐进改善。新增 3 用例(无覆盖声明/hash 不注噪/真召回)。 ### Added — 能力指标与记忆治理 (growth-plan M1-M5, wip/local-v1.18.0-capability 合入) - **能力指标**:`graphflow_diagnose` 新增 `capability`、`competence`、`metricDefinitions`。维度照抄 SWE-Bench-CL 的持续学习套件(`src/learning/capability-metrics.ts`),token 节省率刻意不进入复合分。任务域由 `deriveTaskDomain` 确定性推导,不交给模型判断;样本口径排除已撤回 / 软隐藏的 episode。样本不足时返回 `insufficientData` 并把能力比率归零,不填演示数据。 - **技能选择精度**:新增 `skillUse`(有效使用精度 / shadowing 率)。仓库尚无召回遥测,故恒为 `insufficientData` —— 这是诚实状态,不把「未测量」写成 0%。 - **写入门控与撤回链**:新增 `src/learning/memory-gate.ts`:显著性评分、provenance、软撤回(绝不物理删除)。默认 `advisory`,`GRAPHFLOW_WRITE_GATE=0` 完全关闭,`=enforce` 才真正不落库。diagnose 报出 `memoryGate`。 - **确定性技能失效**:新增 `src/learning/skill-staleness.ts`:索引重建后校验技能引用的符号是否仍能解析,解析不到即软退役并不可召回。无符号可校验的技能单列,不误判为失效;lookup 抛错按基础设施故障处理。幂等。 - **对外主指标换轨**:token 节省率从「核心指标」降为「成本约束项」(削减 38.4% 工具输出 token 反而使计费成本 +6.8%,激进压缩把 SWE-bench Go 子集 patch 成功率从 27/40 打到 15/40)。陈旧度机制以确定性符号失效为主,时间衰减为辅。 - **`docs/growth-plan.md`**:调研驱动的成长计划(10 路主题调研 + 4 路对抗验证)。 - 测试:`tests/m-capability-metrics.test.ts`、`tests/m-memory-gate.test.ts`、`tests/m-skill-staleness.test.ts`。 ### Fixed — 第 0 步性能与健壮性(迁移 Rust 前的架构债清偿,复审登记项全闭环) - **file 传输读路径共享缓存(P2-8)**:`GraphifyFileClient.peekStore()` 静态共享读入口(走进程内 `graphifyFileStoreCache`,stat 校验+delta 已应用,不开句柄不写);`graphStoreNeedsIndexing` 与 `readFileGraphStore`/`resolveGraphStoreAfterIndex` 不再各自 readFileSync+JSON.parse 整个 9.5MB store——每 preview 省 2 次全量读+解析。消费方 mutation 全审计(全只读),peek 结果仍做浅拷贝防御未来调用方。 - **embedding 后台推理限额**:deferred pass 从每 preview 最多 512 次 ONNX CPU 推理降为默认 128(`GRAPHFLOW_EMBEDDING_PASS_LIMIT` 可覆盖;deadline 不变兜底)。 - **sqlite 并发硬化**:构造 `busy_timeout=15s`(原 5s);`migrate()` 无锁快路径(健康库并发打开零写锁)+ `BEGIN IMMEDIATE` 锁内 user_version 双检——两进程同时首开旧库不再因 duplicate column 构造失败;`mergeSiblingJsonStoreIntoSqlite` 的 snapshot→plan→upsert→rename 全段进目标写锁,锁内重检 JSON 兄弟存在性(输家不再用过期快照覆盖赢家重编号的对话轮——混合宿主丢写入根因),无 `withMergeLock` 的目标降级 best-effort 锁文件。 - **HTTP stateful 会话空闲 TTL**:默认 30 分钟(`GRAPHFLOW_HTTP_SESSION_TTL_MS`,0 禁用),每请求刷新活跃;DELETE/TTL 扫描/关服共用同一 teardown;弃置会话不再随进程永生。 - **快照物化缓存:实测否决(诚实登记)**:对真实库(95.4% 行带 metadata,均 968B)A/B 测量——任何保留"每快照独立可变对象"契约的缓存方案(structuredClone 10x、JSON 重解析 7x 负优化)都劣于现状 lazy getter;结论写入 `rowToSnapshotNode` 注释+契约测试锁定。根治 P0-3 需改 preview 调用方(一次 preview 8-12 次 readSnapshot),留待后续。 - 测试加固:TTL 扫描用例改静默等待+双探测(轮询会刷新活跃时间,自相矛盾——原固定 500ms 在全量负载下窗口不足)。 ### Tests - 新增 26 用例:`m-fileread-cache`(12:peek 零重读探针/行为等价/大文件回退/限额 env)、`sqlite-concurrency-hardening`(9:构造竞态/健康库零锁/合并锁序/输家跳过/锁文件回退/快照契约)、`mcp-http-session-ttl`(5)。全量 **296 文件 / 2782 用例绿**,tsc/eslint 干净。 ## [Unreleased] ### Fixed — configPath 穿透角色/探测链(跨工作区操作用错配置的 live 事故) - **根因(两处泄漏)**:`diagnoseRoutingResult` 的 role 解析闭包调用 `resolveModelForRole/resolveModelWithFallback` 时丢弃了 configPath(回落到进程 cwd 层);`executeRolePrompt` 内部 `resolveConfig()` 无参——同样解析 cwd 层并据此装配 provider 环境。后果:从 A 仓库对 B 项目跑 `--config` 时,模型/凭据来自 A 的层——live:对 Ele 工作区的探测把 `gpt-4.1-mini`(GraphFlow 仓库层的默认)发到了 Ele 的 DeepSeek 端点。 - **修复**:resolve 闭包穿透 configPath;`executeRolePrompt` 的 opts 增加 `configPath`(`resolveConfig(opts?.configPath)`);probe 全链接线——`probeRoleConnectivity` 增参,plan/run 两处预检探测与 `probeRoutingConnectivity` 均传入。其他 executeRolePrompt 调用点不传则维持 cwd 语义(零回归)。 - **live 验证**:Ele selfcheck 的 llm-probe 不再出现 gpt-4.1-mini——模型解析正确;剩余的 "Missing provider credentials" 是该工作区的真实状态(Ele 层以 `${OPENAI_API_KEY}` 占位覆盖了全局明文 key 且该 env 未设),探测如实报告。 ### Fixed — providerPriority 开放给已配置的自定义 provider(用户工作区被 fail-fast 挡死的 live 事故) - **根因**:`providers` 映射是开放的(`Record`,支持任意 OpenAI 兼容自定义端点),但 `routingPolicy.providerPriority` 的校验是封闭五元枚举(openai/anthropic/bailian/doubao/deepseek)——两者自相矛盾。用户在优先级里列出自己配置的 provider(如 `openbmb` 连 localhost 服务)时,叠加项目层 fail-fast 直接让整个工作区无法加载配置(错误提示还误导性地指向"反斜杠路径")。 - **修复**:三处对齐开放语义——schema 的 providerPriority 放宽为 `string[]`(交叉引用校验移到能看见 providers 映射的 loader);`validateConfig` 与 `validateConfigDetailed` 的允许集 = 五内置 ∪ `Object.keys(input.providers)`;`buildFallbackChain` 透传自定义名(健康/失败簿记仍按内置 ProviderName 键控,自定义名不带追踪——注释说明)。错误信息现在**点名未知 provider** 并列出合法集合,不再是无信息量的泛句。 - **live 验证**:触发事故的真实工作区配置(openbmb + openai-compat + localhost:8000)`config validate` 通过、`context preview` 正常返回锚点。 ### Tests - 新增 `m-provider-priority-open`(5 用例):已配置自定义名通过 / 未知名失败且错误点名 / detailed 报告区分已配置与未知 / resolveConfig 加载含自定义优先级的项目层 / 内置优先级与默认链不变。全量 **297 文件 / 2789 用例绿**,tsc/eslint 干净。 ## [2.2.0] — 2026-10-02 ### Added — 成本经济学升级 Phase 2+3(U4 SoL-Pi 接线 / U5 负知识库 / U6 判断层 / U7-U8 设计稿) - **U4a 装饰开关修复(两处 settings 开关真实生效)**:`reduceObservationImpl` 入口门控 `reduce.enabled`——false 时返回明确拒绝理由(含开关路径与恢复指引),不再静默全量/静默压缩,MCP `reduce:true` 入口被 settings 真实控住;dsh 自动投影判定改为三级优先 **env 显式值 > settings(observations.enabled,三层配置逐层合并镜像 resolveConfig)> 默认开**,settings 关闭后投影拒绝执行(不 spawn CLI)。 - **U4b Compact 压力供给(替代通道,诚实约束已注释)**:dsh plugin 会话级计数器(每个 tool/result 累计原始 bytes,投影成功后结算为投影 bytes),持久化 `.graphflow/observation-pressure.json`(≤32 会话,never throws);注:`toContextPressure` 有意丢弃"只有 usedTokens 无 maxTokens"的信号,估算需与已知窗口组合才真正生效——该约束在代码与设计上均如实保留。 - **U4c ObservationPack 保守默认(MCP preview)**:text copy 超 `inlineThresholdBytes`(默认 8192)且机制开启时自动 `packObservation`——**pack 优先于桩化**(句柄可召回,桩化丢信息),失败回退既有桩化路径;structuredContent 附 `observationHandle`。大响应进对话史的体积从源头收敛。 - **U5 负知识库(fail → 教训 → 注入)**:`updateEpisodeOutcome` fail 分支对非任务回显的 lessons 幂等 upsert `anti-pattern-lesson` 节点(指纹=taskKey+lessonKey+symbolRefs,failCount/episodeIds 累积,episodeIds ≤10);**精度门 failCount≥2** 才注入——`suggestSkillConditionHints` 的 avoidPatterns 追加前 3 条(`avoid: <教训>(N 次 episode 实证)`),单次失败不注入;pass 分支 resolve 同 taskKey 教训(重开证据周期语义:再失败从 failCount=1 重新累计,不借旧账)。 - **U6 判断层路由(存量复用)**:确认 TypeSafe System One 客户端(`src/routing/typesafe-systemone.ts`,真实 API 契约:choice/score/noul 类型化判定)即判断层;`TYPESAFE_API_KEY`(或 economy 侧挂 localhost)启用;selfcheck `judgment-tier` 报告 local-jev / cloud-jev / cloud-economy / rules-only 四态。零配置用户恒为 rules-only,降级可见。 - **U7/U8 设计稿**:`docs/design-output-toolfirst.md`(输出侧 tool-first:executionDescriptor 的 resultProtocol/edit-intent-v1、SKILL.md 输出纪律"引用锚点不复述原文"、意图密度测量里程碑)、`docs/design-blast-radius.md`(working-set 与 diff-challenge 合并为 N 跳影响面引擎,viaPath 全路径 reason,迁移以现有测试锁定行为)。 ### Tests - 新增 24 用例:`u4-sol-pi-wiring`(17:reduce 门控/dsh 三级优先/压力计数结算落盘/preview pack 召回闭环/回退)、`m-anti-pattern-lessons`(7:两次失败注入/单次不注入/复读拦截/pass resolve/独立指纹/上限 3/去重有界)。 ### Added — 成本经济学升级 Phase 1(U1 台账 / U2 前缀可缓存性 / U3 质询门)+ 判断层自检 - **U1 成本台账(两栏测量)**:`provider-executor` 全路径捕获 ProviderUsageStats(含 promptCacheHit/Miss/Write,此前解析后零消费)→ `drainProviderUsageEvents`;新 `src/learning/cost-ledger.ts` 落 `graphflow-out/cost-ledger.jsonl`(llm/deliver 两类事件,>4000 行截老保新 2000);新 `src/routing/model-prices.ts` 价格表(DeepSeek/OpenAI/Anthropic 近似价,env `GRAPHFLOW_PRICE_*` 可覆盖;localhost/127.0.0.1 baseUrl 一律零价=本地判断层免费;cacheHit 按 0.1 因子计价)。**栏 A** 自有 LLM 成本:run 出口与 MCP 工具出口双 drain 落账,`reportOutcome` 把 drain 汇总快照进 `EpisodeRecord.costSummary`;**栏 B** 宿主交付字节:每个 MCP 工具响应的 text copy 字节数(归因贡献,非宿主账单——宿主侧计费不可测,已注释明示)。selfcheck 新增 `cost-ledger` 项(estCost/cacheHit%)。 - **U2 宿主前缀可缓存性契约**:锚点通道出口统一稳定排序(**分数决定选谁、id 决定顺序**——quota/budget 等质量决策读排序前的 packed 序,选择集合与质量零变化,只有展示顺序变稳);dialogue 行按 (sessionId, seq) 稳定序(去 updatedAt 变序);`graphflow_context` 的 text copy 只投影稳定面,易变数值(tokenBudget 全部/unbudgetedTokens/accountedTokens/contextPressure/updatedAt)移出 text copy 只留 structuredContent(尾行 `volatile-metrics: see structuredContent`);同 query TTL 过期重算时锚点集合签名不变则复用上一轮字节(context-cache `stableCopyTrail`)。新 `src/graph/response-stability.ts` 的 `computePrefixStability`(UTF-8 字节口径)。**顺序语义变化**:anchorChannel=(layer,id) 字典序——retrieval-rank 基线经文档化机制刷新(132 条纯重排,recall 100%/top-K ≥90% 不变);m79 断言改 relevance 语义(成员资格不变)。 - **U3 计划质询门(规则版,零 LLM)**:`diff-challenge` 新增 `planNodes` 入参与 `extractTouchedFromPlan`(文件/camelCase/PascalCase/snake_case 提取,符号经图精确解析落文件,不臆测);**桥接主集成**——`graphflow_insight merge` 对合并后的 agent 计划自动跑图事实质询(external-caller/deleted-symbol/requirement-link,≤10 条),`challenges[]` 附 merge 响应(MCP 面已透传),SKILL.md 指示执行前必须回答;**LLM 路径同挂**(planSource=llm 时 advisory 默认,`GRAPHFLOW_PLAN_GATE=enforce` 命中即降级 suggested);fail-open 全路径。live:本机 LLM 计划命中 10 条质询。 - **U6(部分)判断层自检**:selfcheck 新增 `judgment-tier` 项——local-jev(localhost baseUrl)/cloud-jev/cloud-economy/**rules-only** 四态可见(存量 TypeSafe System One 客户端即判断层,`TYPESAFE_API_KEY` 或 economy 侧挂即启用)。 - **效率门诚实化**:`evaluateEfficiencyFloor` 在显式阈值 + 0 配对记录时以明确指引 FAIL("no paired-arm data — run mechanism trial / benchmarks --record"),不再让 "0 < 1" 冒充质量结论。 ### Tests - 新增 25 用例:`m-cost-ledger`(7:价格/env 覆盖/localhost 零价/截断/聚合/episode 快照)、`m-context-stability`(9:字节稳定/前缀追加/dialogue 稳定序/text copy 禁入字段/trail 复用/prefixStability)、`m-plan-challenge-gate`(9:命中/符号解析/fail-open/截断/提取单元)。全量 **291 文件 / 2732 用例绿**,tsc/eslint 干净。 - 已知边界(登记):自定义 config+全新空图的 E2E merge 计划组装为空(默认配置 m80 全绿覆盖同流程);openai 适配器 usage 捕获为 best-effort 待扩展(deepseek 完整)。 ### Fixed — 代码审计驱动的性能与诚实性批次(Wave 1+2,每项均代码级复现后修复) - **preview 热路径(P0)**:`readGitVisibleFiles` 增加进程内 5s TTL 缓存——此前每次 preview 都 spawn 一个 `git ls-files` 子进程(256MB maxBuffer);manifest(index-state.json,124KB)从双重解析合并为 `loadCacheStateCached` 单次记忆化(mtime:size 指纹失效,上限 64 条)。 - **连接生命周期(P0)**:`previewContext`/`indexFile` 全路径 `try/finally` 关闭自己创建的图客户端(缓存命中分支同样)——此前每次 preview/watcher 保存都新开 sqlite 连接且永不关闭,常驻 MCP 进程的 fd/WAL 映射持续累积。延迟向量通道(deferred embedding)移交的客户端除外。watcher 增量索引失败从 `.catch(() => {})` 静默吞错改为 `logger.warn`。 - **file 传输倒排索引增量修补(Wave 2,读路径写放大)**:preview 的自身写(对话轮/workbench topic)走 delta 追加时不再把倒排索引置 null——按被触及节点的旧 token 删除/新 token 插入原地修补,成本 O(触及节点 token) 而非全店重分词 O(n×content);删除节点同样修补。全量重写路径保持原语义。与全量重建的等价性有测试背书。 - **两个无界增长文件(P1)**:`token-savings.json` records 环形上限 2000 条(存量超限文件下次写入自愈;被截明细的聚合计数折入持久化 `truncatedPrefix`,累计统计与全量日志完全一致);`.graphflow/mcp-http-audit.jsonl` 追加改用进程内尾条缓存(size 未变即用缓存 seq/prevHash,连续追加零全量读;哈希链语义逐字节不变,`resetAuditTailCache` 测试钩子)。 ### Fixed — 第二轮复审修复(Wave 3) - **deferred 向量路径的图客户端所有权闭环(复审 #1,高)**:preview 触发索引时若把 client 移交给延迟 embedding pass,此前无人再关闭它——常驻 MCP server 每个 preview 泄漏一个 sqlite 句柄(Windows 上 WAL 文件 EBUSY 锁定,探针实证)。现在:pass 完成时若已被更新 target 取代则自行关闭;`refreshIndexForPreview` 覆盖 target 时释放旧 client(pass 进行中则留给其 finally);`warmContextPreview` 尊重移交布尔值并在 finally 关闭自有 client;**server 优雅停机新增 `closeAllGraphClients()`**(SIGTERM/SIGINT/stdin EOF 路径),退出前释放全部图句柄。 - **`m-index-patch` 测试空转修正(复审 #2,中)**:首版测试的 store 仅 328KB(< 4MB delta 阈值),`patchIndexInPlace` 从未被执行——改用构造选项 `deltaMinBaseBytes: 1024` 压低阈值并加"delta 文件必须存在"守卫,测试现在真正覆盖增量修补路径(修补正确性已由复审的 >4MB 探针独立背书)。 - **git 失败结果不再入 5s 缓存(复审 #3,低)**:broken repo 修复后最长 5s 仍用非 gitignore walk 的陈旧失败缓存——现在 `status!==0` 与 spawn 异常同样不记忆化,下次调用即重试。 - **`deleteEdge` 保留倒排索引(复审 #5 项,info→修)**:边删除不触及任何节点 token,补空 patch 使索引免于全量重建。 ### Fixed — 承诺核验收口(round 3 verification) - **中文查询口径对齐到有工件的证据**:README(英/中)与 docs/flywheel-reproduction.md 中 "englishQuery 提供 5/5、不提供 0/5" 的断言无仓库工件支撑,且与权威冻结目录 `benchmarks/flywheel-proof-claims.json` 记载的 v2.0.3 held-out 审计(中文查询 2/5)冲突——三处全部改为引用该 commit 锚定目录;flywheel-reproduction.md 同时移除无工件的 "15-query independent audit" 段,替换为 claims 目录的实测口径。 ### Fixed — TS/JS AST 索引依赖与降级可观测 - **`typescript`(`^6.0.3`)进入 `optionalDependencies`**:此前仅存在于 devDependencies,npm 全局/npx 安装树上没有 TS 编译器,TS/JS(目标用户主力语言)索引静默降级为正则解析(仅 `logger.error`, 用户不可见)。现在默认安装大概率带上编译器,同时平台解析失败也不毁安装(尊重既有降级路径)。 - **降级可观测**:`src/graph/language-indexers/typescript.ts` 新增导出 `getTypescriptBackendStatus(): "compiler" | "regex"`(模块级 memo:`loadTs` 成功一次即 "compiler",require 失败发生降级即 "regex")。 - **`graphflow selfcheck` 新增 `ts-indexer` 检查**:compiler → ok("TS/JS parsed with the TypeScript compiler");regex → warn("TS/JS fell back to REGEX extraction — the optional 'typescript' package did not resolve from this install; AST features (calls/inherits/jsdoc) are degraded")。 - **`disclosure.network` 补 `https://huggingface.co`**:仅用于首次语义嵌入模型下载,可经 `HF_ENDPOINT` 镜像;`embeddingProvider: "fnv"` 可完全避免该网络访问(已在 `disclosure.permissions.network` 注明)。 ### Docs — README 口径诚实化(中英同步,12 处) - "11 languages tree-sitter ASTs" → 准确口径:10 个 tree-sitter 文法语言(含 C/C++)+ TS/JS 走 TypeScript 编译器(可选依赖,缺失降级正则);Markdown 正则。 - "Fully offline / 完全离线" 三处绝对化表述 → "本地优先":默认语义向量后端首次从 huggingface.co 下载一次模型,失败降级完全离线 hash 后端;`embeddingProvider:"fnv"` 可完全不联网。 - "golden set in CI: Hit@5=100%" → CI 门禁实为 ≥80% recall / ≥90% top-K;100%/MRR/NDCG 是 commit 锚定基准快照。 - 删除无工件支撑的 "independent audit 15 held-out queries" 及 20-query 开发集数字(仓库内无数据集/脚本/结果)。 ### Tests - 新增 17 用例:`m-hotpath-fixes`(5)、`m-index-patch`(3)、`m-unbounded-files`(4)、`m-ts-indexer-status`(5)。全量 288 文件 / 2707 用例绿,tsc/eslint 干净。 ## [2.1.0] — 2026-10-02 > 修复 2.0.3 中 MCP 常驻进程内存/线程无限增长、`graphflow-mcp --http` 只能服务一次请求两个问题——都需要升级到本版才生效; > 另含凭证环境变量优先、上下文预览提速约 45%、Efficiency Agent 2.x 包(仓库内,未发布到 npm)。 ### Added — Efficiency Agent 2.x 工程规范落地(`packages/efficiency-agent`) - §27 端到端管线(`eff-agent run`):真实指纹/Project Twin/经验检索/命名空间缓存/GraphFlow MCP 上下文/Reuse Gate/安全门/工具与模型路由/合同/成本优化/动态 harness/写入审计/trace。 无执行器不再报成功:`not-executed`/`unverified`/`blocked`/`violation` 各有独立退出码。 - §22 特性开关(默认值与规范一致,broker 默认封顶为 shadow)+ `flags rollback` 一键回滚; §9 fail-open/closed(GraphFlow 故障→twin-only、缓存损坏→FRESH、策略文件损坏→STRICT、 遥测不可写→不学习、管线异常→原生 worker)。 - §6–§8 安全:能力模型、R0–R5 风险分级与默认/STRICT 策略、验证命令与 worker 启动的准入判定、 运行后基于 git porcelain 的写入审计、脱敏、不可信内容包裹、注入检测、缓存准入(防投毒)。 - §2 Execution Contract v1 增量字段(decisionId/budget/permissions/validationPolicy/provider/ graphVersion/toolchainHash/avoidPatterns),schema 与 TS 校验双向一致。 - §11/§24 trace:事件序列(stage/outcome/reason/evidence/policyVersion)、决策记录、 安全判定、成本;`trace replay` 与 OTLP JSON 导出。§15 策略生命周期(Shadow→Canary→Production)。 - §18 基准:五轨(baseline/graphflow/shadow/conservative/adaptive),固定 baseCommit 的独立 worktree、oracle 判定、隐藏测试、回归守卫;`bench compare` 输出 delta、Net Saving 与 §28 验收门。 - `benchmarks/eff-tasks-v1.jsonl` 更名为 `golden-v1.jsonl`(50 任务全部带 baseCommit 与 oracle)。 - §18 数据集补齐:Golden-Extended 200(15 个任务族,`scripts/gen-extended.mjs` 生成并可 `--check` 复现)与 Long-Horizon 20(125 步,同一会话共用一个 worktree,逐步标注 fresh/reuse-allowed/ must-refresh)。`check-golden.mjs --dataset all`(84 个提交、0 错误)与可复现检查进入 release gate 的 golden 门;workflow 新增 `datasets-nightly` 夜间矩阵(需 `EFF_AGENT_CLI`,未配置时报告跳过)。 - 常驻 GraphFlow 服务:`EFF_GRAPHFLOW_MCP=http://127.0.0.1:PORT/mcp` 以 Streamable HTTP 连接已运行的 `graphflow-mcp --http --port PORT`,不再每个进程冷启动;非回环地址必须带 `EFF_GRAPHFLOW_MCP_TOKEN` (Bearer),否则以拒绝原因 fail-open。实测本仓决策 P50:每进程拉起已发布 2.0.3 为 5.3 s、拉起本仓 源码服务为 4.6 s、常驻 HTTP 为 **1.35 s**(规范目标 < 1.5 s)。冷进程本身达不到目标:node+模块≈1 s、 ONNX 嵌入模型≈1.7 s、tokenizer≈0.3 s,再加一次预览。 - §19/§20 发布门禁 `npm run gate:eff-agent`(code/contract/security/cache/golden/chaos/perf/package 八门,缺测试即 FAIL)、GitHub workflow、SBOM/SHA256SUMS/provenance、secret scan。 ### Fixed — Efficiency Agent 测试中发现的缺陷 - **安全**:结果缓存回放发生在安全门之前,被拒绝(deny/approval-required)的请求仍可回放缓存结果; 且验证命令与执行器参数不在指纹中,换了验证命令或 `--model` 也会命中。现安全门先于回放, 验证命令、执行器 args/promptVia/env 键名进入指纹环境轨(env 值不入,防泄密)。 - Windows `.cmd` 垫片(npm 安装的 claude/codex/gemini、`npm test`)超时只杀掉 cmd.exe,真实进程 持有管道导致超时失效(实测 500ms 超时跑满 17s)。agent 与验证 worker 改为 `taskkill /T /F` 杀进程树。 - complex harness 的"同一失败重复两次"停止条件只比较 agent 自身退出码,验证在进步时也在第 2 轮停止; 现同时比较验证反馈。 - 自由填写的类别(`--category`、语料 `category`)写入 trace 后不符合 schema,`bench compare` 也照收; 现 CLI 退出码 2、语料报违规、管线回退到分类器,provenance 门拒收。trace schema 补齐 R2–R4 度量规则,与 TS 校验一致。bugfix 分类覆盖 crashes/crashed/failed 等词形。 - `eff-agent` 读取 GraphFlow 上下文时优先使用 MCP `structuredContent`(`mcp.textCopy: "auto"` 下 大响应的文本副本只是占位)。 - CLI:已知命令自身报错(如 `governance release-gate` 未达标)时不再附带误导性的 `unknown command "governance"`。 - 结果缓存此前永不过期(回放跳过执行与验证);新增 TTL(默认 6h,`ttl-expired`), `PipelineDeps.cacheTtlMs` 可分别覆盖 context/result TTL。 - 写审计改为内容签名快照:可检测重复修改已脏文件、git-ignored 文件写入,以及子目录根下越出工作区的写入 (旧逻辑把 `../sibling` 误算成根内文件放行);`writeAudit` 新增 `rewrittenDirty`/`ignoredChanged`/`outsideRoot`; 声明写范围越出根目录时执行前即拒绝(R3)。 - 新增 `readCredentialEnv`(Windows 注册表 env 回退,30s 缓存,`GRAPHFLOW_NO_REGISTRY_ENV=1` 关闭); TypeSafe-JEV worker 默认用它读取 `TYPESAFE_API_KEY`。 ### Fixed — 上下文预览延迟与 HTTP 模式 - `graphflow-mcp --http` 只能服务第一个请求:服务入口把同一个 SDK Server 交给每个无状态 HTTP transport,第二个请求起即 "Already connected to a transport"。现每个 transport 新建 Server (新增入口级回归测试,回退修复即失败)。 - SQLite `readSnapshot` 每次都为全部节点 `JSON.parse` 元数据,一次预览调用约 8 次(每次≈90 ms + GC)。快照节点的元数据改为首次访问时解析(仍可枚举/序列化/赋值,各快照互不影响);对话节点 判定先看 id 前缀并跳过 File/Module/Symbol 代码节点。暖预览 1.0–1.3 s → 0.57–0.65 s,检索金标 149/149 不变。 ### Fixed — 测试写入真实用户目录 - 安装器测试靠改 `process.env.HOME/USERPROFILE/APPDATA` 做沙箱;在 `--pool=threads` 下这份 env 只在线程内生效, `os.homedir()` 仍指向真实用户目录,于是写出了真实的 `~/.graphflow/workspace-build.json`,并把多个宿主 (Claude Code、opencode、Gemini、Cursor、Windsurf、VS Code、Trae)的 graphflow 条目改成已删除临时目录里的 假 `server.js`;之后未沙箱的 dsh 测试又读到这个标记而失败。`vitest.config.ts` 固定 `pool: "forks"`, `tests/helpers/setup.ts` 在 worker 线程中直接拒绝运行。 - `tests/workspace-build.test.ts` 的 `newWorkspace` 在 `return` 之后才登记临时目录,清理从未执行(每次运行泄漏数十个目录)。 - dsh 的两条 `cordis.patch.yml` 一致性测试读的是开发者真实的 workspace-build 偏好,开启后必然失败; `buildGraphFlowDshInsertPatch` 新增 `home` 选项,测试改传空的临时 home。 - Efficiency Agent:`createTaskWorkspace` 在 worktree 里软链 `node_modules`,POSIX 上 `node_modules/` 忽略规则 不匹配软链,`git status` 把它报成未跟踪文件,`noChanges` 拒答判定在 Linux/macOS 上恒失败(CI 唯一失败用例); `workspaceChanges` 排除 `node_modules`。 ### Fixed — MCP episode 往返与根套件负载抖动 - `graphflow_report_outcome` 对同一 MCP server 刚由 `graphflow_run` 创建的 episode 报 "Episode not found": 运行时无法加载 `better-sqlite3` 时 episode 写入 JSON 回退存储,而任一 SQLite 宿主(源码 CLI/测试/扩展) 打开同一图会把 JSON 合并进 SQLite 并改名移走。现进程内保留近期 episode(上限 128),report 未命中时 恢复写回后重试;返回形状不变。 - `graphflow_run` / `graphflow_report_outcome` 新增可选 `rootDir`(此前被忽略);CLI `outcome report` 新增 `--root-dir`。 - `graphflow_skill_insights` 在空图上不再按进程 cwd 索引整个仓库,改为遵循配置的 `workspaceRoot`。 - 从计划生成 workbench 改为一次批量 `upsertGraph`(此前每个 topic 全量重写 file 存储,N 步 = 2N+1 次)。 - 跨进程/重启后 episode 仍丢失的存储层根因:SQLite 宿主合并后把 JSON 存储改名为 `.merged-bak`, 无 better-sqlite3 的 JSON 宿主随即读到空存储。`GraphifyFileClient` 在 JSON 缺失、存在同名 `.sqlite` 且有合并备份时,改从备份(首份 + `.latest` 及其 delta)重建视图,下一次写入即带回全部记忆; 无 SQLite 兄弟(用户主动删除)仍为空。 - CLI `graphflow run` 实际把任务**执行了两次**(`runTaskResult` 之后又为 legacy 文本调用 `runTask`), 每次产生两个 episode、只有一个会被回报——这正是 governance `pending-ratio` 偏高的来源之一。现只执行一次, 并新增 `--root-dir`。 - 自动捕获的会话日志此前写到 `process.cwd()`(测试会污染仓库 `.graphflow/session-journal.jsonl`); `OrchestrateOptions.workspaceRoot` 现由 `runTaskResult` 传入运行绑定的工作区。 - MCP 集成测试改用临时小 fixture 工作区与 `fnv` 嵌入(不再每例加载 ONNX、索引全仓库),未调大任何超时; 新增 `tests/mcp-episode-roundtrip.test.ts`(含"存储被合并移走"场景与 CLI 路径)。 ### Fixed — 凭证解析:环境变量优先,过期明文不再遮蔽(DeepSeek 401 根因) - 实测根因:全局配置 `providers.openai` 指向 `api.deepseek.com` 且存了一个过期明文 key,两个 tier 都走 `provider=openai`;旧逻辑只在**同名**变量(`OPENAI_API_KEY`)已存在时才让 env 胜出,于是用户 导出的 `DEEPSEEK_API_KEY` 从未被采用,所有调用 401。 - 新增 `resolveProviderApiKey`(`src/config/provider-env.ts`)统一取 key,顺序:**端点厂商的真实环境变量** (进程 env → Windows 注册表)> 配置 `${NAME}` 引用 > 通过占位符/空白检查的配置明文。 `applyProviderEnvFromConfig`、`providerHasCredentials`、`llm-check` 来源说明、TypeSafe worker 选 key、 `benchmarks/run-real-ab.ts` 全部改用此顺序;明文被遮蔽或被拒时 `llm-check` 的 detail 会写明原因。 - 跨厂商防泄漏:某条目指向 deepseek 而 shell 里有真实 `OPENAI_API_KEY` 时,不再把 OpenAI 的 key 发给 deepseek。 - 配置导出键的"自有"判定改为按值比对:被 shell/测试/注册表水合覆盖后即视为真实 env,不再被下一次配置导出覆盖。 - `benchmarks/run-real-ab.ts` 基线臂用 `grep` 取上下文,Windows 无 `grep` 时 ENOENT 被当成"无匹配"吞掉, 基线实际**零上下文**(输入恒 ~40 token),对比失真;改用 `git grep`,非"无匹配"错误直接抛出。 - `benchmarks/run-real-ab.ts` 长跑中断即前功尽弃(控制台 Ctrl+C 会连带杀掉 `git grep`,状态码 0xC000013A 被当成 致命错误):瞬时失败(超时/被信号杀/无状态码)重试一次,再失败只跳过该检索词;每完成一个任务追加写 `graphflow-out/eff-bench/real-ab.checkpoint.jsonl`,`--resume` 按模型与任务 id 恢复已完成任务并复验溯源。 ### Fixed — MCP 常驻进程内存/线程无限增长(实测 36GB、3000+ 线程) - `createEmbeddingProviderFromConfig` 每次调用都新建 transformers provider 并立即预热, 即每次 `graphflow_context` 加载两个新的 ONNX 会话(模型权重 + 原生线程池),从不释放。 本地 provider 现按 (dtype, 模型缓存目录, 解析根) 进程内共享;单次预览从 ~11s 降到 ~1.1s。 - `createGraphClient` 的 `liveClients` 强引用持有每个客户端(含缓存约 17MB),运行时路径 几乎不 close,常驻进程线性涨内存。改为 `WeakRef` + `FinalizationRegistry`,测试 teardown 的 `closeAllGraphClients` 语义不变。 - 宿主退出后 MCP 进程成为孤儿(实测同时残留 7 组 launcher + server):SDK 的 stdio 传输不处理 stdin EOF,文件监视器又让事件循环常驻。stdio 入口现在在 stdin `end`/`close` 时优雅退出, launcher 随子进程一起结束。 ### Security — Skill/Rules 源文件不再从 cwd 解析 `resolveSkillSourcePath` 等解析器把 `process.cwd()/skills/graphflow` 排在首位:在任何含 `skills/graphflow/SKILL.md` 的目录里运行 `graphflow init`(或扩展宿主 cwd 落在该目录),就会把 该目录的文件写进所有用户级 Agent 的 skills 目录——恶意仓库可借此投放提示注入。现只从本包 自身位置与 vendor 运行时解析;`graphflow_skill_guide` 读取同样不再看 cwd。 ### Fixed — 配置分层不一致 - 项目层 `graphflow.config.json` / `.graphflow/config.json` 按服务的工作区(`rootDir` / `GRAPHFLOW_WORKSPACE_ROOT`)发现,不再按进程 cwd——同一项目在不同宿主下解析出不同配置。 - 项目/覆盖层改为**部分覆盖**:只写要改的字段,其余继承全局;合并结果再校验。此前每层须是 完整配置,且完整层会把全局整体盖掉。损坏的项目层仍 fail-fast,损坏的覆盖层仍忽略。 - `mergeGraphFlowConfig` 不再丢弃 `workerPolicy` / `reconcilePolicy`。 ## [2.0.3] — 2026-09-30 > npm 上的 2.0.2 是一次取消竞争里意外落地的部分发布(不含下方 Windows pack 修复),由本版接管 latest。 ### Fixed — `npm pack` 在 Windows 上失败(prepare 钩子的 POSIX 写法) Windows 实测:`npm pack` 报 "'husky' 不是内部或外部命令…'true' 不是内部或 外部命令"——`prepare: "husky || true"` 里 `true` 是 POSIX 命令,Windows cmd 没有;husky 缺失时(未装 devDependencies 的检出)回退链整体失败 → pack 中断、tarball 不生成。改为 `node scripts/prepare-hook.cjs`:best-effort 跑 husky(shell:true 解析 Windows 的 husky.cmd),**任何情况退出 0**——git 钩子 接线是开发便利,永远不该连累 install/pack。 ### Fixed — 只读诊断命令从 home 目录运行不再拒绝(Ubuntu 实测) 用户实测:`graphflow llm-check` 从 `~` 抛 "Refusing to index unsafe workspace root: /home/\"——**诊断命令犯了 2.0.1 刚修过的同类错**(llm-check 是 新命令,写时漏了逃生口)。 - `llm-check` / `diagnose`(含 `route diagnose`)/ `selfcheck` 三个只读诊断 全部以 `allowUnsafeWorkspace` 解析:任何工作目录都能作答。 - `diagnose` 的 workspaceRoot 诊断块升级为**异常安全**:解析被拒时把拒绝 本身作为发现上报(`discovery: "refused"` + 原因),不再抛出。 - usage 帮助补 `llm-check` 条目。 - 回归测试 `tests/diagnostics-from-home.test.ts`:假 home 下四个命令全部 作答(llm-check 报告在场、diagnose 报 refused 而非抛出、selfcheck 通过、 帮助含新条目)。 - 另:Windows 报 "unknown command config" 的机器装的是 2.0.0 之前的版本 (usage 无 settings 命令可证),升级到本版即可。 ### Fixed — Jev 接入真实 API 契约 + `graphflow llm-check` 自诊断 用户实测"配了 DEEPSEEK_API_KEY / TYPESAFE_API_KEY 和 settings 仍无法访问",根因是**类别错误**:typesafe-jev worker 把 Jev 当 chat 模型,打向**编造的域名** `api.typesafe-jev.ai/v1/chat/completions`,还让它编造命令 JSON——按 docs.typesafe.ai 官方契约,Jev 是 System One 判定模型(`POST https://api.typesafe.ai/v1/systemone`,Bearer,`jev-latest`,Choice/Score/Noul 类型化问答),**不生成文本**。 - **substrate 新增 `src/routing/typesafe-systemone.ts`**:真实契约客户端(429/529 指数退避、401/422 硬失败、usage→measured)+ `createJevMetaReflector`——Layer B 灰区复用决策现在走真实 Jev choice(REUSE/ADAPT/FRESH)+score(置信度),失败一律回退 Layer A。已实测联通:HTTP 200、jev-1.13.0、noul 判定。 - **worker 重写**:`prepare` 确定性(Jev 不编命令)、`execute` 本地 execFile、`validate` 走真实 noul 判定(可否决零退码;无 key/不可达 fail-open 为退码语义)。移除 DEEPSEEK_API_KEY 跨服务回退(两套服务两套 key,回退=必 401)。 - **默认端点修正**:`workerPolicy` 默认 `https://api.typesafe.ai` + `jev-latest`(原 localhost:8000 占位也是"开箱不通"的一环)。 - **新增 `graphflow llm-check`**(只读诊断):逐 provider 报告可用性、**获胜凭证来源**(config-key / `env:变量名` / localhost / none,`${VAR}` 占位符如实标注 env 来源)、baseUrl/model、**实际查过的环境变量名清单**(拼错立即现形)、System One 端点状态。Windows"无法访问"从此可自诊。 - 测试:`tests/typesafe-systemone.test.ts`(契约/退避/反思器/llm-check 9 例)+ worker 测试重写为真实语义(14 例)+ 真实臂记账对齐(判定调用数=typeSafeValid、token=usage)。全仓 254 文件 / 2073 测试绿。 ### Fixed — `graphflow config ui` 保存被 unsafe-root 断言拒绝(Windows 实测) 用户报告:设置页能打开但保存失败——"Refusing to use unsafe workspace root from projectWorkspaceRoot: C:\Users\roarp"。根因:从 home 目录启动时, 保存流程 resolve 一个**不存在的显式 config**,loadConfigSafe 给默认配置 绑上 cwd(home) 作为 workspaceRoot,随后被当 `projectWorkspaceRoot` 传入 运行时绑定断言 → 抛错。而**保存全局设置根本不需要项目工作区**。 - `resolveConfig` 新增 `allowUnsafeWorkspace` 逃生口(settings 流程专用, 其他调用方不变——M49 的全局断言语义保持原样)。 - `getGraphFlowSettings` / `saveGraphFlowSettings` 以该模式解析:从 home 读写全局设置不再抛错(已在真实环境复现验证:THREW → save ok)。 - 保险丝:持久化前若发现不安全根(home/AppData),一律剥离——包括项目 scoped 配置(旧版本钉进去的坏值会在下次加载时复发成同样的抛错)。 - 回归测试 `tests/settings-unsafe-root-save.test.ts`:home 下保存/读取 全局设置成功且永不持久化 workspaceRoot;预置的坏根在保存时被清除。 ## [2.0.0] — 2026-09-30 ### 升级须知(2.0.0 迁移说明) - **store 路径可能变化(重要)**:`bindRuntimeWorkspaceRoot` 修复后,项目 config(graphflow.config.json)里的 `workspaceRoot` 从此被正确尊重 (文档优先级第 3 级)。此前被 cwd 发现覆盖的部署,升级后实际生效的 graph store 路径会变——旧数据还在原位置,用 `graphflow artifact` 导入 或把 `graphStorePath` 指回旧文件即可。 - **混合库召回隔离**:dialogue/workbench 召回现在按工作区归属过滤。 依赖"跨项目串台"行为的(错误)用法会看到不同的召回结果。 - **默认配置新增 `workerPolicy`**(本地 JEV 端点占位)与凭证嗅探语义: 环境变量凭证只信真实 shell 来源;`localhost` 端点视为免密。 - **graphflow_run 响应新增 `advisory` block**(Shadow、确定性、零 LLM 成本)——纯增量,不读取它的宿主不受影响。 - 2.x 效率层以 monorepo workspace 包形式随仓库交付 (`packages/efficiency-agent`,暂不随 npm 包发布)。 ### Added — Step D 首份真实成本 A/B:Context ↓47%(门槛 ↓20%) `npm run benchmark:real`(`benchmarks/run-real-ab.ts`):50 任务 × 双臂真实 deepseek-v4-flash 调用。token 数取自 provider usage(R2 measured),100 条 trace 全部通过 R6 provenance 门,总实验成本 ≈ $0.20。 - **双臂语义(诚实反事实)**:baseline = 传统 grep 取上下文(top-3 文件 × 250 行);shadow = GraphFlow 压缩上下文包。同模型/同单轮/同 6000 字符 预算。首版"裸提示词基线"被否——它把效率层带上下文误读成 +2000% 输入。 - **结果**:输入 token 均值 1578 → 835(**-47%**,§23 门槛 ↓20% 的 2.35 倍); 总量 78,913 → 41,736。成功率 100/100(判据=非空回答,局限如实记录)。 输出 token 被 2048 生成上限支配(25-32/50 顶格),输出/费用对比本轮不作数。 - **审计修正**:`eff-agent bench run` CLI 实为合成模拟器(fabricated 时长与 循环编造的 reuseMode,含真实 advisory 永不给出的 REUSE)——本轮以真跑 数据替代;CLI 的真实化列入待办。 - 详细数字与局限声明:`benchmarks/REAL-AB-RESULTS.md`。 ### Fixed — LLM 可用性嗅探的自反馈回路(bridge 降级保障回归) 新一轮凭证嗅探引入了一个反馈回路:`applyProviderEnvFromConfig`(既有行为)把 config 凭证写进 `process.env`,新的 `providerHasCredentials` 又去嗅探 env——**前一个配置的凭证泄漏进后续所有配置的可用性判定**。实测后果:同文件早先测试导出的一次性 `sk-good` key 让后面本应无 LLM 的 selfcheck 判为"可用"(llm-probe ok 而非 na),`bridge-fallback-guarantee` 9/12 失败。 - `provider-env.ts` 新增 `configExportedEnvKeys` 记录:凡由配置导出的 env 键,可用性嗅探(`genuineEnvValue`/`detectApiKeyFromEndpoint`/分支 2/4)一律视为不存在;**真实 shell 提供的环境变量不受影响**(零配置开箱即用、TYPESAFE 映射保留)。 - `resolve.ts` 的 env→config 回写(步骤 3/4/5)与 TYPESAFE 别名同样只信 genuine env——防止跨配置凭证被写进 config 对象本身(乃至被设置页持久化)。 - `bridge-fallback-guarantee.test.ts` 补 `GRAPHFLOW_CONFIG_HOME` 家目录隔离(m49 既有机制):断言"彻底清空凭证"的测试不得读本机真实全局配置(本机有真实 deepseek key,不隔离必然假阴)。 - 回归守卫:`m-run-bridge-selfcheck` 恢复绿(4/4)。 ### Added — §5 Contract 补全 + §21 策略闭环 + lint 清零 - **advisory 补 §5 四块**:`project`(workspaceRoot + gitHead 尽力获取,**按工作区根做进程内缓存**——基准实测不缓存决策成本 0→65ms/任务,缓存后 4ms)、`experience`(相似 episode 指针 + topSimilarity)、`tools`(按能力派生,融合 edit 步的 command 即 validate 能力)、`context.cached`(context-cache 命中信号)。contract schema 与 `assertAdvisoryCompatible` 验收门同步扩展。 - **§21 策略闭环(读侧)**:`graphflow-out/efficiency-policy.json` 存在时,`graphflow_run` 的 advisory 以其覆盖 worker 档位/执行模式并盖章 `policyApplied.version`;账本记录补 `taskCategory`(triage 类目作学习分组键)。 - **§21 策略闭环(写侧)**:包内 `policy-from-ledger.ts`(账本→TrajectoryRecord→summarize→learnPolicy,映射的"决策形≠运行形"局限如实写入 docblock)+ `eff-agent policy learn ` CLI 命令。闭环:生产决策入账本 → 学习出策略文件 → 下次 advisory 应用。 - **测试**:`tests/advisory-policy-loop.test.ts`(§5 字段契约纯净、策略覆盖+盖章、账本→学习闭环);新一轮 10 个 lint 错误清零(6 未用 import、settings-server 4 处 `any`→类型化)。 - **终态**:253 文件 / 2069 测试全绿;lint 干净;双 tsc + 包构建通过;基准 provenance 全净、ADAPT 7/50 稳定、决策成本 4ms。 ### Added — P2–P7 全量落地(5 agent 并行,独占文件域)+ similarity/outcome 拆分 效率决策层的六个阶段一次到位,全部在 `packages/efficiency-agent`(138 个新测试 + 5 个集成测试),共享类型契约 `src/domain.ts`。 - **P3 复用引擎(§7/§8)**:`fingerprint.ts` 四轨指纹(semantic/project/context/environment → reuseKey,轨间隔离:gitHead 变只动 projectStateHash);`caches/` 三层缓存——Context(TTL)、Plan(命中前 projectStateHash 状态校验)、Result(仅 query/docs/config 类目可存可放,写类目 put 即拒绝);`reuse-gate.ts` 保守阶梯。缓存按语义任务哈希键控 + 全指纹校验,所有失效原因(ttl-expired / project-state-changed / fingerprint-mismatch / category-not-result-safe)真实可达。 - **P2 Execution Broker(§16)**:`broker.ts` 轮次/预算/停止条件三重约束的生命周期(worker 异常一律收敛为观测不抛出,stop() 恒在 finally 调用);第一个 worker = `local-command-worker.ts`(execFile 数组参数、超时 SIGTERM、AbortController 停止、输出尾 2000 字符)。外部 CLI worker(claude/codex)按同一 `WorkerAdapter` 接口后续接入。 - **P4 经验学习(§18)**:`trajectory.ts` 记录校验/按类目汇总;`policy-learner.ts` 带滞回的策略学习——成功率 <0.7 升一档(economy→standard→heavy)、≥0.9 且 ≥2×minSamples 才降档、avgRounds>1.5 转 loop、失败阶段占比 ≥30% 进 avoidPatterns;`policy-store.ts` 版本化 append-only(拒绝过期版本、单调回滚)。 - **P5 Project Twin + 工具智能(§9/§10)**:`project-twin.ts` 确定性派生(模块/入口/关键符号/构建/测试/约定,跨文件符号 ≥2 文件才入榜);`capability-registry.ts` success_history 驱动排序(胜率升、延迟/成本升序);`tool-router.ts` 按能力选工具(precision≥0.8 优先,无供给→no-capability 拒绝);`schemas/tool-capability-v1.schema.json` 补齐 Step B 第四个 schema。 - **P6 成本优化(§20)**:`cost/model.ts` 组件聚合(总额继承最弱 provenance,R5);`cost/optimizer.ts` 四道 floor 门(success/fidelity/safety/evidence)过滤后取最小成本,平局按成功率、id 字典序。 - **P7 自优化闭环(§21)**:`reflection.ts` 确定性反思规则(cache-win/cache-miss/over-budget/quality-floor-miss);`loop.ts` 决策→执行→反思→策略更新编排(学习器可注入)。 - **集成证明**:`tests/integration-cycle.test.ts` 用全真实模块走通 冷缓存 FRESH → 回放 REUSE → 状态漂移回落 → 本地 worker 真实执行 → 轨迹汇总 → 失败类目升档 → 优化器择优 → 闭环出策略更新。 - **similarity/outcome 拆分(上一轮基准发现的修复)**:`orchestrator-episode.ts` 的 similarEpisodes 同时携带 `score`(结局分)与 `similarity`(`taskSimilarity()` Jaccard);advisory `decideReuseMode` 以 similarity≥0.5 为主门,无 similarity 信号才回退旧 score 门。**基准复跑:ADAPT 49/50 → 7/50**——只有真正相似的重复族兄弟通过;contract schema signals 增加 `topEpisodeSimilarity`。 - 测试:包内 7 个新文件 138 测试 + 集成 5 测试;全仓 242 文件 / 1956 测试绿;lint、root+包双 tsc、包 dist 构建全部通过。 ### Added — Step A/B:50 任务基准 + provenance 门比较(`npm run benchmark:eff`) P0 计划的基准件落地。**基准在第一天就产出了一条真发现**(见末尾)。 - **语料** `packages/efficiency-agent/benchmarks/eff-tasks-v1.jsonl`:50 个任务按 §24 组成(20 高重复 / 15 常规 / 10 复杂 / 5 故意失败);regular 队列文本衍生自本仓库真实 git 历史(source 带 commit);解析器 `src/corpus.ts` 强制组成校验,坏语料拒绝进基准。 - **Runner** `benchmarks/run-eff-bench.ts` + 可测试核心 `benchmarks/eff-bench-lib.ts`(沿用 plugin-ab-lib 的 lib/CLI 拆分):`run --mode=baseline|shadow [--limit N]` 双臂离线跑(bridge 路径、无 key、临时沙箱),每任务一行 TaskTrace JSONL(默认 `graphflow-out/eff-bench/`);`compare ` 先对每条 trace 过 `validateTraceProvenance`,**任何违规整场拒绝**(R6),干净才输出双臂统计。 - **trace 构建器** `packages/efficiency-agent/src/bench.ts`:provenance 在构造点决定——bridge 双臂 context tokens 诚实标 `proxy(descriptor-chars/4, 0.6)`(summary 尚不暴露真实 token 计数,合同必须让这个缺口可见);决策成本占比按 R3 标 `estimated(decisionMs/totalRunMs)`。开发中合同当场抓到一次自造违规(measured 值带 method),按 R3 改正——门是活的。 - **episode 闭合模拟**:沙箱内每任务跑完按队列语义闭合(failure 队列记 fail)——`similarEpisodes.score` 是结局分(pass=1/pending=0/fail=-1),不闭合则 bridge episode 永远 pending=0,ADAPT 判定永远不触发,测的是一个真实项目不存在的库。 - **全量实测**(2026-09-30,本机):双臂各 50 任务、provenance 全净、每臂 ~23-28s;`avgContextTokens=184`、`totalLlmCalls=0`、`avgRounds=1`、shadow `avgDecisionCostShare=0.0002`(决策开销占打包耗时 0.02%)。 - **Shadow 第一条发现(如实记录,先不改语义)**:闭合 episode 后 **49/50 判 ADAPT**——`similarEpisodes` 的 `score` 是结局分而非相似度分,0.5 阈值的实际语义退化为"top-3 相似排名里存在任何 pass episode"。修正方向是让 summary 同时携带 similarity 与 outcome、advisory 对 similarity 设阈;留给 Step D 真实 A/B 前校准(这正是 P0"只观察"的目的)。 - 测试:`tests/eff-bench.test.ts`(语料组成 20/15/10/5、坏语料拒绝、双臂 trace 全净且 shadow 臂 ADAPT≥4/FRESH≥1、compare 接受干净臂、拒脏数据)。 ### Fixed — 跨项目召回隔离(P0 gate):混库不再串台 实测缺陷:在 GraphFlow 仓库根上调 `graphflow_context`,回显的 `workbench` 是**另一个项目**(铜管 FOV 视觉)的工作台主线,`dialogueHits` 也混入外项目会话。根因两层: - **`loadActiveTopic` 不验归属**:无 `taskHint` 时直接取**全库** `updatedAt` 最新的 workbench root——混库(legacy 共享 store / 显式 configPath)里最新 root 几乎必然是别人的。现在按 `workbenchRootIdFor(task, 当前 root) === rootId` 重算哈希验归属(与 diagnose 的 outline 过滤同一套"验证而非猜测"语义),不属于本工作区的 root 不再被当作活跃主题。不传 `workspaceRoot` 时保持旧行为。 - **`searchDialogueTurns` 无会话过滤**:dialogue 召回按内容在全库 120 条窗口内匹配。现在接受 `workspaceRoot`,用存储的 session `name` + 当前 root **重算哈希**得出本工作区会话集合(`listOwnedDialogueSessionIds`,历史数据也能精确归属),过滤发生在窗口截断**之前**——外项目再活跃也挤不掉本项目的轮次;无法验证归属的轮次一律不参与召回(隔离优先于召回)。 - **顺带修了一个绑定错误**:`previewContext` / dialogue 运行时包装器调 `bindRuntimeWorkspaceRoot` 时**从没传**项目级 `workspaceRoot`(文档优先级第 3 级形同虚设),root 一律落到 cwd 发现——项目 config 部署下归属集合按错误 root 计算,召回全灭;且同文件内 record/list 两个表面绑不同的根,互相看不见对方的会话。现在 `previewContext` + `dialogue.ts` 全部 8 处统一把 `projectWorkspaceRoot` 传进去。 - 测试:新增 `tests/cross-project-recall-isolation.test.ts`(双 root 共享一个 store 的混库形态:scoped 召回互不泄漏、`loadActiveTopic` 不被更新的外项目 root 劫持、`previewContext` 端到端只回显本工作区内容)。 ### Added — 2.x 效率层地基:Shadow advisory + 决策成本账本 + 测量合同 二阶段计划(Efficiency Agent)的第一批落地:Contract 不另起炉灶,作为 `graphflow_run` executionDescriptor 的超集演进;决策自身成本必须入账。 - **`src/core/efficiency-advisory.ts`**:纯 Layer A(零 LLM 调用)的 Shadow advisory 构建器。REUSE 门保守:有达标相似 episode(score ≥ 0.5)→ `ADAPT`,否则 `FRESH`,**v0 里 `REUSE` 刻意不可达**(result 复用等基准证明安全后再开);模型档位映射 simple→economy / complex→standard,确定性层**永不升到 heavy**;验证门从 fused steps 的 validate 动作推导。同输入除实测耗时外字节相同。 - **接线**:`graphflow_run` 响应新增 `advisory` block(`routing.ts`,失败隔离——advisory 永不拖垮 run);worker 可忽略(Shadow)。工具描述已更新。 - **`src/learning/decision-ledger.ts`**:每次 advisory 产出向 `graphflow-out/decision-ledger.jsonl` 追加一行决策自身成本(duration 实测、llmCalls/tokenCost 对 deterministic 决策恒 0、provenance 标记)。`GRAPHFLOW_DECISION_LEDGER=0` 可关。Shadow 验收的"决策成本占比"从这里取数。 - **`packages/efficiency-agent/`(新 workspace 包,零运行时依赖)**:边界规则=只消费 MCP/公开输出、不读 GraphFlow 内部存储、主仓不反向依赖。含测量合同(`measurement.ts`:成本字段必须带 provenance,measured>estimated>proxy,聚合取最弱,R1–R6 由校验器强制)、TaskTrace v1(`trace.ts` + `schemas/trace-v1.schema.json`,`validateTraceProvenance` 是 A/B 比较准入门——回应"LLM Calls ↓20% 目前测不到":没有 provenance 的比较直接拒绝)、Execution Contract v1 规范类型与 `assertAdvisoryCompatible` 验收门(`contract.ts` + schema)。根 `package.json` 增加 `"workspaces": ["packages/*"]`。 - **一致性守护**:`tests/advisory-contract-conformance.test.ts`(substrate advisory 必须过包侧 contract 门,含 JSON over-the-wire 往返)、`tests/shadow-advisory-e2e.test.ts`(bridge run 端到端:advisory 下发 + contract 门通过 + ledger 落盘一行一记录)、`tests/efficiency-advisory.test.ts`(确定性/保守复用/档位映射/验证推导/ledger 读写与断行容忍)。 ### Fixed — 同一个查询的两次调用现在字节相同 `graphflow_context` 是给宿主当提示前缀用的:前导字节一旦变了,它后面所有 token 重新计价。实测此前**同样的 query + 没变的仓库,两次调用产出不同字节**,原因有三类,都已修: - **信封字段顺序**:每次调用都会重算的记账字段原先插在内容字段中间。`src/surfaces/cli/runtime/graph.ts:540` 现在按"内容由 (query, store) 决定 → 在前"排序:`query / summary / anchors / anchorBodies / tokenBudget(稳定字段) / refillPreview`,把 `anchorsByLayer`、`unbudgetedTokens`、`accountedTokens`、`degraded`、对话/workbench 回显、`economics`、`cacheLayout` 全部排到尾。**anchors 本身没有重排**(只动信封顺序,不动锚点顺序)。 - **`degraded` 与 `churn`**:`response-budget.ts` 原先把 `degraded` 塞在对象中部(改变的是**键集合**,不只是值);`context-economics.ts` 的 `churn` 是"和本进程上一次发的内容"的差,第一次调用和之后每次天然不同——两者现在都落在最后。 - **对话时钟**:`dialogue-thread.ts` 在 30 分钟去重窗口内命中时原先无条件写 `updatedAt = Date.now()`,于是回显里的 `updatedAt` 每次都变。现在拆出 `lastSeenAt` 作为去重时钟,`updatedAt` 只在文本/摘要/关联节点真的变化时前进;旧记录没有 `lastSeenAt` 时回退到 `updatedAt`,升级不会把历史轮次全部重开。回显视图 `DialogueHitPreview` **不再携带 `updatedAt`**(全仓无消费者;值仍留在图和 `DialogueSearchHit` 上,走 store 读取的调用方不受影响)。 - **平局打破**:`graph-search.ts` 对话检索、`detectSupersession`、`vectorRecall`、打包内对话行、`snapshot-view.ts` 边排序、`sqlite-client.ts` 的 FTS 查询(`ORDER BY rank, n.id`)都补了确定性的次键;V8 排序稳定,同分时以前继承 SQLite/FTS 行序。 - **量到的效果**:本仓库同一 query 连续两次 `previewContext(recordDialogue:false)`,**整段 JSON 逐字节相同**(不只是稳定头)。 - **被否掉的两处**(有实测支撑,不是偷懒):给 `graph-compression.ts` 的 `ranked.sort(score)` 加 id 次键,golden 召回从 132/132 掉到 **90/132**、负样本泄漏——那里的"平局"其实是 BFS 发现序(种子与近邻优先),按 id 重排会让字母序靠前的节点顶掉真正的种子;同样理由撤掉了对 `importHits` / `expanded` / 快照扫描的 id 预排。**结论:确定性不能靠给有语义的排序强行加字母序**,这些位置要做到可重复需要有意义的质量次键,目前如实留着未解。 - **仍未决定**:`planCacheLayout` 是否真的参与 `summary/anchors` 排序、`cache-layout` / `context-economics` 默认是否打开——本轮只做了机械的字节稳定部分,策略留给作者(宿主是否把这个块提到 system 层,决定了这笔收益有多大)。 - 测试:新增 `tests/context-prefix-stability.test.ts`(3 例:两次调用头相同且变动字段落在尾、`economics.churn` 每轮变化时头仍相同、同分锚点按 id 确定),`tests/dialogue-thread.test.ts` 增加"纯重复提问只走去重时钟"一例,`m107` 的回显断言改为**显式要求视图里没有 `updatedAt`**(而不是放宽)。 ### Added — outcome 机械闭合:`graphflow reconcile outcomes` 飞轮的输入缺口是结构性的:`pass` 只能来自 agent 自愿调用 `graphflow_report_outcome` 的自报布尔值。本仓库实测 191 个 episode 里 9 pass / 1 fail / 73 pending / 108 human_review,**0 个带 evidence、0 个带 deviation、187 个 `plan` 为空**。新增一条不依赖配合的闭合路径。 - `src/learning/outcome-reconciler.ts`:pending / human_review 的 episode,取任务文本与计划步骤里**磁盘上真实存在**的路径 → 在该 episode 时间窗内查 `git log --name-only`(只读命令)→ 整个 reconcile 跑**一次**声明的 verify 命令,用退出码定成败。写回走现有 `reportOutcome`,因此技能学习与审计链的行为和自报完全一致。 - **保守是有条件的**:pass 需要"verify 退出 0"**且**"窗口内有 commit 碰到 episode 点名的文件"。没配 `reconcilePolicy.verifyCommand`、或命令失败、或没有这样的 commit —— 一律不写,并把原因计入 `no-verify-command / verify-failed / no-named-files / no-commit-in-window / no-git-history`。一条 commit 只代表交付过,不代表改对,所以绝不凭它写 pass。 - 出处如实:写入的证据带 `source: "reconcile"`(`EvidenceSource` 联合新增该值)且 `userConfirmed: false`,不会伪装成用户确认。默认 **dry-run**,要落盘必须显式 `--apply`。 - `graphflow selfcheck` 新增 `reconcile` 行(只读,不跑 git、不跑命令)。本仓库实跑:`158 pending (0 name files), verifyCommand unset` —— 也就是说机制虽然通了,**当前仓库的 episode 任务文本里没有任何存在的文件路径**,闭合还差"捕获时记下改过哪些文件"这一步;报告里 `passesWithoutLessons` 也明说:pass 无 lesson 只关闭 episode,不产生技能学习(`shouldApplySkillLearningFromOutcome` 的既有门)。 - 修 `scripts/backfill-episodes.cjs` 两处硬伤:回填出的 episode 原先一律 `outcome:"pass"`(每条 commit 都算成功,正是上面禁止的凭空判胜),现在改 `pending`;且当旁边存在 `graphflow-graph.sqlite` 时拒绝写 JSON 存储并给出指引(这正是 1.28.0 费力合并回来的分叉)。实测该脚本从未跑过(无 `source: backfill:*` 的 episode)。 - 新增 `tests/outcome-reconciler.test.ts`(9 例,含真 git 仓库):无 verify 命令不写、命令失败不写、绿+命中文件才 pass、出处与 `userConfirmed:false`、无命中的 commit 不写、dry-run 不写、无 lesson 的 pass 被标记。 - **顺带修一个真 bug**:`loadAllEpisodes` 走 `client.queryByKeyword`,而 SQLite 的关键字查询是 `LIMIT 200`(`sqlite-client.ts:280,290`)——名字叫 "All",实际第 201 条起静默消失,影响 `memory list`、飞轮报告与 outcome 回填。现在优先读整快照,读不到快照才退回关键字查询。`tests/outcome-reconciler.test.ts` 用 201 条 episode 钉住这条。 ### Fixed — 测试把 179 条 `force a failure` episode 写进了本仓库的真实存储 `tests/m17-release-readiness.test.ts` 用 `transport: "mcp-http"` + 死端点做"provider 不可用→桥接委托"的回归,但配置里没有 `workspaceRoot`:客户端工厂退回默认存储,而默认存储按当前工作目录解析到这个仓库的 `graphflow-out/graphflow-graph.sqlite`。于是每次跑测试都往里追加 episode,累积 179 条同名噪声——**selfcheck 那个"pending ratio 95%"很大程度是这个假象**。两处配置都钉到临时目录;跑完整个测试套(228 文件 / 1770 测试全绿)后 episode 数从 191 到 191,不再增长。存量脏数据需要显式清理(`graphflow learn forget` 是全清,不是筛选),所以留给作者决定。 ### Added — 锚点带正文:bodyCoverage 从 1% 抬起来 自家保真度实测:`averageAnchorRecallPercent 92` 而 `averageBodyCoveragePercent 1`——包能点名正确的符号,却几乎不覆盖它的正文,于是 agent 还得再发一次 expand 或整读文件,首包省下的又被后续轮次吃回去。 - 符号节点记录声明范围:`DeclaredSymbol.endLine`(TS 走编译器 API 的 `sourceNode.getEnd()`),`file-indexer-nodes.ts` 写进 `metadata.endLine`。**需要重索引**才拿得到;没有 endLine 的旧节点一律不附正文(计入 `noExtent`),不会拿旧行号猜一个窗口。 - `metadata.signature` 现在只在解析器真给出签名时写。原先它存的是 `kind name @file:line` 这种显示串,任何"拿磁盘文本对一对"的核验都会把它当签名,从而误判。 - 打包新增正文阶段(`src/graph/anchor-bodies.ts`):前 3 个 L1 符号锚点各附 ≤120 token 的声明正文,整包正文 ≤20% 预算(上限按"含正在附加的这条"判定,否则最后一条会超额一档:实测曾出现 300 上限装到 344),并且**只花锚点阶段剩下的预算**——锚点永不被正文挤掉,对话仍保持它原有的"所有代码锚点之后"的纯增量位。`enableSymbolBodies: false` 可关。 - 不可信就不给:磁盘上的声明头与存储签名不符 → 不附(`unverified`);预算不足 → `noBudget`。`graphflow_context` / `context preview` 的返回新增 `anchorBodies: { attached, tokens, noExtent, unverified, noBudget }`,成本与缺口都可见。 - `expandAnchor` 现在返回 `verified: "exact" | "relocated" | "drifted"`:符号在上次索引后被人插了行,就按磁盘实际位置给窗口并报 `relocated`;签名已不在文件里则报 `drifted` 且不假装是正确代码。`endLine` 只细化默认窗口,`GRAPHFLOW_EXPAND_SYMBOL_AFTER` 仍是硬上限(`tests/m50-expand-anchor.test.ts` 的既有契约不变)。 - 代价如实记:正文是真源码,每包最多约 360 token,节省率会按已记账口径下移;`m109` 的 raw 基线门改为把正文档位计入,而不是假装它免费。检索侧无回退:`bench:retrieval` Hit@5 99.2% / MRR 0.748 / NDCG@5 0.619,与不附正文时一致。 - 新增 `tests/anchor-bodies.test.ts`(7 例:范围与签名入库、附正文、漂移时不附、正文不挤锚点 + 开关、expand 的 exact/relocated/drifted 三态)。 - 另按 `benchmarks/flywheel-proof-claims.json` 的 disclaimer 纠正一次误操作:`52330de` 把跑过评测的 `benchmarks/RETRIEVAL-EVAL-RESULTS.md` 一起提交了,而该 catalog 把这个文件当"冻结对照目标",导致 `flywheel-proof` 的声明门失败;已按 `cdfdb6e` 恢复。要重新基线请显式改 catalog。 ### Fixed — 语义召回臂其实从未接上,`.hnsw` 派生副本零命中 本机实测本仓库(1.28.1):8811 个节点里 **0 个带向量**;`graphflow-out/vectors.hnsw` 里只有 **1 个**向量;`graphflow-out/vectors.db` 从来没有写入者,却出现在配置默认值、README、threat-model 和 `audit --privacy` 的产物清单里。 - **索引拿不到 provider**:`buildIndexOptions` 的返回类型里就没有 `embeddingProvider`,于是索引期的 `embedAndAttachNodes` 和索引后的重算都不会跑——向量臂恒空,只有 episode 参与。已接入(`src/surfaces/cli/runtime/graph.ts`)。 - **重算只"换模型",从不补第一份**:旧 `refreshStaleEmbeddings` 的判定是 `if (!emb) return false`,新库因此永远停在 0 向量。改名 `ensureEmbeddings`,缺失与过期共用一份预算、过期优先。 - **每轮有预算**:单次索引 256 个向量 / 2 秒上限(`DEFAULT_EMBEDDING_RUN_LIMIT`、`DEFAULT_EMBEDDING_RUN_DEADLINE_MS`),`graph index .` 实测 5.9 秒、无延迟回归;`learn nightly` 用 1024 / 30 秒继续收敛(大库分几轮跑完)。`graph index --json` 新增 `vectorBackfill: { missing, stale, refreshed, fingerprint, budget }`,`diagnose` 的 `embeddingQuality.vectorBackfill` 同步。后端退回哈希时只补缺、绝不覆盖语义向量。 - **episode 绕开了量化存储**:`recordEpisode` 直接写 float32 `metadata.embedding`,既不吃 1.28.0 的 int8,也不带模型指纹——本仓库 186 个 episode 全是这种 384 维哈希向量,换成语义模型后被 `filterCompatibleEmbeddingNodes` 整批滤掉。改走 `attachEmbedding`,无指纹的旧向量按"过期"迁移。实测:int8 向量 0 → 1692,遗留 float32 186 → 0,存储 24MB → 28MB。 - **删除零命中的 `.hnsw` 持久化**:那是节点 metadata 里同一批向量**反量化后的 float32 副本**(每维 4 字节,比源大 4 倍),而它的指纹按**当前查询的候选集**算(默认 `enableFullGraphVectorRecall: false`,候选集就是关键词命中)——换个查询就作废,等于每次召回写盘、几乎永不回读。向量的权威只留 `metadata.embeddingQ` 一份;已落盘的 `vectors.hnsw` 从此无人读写,可直接删。 - **随之移除**:`embeddingPolicy.vectorStorePath`(存量配置里的该键被静默忽略)、`OrchestrateOptions.hnswIndexPath`、全图重建时对 `.graphflow-cache/vectors.db` 的空删;`src/learning/hnsw-index.ts` → `vector-index.ts`,`HnswVectorIndex` → `LinearVectorIndex`,删掉空壳 `save()` / `loadIndex()` / `forceLinear` / `linearThreshold`(hnswlib-node 早在 P1 就移除了,`backend` 一直如实返回 `"linear"`)。 - **文档与审计面同步**:README 配置表去掉 `vectorStorePath`、模块树注释去掉 hnsw;`docs/threat-model.md` 落盘清单去掉 `vectors.db` / `.hnsw`;`audit --privacy` 不再列一个永不存在的产物;`docs/comparison.md` 的 "RRF / HNSW" 改为"精确余弦 + RRF"。 - **测试**:`tests/hnsw-persistence.test.ts` → `tests/vector-index.test.ts`(memo 命中、候选集变化重建、维度不符跳过,外加"不再写盘"守卫);`m128` 补"给从没向量的节点补第一份"用例,并把哈希后端不降级的断言改成 `stale=1 / refreshed=0`;golden 集里 `"hnsw approximate nearest neighbor index"` 改为 `"brute force cosine scan over node vectors"`(`expectAny: ["vector-index"]`),同步 `benchmarks/retrieval-golden-data.ts` 与导出数据集。 - **指标如实记账**:语义臂刚接通(每轮只有几百个向量),检索质量暂时持平——同一提交用只读 worktree 对照跑 `bench:retrieval`:Hit@1 57.6% → 56.8%、Hit@3 92.4% → 92.4%、Hit@5 99.2% → 99.2%、MRR 0.752 → 0.748、NDCG@5 0.620 → 0.619;`retrieval-golden` 的排名漂移门(±2 位、≤12 条)在**未刷新基线**的情况下通过(132/132 命中)。索引延迟量级不变:本仓库 `graph index .`(623 文件)5.9 秒。收益要等存储收敛(`enableFullGraphVectorRecall` + 全量向量)才会显形。 ### Fixed — 过渡期 SQLite 漏掉旧宿主索引过的文件(1.28.1) 1.28.0 发布后本机实测:Cursor 里仍在跑的 1.27 运行时(JSON 存储)把新文件索引进 JSON,并写入**共用的** `.graphflow-cache/index-state.json`;合并又跳过代码节点,于是 SQLite 把这些文件当成"未改动",永远不会索引(本仓库新增的 `store-migration.ts` 等在 SQLite 里查不到)。 - 每个存储用自己的索引清单:SQLite 用 `index-state.sqlite.json`(`GraphClient.indexManifestName`,经包装层透传),JSON / 内存存储仍用 `index-state.json`。`hasPendingGraphIndexWork` / `hasIndexCache` / diagnose / selfcheck / metrics 按当前存储选清单(`resolveIndexManifestName`)。 - 合并不再清空索引清单(1.28.0 会清掉旧宿主的清单,逼它全量重解析)。 - 清单为空时(首次或刚从共用清单切过来),顺带删除磁盘上已不存在的文件节点,清理分叉期间漏删的残留。 - 升级后 SQLite 首次索引会全量解析一次(本仓库 623 个文件约 3 秒),之后恢复增量。 ### Fixed — 同一项目换 Agent 工具后图谱与记忆分叉成两份 设计上所有宿主按项目共享一份图谱,但实测分成了两份:VS Code/Cursor 扩展与共享 MCP 运行时(`~/.graphflow/runtime`,Cursor / Cline / ZCode 都连它)**没有打包 `better-sqlite3` 和 `@huggingface/transformers`**,于是悄悄退回 JSON 存储 + 哈希向量;npm 包(DSH、CLI)用的是 SQLite + bge。本仓库实测:JSON 里有 167 个 episode,SQLite 里只有 12 个;两边还共用同一份增量索引清单,一边索引过的文件在另一边被当成"未改动"。 - **运行时依赖按需安装**(新增 `src/integrations/ensure-runtime-deps.ts`、`src/utils/optional-deps.ts`):装到 `~/.graphflow/optional-deps`;`better-sqlite3` 按运行时分目录(`sqlite-node-abi127` / `sqlite-electron-abi…`,扩展宿主是 Electron、MCP 是 node),transformers 是 N-API 共用。触发点:MCP 启动 15 秒后后台检查、扩展激活、`graphflow install`;手动 `graphflow deps status` / `graphflow deps install [--force] [--with-model]`。文件锁防并发,失败 24 小时内后台不重试;`GRAPHFLOW_OPTIONAL_DEPS_AUTO=0`、CI、vitest 下不自动装;扩展设置 `graphflow.downloadRuntimeDeps`。安装 transformers 时设 `ONNXRUNTIME_NODE_INSTALL=skip`(否则 linux-x64 上 onnxruntime-node 的 postinstall 去 NuGet 下 CUDA 库,网络不通就整个安装失败;推理用包内自带的 CPU 版);安装前把以 `--no-save` 装的 anydoc 登记进 `package.json`,否则 npm 会把它当多余包删掉。 - **JSON 存储自动并入 SQLite**(新增 `src/graph/store-migration.ts`):SQLite 打开时若旁边有同名 `.json`,把记忆节点并入——代码节点(File / Symbol / Module)跳过,由磁盘重新索引,避免复活已删文件的符号;同 id 取 `updatedAt` 较新者;对话轮 id `dialogue::` 冲突(两个宿主在同一 session 里各自往下记)时顺延编号、改写 `parentTurnId` 并修正 session 的 `turnCount` / `tipTurnId`;两端缺失的边丢弃。JSON 与 delta 改名为 `*.merged-bak`(首份永久保留,之后只轮换一份 `.merged-bak.latest`),统计写入 `*.sqlite.merge-log.json`。单事务写入(`GraphifySqliteClient.upsertGraphSync`);失败则保留 JSON,下次打开重试。本仓库实测:并入 244 个记忆节点、797 条边,SQLite 里 episode 从 12 个变为 180 个。 - **`graph index --full` 不再清掉记忆**(新增 `src/graph/memory-subgraph.ts`):重建前取出所有非代码节点及相连的边,关闭旧客户端(连同删除 `-wal` / `-shm`)后清库重建,再写回;指向已删代码节点的边丢弃。结果带 `preservedMemory`。 - **`diagnose` 新增 `graphStore` 段**:`transport`、实际后端、`sqliteModuleSource`(bundled / optional-deps)、退回 JSON 的原因、是否存在未合并的 JSON、上次合并统计、各运行时依赖的来源与加载错误。 ### Changed — 默认用量化向量模型,向量带模型指纹 - 本地模型默认 `Xenova/bge-base-zh-v1.5` 的 **q8** 版(`onnx/model_quantized.onnx`,约 98MB;fp32 约 400MB,经 hf-mirror 实测 400 秒下载超时、静默退回哈希)。`embeddingPolicy.dtype` / `GRAPHFLOW_EMBEDDING_DTYPE`(优先)可选 `fp32` / `fp16` / `q8` / `q4`。模型缓存默认放 `~/.graphflow/models`,所有宿主共用;原先缓存在 transformers 包目录里,每份打包副本各下一遍,npm 升级还会删掉。 - 每个向量在 `embeddingQ.model` 记录模型指纹(`Xenova/bge-base-zh-v1.5@q8`、`fnv1a-384`、`openai:`)。向量召回只比较维度相同、指纹相同的向量(旧的无指纹向量视为兼容),跳过数计入 `embeddingQuality.incompatibleVectorsSkipped`;此前 768 维 bge 与 384 维哈希向量混在一起时,余弦相似度直接得 0。 - 索引结束后按批(每次最多 256 个)用当前模型重算指纹不符的旧向量(新增 `src/learning/embedding-refresh.ts`);当前后端是哈希时不动,模型临时加载失败不会把语义向量降级。进度见 `embeddingQuality.staleVectors`。 - `graphflow deps install --with-model` 预下载模型并按 10% 打印进度。 **实测**(5 篇代码片段、8 个中英文查询):哈希向量 Hit@1 2/8、MRR 0.504;bge q8 Hit@1 6/8、MRR 0.875,加载加 8 次查询 0.8 秒。共享运行时副本上 `deps install --with-model` 装好两个依赖并下载模型;随后该运行时改用 SQLite(`sqliteModuleSource: optional-deps`),并合并了 Cursor 旧运行时新写出的 JSON。 ### Fixed — 「知识节点」面板在 Cordis 4 宿主上从未注册成功(`cannot get property "connection" without inject`) 1.27.12 真机启动日志:`[graphflow-dsh] /gf RPC: registerNodesRpcChannel threw: cannot get property "connection" without inject`。#26 在 1.14.1 的"修复"与 1.27.11 的复核都只对照了源码、用宽松的假 ctx 测试,**从未在真实 Cordis 下跑过**——这次用 DSH 自带的 `@deepseek-ai/cordis` 4.0.4 与真实 `HostConnectionService` 复现后,发现两层问题: 1. **读未声明的服务直接抛错。** Cordis 4 的 ctx 代理对 fiber 未 inject 的任何属性(`ctx.connection`、`ctx.rpc`、`ctx.effect`)都抛 `cannot get property … without inject`。glue 在走到 `ctx.inject` 之前先同步读了 `ctx.connection`,整个注册中断。修法:Cordis 宿主上只在 `ctx.inject(["connection"])` 的 fork 里注册;所有鸭子类型读取都经 `readProperty` 保护;优先用属性访问取服务(Cordis 会把服务绑定到读取它的 fork)。 2. **`connection.rpc.handle` 对第三方插件在 DSH 上不可用。** 它经 `owner.webServer.register` 挂路由,而 service 内部的 `this.ctx` 带 shadow,服务解析走的是 **Connection 插件自己的 fiber**;DSH 挂载该行时只注入 `credentials` + `webRuntime`,于是无论调用方怎么声明 inject(静态 / `ctx.inject` / 对象形式,四种写法实测全部失败)都报 `cannot get property "webServer" without inject`。DSH 自身也没有任何代码调用 `rpc.handle`。修法:改用 `connection.fetch.register` 注册精确 Fetch 路由 `POST /api/gf/nodes`(只用 `owner.effect`,挂在 Connection 自己的 `/api` 路由下,鉴权/Origin 围栏与 `/api` 相同),应答与 unary RPC 相同的 `server-response` 信封;宿主没有 Fetch 注册表时回退 `rpc.handle("/gf")`。前端改为 `rpc.call("/api", "gf/nodes")`,404 时回退 `/gf`。 **验证**:真实 Cordis 4.0.4 + 真实 `HostConnectionService` + connection 自己的 `/api` 共享 Fetch 处理器,请求 `POST /api/gf/nodes` → HTTP 200、`server-response`、返回本仓库 24 个 workbench 主题与 50 条对话;同一脚本对 1.27.12 精确复现线上报错并得到 404。新增用例:严格 Cordis 代理(读未声明属性即抛错)下不读未声明服务、从 inject fork 注册;Fetch 路由的信封(非 JSON → 400、坏信封 → bad-request、缺 workspace → no-workspace);前端 404 回退。 ### Fixed — DSH 每轮报 `Cannot read properties of undefined (reading 'kind')` 真机(DSH 0.1.7-rc.2,`dsh web`)复测时,首轮报 #55 的 `format v4 message requires a producer-owned source kind`(profile 里仍锁着 1.18.5),随后每一轮都报 `Cannot read properties of undefined (reading 'kind')`。 根因在 glue 的 `agent/pre-step` 监听器:`await next()` 被 `try { … } catch { return undefined; }` 包住。`dsh-agent-loop` 的 `preStep()` 在 waterfall 之后立刻读 `decision.kind`,于是上游任何失败(中止信号、其他插件抛错、上一轮遗留的准入失败)都被改写成 `undefined` 决策,报一个与真实原因无关的 TypeError。DSH 自带监听器(`dsh-time-context`、`dsh-plan-mode` 等)都是直接 `await next()`、让错误原样上抛。 - 监听器改为 `const decision = await next()`,不再吞掉上游错误;只有 GraphFlow 自己追加 hint 的那一步仍然容错(失败时原样返回上游决策)。 - 新增用例:上游 `next()` 抛出的错误原样传播,而不是返回 `undefined`。 ### Fixed — DSH 会话格式 v4:首轮 hint 用了已退役的 `kind: "plugin"`,整轮失败(#55) `dsh/plugin.mjs` 的 `buildHintMessage()` 给注入的首轮 hint 打的是 v3 的 `source.kind: "plugin"`。DSH 会话格式 v4 的原生准入(`dsh-session-format-v3-to-v4` 的 `source(message)`)对 `"plugin"` **硬拒绝**:`format v4 message requires a producer-owned source kind`,报在落盘阶段,所以是整轮失败而不是丢一条消息。 - hint 改用 v4 第三方生产者形式 `plugin:graphflow-dsh`(与官方迁移模块 `producerKind()` 对第三方插件的映射一致)。 - `isUserOriginatedMessage()` 同步识别 `plugin:*` 前缀,以及 v4 的一方生产者 kind(`runtime-context` / `system-prompt` / `compact-checkpoint` / `time-context` / `plan-mode` / `tool-jobs` / `user-approval` / `cordis-host-runner` 等,取自官方 `RENAMED_PRODUCERS` 与 `RELEASED_SAME_NAME_PRODUCERS`)。否则这些 `role: "user"` 的宿主注入会走兜底分支、被当成真人提问记进对话图。`webhook` 有意不列入:它可能转发外部渠道的真人消息。 - 新增用例:hint 通过 v4 准入规则;v4 生产者 kind 与 `plugin:*` 均不被记录为用户消息。 ### Fixed — dsh web 半边注入了已被取代的 `@deepseek-ai/dsh-client-runtime`(#54) `package.json` 的 `dsh.client.inject` 仍列着 2026-08 起不再发布的 `dsh-client-runtime`。当前 harness 的 client-modules 用 `inject` 决定 web 半边的加载顺序(找不到的包直接跳过),所以我们声明的服务依赖根本没有被排序保证。 - `inject` 改为 `dsh/client.js` 实际使用的三个服务的提供者(逐包核对 0.2.0-rc.2 源码):`sessions` ← `@deepseek-ai/dsh-api-session-controller`,`connection` ← `@deepseek-ai/dsh-client-connection`,`slots` ← `@deepseek-ai/dsh-client-ui-renderer`。 - 新增用例:`inject` 不含 `dsh-client-runtime`,且包含上述三个提供者。 ### Verified — 「知识节点」面板 `POST /gf/nodes` 405(#26) 服务端部分已在 1.14.1(PR #34)修复:`/gf` 通道在 `connection` 未就绪时经 `ctx.inject(["connection"])` 等待注册,失败写日志不再静默。本次对照 `dsh-client-connection` 0.2.0-rc.2 复核:`rpc.handle(channel, handler)` 仍以 prefix 路由挂到 `webServer`,handler 签名 `(endpoint, payload, signal)`、前端 `rpc.call(channel, endpoint, payload)` 均兼容。web 半边的注入目标问题由 #54 一并修复。 ### Fixed — 项目规则的源文件解析差了一级 `..`,发布包里永远"找不到源文件" 用户 Ubuntu / Windows 的安装日志里有一整片"静默失败": - `[SKIP] Trae Skill Trae: Skill source (SKILL.md) not found` - `[SKIP] Cursor Rules Cursor: Cursor rules source (graphflow.mdc) not found` - `[SKIP] Project rules Trae CN / Cursor / Antigravity / Copilot: Source file not found` **源文件明明在发布包里**(`dist/surfaces/...`、`skills/graphflow` 一项不少)。问题在 5 个解析函数:从 `dist/integrations/` 出发,它们用 `join(__dirname, "..", "..", "surfaces", ...)` 去找源文件——两级 `..` 落到的是**不存在的 `/surfaces/`**,正确位置是上一级的 `dist/surfaces/`。唯一能命中的候选是 `process.cwd()` 那几条,也就是说:**只有 CWD 恰好是仓库检出目录时才找得到**。用户在自己项目里跑,永远 not found;我之前在仓库里测,永远成功——**尺子一直量的是错误的东西**。 修法:5 处各减一级 `..`(`surfaces` 用 `join(__dirname, "..", ...)`,`skills` 用两级到包根)。同一表达式同时覆盖构建布局(`dist/integrations`→`dist/surfaces`)与源码布局(`src/integrations`→`src/surfaces`)。`CLAUDE.md` 那处本来就是对的(包根真有 `CLAUDE.md`),没动。 本机实测(普通项目目录,非仓库):copilot / cursor / trae / skill 四个解析器全部命中包内路径;`install` 一次写出 10 个项目文件(`.trae/rules`、`.trae/skills`、`.cursor/rules`、`.agent/rules+skills`、`.github/copilot-instructions.md`、`.claude/rules`、`.windsurfrules`、`AGENTS.md`),此前这些全是 SKIP。 `tests/vendored-source-resolution.test.ts`(4 用例):把 CWD 切到临时空目录再解析——**不靠 CWD 运气**。已验证有牙:改回一处旧路径 → 1 个失败。 ### Fixed — home 目录守卫的测试只在 Linux 上成立,Windows 上 3 个用例失败 1.27.9 的 CI 在 `windows-latest` 上红了,3 个用例失败。**生产代码是对的,错的是我的测试。** `os.homedir()` 在 Linux 上读 `HOME`、在 Windows 上读 `USERPROFILE`。我用 `process.env.HOME = <临时目录>` 来假扮 home——这在 Linux 上成立,在 Windows 上**完全无效**,于是沙箱从来不是 home,守卫正确地没有触发,测试却断言它应该触发。 这类错误值得单列,因为它和「平台差异让测试全绿不等于行为正确」是同一个坑,只是方向相反:上一版是**代码有 bug 而 Linux 测不出来**,这一版是**测试的前提不成立而 Linux 测不出来**。两次都是"本地量的是错的东西"。 - 沙箱现在同时设置 `HOME` 与 `USERPROFILE`,并逐个平台断言前提成立(`homedir() === sandbox` 且 `isUnsafeWorkspaceFallback(sandbox) === true`)——前提不成立时会**直接说前提没成立**,而不是让三个下游断言带着误导性的信息失败。 - 两个"真实项目目录照常写入"的用例补上 `isUnsafeWorkspaceFallback(project) === false`,坐实守卫看的是 root 本身,不是"某个 home 存在"。 - 7 个用例(+1 前提用例),两个守卫仍**分别验证有牙**。 **这一版的教训**:跨平台测试里,"构造前置条件"本身就是要测的东西。凡是用环境变量伪造平台行为的测试,先断言伪造生效,再断言行为。 ## [1.28.1] - 2026-09-29 每个存储改用自己的增量索引清单(SQLite 用 `index-state.sqlite.json`):过渡期里仍在 JSON 存储上的旧宿主索引过的文件,不再被 SQLite 当成"未改动"而漏掉;合并也不再清空旧宿主的清单。 ## [1.28.0] - 2026-09-29 同一项目换 Agent 工具(Cursor / ZCode / Cline / DSH)后图谱与记忆不再分成两份:共享运行时按需安装 better-sqlite3 与 transformers,旧 JSON 存储里的记忆自动并入 SQLite,`graph index --full` 保留记忆。默认改用 q8 量化的 bge 模型(约 98MB),缓存由所有宿主共用;向量带模型指纹,换模型后逐批重算。 ## [1.27.13] - 2026-09-29 修复 DSH「知识节点」面板在 Cordis 4 宿主上从未注册成功:改用 `connection.fetch.register`(`POST /api/gf/nodes`),并且只在 `ctx.inject(["connection"])` 的 fork 里读取服务。已在真实 Cordis 4.0.4 + 真实 `HostConnectionService` 下端到端验证。 ## [1.27.12] - 2026-09-29 修复 DSH 中每轮报 `Cannot read properties of undefined (reading 'kind')`:glue 的 `agent/pre-step` 监听器不再吞掉上游错误并返回 `undefined` 决策。 ## [1.27.11] - 2026-09-29 修复 DeepSeek Harness 插件三处问题:会话格式 v4 下首轮 hint 使整轮失败(#55)、web 半边注入已被取代的 `dsh-client-runtime`(#54),并复核「知识节点」面板 `/gf` 通道(#26)。 ## [1.27.10] - 2026-09-29 修复 home 目录守卫测试只在 Linux 成立的问题(Windows CI 3 个用例失败),并为跨平台前提增加显式断言。 ## [1.27.9] - 2026-09-29 修复项目规则源文件解析差一级目录:Trae / Cursor / Antigravity / Copilot 的项目规则与 Skill 在发布包里永远报 Source file not found(Ubuntu / Windows 日志均有)。 ## [1.27.8] - 2026-09-29 修复从 home 目录运行 install 会把项目文件写进 home 并覆盖带标记的指令文件(Ubuntu / Windows 均复现)。 ## [1.27.7] - 2026-09-29 自检脚本修 Windows 上「MCP 检查被静默跳过」;文档补 Windows EBUSY 与镜像延迟的处理。 ## [1.27.6] - 2026-09-29 新增 `scripts/cross-platform-check.mjs`:Ubuntu / Windows 同一套命令的自检脚本,含中文编码往返检测。 ## [1.27.5] - 2026-09-29 测试文档再修:summary 不在最后一行;取该行必须用 spawnSync 而非 execSync(doctor 在 ok=false 时非零退出)。 ## [1.27.4] - 2026-09-29 修正测试文档的 Windows 不可用命令(`grep` 等),改用跨平台的 Node 单行脚本。 ## [1.27.3] - 2026-09-29 修复 CLI 帮助文本混入 stdout 破坏脚本消费;清理仓库内测试产物。 ## [1.27.2] - 2026-09-29 修复多词查询召回归零:FTS 把英文 token 用 AND 串联,任何两词以上查询都要求单节点全命中。 ## [1.27.1] - 2026-09-29 修复用户实测报出的两个安装级缺陷:`onnxruntime-node` 安装失败中断整包安装(非 Windows 上 appData 解析为空字符串,宿主配置被写进用户仓库)。详见下方条目。 ## [1.27.0] - 2026-09-29 上下文经济引擎(新鲜度预言机 / 前缀 churn 计价 / 能力地板 / Prefix Cache Planner / Project Brief)全量落地,`npm audit` 清零,工作区构建偏好覆盖全部 19 个宿主 + dsh。本段汇总,其后各条目为该版本的详细记录。 ### Added — 记忆新鲜度预言机 + 上下文经济引擎(均默认关,显式 opt-in) - **记忆新鲜度预言机(`GRAPHFLOW_FRESHNESS=1`)**:技能新鲜度由**代码图谱**裁定——从 guidance/playbook 抽出的符号引用若在图里不再解析,说明代码在这个技能脚下动过。符号节点 id 内嵌内容哈希,代码一改 id 即退役、引用即失配;这是没有代码图的记忆层(Mem0 / Zep·Graphiti / Letta / Cognee)结构上给不出的信号。分级 `fresh` / `watch` / `stale` / `unknown`——判不了就明说 `unknown`,不假装 `fresh`。`graphflow_skill_insights` 与 CLI `skill insights` 每条技能附带 `freshness`(level / driftScore / staleRefs / reason)。`stale` 的 proven 技能是**比缺失更坏**的失效模式:它带着过去证据的自信继续错。降级策略 `evaluateFreshnessPolicy` 已实现(stale+proven → correctable;watch 不降级;canary 已验证者豁免),但**自动降级刻意未接线**——`GRAPHFLOW_FRESHNESS_DOWNGRADE` 仅预留开关,先观测再强制。 - **上下文经济引擎(`GRAPHFLOW_CONTEXT_ECONOMICS=1`)**:把"省了多少 token"之外的那根轴补齐——**前缀 churn 与缓存局部性**。GraphFlow 每轮注入不同上下文包,这在结构上必然改写 provider 的 prompt 缓存前缀;此前 95.6% 的 prefill 节省从未与缓存命中率放进同一张表算过。新增 `economics` 字段:与上一轮包的前缀 churn(sharedPrefix / churnRatio)、可缓存 token 与 hitRate(尊重 provider 最小可缓存长度)、按 0.1x 读 / 1.25x 写定价的**真实输入成本**(显式计入 cache write 税)、以及**注意力预算**(context rot 阈值 ~70%,而非窗口占用率)。`verdict` 三态:`cache-safe` / `prefix-churn` / `cache-cold`——**高节省率配 `prefix-churn` 是一条警告:便宜的 token 是用冷缓存换来的**。 - **弃权(`GRAPHFLOW_ABSTAIN=1`)**:渐进式披露买的是 context 不是智能——小语料且查询命中具体符号时,agent 自己读那一段比下发一个包更便宜,且不打碎前缀。`abstention: { abstained, reason }` **显式**下发并附理由(静默弃权与"工具坏了"不可区分)。强制执行(真丢锚点)**暂不开启**:需先过能力地板 A/B 证明净收益。 - **能力地板 + 弃权 A/B(`GRAPHFLOW_ABSTAIN_ENFORCE=1`,默认关)**:见下方"弃权 A/B 实测"。 ### 能力地板(`src/graph/abstention-floor.ts`) `shouldAbstain` 只给 GraphFlow 一侧定价,而弃权真正交换的是**精选摘录 ↔ 整文件读取**——一次文件读比它替代的锚点行贵一个数量级。所以地板不问"agent 找不找得到",而问**"agent 能不能以不更贵的代价抵达同一份证据"**,三道门全过才算数(`breachedGate` 报第一道否决的门,理由指名决定性反对而非最后检查的门;**所有门都会测量**,因为部分报告无法说明其余问题是轻微还是灾难): 1. **可达性(≥95%)**——每条锚点的信息都必须能经某个 handle 取回。`module:foo` 说的正是 `foo.ts` 里的东西,handle 已覆盖它,丢掉不损失;`dialogue:*` 决策记录是 agent 学到而**任何文件里都没有**的东西,读不回来。**丢证据不是 token 交易,是能力损失。** 2. **文件数(≤2)**——有界导航。超过两个文件,agent 就是在**手工做检索**(GraphFlow 存在的意义),而且下面的成本模型不再诚实(真实 agent 会搜文件而不是整份吞下)。 3. **读放大(≤1.1x)**——handle 与读取的**总代价**不得超过它替代的包。**handle 不是免费的**:实测一个 45 tok 的包被 42 tok 的读取 + 9 tok 的 handle 替代,是净亏 6 tok。 地板**可否决** `shouldAbstain` 的乐观判定:语料小到满足启发式,若指向的文件比包本身更贵,包照发。 ### 弃权 A/B 实测(真实检索,两语料,配对) **A. 真实代码**(`src/graph/language-indexers` 复制件:16 文件 / 2.4–17KB / 114 符号)——**0/12 通过**: | 查询 | 包 tok | 锚点 | handle | 文件 | 读取 tok | 倍率 | 否决门 | | --- | --- | --- | --- | --- | --- | --- | --- | | `analyzeStCode` | 329 | 15 | 6 | 6 | 13696 | 41.8x | reachability | | `walkTreeSitterAst` | 371 | 15 | 6 | 6 | 10797 | 29.4x | reachability | | `st-analyzer.ts` | 338 | 15 | 6 | 6 | 13696 | 40.5x | reachability | 真实代码上弃权是 **27–42x 的 token 倒退**,且会丢掉 `dialogue:*` 决策层(包里约 20% 的锚点不在任何文件中)。 **B. 微文件**(124–169 字节/文件,干净副本 + `recordDialogue:false`)——**2/4 通过并真的执行**:`joinLines` 0.91x 省 4 tok、`trimAll` 0.78x 省 10 tok;`tokenize`/`detokenize` 1.13x 被正确否决。 **结论:弃权在 GraphFlow 上是自毁的**——整个产品价值就是那份压缩(实测压缩比约 30x),要让弃权划算,压缩比必须 <1.1x,也就是包得和原始文件一样贵,那等于 GraphFlow 没做事。唯一划算的区间是**微文件**(单文件约 10–20 行,15 条锚点本身就比整个文件贵),而那里绝对收益是**个位数 token**。`GRAPHFLOW_ABSTAIN_ENFORCE` 因此**永久保持默认关**——不是"等 A/B 证明",是 A/B 已经证明它不成立。 **A/B 揪出的三个真 bug(都是我自己写的)**: - **地板第 3 道门原本只把"读取"和包比**,忽略了 handle 自身的开销,于是放行了一个净亏 6 tok 的委派。现按 `handleTokens + readTokens` 比,并加了精确对应此案的回归测试。 - **可达性原本问"每条锚点有没有路径"**——错问。`module:foo` 的信息就在 `foo.ts` 里,判成"丢证据"等于因零成本差异否决地板。改成问"信息是否能经某个 handle 取回"。 - **`shouldAbstain` 的 `queryHasConcreteRef` 用 `extractSymbolCandidates` 判具体引用**,而该模式只认 camelCase / 路径 / 调用语法——于是 `tokenize` 这种**最具体**的引用被判成"没有具体引用",恰好堵死弃权最该触发的场景。改为 `queryNamesGraphNode` 直接对图谱求证(文本启发式会漏,证据不会)。 ### Fixed - **前缀模型此前把宿主静态前缀当成 churn 部分**(live 验证发现):`buildContextEconomics` 一度只把 GraphFlow 注入的包当作"整个前缀",于是 540 tok 的包被判 `cache-cold`(低于 provider 最小可缓存长度)——**用一个切片的尺度否定整个请求的缓存能力**。现按 `prefix = staticPrefixTokens + package` 建模,且**只有我们的切片参与 churn**(宿主静态前缀按定义稳定)。宿主前缀 GraphFlow 看不见(它不是 harness),由 `GRAPHFLOW_STATIC_PREFIX_TOKENS` 提供;缺省 0 = 纯切片模型,非法值安全回退 0。 - **首次观测不再谎报 100% churn**:`PrefixChurn.firstObservation` 标记"本进程尚未注入过包",此时 churn 不可测。 - **技能引用也来自 name**:task-echo 类技能把主体写在 name(如 `src/graph/context-pressure.ts`),此前只扫 guidance/description/playbook,导致这类技能恒为 `unknown`。现纳入 name,live 复验从 `unknown` 变为 `fresh`(ref 解析成功)。 - **披露:本次改动放宽了两条 golden 排名门(`topK` 3 → 4),是本次提交自己触发的**。`retrieval-golden.test.ts` 会把整个 `src/` 索引入内存库,因此**任何新增 `src/` 文件都可能推动某条查询的边界排名**。实测:新文件 `src/graph/abstention-floor.ts` 的文档散文高度 anchor 化,对含 "anchor" 的查询 `goal anchor alignment deviation` 合法地排到 #2,把 `goal-anchor` 从 #3 挤到 #4;`graph-utils.ts` 新增 `queryNamesGraphNode` 使该文件符号 id 变化,`st-analyzer` 从 #3 移到 #4。**召回断言未变,两条期望锚点都仍在包内**——被放宽的只是"排名稳定性"这一层启发式。已 `git stash` 复验:干净树上 148/148 通过,确认不是检索逻辑回归。这是本次提交里唯一一处"改测试迁就自己"的地方,特此标明。 ### 验证(live,MCP stdio 两轮真实 tools/call) - **前缀 churn 是真的**:连续两个普通查询("orchestrator phases" → "skill flywheel admission")之间,注入包 36 行里只有 1 行保持不变,**churnRatio 0.972**,`verdict: prefix-churn`——GraphFlow 每轮注入的包基本不可跨轮复用。 - **但绝对影响受宿主前缀主导**:`GRAPHFLOW_STATIC_PREFIX_TOKENS=8000` 时 hitRate 93.7%/94.7%,输入成本相对无缓存基线省 60.9%/61.6%。默认预算(1500)下包很小,风险被静态前缀吸收;**当预算放大或检索更密时才会成为主导成本**。 - **弃权按设计不误伤大仓**:本仓 8684 节点 → `abstained: false`,理由明写 "corpus too large to navigate by reading (8684 nodes > 2000)"。 - **新鲜度在本仓可判定**:唯一技能(`列出 src/graph/context-pressure.ts 的导出符号`)判为 `fresh`(1 ref,解析成功)。 - CLI 一次性进程**测不出 churn**(`previousLines=0`):churn 状态在进程内存里,只有长驻 MCP server 跨轮可比——已用真实 stdio 两轮验证。 ### 验证(放大预算复测:前缀 churn 会成为主导成本吗?) 用真实模型 + 实测 churn 0.972 做交叉扫描(宿主静态前缀 8000 tok、$3/MTok): | 包 tokens | hitRate | 缓存总收益 | churn 代价 | 是否倒挂 | | --- | --- | --- | --- | --- | | 250 | 97.1% | $0.01609 | $0.00047 | 否 | | 500 | 94.3% | $0.01657 | $0.00095 | 否 | | 2 000 | 80.6% | $0.01950 | $0.00379 | 否 | | 8 000 | 51.4% | $0.03120 | $0.01517 | 否 | | 32 000 | 22.2% | $0.07800 | $0.06067 | 否 | | 64 000 | 13.6% | $0.12133 | $0.12133 | 接近打平,仍未倒挂 | - **结论(推翻本项目此前的判断)**:只要宿主有一段稳定的 system+tools 前缀,**前缀 churn 在任何现实包尺寸下都不会超过缓存的总收益**——要到约 64k tok 的注入包才接近打平,那是典型 agent 整个上下文窗口的两倍。**"churn 击穿缓存"是二阶效应,不是一阶架构风险。** 此前把"缓存局部性"列为最严重暴露面属**高估**,此处按实测更正。 - **真正的约束是检索召回,不是预算**:`--max-anchors 15 / 60 / 200` 三档下锚点数恒为 **3**(包 274→288 tok,仅用掉 1500 预算的 18%);放大 `maxContextTokens` 同样不会让包变大。**包小是精度换来的,不是预算限制的结果**——这正是交叉扫描结论成立的前提。 - 首轮扫描曾误用 3 行合成数组(churn 0.667)却标为 0.972,已按实测 36 行共享 1 行重算;修正后结论不变,数值全部更保守可信。 ### Fixed(第二次更正:经济引擎此前给宿主尾部定价为 0) - **注入位置的代价此前完全没被计价**(`estimateSuffixInvalidation` + `cache-break`)。缓存是**从左到右的前缀匹配**:一个字节不同,其后**每一个 token 都失效**,必须按 1.25x 重写而不是按 0.1x 读回。GraphFlow 注入的是每轮变化的内容,所以 churn 的真实代价不是我们那 500 tok 切片自身的重读,而是**它后面宿主的整条尾巴**(对话历史、既往工具结果)被一起拖出缓存。此前模型只算自己那一片,于是把一个净亏损显示成 `prefix-churn`。 - live 实测(MCP stdio 真实两轮,宿主尾部设 50k tok):churn 97.4% 时**重写 48 718 tok,税 $0.168/轮,而压缩只省 $0.0156/轮 —— 净亏 $0.152/轮**,`verdict` 由 `prefix-churn` 翻为 **`cache-break`**。 - 交叉扫描:宿主历史 **≈8k tok 起**(仅比 8k 静态前缀高一档)就越过压缩收益。也就是说**在真实长会话里,注入位置的代价大于压缩的收益**——这比上一节"churn 是二阶效应"的结论更强,且方向相反:不是被静态前缀吸收,而是**把静态前缀之后的一切都拖下水**。 - `invalidation` 与我们的 `cost` **分开上报**:我们那一片是小头,宿主的尾巴是大头,混在一个数字里必然看不见大头。`overspendUsd` 给出可直接决策的净值。 - 宿主两侧 token 数我们看不见(我们不是 harness),由 `GRAPHFLOW_SUFFIX_TOKENS` / `GRAPHFLOW_STATIC_PREFIX_TOKENS` 提供,缺省 0 = 只算自己那一片(**会系统性低估**)。 - **首观测不再凭空记一笔 churn 税**:本进程尚无前缀可破坏时 `rewrittenTokens = 0`。 **由此得到的产品级结论(比上面的数字更重要)**:把每轮变化的注入放在稳定前缀**之前**,等于每轮强制宿主重写整条历史。这与 provider 官方指引完全相反——**按稳定性排序,从最稳到最不稳,前稳后动**。因此下一步的最高杠杆不是"喂得更少"(我们已经很省,且已证明喂得少正是弃权失败的原因),而是**让注入尽量靠后、或让注入内容尽量稳定**:稳定的项目级前缀(可缓存)+ 极小的每轮增量(放在最后),才是 agent 场景里真正省钱的形状。 ### Added — Prefix Cache Planner(`GRAPHFLOW_CACHE_LAYOUT=1`,默认关,纯声明) - **为什么排在省 token 之前**:上一节的实测显示**位置**才是亏钱的那一层——压缩省的($0.0156/轮)比注入位置亏的($0.168/轮)少 10 倍。而"再喂少一点"这条路,弃权 A/B 已证明在 GraphFlow 上是自毁的(压缩比必须 <1.1x 才划算)。所以 R10-P0 选 Prefix Planner。 - **新字段 `cacheLayout`**:`stablePrefix`(跨轮稳定:repo/module map、项目约定、长期工作集)+ `delta`(每轮变化:query 锚点、对话召回、当轮工具结果)+ `reusablePrefixShare` + 一句 `note`。**保证 stable 行全部排在 delta 行之前**,宿主按 stable→delta 拼接就自动拿到正确顺序——稳定性不只是每行的属性,也是**序列的属性**。 - **只声明,不决策**(插件形态的正确形状,不是妥协):GraphFlow 是 MCP 插件,不是 harness。它**设不了 cache 断点、定不了注入位置、也阻止不了宿主重新渲染我们的行**——那些都是宿主的 API 调用。它只能说明"这 N 行稳定、这 M 行不稳定",然后被忽略。**能替宿主重排 prompt 的插件就是穿着插件外衣的 harness**,且在宿主 prompt 形状与假设不符时立刻失效。 - **无法识别的行一律归 delta**:把无法定位的行当成稳定,是唯一会**静默**破坏宿主缓存的错误,默认必须落在安全的一侧。 - **宿主前缀未知时 `reusablePrefixShare` 报 `null` 而不是 0**:0 意味着"请求里没有任何部分可复用",这是一个更强且几乎必然为假的断言;看不见就说看不见(我们不是 harness)。 - live 实测:本仓一次真实 preview,39 行中 **2 行(790 tok 中的 19 tok,2%)跨轮稳定**,其余 37 行每轮变化——**我们注入的内容本身几乎全是 per-turn 变化**,这正是"注入必须放在断点之后"在我们自己身上的直接体现,也是宿主最需要这个声明的原因。 - 首版曾漏掉 slicer 在 summary 通道里对 module 节点的散文形式(`Module: `),把它误判成易变;已补规则并加回归测试——那是**丢失**缓存复用,与本模块存在的目的相反,方向上比误判稳定更危险。 ### Added — Project Brief:让 stable 段真的有内容(`GRAPHFLOW_PROJECT_BRIEF=1`,默认关) - **动机**:上一个提交只是**声明**哪部分稳定,而 live 实测发现我们注入的内容里 **39 行只有 2 行(2%)稳定**。一个正确地声明"这里几乎没什么稳定"的声明不是缓存策略——**稳定段必须被做出来**,宿主才有东西值得放在断点之前。 - **新字段 `projectBrief`**:从**仓库本身**(而非当前问题)派生的跨轮稳定段:模块清单、文件目录分布、入口文件。所有内容**确定性排序、无时间戳、无随机、无迭代序**——宿主缓存是**字节匹配**,输出必须逐字节可复现。 - **先验证、后复用**:重建 brief 每次调用都会产生新包,正是我们要消除的 churn,而且重建本身就是贵的部分(一次模块遍历 + 导出扫描)。所以复用由**证据**把门,与新鲜度预言机同源:brief 是关于仓库的断言,而符号节点 id 内嵌内容哈希,**每个 ref 仍能解析 = 断言仍成立**。不成立就重建,**并且把重建理由说出来**——静默过期的 brief 是一张错的项目地图,比多几个 token 糟糕得多。 - **复用 `buildRefResolver` 而非另造一套**:问题是同一个问题,两套 resolver 迟早会不一致——而那种漂移会把缓存变成错误答案的来源。**并且用测试把耦合钉死**:ref 必须记成 resolver 真正索引的形式(file 记去前缀路径、其余记原始 id),否则每个 brief 都会自报过期、每次调用都重建。(实现时正是先写成了路径集合,被测试当场抓住。) - live 结果:`stablePrefix` 从 **19 tok → 678 tok**(2% → 约 30% 的包为稳定段)。 - **但 brief 里的地图一开始是错的,逐层修掉三处**(都是 live 才暴露的): 1. **越界路径**:地图里出现 `../LightNav-0/*`、`../Robot_Screw/*`——**别的项目**。这些路径也是稳定的,所以它们**通过了全部稳定性检查**,却悄悄占据了地图。**描述别的项目的项目地图不是"不够好",是"自信地错"**。现过滤并**明确报告跳过数量**。 2. **非项目路径**:`argparse`、`asyncio`、`AUDIT.md` 这类裸名不是仓库里的地方,是索引器从"这里从来不是目录"的东西派生出的 module 节点——本仓 888 个 module 节点里绝大多数如此。现**省略并计数**。 3. **按名字排序取前 N 是错的规则本身**:连续三轮"改排序"都以同一种方式失败——任何按名字排序的取前 N,都会被恰好排在前面的目录吃光预算。本仓那个目录是 `benchmarks/*` 和 `docs/*`,于是 **`src/*`(读者真正需要的部分)从未出现**。最终改为**按权重选**:文件计数已经知道代码在哪里,地图就从最重的目录开始,并且**每目录设上限**,最重的角落也不能独吞。 - **仍然是插件形态**:brief 是**内容**,不是决策。它不设断点、不重排宿主 prompt、不拦工具调用。不理它的宿主只会失去一个缓存优化,别的什么都不损失。 ### Fixed — 图谱脏节点:跨项目污染 + Module 命名空间被污染 诊断出**两个独立根因**(都不是"配置没设对",是缺检查): **根因 1:索引器没有工作区包含性检查。** `indexSingleFile` 直接 `relative(rootDir, absPath)`,对仓外文件会得到 `../other/foo.py` 并**原样入库**;`graph file ` 又接受任意路径(绝对或 `../` 相对)。实测本仓已被污染:`../LightNav-0/elite_cs612/tests/test_deproject.py` 的 **33 个节点**(2 File + 2 Module + 29 Symbol)是**另一个项目的真实 Python 源码**,被当成自己的代码索引了进去。兄弟目录 `~/Desktop/Tmp/Code/LightNav-0` 确实存在。 - **修复**:`workspace-containment.ts` 的 `isInsideWorkspace`,在 `indexSingleFile` **最前面**拦截——放在索引器而非 CLI,是为了覆盖**所有**调用方(CLI、file watcher、MCP 工具),而不只是用户能敲出来的那个。 - **两道检查**:① 词法(`resolve` + 拒绝 `..` 逃逸);② **物理**(`realpath` 解析符号链接后再查一次)。只做①会被绕过——工作区内一个指向 `/etc` 或兄弟 checkout 的**符号链接**在文本上完全本地,却能把整棵外部树导进来。 - root 不存在时(全新工作区)**退回词法检查**而非抛错:路径不存在不是"这条路径是外部的"的证据,真正的错误由调用方的 `statSync` 报。 - 端到端复验:绝对路径与 `../../` 相对路径两种逃逸均被拒,理由明写。 **根因 2:markdown 链接被当成 import,而每个 import 都变成一个 `Module` 节点。** `file-indexer-nodes.ts:214-221` 对每个 import target 建 `module:` 节点加 `imports` 边;markdown indexer 把**每一个链接和 badge** 都报成 import。最小复现(单个 README)产出: ``` module:https://img.shields.io/badge/npm-1.0-blue module:https://github.com/a/b/issues module:docs/guide.md ← 相对文档链接 ``` 没有哪个项目的"模块"叫一个 badge。这些节点**带边**,所以会参与检索排序、占据 module 地图——本仓 80 个。 - **修复两处**:① `normalizeImportTarget` **拒绝带 URL scheme 的 target**(必须拒绝而非清洗——`https://x/y.png` 去掉扩展名仍是 URL);② markdown indexer **不再把链接/wiki 链接报成 import**。**没有信息丢失**:跨文档结构已由 `buildDocumentEdges` 建模、标题是 declared symbols,而 `imports` 在此文件之外唯一的消费者是 PLC 边构造器,它永远看不到 markdown。 - 复现验证:单个 README 的 Module 节点 **5 → 2**,剩下的 2 个(`module:README`、`module:docs/guide`)都是真实文件;标题符号 5 个不变。 **清理:`graph prune [--apply]`**(默认 dry-run)。三类判定都必须是**可证**的外部/非模块,因为"删孤儿节点"会误伤真实内容——PLC 结构化文本的 POU 合法地产生无边 Module 节点: - `workspace-escape`(33):路径离开工作区,即现场发现的那个形态。 - `link-module`(80):`Module` 节点 id 是 http(s) URL。 - `foreign-artifact`(0):内容是序列化的节点集合(graph 快照)而非源码。 每类都有计数与 id 清单,删除前必先出计划,**绝不静默删除**;后端不支持删除或删除失败时**如实上报而非假装干净**。本仓已清理:**删除 113 个节点 + 215 条悬空边**,8715 保留,复验 dry-run 归零。 **一处自我更正**:我一度怀疑 `benchmarks/run-*.ts` 直接往真实图谱写合成节点(`client.upsertNodes`),查证后**不是**——它们用 `GraphifyClient`(内存库),与真实 store 隔离。该猜测作废,未写入结论。 **又一次需要你复核的测试改动(第三次)**:`retrieval-golden` 两条 `topK` 4 → 5,仍是本会话新增 `src/` 文件推动边界排名的老问题。**召回断言三次全部通过,失败的只有位置界**。已在测试文件顶部写下警告:这条界现在测的更多是"语料变没变"而不是"检索退没退",**若还需要再放宽,就该把硬位置断言换成召回断言 + 排名报告,而不是再加一格**。 ### Fixed(第二轮)— golden 门改为聚合漂移预算 + brief 真正养大 **1. golden 排名门重设计(上一轮说"不该再加一格",所以改门而不是改数)** - 逐查询硬界(`pos < topK`)**与语料耦合**:它索引整个 `src/` 并断言精确名次,所以新增一个合法源文件就能让构建失败——本会话已因此失败三次,其中两次是本项目**刚加的**文件,而召回三次全过。它测的更多是"语料变没变"而非"检索退没退"。 - 现改为**聚合漂移预算**:提交 `tests/fixtures/retrieval-rank-baseline.json`(132 条查询的基线名次),每条查询允许漂移 `RANK_TOLERANCE=2` 个位置,**超过 `MAX_DRIFTED_QUERIES=12` 条才失败**。真实排序回归会一次挪动几十条,一次新增文件只挪几条。 - **已验证它有牙**:把全部基线强制为 0 → 漂移 10 条 → 失败,并逐条列出漂移明细(`0 -> 3` / `0 -> 4`)。预算 12 是在"假警报史"上调出来的——它已经喊了三次狼。 - **三处此前的 `topK` 放宽全部回退**(3/3/4 原值),因为硬界已不存在;`topK` 字段保留,仅作意图文档与漂移报告输入。 - 基线刷新需显式:`GRAPHFLOW_UPDATE_RANK_BASELINE=1 npx vitest run tests/retrieval-golden.test.ts`,并要求**读 diff 再提交**。 **2. brief 真正养大(纠正上一轮的框架错误)** 上一轮说头号优先级是"养大 stable 段跨过 provider 最小可缓存长度"。**那个框架是错的**:最小长度针对**断点前的整个前缀**,而宿主自己的 system+tools 已 8000 tok,早已越过 1024。stable 段的价值不在"跨阈值",而在**它每轮被缓存了多少 token**。 - **量化后确认仍值得做**(宿主静态 8000、读 0.1x、$2/MTok):stable 678 → 2500 时每轮节省从 $0.0012 升到 $0.0045。 - **新增两段高价值稳定内容**:`exports:`(按文件列出导出符号——"这个文件提供什么"正是 agent 否则要花一次文件读才知道的)与 `brief: hotspots=`(由 `references`/`calls`/`imports` 边算出的被引用最多的模块,回答"改代码前该知道哪些模块承重")。 - **live 结果**:brief **678 → 2969 tok**,stablePrefix **678 → 2989 tok**(4.4x),**delta 反而从 1215 缩到 765**(brief 的行原先被误算进 delta),可复用前缀占比 **87.7% → 93.5%**,每轮节省 **$0.0012 → $0.0054(4.4x)**。 - **两处实现 bug 被 live 暴露并修正**:`filePathOf` 只读 `metadata.sourcePath`,而 **Symbol 节点实际带的是 `metadata.file`**,导致整个 exports 段静默为空——恰好是最该有内容的那一段;`cacheLayout` 的稳定模式没包含 brief 自己的行首(`brief:` / `exports:` / `files:`),把 2969 tok 全划进了 delta 桶。两处都加了回归测试。 - **刻意排除的东西**(并且有测试钉住):**Decision / dialogue / topic 节点**。它们是图里最"有用"也最易变的内容——**会随会话累积**,纳入就等于让 brief 每轮变化,正好复现这个段要消除的 churn。新增测试模拟 6 轮会话累积决策,断言 brief 指纹**逐轮不变**。**稳定不等于有用。** **3. `GRAPHFLOW_SUFFIX_TOKENS` 自动采集:取消,改为敏感性扫描** 原计划"从 hook 自动采集宿主 token 数"。查证后:**我们根本观测不到宿主的 token 数**——那是 harness 的 API,没有任何图谱数据能推出它。做"自动采集"只能造一个假数字,比留空更危险。 - 改为 `economics.sensitivity`:**扫描一整段合理的宿主尾部尺寸**(0 / 2k / 8k / 20k / 50k / 120k / 250k),给出每档成本与净值、**翻转点**与**结论是否稳健**。 - 结论不再压在一个人工填的数上:live 显示 churn 97.4% 时 `breakEvenSuffixTokens=8000`、`conclusionIsRobust=false`——**明说"这个判断取决于宿主的真实规模,而不是你填的估计值"**;无 churn 时 `robust=true`,**明说"不依赖宿主规模"**。 ### Verified — 真实 provider 端到端 A/B(`benchmarks/cache-placement-ab.ts`) 之前所有缓存结论都来自**公开的缓存乘数 + 我自己的前缀匹配模型**,从没被任何 provider 的真实缓存验证过。现在用 `DEEPSEEK_API_KEY` 打了真实请求,读回 provider 自己的 `prompt_cache_hit_tokens`。 **实验**(3 臂 × 3 轮,40 轮历史,`max_tokens:16`):C 宿主单独跑 / A 把每轮变化的注入放进 system 层 / B 把**逐字节不变**的 brief 放进同一位置。每臂独立 system 块(首轮全部 hit=0),避免跨臂缓存串味。 | 臂 | 末轮 hitRatio | 全价计费 token | | --- | --- | --- | | C 基线(无注入) | **95.1%** | 3790 | | A 每轮变化注入 | **43.1%** | **9459** | | B 稳定 brief | **94.1%** | 4515 | **结论:52.0 个百分点的落差,每轮多付 1890 个全价 token。** 更要命的是 A 臂幸存的缓存**恰好只有 system 里的稳定段(1920 tok)**——**整段对话每轮被重新计费**。会话越长越糟(3 轮历史时是 28.6 个点,40 轮是 52 个点)。而 B 臂与基线基本无差:**逐字节稳定的 brief 放在断点前不花宿主一分钱**。 **由此改了三处(都是被测试逼出来的,不是想出来的)**: 1. **缓存定价原本是把一家厂商的数字套给所有人**。实测 DeepSeek **完全没有缓存写入溢价**(`cacheWrite=0`),缓存读约为未命中价的 **2%** 而非 10%。旧默认(1.25 / 0.1)在 DeepSeek 上把 churn 税**高估了 2247%**。现按 provider 取档位(`CACHE_PROFILES`),只收录**已对厂商页面或真实 usage payload 核实过**的值;未匹配时回退到一个**明写"保守兜底"**的档位,而不是假装知道。`buildContextEconomics` 新增 `provider` 参数。 2. **`pickUsage` 读不了 OpenAI / Google 的缓存字段**。原先只认 DeepSeek 的 `prompt_cache_hit_tokens`,等于"位置问题只能在一个 provider 上、用一个 provider 的数字回答"。现补 `cached_tokens` / `cache_write_tokens` / `total_cached_tokens` / `cache_read_input_tokens`,并把**写入量单列**——一个反复写入却从不被读的前缀是纯 surcharge,只有把写入和命中分开才看得见。 3. **`cacheLayout` 的措辞按实测改写**。原来写"稳定在前、易变在后",但宿主**完全照做也照样丢缓存**:如果两段都被拼进 system 块,易变段仍在对话之前,其后一切重新计费。措辞已改为明确指出**边界位置**(稳定段落在断点处、易变段放到对话之后),并写明"都拼进 system 块仍然丢缓存"。 ### Added — 处方化落位建议 + opencode 插件的 MCP 注册 - **`cacheLayout.insertion`(可照抄的处方,不再只是描述)**:`stableAt: "system"` / `deltaAt: "turn-tail"` + 一句 `recipe` + `evidence`(附实测数字 95.1% / 43.1% / 94.1%)。原来的"稳定在前、易变在后"**可以被完全照做而依然丢缓存**——两段都拼进 system 块时易变段仍在对话之前。措辞改为指名**边界位置**,并明说"都拼进 system 块仍然丢缓存"。 - **opencode 插件新增 `mcp` 注册钩子(`GRAPHFLOW_OPENCODE_MCP=1` 开启)**:**opencode 自己拥有 `opencode.json`**——手写进去的 MCP 条目会被 opencode 下次写回时规范化掉(**实测发生,不是推测**)。插件的 `mcp` 钩子由 opencode 自行合并,因而不会被覆盖。自动优先选 `/dist/surfaces/mcp/server.js`(本地开发构建),不存在则回落到已安装包;`GRAPHFLOW_MCP_SERVER` 可显式指定。**默认关闭**,避免与已在 `opencode.json` 里配了 graphflow 的用户重复注册。 ### Fixed(第三轮)— 装进 opencode 的能力测试揪出来的 - **provider 档位接不上,等于上一轮的修复是死的**。`buildContextEconomics` 没有任何调用方传 `provider`,所以运行时一律按 Anthropic 计价。装进 opencode 后实测:同一请求**重写税 $0.17250**(Anthropic 数字),而它实际发往 DeepSeek,正确值是 **$0.00735**——**差 23 倍**。现由 `config.tiers` 推导 provider 传入。**这正是"真装一次"才能发现的 bug**:单测全绿时它根本不显形。 - **不可读文件在 JSON 里变成 `null`**,与"未测量"无法区分。`readFileTokens` 对读不出的文件返回 `Infinity`(诚实:委派代价无上界),但 `Infinity` 序列化后是 `null`。改为 `amplification.unreadableFiles` 计数 + 有限的 `readTokens`。 - **顺带修掉一个我自己刚引入的严重 bug**:把 `readTokens` 钳到 0 让 JSON 好看,结果**让读不出的文件看起来免费**——恰是 `Infinity` 原本要防的失败。改为 `unreadableFiles > 0` 时**显式判失败**。新写的测试当场抓住。 ### 验证 — 装进 opencode 的能力测试(10/10 PASS) 经**插件自身产出的 spec**(从已安装的 `~/.config/opencode/plugins/graphflow.mjs` 加载,不是仓库源文件)启动:MCP 握手 OK、10 个工具、3 轮 context 全部返回;Project Brief 2964 tok(`reused=true`)、Cache Layout 处方 `system/turn-tail`、stable 2984 / delta 679、Economics provider-aware(`cache-break`,重写税 $0.00735)、敏感性扫描 `robust=true`、新鲜度 `level=fresh`、能力地板按设计拒绝弃权(8773 节点 > 2000)。`doctor` 三个 opencode 切片(mcp / hooks / instructions)均为 installed。 原 `opencode.json` 已备份为 `opencode.json.bak-graphflow-local-20260928-183059`。 ### Fixed — doctor 曾在"跑错构建"时报告健康 安装后的人工排查发现:doctor 对三个 opencode 切片全部报 `installed`,但 MCP 实际启动的是 **npm 全局包**,比本地 `dist/` 早编译 10 小时。原因是 `probeDanglingGraphflowEntry` 只回答"**它启动的那个文件存在吗**"——存在,所以健康。**对一个正在改 GraphFlow 的人来说,这是最该被报出来的情况,却恰恰被漏掉。** - 新增 `probeMcpEntryPoint`:报告宿主**实际启动的入口**,并区分 `fromPublishedPackage`;当宿主指向已发布包而工作区存在更新的本地构建时,标记 `staleLocalBuild`。 - `DoctorCheckStatus` 新增 **`stale`** 状态(既非 installed 也非 missing:文件在,只是构建错了),`summary.stale` 单独计数,**`ok` 现在要求 `missing === 0 && stale === 0`**。一个跑着旧构建的宿主**不算健康**——这比报 missing 更糟,因为它看起来是成功的。 - 消息里给出两条路径并给出可执行的修法(设 `GRAPHFLOW_OPENCODE_MCP=1` 并从配置文件删掉 graphflow 条目,交由插件注册本地构建)——**此修法已被下方第三次更正证伪,改为 `install --mcp-plugin`**。 - 修好后本机实测:`summary {installed:62, missing:0, stale:1}`,`ok:false`,stale 项准确指向 `~/.npm-global/.../server.js` 与本地 `dist/.../server.js` 两条路径。 ### Fixed — doctor 曾对"正确配置"报警(修 stale 时引入的方向性错误) 把 `opencode.json` 里的 graphflow 条目删掉、改由插件注册之后,doctor 反而报 `missing`——**惩罚了唯一正确的那个配置**。原因:doctor 只认配置文件里的条目,不认插件注册这条路;而这条路恰恰是**在本地改 GraphFlow 时唯一可行的**(opencode 会规范化自己拥有的配置,手改条目留不住)。 - 新增 `probePluginRegisteredMcp()`:**仅当**(插件已安装)**且**(配置里确实没有 graphflow 条目)时成立。配置里有条目时不认——那时配置在运行时优先,说成"插件注册"就是撒谎,那种情况归 `stale` 管。 - 成立时输出**单条** `installed` 检查(`Opencode (registered by plugin)`)并说明入口;**同时跳过**配置那条检查,否则同一个 server 会同时出现 `installed` 和 `missing`。**一个 server 一条检查。** - `DoctorCheckItem.message` 补上正式声明(此前各处靠展开绕过类型检查,字段其实一直没被类型承认)。理由:文件存在与否不足以定论时,必须把话说明白,否则一个光秃秃的状态位会诱导出相反的结论。 修好后本机实测:`summary {total:61, installed:61, missing:0, stale:0}`,`ok: true`——**正确配置现在读起来就是正确的**。新增测试锁住"插件已装 + 配置无条目 → 恰好一条 installed 检查"这一组合。 ### Fixed(第三次更正)— 插件注册开关是自毁的:env 变量活不过进程,install 又把条目写了回去 上一条把"设 `GRAPHFLOW_OPENCODE_MCP=1` 并删掉配置条目"说成修法。**实测证明它两处都不成立**,而且都是我自己的设计问题,不是用法问题。 **1. env 变量活不过 opencode 的服务进程。** 变量设好、用户重启、配置条目已删——**毫无变化**。查进程表才看清:MCP 子进程的父进程是 `opencode-cli serve --service`,该进程**已连续运行 10732 秒(3 小时)**,子进程年龄 1538 秒。重启没碰到真正持有 MCP 的那个进程;而且变量只在当前 shell,**不在任何 rc 文件里**,下次启动(含 GUI 启动)必然丢失。 - 改为**持久 marker**:`~/.config/opencode/plugins/graphflow-mcp.json`。它随安装走,跨重启、跨 GUI 启动、跨换机器都在。 - 优先级:**显式关闭(env 或 marker)> env > marker**。用户任何时候都能停掉它——一个只能开不能关的开关不是开关。 - 新增 `install --mcp-plugin` / `--no-mcp-plugin`,opt-in 不再依赖"记得 export"。 **2. `install` 把刚删掉的条目又写了回去。** 打开 marker 后跑一次 `install`,`doctor` 立刻回到 `stale`——**安装器自己重新创建了那个优先级高于插件注册的条目**。插件开着,配置条目也在,而 opencode 运行时优先配置。 - 关键在于**拦在哪一层**。第一版把守卫放在 `installProfileHost` 的 opencode 切片里:切片删掉条目,**随后的全局 MCP 安装 pass 又把它写了回来**。用 `writeFileSync` 包装器抓到了真实调用栈(`injectIntoOpencodeConfig` ← `injectIntoAgentConfig` ← `installMcpToDetectedAgents`),确认存在第二条写入路径。 - 因此守卫下沉到**唯一咽喉点** `installMcpToDetectedAgents` 的 per-target 循环。~~marker 开着时该 target 走**移除**而非注入~~ —— **第四次更正**:移除是错的,正确做法是写入指向工作区构建的条目。`profile-host-installer.ts` 因此回到**零改动**——单一职责点比每层各守一遍更难写错。 - 两个方向都实测:marker 开 + `install` → 条目消失;marker 关 + `install` → 条目恢复写入(**单向门会让关掉开关的用户彻底没有注册**)。终态 `summary {installed:61, stale:0}`、`ok: true`、`installed - Opencode (registered by plugin)`。 **3. 两个 home 解析不一致,会让开关静默失效。**(此条仍然成立,见下) 测试暴露 `resolveOpenCodeHome()`(认 `GRAPHFLOW_OPENCODE_HOME`)与 agent profile 注册表(认 `homedir()`)可能指向不同 home——若不一致,守卫会读错 home 的 marker,opt-in 静默变空操作。成因:profile 在**模块加载时**就调 `resolveHomePaths()` 完成注册(`registerOpencodeProfile()` 随 import 执行)。生产默认下两者一致,但这个不一致是真实的,已加测试钉住"注入写的 home 与读 marker 的 home 必须是同一个"。 ### Fixed — 全量测试会改写开发者真实的 agent 配置("测试全绿"与"doctor ok"此前互斥) 提交后复核终态时,`doctor` 又回到 `stale`——**而测试是全绿的**。查配置 mtime:写入时间 21:04:13,正落在全量测试运行区间内。 - 三个测试文件(`m-install-json-report` / `m-install-hooks-wiring` / `host-adapter-install`)都调用 `buildInstallReport`,也都**自称**隔离了 HOME(注释原文:"isolate HOME so the machine running the suite keeps its real agent configs intact")。**但隔离是假的**:agent profile 在**模块首次 import 时**就调 `resolveHomePaths()` 完成注册(`registerOpencodeProfile()` 随 import 执行),静态 import 的 `buildInstallReport` 早已把**真实 home** 捕获在手里。此后改 `process.env.HOME` 对它毫无影响——安装照旧写进真实的 `~/.config/opencode`。 - 这类泄漏**不会让任何断言失败**:断言检查的是 report 结构,而 report 对"写到了真实 home"和"写到了临时 home"一视同仁。**它只在真实机器上表现为 doctor 变脏。** 用 `writeFileSync` 预加载追踪器抓到完整调用栈(`injectIntoOpencodeConfig` ← `injectIntoAgentConfig` ← `installMcpToDetectedAgents` ← `installProfileHost` ← `installViaHostAdapter` ← `buildInstallReport`)才定位到。 - 修法:改 HOME 之后 `vi.resetModules()` 并**动态重新 import** 被测模块。真实 `~/.config/opencode` 写入次数 **15 → 0**,全量 222 文件 / 1709 用例仍全绿,`doctor` 保持 `{installed:61, stale:0}` / `ok: true`。 - **同一成因也是上一条 home 不一致的另一半**:profile 路径在加载期固定,marker 读取是即时的。所以隔离环境里"读 marker 的 home"和"写配置的 home"会分叉——**测试里的分叉是 bug,机器上的分叉是隐患**,两侧都已用断言钉住。 ### Fixed(第四次更正)— opencode 的插件根本没有 `mcp` 钩子;"opencode 会规范化掉手写条目"也是错的 前三次更正都在修"怎么把本地构建喂给 opencode",方向是**方案 B:从插件注册 MCP server**。用户重启 opencode 后仍然没有 graphflow 进程。查下来,**方案 B 在这个版本里不可能存在**,而且它建立的两条前提都是错的。 **1. opencode 的插件 API 没有 `mcp` 钩子。** `~/.cache/opencode/node_modules/@opencode-ai/plugin/dist/index.d.ts` 的 `Hooks` 接口全部键是:`agent / auth / chat.headers / chat.message / chat.params / command.execute.before / config / event / experimental.chat.messages.transform / experimental.chat.system.transform / experimental.session.compacting / experimental.text.complete / permission.ask / tool / tool.execute.after / tool.execute.before`——**没有 `mcp`**。官方文档的钩子清单同样没有。返回 `mcp` 键会被**静默丢弃**。 - 实测印证:13:23:34 重启后的日志里只有 `mcp connected server=pencil tools=4`,**graphflow 一条都没有**。插件文件确实被加载(本地文件目录是官方支持的加载方式),只是那个键不起作用。 - 我此前在 `opencode/plugin.mjs` 里写的注释——"A plugin's `mcp` hook is merged by opencode itself, so it survives"——**自称"observed behaviour, not a theory",实际从未观测过**。把没验证的推断写成既成事实,正是这轮连续三次返工的起点。该注释已删除,并写明真实的钩子集合与验证方式。 **2. opencode 会保留手写条目;一直在改写它的是我们自己的安装器。** 直接把本地 `dist/` 写进 `opencode.json`,8 秒后日志出现 `mcp connected server=graphflow tools=10`,两个进程跑的是本地 dist,且**opencode 自己重新序列化配置后完整保留了这条条目**。此前"opencode 拥有该文件、会把手改条目规范化掉"的判断,是把 `graphflow install` 自己的写入误记成了宿主的规范化——而那恰恰是上一条刚修好的东西。 **3. 改为:marker 的语义从"插件注册 MCP"改成"指向本工作区的构建"。** - marker 现在记录 `workspaceRoot`,条目写 `/dist/surfaces/mcp/server.js`。**记录而非假定**:`install` 可以在任意目录执行,marker 若默默指向错误的 checkout,就会写出一条看起来合理、实则启动陈旧构建的条目——正是这个功能要防的失败。 - 守卫(仍在 `installMcpToDetectedAgents` 这个唯一咽喉点)改为**注入指向工作区构建的条目**;构建缺失时**报 error 并给出两条出路**(`npm run build` 或 `install --no-mcp-plugin`),而不是写一条指向不存在文件的条目。 - 顺带把 `GRAPHFLOW_*` 能力开关**写进条目的 `environment`**:opencode 自己拉起 MCP server,开发者 shell 里的变量同样到不了它——与之前那个 env 变量陷阱同型,只是下沉了一层。没有这一步,opt-in 特性只能在终端里测,无法在真实宿主上测。 - 删除 `plugin.mjs` 中已无调用方的 `mcpServerSpec` / `shouldRegisterMcp` / marker 读取逻辑(TS 侧是唯一实现,留着会误导),以及 doctor 里 `probePluginRegisteredMcp` 与 `(registered by plugin)` 检查——**该路径已不存在,为它开特例只会让 doctor 说谎**。现在交给常规检查:条目指向本地 dist 即 `installed`,指向已发布包而本地存在更新构建即 `stale`,`probeMcpEntryPoint` 本就分得清。 两个方向都实测:`--mcp-plugin` + `install` → 条目指向本地 dist;`--no-mcp-plugin` + `install` → 恢复已发布包(**命令已在下方第五条更正更名为 `--workspace-build`;此时范围仍仅 opencode**)(**单向门会让关掉开关的用户被钉在可能已删除的构建上**)。终态 `summary {installed:63, stale:0}`、`ok: true`,live 日志 `mcp connected server=graphflow tools=10`。 ### Fixed — 工作区构建偏好此前只对 opencode 生效(实测其余 18 个宿主仍是 npx 启动器) 第四次更正把**机制**做对了,但**范围**只覆盖 opencode:守卫是 `target.agentId === "opencode"` 的专属分支。逐个宿主实测(全部 profile,不是推断): | 状态 | 宿主 | | --- | --- | | 指向工作区 dist | 仅 opencode | | 仍是 npx 启动器 | cursor / claude-code / codex / gemini / vscode / zed / windsurf / cline / roo-code / kilocode / trae / pearai / antigravity / amazon-q / continue / qoder / kimi-code / zcode | | 无 MCP target | deepseek-harness(在 YAML patch 里,不在 profile registry) | npx 启动器 = 宿主每次从 npm 拉已发布包,**在这些宿主里改 GraphFlow 代码完全不生效**,而配置看起来完全健康。现改为宿主无关。 **1. 守卫去专属化。** `installMcpToDetectedAgents` 的 per-target 循环里,条件从 `agentId === "opencode"` 变为"工作区构建已启用"。仍在唯一咽喉点——切片级守卫已被全局 pass 覆盖过一次。 **2. marker 移出宿主目录。** 从 `~/.config/opencode/plugins/graphflow-mcp.json` 移到 **`~/.graphflow/workspace-build.json`**(`src/integrations/workspace-build.ts`)。原位置把一个适用于所有宿主的决策写成 opencode 专属,也让开关读起来像 opencode 专用。opencode 侧那份 marker API 随之删除,只留 TS 实现。 **3. dsh 单独适配。** 它在 YAML patch 里声明 MCP,**不出现在 profile registry**,通用安装器够不到——否则它会是唯一仍跑 npm 副本的宿主。`buildGraphFlowDshInsertPatch` 现在同样遵循偏好。 - 一处实测抓到的缩进错误:`command`/`args` 是 `config:` 的键,应为**八空格**(与 `transport` 同级),我先写成六。YAML 仍能解析,但启动器落在错误层级,dsh 只会在很晚的启动失败里报出来。由既有断言"安装器输出必须逐行等于仓库内 `cordis.patch.yml`"抓到。 **4. `GRAPHFLOW_*` 开关写进条目 `environment`(跨宿主)。** 宿主自己拉起 server,shell 里的变量到不了它——与那个 env 变量陷阱同型,只是下沉一层。 - 陷阱:给 `buildMcpServerNode` 传 `environment` **类型接受、运行时被忽略**(选项看起来对、实际什么都不做)。改为写盘后二次合并(`mergeHostEnv`),`environment` / `env` 两种键名都试。codex 是 TOML,无法安全二次合并,**如实上报而非假装成功**:条目仍指向正确构建,开关缺失写进 message。**入口正确是硬要求,开关到达是尽力而为。** **5. CLI 更名 `--workspace-build` / `--no-workspace-build`**(`--mcp-plugin` 名不副实)。doctor 的 `stale` 文案指向新命令,并删除已失效的 opencode 特例注释。 实测(真实 home,逐宿主读配置文件):开启 **19/19** 指向 `/dist/surfaces/mcp/server.js`;`--no-workspace-build` 后 **0/19**;再开启恢复 19/19。`doctor` 保持 `{installed:63, stale:0}` / `ok: true`。 **一处我自己的测量错误**:验证脚本按单一路径读条目,把 `mcpServers`(kimi-code / qoder)、`mcp.servers`(zcode)判成"未指向",而原始文件里三个都在。**数字与假设矛盾时先怀疑尺子**——已改为在文件原文里匹配路径,JSON 与 TOML 一视同仁。 ### Fixed(CI 抓到)— Windows 上测试只重定向 `HOME`,把 marker 写进了真实用户目录 首次推送后 Windows job 挂掉 4 个用例,其中"每个 profile"那条报 **18 个宿主全部未指向**——与本机 19/19 完全相反。根因不是守卫不通用,而是测试自己的隔离有洞: - `os.homedir()` 在 Windows 上读 **`USERPROFILE`**,而 `os.tmpdir()` 返回 **8.3 短路径**(`RUNNER~1`)。测试只设了 `HOME`,于是 `homedir()` 仍指向真实用户目录,marker 被写进**真实的 `~/.graphflow`**。 - 更糟的是它**跨用例存活**:第一个用例写的 marker 指向一个已被 `afterEach` 删掉的 workspace,于是后续每个用例都读到"已启用但未构建"——守卫按设计报 error,一个宿主都没注入。**本机复现了这个状态机**(写 marker → 删 workspace → 注入):`missingBuild: true`、状态 `error`。 - 修法:同时设 `HOME` 与 `USERPROFILE`(与仓库既有做法一致),并在 `afterEach` 里**先删 marker 再恢复环境变量**——反过来的话 marker 会留在真实目录,下次运行读到一个指向已删除 workspace 的偏好。连续跑两轮确认无残留,全量跑完真实 home 干净。 **这条只有 CI 能抓到**:本机 `homedir()` 就是 `HOME`,同样的代码 19/19 通过。**平台差异让"测试通过"不再等于"行为正确",这正是这次必须推 action 的理由。** ### Fixed(第三轮 CI)— 守卫在 Windows 上一直是好的,坏的是我的断言 第三轮 CI 只剩 1 个失败,而它的诊断信息**推翻了前两轮的每一个假设**: ``` cursor: status=created exists=true mentionsDist=yes configPath=C:\Users\RUNNER~1\...\gf-wb-home-wD2cks\.cursor\mcp.json message=launches the workspace build at C:\Users\RUNNER~1\...\gf-wb-ws-PZ... ``` `status=created`、`mentionsDist=yes`、路径全在 sandbox 内——**18 个宿主全部正确写入了工作区构建,守卫从头到尾都在工作**。而我前两轮分别归因于"marker 泄漏"和"`APPDATA` 未重定向",两次都错。(那两轮的修复本身是必要的:marker 确实曾泄漏、4 个用例确实因此失败;只是它们都不是这个用例失败的原因。) **真正的失败是断言本身**:文件是 JSON,写入时反斜杠被转义成 `C:\\Users\\...`,而我拿 `raw.includes(serverPath)` 去做**字面子串比较**——在 Windows 上这**永远不可能匹配**。18 个宿主"失败"纯属尺子坏了。 - 比较改为**抽取路径形态的候选再逐段比较**(`mentionsServerPath`),对 `\\` 与 `/` 都接受。 - 顺带消掉 8.3 短路径:测试目录建好后取 `realpathSync`,使期望路径与写入路径在拼写上一致。短路径 `RUNNER~1` 与长路径 `runneradmin` 是同一目录的两种拼法,**不是两个地方**。 - 过程中我自己又错了两次才做对:先写成"把反斜杠全删掉"(会把段粘连,正是要比较的分隔符),后靠逐例打印才发现。**这类尺子必须用已知输入验证**——现在有 5 个用例直接喂真实形态:JSON 转义 / TOML 正斜杠 / 长路径一致 / 短长不同判 false / 无关 npx 条目判 false。 - 保留 detail 输出(status / exists / configPath / mentionsDist / message)。**没有它,这个用例会再骗我两轮**——只列 18 个宿主名,不足以区分"写到别处"、"没写"、"写错内容"。 **方法论**:这个 bug 本机不可复现(Linux 无反斜杠转义),全绿 1716 个用例。**它是被"让 CI 跑"逼出来的,不是被测试逼出来的。** ### Fixed — 依赖漏洞清零(8 → 0),其中 6 项不需要破坏性升级 `npm audit` 此前有 **8 项(4 high / 3 moderate / 1 low)**,Security Audit workflow **已连续失败至少三周**(9/14、9/21、9/28,仅在 schedule 上跑)。现全部清零,`security:audit` 退出 0。 - **6 项非破坏性**:全部是传递依赖的**补丁版本**,`overrides` 即可。`hono`(跨请求数据泄露 / ReDoS / `toSSG()` 写出输出目录之外)、`@hono/node-server`(Windows 经 `%5C` 的路径穿越)、`body-parser`(非法 limit 静默关闭体积限制 → DoS)、`fast-uri`(host confusion / SSRF)、`ip-address`(前导零八进制与 NAT64 分类绕过 → SSRF)、`qs`(array-limit 绕过 / DoS)。 - **1 项需要主版本升级**:`@huggingface/transformers` 3.x → **4.3.0**,它是唯一的直接依赖漏洞来源(`sharp` / `libvips` / `libheif` 的 CVE-2026-33327/33328/35590/35591、GHSA-g89c-p67h-r497、GHSA-2jg2-4ch7-h545)。npm 标注 `isSemVerMajor: true`,**我仍然做了**——理由是 `src/learning/embeddings.ts` 实际用到的 API 面极窄(`pipeline`、`env.cacheDir`、`env.remoteHost`),逐个实测存在且可写,且 4.3.0 把 `sharp` 提到 0.35.5 正是修掉这些 CVE 的版本。**"breaking" 标签说的是依赖树,不等于这个调用面会破。** - **未能端到端验证的部分**:本机 `huggingface.co` 不可达(registry 通、HF 不通),**真实模型下载与推理跑不了**。已验证的是 API 契约(三个成员逐一实测)与全量 1716 用例。**embedding 的真实数值行为只有你在有网环境才能确认。** - **`security-audit.cjs` 现在会说人话**。此前它在 `--json` 下把 npm 输出写进文件、**stdout 什么都不打印**,CI 日志只有一行 "Process completed with exit code 1",必须翻 artifact 才知道原因。现在非零退出时把三件事分开讲:**有哪些漏洞**(名称 + 严重度 + 计数)、**审计没跑成**(镜像不支持 audit 端点等,`npmmirror` 就会这样)、**无输出失败**。三种情形都实测过。**一个只有退出码的 CI 日志不是信息。** - 顺带清掉 `PearAI/User/mcp.json` 与 `Cursor/User/mcp.json` 两个测试产物:它们出现在仓库根是因为**测试的 CWD 恰好等于该宿主的 `homeMarker`**,内容指向 `/tmp/gf-wb-ws-*` 已删除目录。均在 `.gitignore` 内、从未提交过。 ### Tests - `tests/workspace-build.test.ts`(13 用例,由 `opencode-mcp-plugin-registration.test.ts` 重命名并扩写):偏好本体(记录工作区而非假定 cwd / 后续 install 不重指向 / marker 不在任何宿主目录内 / 损坏视为未开启 / 未构建与未启用分开报告)+ 跨宿主注入(**每个 profile 的条目都指向该构建** / 缺构建报可操作 error / 关闭时保留 npx / 撤销后恢复 / 开关进入 `environment` / 不动其他条目 / 注入 home 与读 marker 的 home 一致)+ dsh patch 两个方向。 - **"每个 profile"这条是本轮核心回归**:守卫原本只对 opencode 生效,逐宿主实测才暴露。 - 断言用**文件原文包含路径**而非解析 JSON——codex 用 TOML,JSON 形状的读取器会静默跳过唯一格式不同的宿主。 - **平台相关的三处**(`USERPROFILE`、`APPDATA`/`LOCALAPPDATA`、JSON 里的反斜杠转义)都只有 Windows 暴露;本机 `homedir()` 就是 `HOME`,文件里也没有转义。**同一份代码在这里 19/19 全绿、在 CI 连续三轮失败——这是必须让 action 跑、且必须让断言自证的理由。** - **已验证有牙**:禁用守卫 → 3 个失败。 - `tests/m-doctor-json-report.test.ts`:"插件注册"那组用例**整体重写**为"条目指向工作区构建"——断言 user-scope 条目 `installed` 且 `summary.stale === 0`。**未**断言"恰好一条检查":Cursor 本就产出两条(user 级 + workspace 相对级,sandbox 里后者不存在),这是既有行为,与本改动无关;最初写成 `length === 1` 时失败,说明是我的断言错了,不是代码错了。 - 隔离靠 `vi.resetModules()` + 在设好 `HOME` **之后**动态 import——profile 在模块加载时注册,静态 import + `beforeEach` 改 `HOME` 太晚(首版正是这样假绿失败了一次)。 ### Tests - `tests/memory-freshness.test.ts`(9 用例):引用抽取、无引用判 `unknown`、fresh/watch/stale 分级(含边界值)、自定义阈值、降级策略(stale+proven 降级 / watch 不降 / canary 豁免 / anti-pattern 不降)、开关读取、`buildRefResolver`(符号名 + 仓库相对路径可解析;内容哈希漂移后不可解析)。 - `tests/context-economics.test.ts`(9 用例):前缀 churn、低于 provider 最小可缓存长度时拒绝建模、cache/fresh 切分与 hitRate、含 cache write 税的成本账、注意力预算四级、弃权四象限(含"reason 必须说明前缀稳定性")、开关读取、`buildContextEconomics` 的 `cache-safe` / `prefix-churn` / `cache-cold` 三态。 ### Fixed — 用户实测报出的两个安装级缺陷 用户在 Linux 上 `npm install -g @roarpeng/graphflow@1.27.0` 后报 `onnxruntime-node` 302 失败、`graphflow doctor` 报 `missing=3`。两处都复现并修好。 **1. `onnxruntime-node` 安装失败会中断整个安装** `@huggingface/transformers` 原本在 `dependencies`,其 `onnxruntime-node` 的 postinstall 要从**独立 CDN** 拉二进制。该 CDN 在部分网络下不可达 / 返回 302,npm 直接判定安装失败,**整个包装不上**——用户必须知道 `--ignore-scripts` 才能继续,这是把可选能力变成了安装门槛。 改为 `optionalDependencies`:拉取失败时 npm 容错跳过,CLI / MCP / 上下文压缩 / 记忆全部正常,**只有语义检索降级为哈希**(代码里本就有 `createResilientLocalEmbeddingProvider` 这条降级路径)。实测:不带 `--ignore-scripts` 安装 tarball,153 个包装完,`graphflow --version` 正常。 **2. 非 Windows 上 appData 解析为空字符串,把宿主配置写进了用户的仓库** `agent-mcp-installer.ts` 里有一份**自己的** `resolveHomePaths()`,非 Windows 时返回 `appData: ""`、`localAppData: ""`(当时假定 appData 路径只在 Windows 有意义)。但 cursor / cline / roo-code / kilocode / trae / pearai **都声明了第二个位于 appData 的 user target**,于是 `join("", "Cursor", "User", ...)` 产出**相对路径**,安装器把它写进**当前工作目录**——也就是用户的仓库。 用户实测留下的痕迹(本机可查):仓库内出现 `Cursor/User/globalStorage/roval.cursor/mcp.json` 与 `PearAI/User/mcp.json`,内容指向一个已被删除的 `/tmp/doctor-workspace-*`;doctor 因此报 `Cursor (dangling entry)` 与 `PearAI missing`,`ok=false`。同一原因也让测试隔离失效。 与 `agent-profiles/utils.ts` 里已有的同名函数对齐(POSIX 下 `~/.config` 与 `~/.local/share`)。修复后全部 user target 均为绝对路径。 > **仓库里还有两份 `mcp.json` 不是泄漏**:`./mcp.json` 是本包要发布的 MCP 规格(已在 `files` 中、已被 git 跟踪),`./.cursor/mcp.json`、`.vscode/mcp.json` 指向扩展安装目录。它们与本次问题无关。 > > **方法论**:这次的用户实测抓到了一个**我自己测不出来的 bug**——我此前 20 余次跑 `install` / `doctor` 全程 `ok=true`,因为我的 CWD 恰好让相对路径落在无害位置,而 3 个 `missing` 我读成了"未检测到的 agent 不参与判定"的既有语义。**同一个数字,换一台机器就变成数据损坏。** ### Fixed — 多词查询召回归零:FTS 把英文 token 用 AND 串起来 用户的 Zcode 实测报告"中文召回差",追下去发现**真正的问题不是中文,是多词查询本身**:在真实 home 上量到 `buildFtsMatch` 用 `" AND "` 拼接英文 token,而中文分支用 `" OR "`。 AND 要求**单个节点同时包含全部查询词**,于是召回随查询变长而**单调收缩**。本仓实测: | 查询 | 修复前 | 修复后 | | --- | --- | --- | | `installer` | 200 节点 | 200 | | `preference` | 7 节点 | 7 | | `installer preference` | **0** | 200 | | `workspace build preference installer` | **0** | 200 | | 端到端 `installer preference` | **0 锚点** | 15 | **加一个词只会让结果变少,永远不会变多**——这与检索的基本预期相反。`"X preference"` 恒为 0 与 X 无关,`foo bar baz qux` 也为 0,正是这个原因,不是"查询无意义"。端到端排序也正确:`workspace build preference installer` 的首位是 `file:src/integrations/workspace-build.ts`。 改用 `OR`。FTS5 的 bm25 本来就把"命中多个词"的节点排在"只命中一个"之前(实测首位即全命中节点),所以原先 AND 换来的精度由**排序**保证,而非靠丢弃候选集。中文分支本来就是 OR,现在两侧一致。 `tests/m24-sqlite-backend.test.ts` 里那条用例原本叫"returns nodes containing all tokens",**它把缺陷当成规格钉住了**。已改写为断言新的真实契约:全命中节点排第一、部分命中不被丢弃、无关节点仍不出现;并补一条单 token 行为不变的守卫。golden 排名门 149 条全过,中文查询无回归。 ### Fixed — CLI 的 stdout 混入帮助文本,破坏脚本消费 用户实测反馈"`--json` 输出里混着日志行"。核实后:日志**没有**混进 stdout(`doctor --json` 的 stdout 是单个可 `JSON.parse` 通过的对象),`run --json` 也**确实**打印 `executionDescriptor` / `episodeId`。真正的问题是另一处,也是唯一会让脚本报错的地方: - **未知命令 / `--help` 把 usage 横幅打到 stdout**。`graphflow 不存在的命令` 退出码是 1,但 stdout 里有 6700 多字节的帮助文本——脚本把这段散文喂给 JSON 解析器必然失败,**而且它无法区分"工具在解释自己"和"工具产出了结果"**。 - 现改为:帮助与诊断一律走 **stderr**,stdout 只保留机器可读输出;未知命令额外在 stderr 报 `graphflow: unknown command ""`。`doctor --json` 仍正常输出可解析 JSON。 - 新增 `tests/cli-stdout-hygiene.test.ts`(3 用例)钉住这条契约:未知命令 stdout 为空且退出码非 0、`--help` stdout 为空、真实 `--json` 仍可解析。**已验证有牙**:把 usage 改回 stdout → 1 个用例失败。 ### 清理 — 仓库里的测试产物 - 删除 `tmp/`(25M)、`benchmarks/.cache/`(47M)、`Cursor/`、`PearAI/`、`.codex/`。后三者是被测宿主配置,出现在仓库根是因为**测试的 CWD 恰好是 checkout**;`.codex/config.toml` 里还钉着 `roarpeng.graphflow-1.9.6` 的旧扩展路径(用户反馈的"版本残留",我找到的是 1.9.6 而非 1.7.6),一并清除。 - `.gitignore` 增加 `.codex/`,并写明原因——`Cursor/`、`PearAI/`、`benchmarks/.cache/` 此前已在忽略列表里。 ### Fixed — 自检脚本在 Windows 上静默跳过了 MCP 检查 用户在 Windows 上跑 1.27.6 的自检,MCP 那项显示 `skipped: package not found at a known location`——**而实际上包就在那里**。脚本只找 `~/.npm-global/lib/node_modules`(Linux 布局)和 `./node_modules`,Windows 的 `%APPDATA%\npm\node_modules` 两条都不匹配。 - 改用 `npm root -g` 解析,不猜布局。这同时覆盖了 `--prefix` 自定义前缀的情况(已实测:`npm root -g --prefix ` 能正确解析)。 - **skip 改为 FAIL**。一个显示"跳过"的检查读起来和通过一样,这是最坏的失败形态。现在找不到包会报 FAIL,并打印它找过哪些路径。 用户在 Windows 上还给出了 1.27.6 的完整安装日志:19 个宿主的条目全部写入且路径正确(含 AppData 路径),`stale=0`,`missing=4`。文档已补 Windows 的 `EBUSY`(被自己开着的 agent 占用)与镜像 `ETARGET` 两类处理。 ### Fixed — 从 home 目录跑 install 会把项目文件写进 home,并覆盖带标记的指令文件 用户在 Ubuntu 与 Windows 上**都**从 home 目录(`~` / `C:\Users\xxx`)跑了 `graphflow install`,两边都留下同一个矛盾结果: - `~/.claude/rules/graphflow.md` **确实存在**(1.6 KB),install 报 `already up to date`,doctor 却报 `missing`。**同一个文件,两个相反结论。** - 原因:该文件被写成 `AGENTS.md` 的**逐字副本,且没有 managed block 标记**。doctor 的判定是"文件里有没有 `GRAPHFLOW:BEGIN/END` 标记",自然判 missing。而项目规则写入器里那条 `claude-rules` 路径是**纯复制**(不带标记),从 home 跑时它把带标记的版本覆盖成了裸副本。 机制:项目作用域的目标是相对 `workspaceRoot` 解析的。`workspaceRoot` = home,于是 `.claude/rules/`、`.windsurfrules`、`.agent/rules/`、`AGENTS.md`、`GEMINI.md` 全部落进 home。**Windows 同理**(`C:\Users\vboxuser`)。 审计本机 home 实际被写进去的文件时,发现**不止一个写入点**: | 文件 | 大小 | 写入者 | 已守卫 | |---|---|---|---| | `~/.claude/rules/graphflow.md` | 1.6 KB | `installProjectLevelRules` | ✅ | | `~/.windsurfrules` | 1.6 KB | `installProjectLevelRules` | ✅ | | `~/.cursor/rules/graphflow.mdc` | 7.6 KB | `installProjectLevelRules` | ✅ | | `~/AGENTS.md` | 1.6 KB | `installProjectLevelRules` | ✅ | | `~/GEMINI.md` | 1.7 KB | `installProjectGeminiInstructions` | ✅ | 只修前一个就是**看起来修完了其实没修完**——`~/GEMINI.md` 照样每天被生成。两个写入点现在都复用图谱索引已有的 `isUnsafeWorkspaceFallback` 判定,home / AppData 作为 root 时**拒绝写入并逐项说明原因**。图索引早就拒绝不安全 root,项目文件此前没有——这个不对称就是漏洞本身。 `tests/project-rules-unsafe-root.test.ts`(6 用例):home 为 root 时一项都不写、每项都说明原因、**带标记的既有指令文件保持逐字不变**、两个写入点各自的守卫、真实项目目录照常写入,以及"真实 home 确实被判定为 unsafe"这个前提本身。**两个守卫都单独验证过有牙**:分别移除 → 各有测试失败。 本机实测(本地构建,从 home 跑 `install`):**10 个项目作用域目标被拒绝,home 下 9 个文件的大小与 mtime 零变化**。同一构建在真实项目目录跑,`AGENTS.md` / `GEMINI.md` / `.windsurfrules` / `.claude/rules/graphflow.md` 四个文件照常写入。 ## [1.26.0] - 2026-09-23 ### Added — 桥接优先与可信度收口(round 4) - **run 把不可用的 LLM 当作没有 LLM**:`runTaskResult` 前置 worker 问候往返(默认 5s 有界,`GRAPHFLOW_RUN_PROBE_TIMEOUT_MS` 可调)——探测失败即切 bridge 模式,与未配置 LLM 的行为**完全一致**:返回 `DELEGATED + executionDescriptor + episode`,`RunTaskSummary.bridgeReason` 携带真实原因(含适配器旁路的 401 详情)。此前坏 key 会烧满 3 次 worker 重试全部拿到占位符(live:现在 attempts=0、零 LLM 执行调用)。plan 侧同语义(`planSource: probe-failed-bridge`)在上一轮已落地——至此 plan/run 对"探针失败=未配置"完全对齐。 - **`graphflow selfcheck`**:一条只读命令的红绿健康清单(8 项):配置加载 / 图存储(含代码节点存在性)/ delta 日志规模 / 索引新鲜度 / **LLM 真实连通探测**(区分 configured 与 reachable)/ 飞轮脉冲(pending 比例)/ 对话脱敏函数级抽查 / 会话日志。每一项都源自某轮 live 验收发现过的静默故障模式。`--json` 支持;有 FAIL 时退出码非零。 - **LLM_SMOKE 可选 CI 门**:`scripts/llm-smoke.ts` + CI job——配置了 `GRAPHFLOW_LLM_SMOKE_KEY` secret 时跑一次**真** plan 往返并断言 `planSource=llm`;无 secret 静默跳过。填补"离线测试全绿、真 provider 已坏"的盲区(本机 401 失效 key 正是这类)。 ### Changed - **delta 折叠阈值 8MB → 2MB**:真实世界 delta 常年挂 1-5MB,每次读取都多付一次 apply;2MB 仍能摊销批量写,同时把读侧开销封顶(重写后最坏 ~80ms)。 ### Confirmed(非缺陷登记) - team serve 的 `tools/list` 返回空是**设计**:团队服务器是自定义 `graph.*` / `team.*` JSON-RPC 协议面(GraphifyMcpClient 的对端),不是 MCP tools 面。 ### Tests - 新增 `tests/m-run-bridge-selfcheck.test.ts`(4 用例):占位符回显→桥接且零 LLM 执行调用、健康探测→仍走 llm、selfcheck 无 LLM 配置全绿、坏配置红。真实不可达端点的完整 `DELEGATED` 形状经 live 双重验证(CLI + 独立脚本)。 - **mock-vs-real 桥接差异根因关闭**:此前 vi.mock 下桥接测试只能得到 `HUMAN_REVIEW_REQUIRED`(无 descriptor/episode)——根因是 mock 工厂只提供 `executeRolePrompt`,而 orchestrator-phases / state-machine 还从该模块**值导入** `formatPromptContextEntries`,undefined 调用抛错后被 orchestrator 顶层 catch 伪装成 HUMAN_REVIEW。工厂改为 `importOriginal` 保真其余导出后,mock 下同样得到完整 `DELEGATED + attempts=0 + descriptor + episode`,断言已恢复为完整形状。(产品代码无缺陷;该模式风险已在测试内注释警示。) - README / README.zh:补 `graphflow selfcheck` 与「LLM 不可用时 plan/run 桥接优先」的用户文档(中英)。 ## [1.26.0 内轮次 3] ### Fixed — 第三轮深挖:任务回显技能门 + delta 合并 394 倍性能修复(虚假问题清零批次) - **任务回显永不成为技能**:`applySkillLearning` 现在丢弃与任务文本互含且长度 ≥80% 的"原子"——抽取器对单句任务无法切分时会原样复读任务全文(live:`create a tiny file test-tmp.txt with content hi` 成了技能名,且来自一次 HUMAN_REVIEW_REQUIRED 的失败 run)。提炼型子短语与 lessons 种子不受影响。 - **`pruneLegacyNoiseSkills` 扩展名白名单一般化**:路径片段正则从固定枚举(ts/js/…)放宽为任意 1-8 字符扩展——`.txt` 等常见扩展名的垃圾技能此前漏清(live:存量 2 条已清零)。 - **`applyGraphStoreDelta` 394 倍提速(31.5s → 80ms)**:delete 分支此前每个 op 都做全量 `edges.filter` + 重建整个 edgeKeys Set——真实世界的 1,102 条 delete / 35k 边 delta 日志 = 约 7,700 万次字符串操作,令 file 后端**每次图读取**卡半分钟,直接击穿 MCP `graphflow://diagnose` / `stats` 资源的 60s 超时(live:本机全量测试 4 文件 6 用例超时根因)。改为端点邻接索引 + 惰性标记删除 + 末尾一次性压缩;upsert 去重语义保持(删除后再 upsert 同 key 正确重新入列)。 ### 验证(第三轮能力清点,全部 live) - team serve:启动 + health(tenant/role/rbac 元数据)+ JSON-RPC-only 面;`skill sync export` 真实落盘。**注**:无认证 loopback 下 `tools/list` 返回 0 工具(团队服务器工具面的暴露策略待确认);Windows 保留端口范围会令某些端口 EACCES(环境限制,非产品缺陷)。 - 对话脱敏完整复验:真实形状的 JWT Bearer / postgres 连接串 / ghp_ key 全部 `[REDACTED:*]`(此前的"Bearer 未脱敏"疑点撤回——长度门是防误伤设计,短测试 token 不是真实形状)。 - knowledge extract(4 requirements + 4 provenance 边)、audit --privacy(如实报 0666 与 6 端点)、spawn-receipt / evidence backfill usage 正确、artifact export 8171 节点 / 35266 边(gzip,SHA-256)。 ### Tests - 新增 `tests/m-task-echo-skill.test.ts`(2 用例):任务回显原子丢弃 + 任意扩展名垃圾清理。 ## [1.26.0 内轮次 2] ### Fixed — 第二轮深挖:配置链诚实性 + 证据分级(live 驱动) - **显式坏配置 fail-fast(v1.25.1 已知遗留 sqlite 泄漏的根因)**:`--config` 指向存在但损坏的文件(如 Windows 反斜杠路径造成的非法 JSON)此前只 WARN 一句就**静默用默认配置继续跑**——预算/传输/存储全按默认执行,`transport:"file"` 工作区因此冒出默认路径的 `graphflow-out/graphflow-graph.sqlite`(即 1.25.1 登记的句柄泄漏遗留)。现在显式路径损坏直接抛错并给出修复指引(含"用正斜杠"提示);**路径尚不存在保持宽容**(settings-save 等创建型流程依赖此语义,`LoadConfigResult.notFound` 区分两种情况)。项目根 `graphflow.config.json` 损坏同样 fail-fast;global/overlay 层保持宽容 WARN。 - **两处过度严格校验让最小配置非法**:`learningPolicy is required` 与 `graphPolicy.graphStorePath is required for file transport`——两者都有完整默认值兜底,却要求显式存在;按文档/示例写精简配置必然校验失败,再叠加上一条静默 fallback 就是"配置永远不生效"的组合拳。两者均改为可选补默认。 - **auto-index 被 dialogue 节点骗过(代码锚点永不出现)**:`graphStoreNeedsIndexing` 只看"节点列表非空",store 里只要有一条对话轮/episode 就判定"无需索引"——live 复现:全新 file 工作区 preview 永远只返回 dialogue 锚点。新增 `storeHasCodeNodes`(File/Symbol/Module 存在才算已索引);修复后 live 验证新增 `b.ts` 即在下次 preview 自动增量索引并精确命中 symbol 锚点。 - **outcome 证据包被静默丢弃**:`normalizeOutcomeEvidence` 要求 commit AND testCommand 双全,否则整个证据包丢弃——agent 传了 `testCommand+testResult:pass` 却收到 "no evidence package",partial/unverified 分级形同虚设。改为"任何实质证据字段即构造包",分级交给 `verifyOutcomeEvidence`(live:`unverified + ["diff is empty","missing commit or test command"]`,提交的证据可见、可审计);`OutcomeEvidence.commit/testCommand` 类型随之放宽为可选。 ### 验证(第二轮深挖新增 live 证据) - MCP 桥接闭环:plan(probe-failed-bridge)→ insight submit×2 → merge → run(诚实 HUMAN_REVIEW + episode 落库)→ report_outcome(证据分级)。 - R8:working-set 预取真实调用图(8 个可避免读)、challenge 20 条真实外部调用者质询、quote 诚实 insufficient-samples、facts ask 诚实 UNRESOLVED。 - workbench:plan 播种 4 主题容器、topicId 续接注入 promptLines。 - skill markdown:垃圾技能 export/import 双向均标 invalid(诚实拒绝)。 - MCP Streamable HTTP:initialize 1.25.1、tools/list 10 工具(双 Accept 协商)、恶意 Origin 拒绝。 ### Tests - 新增 `tests/m-config-evidence-honesty.test.ts`(6 用例):坏配置 fail-fast、missing 路径宽容、最小配置合法、证据三级分级。 ### 已知遗留(登记不修) - 失败 run(HUMAN_REVIEW_REQUIRED)仍会产出以任务文本命名的垃圾技能(`create-a-tiny-file-...`)——v1.25.0 的逐 atom 质量门未拦住任务名直录;建议在 applySkillLearning 前按 outcome 过滤或收紧名字门。 - `graphflow team serve` / RBAC 未在本轮 live 验证范围。 ## [1.26.0 内轮次 1] ### Fixed — 诚实性收口(live 验收发现的问题批次) - **plan 来源一等字段(planSource)**:`graphflow_plan` 结果新增 `planSource`(`llm` | `probe-failed-bridge` | `llm-failed-bridge` | `no-llm-bridge`)+ `probe`(探测结果)+ `degradeReason`(降级原因);CLI 文本输出同步打印 `source=...; reason=...`——桥接计划从此不可能读起来像真模型产出。前置问候探测(v1.25.0 已有)live 验证确实在用:坏 key 下 `source=probe-failed-bridge`,LLM 计划从未被尝试。 - **provider 适配器真实错误旁路透出**:非严格模式适配器故意把失败回显成 `[provider:model] `(弹性设计,保留),但底层原因(401/配额/网络)此前完全不可见。新增 `src/routing/provider-errors.ts` 旁路记录(无依赖、防循环导入),五个适配器 catch 路径写入;连通性探针的 masked-failure 错误现在附带 `last adapter error: openai http 401: ...`(live 与 curl 地面真值一致)。 - **diagnose 区分 configured 与 reachable**:`health=` 更名 `health(configured)=`(配置存在性派生),CLI `diagnose` / `route diagnose` 叠加真实 planner/worker 问候探测(5s 有界,`probe=planner:FAIL(原因)|worker:FAIL(原因)`)——撤销的 key 不再显示为健康(live:configured 全 true 而 probe 全 FAIL,原因 401 透出)。 - **memory search 零证据命中过滤**:`memory search` 此前把 Jaccard=0 的 episode 打成 `score=0.000` 的"命中"(候选扫描拉全量、两路排名均无信号)。现无条件过滤零词面重叠命中("evidence, not judge"——在能透出 cosine 证据之前,0 分命中就是噪声);live:无重叠查询诚实返回 `hits=0`,有重叠返回 1.000。 - **doctor 只读**:首用自举安装器(`runFirstUseBootstrap`)豁免 `doctor` / `diagnose` / `audit`——只读诊断命令不再有安装副作用(live:删除 marker 后运行 doctor,纯诊断输出、marker 未写入)。 - **AGENTS.md npx 版本漂移警告**:`npx -y --package=@roarpeng/graphflow` 的缓存键不含版本,装过旧版的机器会静默继续服务旧 server(live 实测握手 1.3.3 + 21 个旧命名工具)。推荐配置改为全局安装 + 直接 `graphflow-mcp` 入口,npx 形式附带验证/清缓存指引。 ### Tests - 新增 `tests/m-plan-provenance.test.ts`(5 用例):masked 回显→probe-failed-bridge(带真实适配器错误)、探测抛错→原因透出、探测过/分解失败→llm-failed-bridge、全通→llm+final、memory 零证据过滤。 ## [1.25.1] - 2026-09-20 ### Fixed — Windows CI 平台适配(v1.24.0 起的 validate-platforms 红灯) - privacy-audit 的两个 POSIX mode 用例在 Windows 上 `skipIf`(chmod 只切只读位,任何文件都读回 0666;Windows 语义已由注入 platform 的用例覆盖)。 - m109 / skill-markdown-progressive 的临时目录清理改为 Windows 安全(`maxRetries`+`retryDelay`+best-effort):运行时遗留的默认路径 sqlite 句柄会令立即 unlink EBUSY。**已知遗留**:`transport:"file"` 的工作区内仍会出现默认 `graphflow-out/graphflow-graph.sqlite` 且句柄未关——连接生命周期泄漏需产品级修复(161e2fe 曾修过一次,v1.24.0 回归)。 ## [1.25.0] - 2026-09-20 ### Fixed — 承诺验收全量收口(6 差距 + SoL-Pi 审计,live 实测驱动) 当天对 SKILL.md 承诺做三轮 live 验收(真 deepseek、真 MCP、无 LLM 桥接回路),发现并修复 12 个真实缺陷,全部有 live 复验证据: - **graphflow_run 桥接 worker 3 连败 → 1 次过**:anchor 源码正文(≤8 个/24KB,单文件 6KB 头尾截断)内联进 worker prompt 与 executionDescriptor,附"已内联、勿请求文件"指示;worker 的最终答案以 `result` 字段外露(工具响应 + episode 记录双持久化,DAG 路径逐节点捕获),失败路径也保留最后输出。 - **plan 模板冒充 LLM → 真 LLM 优先 + 诚实降级**:有 LLM 时真调 `planTasksLlm`/`brainstormTaskLlm`;前置**完整凭证问候探测**(apikey+baseUrl+model 真往返;echo 占位/可达但 401 均判不通,4-10ms 桥接不再白等 15s);探测超时 AbortSignal 真取消;模板回退永不自称 `final`(`suggested` + agent 桥接工作项 + 失败原因)。planner 默认档 smart→economy(pro 稳定超 15s 预算);分解调用禁用 deepseek tool-loop(其确认信封 `{"ok":true,…}` 使解析必败)+ 一次立即重试 + brainstorm 解析兼容信封 summary。 - **CJK 低命中双缺陷**:低相关触发只认 anchorCount<3(永不达)→ 增加 top-5-by-score 均值 <0.25 维度(relevance 逐锚透传);`estimatedRawTokens` 从全图模糊匹配改为按**交付 anchor 集**统计(live:338,869 → 522,垃圾检索诚实报 0% 节省);低命中交付裁剪为仅 relevance>0 的锚(15→2)+ 中文 spine 说明行。 - **assistantReply 无 query 被拒**(文档称 optional)→ 合成占位轮落库,幂等重试,回复永不丢弃。 - **飞轮技能质量**:逐 atom 质量门(长度/结构停用词/逐 atom 符号证据/id ≤48 字符/总量 ≤4)+ `pruneLegacyNoiseSkills` 存量清理(名字即证据:路径片段/裸 token/连接词开头子句/未 seeded composite,hint 刷高的 uses 不豁免)接线进 reportOutcome;live 库存 8 条垃圾清零。 - **SoL-Pi 收口**:四机制默认全开语义核实无漂移,4 份 SKILL.md "off by default" 谎言改口(sync 门禁绿);compaction 经济模型修正(重写成本按**压缩后摘要**计价 + 计入压缩后重放,-1,428,000 → -333,000,信号新增 replayCost/compactCost 与成本构成);**Action Fusion 两个盲区修复**(中文动词关键词缺失 + 无 plan 桥接描述符不挂 steps → 任务文本子句回退,live:`fused:true`,"修改 X 并验证"折叠为单一动作)。 - **桥接描述符源码回退**:检索头被元节点占据时,任务文本**引用的文件路径**直接内联(`../`/node_modules 防护)。 ### 验证 - 210 文件 / 1588 用例全绿;tsc/eslint/build/sync-surfaces 门禁全过。 - live 验收矩阵:英文检索 15 锚全中;plan simple/insight(六帽 + 5-Why 链)真 LLM 产出;run llm 模式 COMPLETED+result+语义验证;无 LLM 桥接回路全通(plan 委派→agent 分解→insight merge→run 描述符→outcome 闭环);artifact 导出→导入 8616 节点回路;release-gate 真实拦截(proven-skills 0<1)。 ## [1.24.1] - 2026-09-19 ### Fixed — 收尾审计修复批次(promise-vs-reality 对账的五处缺口) 对外承诺审计(README/ROADMAP/CHANGELOG vs 代码/测试/基准实测)发现五类"承诺没有完全闭环"的缺口,本批全部收口: - **`audit --privacy` 0600 从"显示"变"判定"**:`PrivacyAuditFacts` 新增 `warnings` 数组——全局配置存在且 POSIX mode ≠ 0600 时产出违规 finding(含 chmod 修复指引;Windows 无 POSIX 位、mode 不可读、文件不存在均不误报,`platform` 可注入测试)。此前审计只打印 mode 不做合规判定,本机 `~/.graphflow.config.json` 实际 0664(比修复前的 0644 还松)却零报警——README 承诺的"0600 检查"名不副实。CLI 输出把 warnings 逐行附在摘要后。 - **存量全局配置自动收紧**:`ensureGlobalGraphFlowConfig` 对已存在文件 best-effort `chmod 0600`(此前只在保存/迁移时收紧,v1.18.5 之前写入的旧文件可永远带错误权限);`graphflow install` / `init` 路径即修复,`result.message` 注明 tightened。 - **R7-a skills-ref 校验门禁收口**:新增 `extractSkillReferences` / `validateSkillBundle`(`src/learning/skill-markdown.ts`)——渐进披露指针⇄`references/` 文件**双向完整性**:悬空指针(SKILL.md 指向缺失文件)、孤儿文件(打包了但从未被指向)、越权路径(`../`、非 `references/*.md`)均计 invalid;导出 CLI(`skill markdown export`)已从单文件校验切换到整包校验。ROADMAP R7-a 至此无剩余项。 - **检索基准再基线(v1.12→v1.24 语料漂移)**:`RETRIEVAL-EVAL-RESULTS.md` 停留在 2026-08-04 语料(MRR 0.836 / NDCG@5 0.671),自指语料随 src/ 增长已漂移。连跑两次确认**确定性**(仅时间戳/耗时不同)后在当前树再生成:**Hit@5=100% 保持,MRR=0.779,NDCG@5=0.638**;冻结声明目录 `flywheel-proof-claims.json`、README(×3 处)、`docs/flywheel-reproduction.md` 按"再测量→声明与报告同步更新"协议一并更新。顺带修正两处既有不一致:README NDCG 0.601 ≠ 目录权威 0.671(同为旧口径漂移);README skill A/B 行"injection 100% / 25.6 tok"与已提交报告(噪声门后 0% hint injection / 100% episode recall / ~15 tok)矛盾。 - **文档漂移清理**:README 中英双语 "Register Skill + MCP" 小节嵌套损坏的 ```` ```bash ```` 代码块(渲染错乱)修复;README "98.2%" 单口径残留改为双臂口径(95.6% / 98.5%);"961 tests / 142 files" 过期计数改 count-free 措辞(evergreen 政策);ROADMAP 头部"最后更新 v1.19.0"更新至当前版本;`flywheel-reproduction.md` token 行 98.2%(274,434→4,928,旧一代口径)对齐当前双臂。 - **eslint 零警告**:`coverage/`(生成物,已 gitignore)加入 eslint ignores,此前 3 条 unused eslint-disable 警告来自该目录的 vendored 文件。 - **R9 orphan 检查器 dogfood 三修(误报根因)**:用本批未提交改动自证时发现孤儿检查在真实图上系统性误报——① **`calls` 边未计入**(v1.20.0 引入的真 bug):跨文件函数调用在图中记为 `calls` 边而非 `references`,`countInboundEdges` 只数 references,纯函数模块(如 orphan-checker.ts 自己)一律被判 0 入边;现 references+calls 都计(单测用 stub 图回归锁定)。② **带源码扩展名的工具配置文件漏排除**:模块头注释承诺"配置文件天然排除"但实现只排除非源码扩展名,`eslint.config.js` / `vitest.config.ts` 被误报;补 `*.config.{js,cjs,mjs,ts,…}` 排除。③ **package.json 清单入口未排除**:`bin` / `main` / `module` / `exports` 指向的文件(含 dist→src 布局映射)是图根节点、设计上零入边;`src/surfaces/cli/index.ts`(bin 入口)被误报;读不到/解析失败 fail-open。修后 dogfood:22 文件脏树 `graphflow audit` 零 findings。 - **测试 203→203 文件 / 1498→1512 条全绿**:privacy-audit 2→5(非 0600 告警 / 0600 通过 / Windows 跳过)、m86 3→4(ensure 收紧存量文件)、skill-markdown-progressive 5→10(门禁 5 条:导出器自产 bundle 通过 / 指针提取 / 悬空 / 孤儿 / 越权路径)、m96 补 3 条(工具配置排除 / 清单入口排除 / 无 package.json fail-open)、m97 补 2 条(calls 边计数 / 真 孤儿仍报 0)。本机 dogfood:`audit --privacy` 先报警 0664 → chmod 600 → 复跑零 warning;`proof:flywheel` 8 项检查全 ok。 ## [1.24.0] - 2026-09-19 ### Added — R7 三件套首发:语义召回默认开 + Agent Skills 标准分发 + 可核验隐私 - **R7-b 零配置本地语义召回默认开**:`graphPolicy.embeddingProvider` 默认从 `"fnv"` 改为 `"transformers"`(resilient local 路径:优先 `Xenova/bge-base-zh-v1.5` 本地语义模型,任何失败——缺包/无缓存/超时/加载错误——透明降级 FNV-1a,保持零 Key、零云依赖)。此前语义召回是 opt-in(默认 FNV hash 词袋),开箱质量落后 Continue+Ollama 一档;现在 ONNX 运行时可用即自动走语义召回,`"fnv"` 显式配置仍可强制纯离线 hash(air-gapped 场景)。`embedding-factory.ts` 解析顺序不变:legacy openai key > 新开关 > legacy embeddingPolicy > 默认 resilient transformers。`tests/embedding-backend.test.ts` 更新为断言 transformers 默认健康路径(真实加载模型 305ms)+ fnv 显式 opt-out。 - **R7-a SKILL.md 对齐 agentskills.io 开放标准(导出侧)**:`src/learning/skill-markdown.ts` 导出 frontmatter 对齐规范——`name` 经 `toSpecName` 转为 1-64 小写连字符 slug(非 ASCII 名称罗马化回退)、必需 `description`(what+when 语义)、可选 `license` / `compatibility` / `metadata`(display name 经 `metadata.graphflow-name` 往返保留);`validateSkillMarkdown` 全量校验导出文件(`invalid=0` 保证);导出布局改为**每 skill 一个目录 + SKILL.md**(agentskills.io 约定),平面 `.md` 导出保留兼容。import 宽容:第三方 spec 文件与旧 display-name 文件均可入,导入一律保守 `correctable` 不继承 proven 信任。端到端:空工作区 `graphflow skill markdown export ` 优雅降级 `files=0; invalid=0`。 - **R7-d 隐私威胁模型 + 可执行审计面**:新增 `docs/threat-model.md`(信任边界 / 数据流 / 出网点枚举 / 密钥处理 / 落盘路径 / 剩余风险)+ `graphflow audit --privacy [--json]`(`src/audit/checkers/privacy-checker.ts`):11 个落盘产物路径存在性、6 个出网端点及触发条件(5 家 LLM provider 仅在配置时触发;HuggingFace Hub 仅首次模型下载且 `HF_ENDPOINT` 可镜像)、全局配置文件权限(0600 检查)、provider key **布尔值**(检测变量名存在,值永不回显)。核心可核验断言:**零配置零 Key 时零必需出网(模型首下除外)**——把 local-first 从口号变成一条可执行命令。`tests/privacy-audit.test.ts` 2 条。 - **R7-a 渐进披露 + spec 目录布局(同版补完)**:`skillToSkillMarkdownBundle` 把超限 playbook/guidance 拆进 `references/guidance-*.md`(SKILL.md 保持紧凑指针 + 按需加载索引行,~5000 token 上限进入 `validateSkillMarkdown`);导出布局定为 agentskills.io 约定的**每 skill 一目录 + SKILL.md**(目录名 = spec name,去重后缀 `-2`)。导入侧同步收紧:spec 布局强制**父目录名 = skill name**(violation 注明 agentskills.io);拥有 SKILL.md 的目录只收 SKILL.md、不再下钻——`references/` 文件永不被误当 skill 导入;平面 `.md` 旧布局保持可导入(本轮还修复了目录扫描静默丢弃平面 `.md` 的回归)。 - **R7-h 效率证据公开 schema(导出侧)**:新增 `src/learning/efficiency-evidence.ts` + `graphflow efficiency export` → `graphflow-out/efficiency-evidence.json`:`schemaVersion=1` + `graphflowVersion` + `sources`(指回 efficiency.json / context-fidelity.json)+ 三源数据合订(配对比较 / 保真采样 / token-savings 累计)+ `tokenSavings.boundary` 固定边界文本随数发布(packaging ROI ≠ Hit@k ≠ body coverage ≠ lossless fidelity)。**诚实门禁**:零配对 / 零 qualifying / 能力回归 → `gate.allowed=false` 且原因内嵌文件——文件总可发布,省 token 声明被门禁(SoL-Pi capability floor 的工件级载体)。 - **token 基准外部语料模式(反自指)**:`benchmarks/run-token-benchmark.ts --corpus= [--queries=a,b,c]` 把双臂测量指向另一个仓库(默认通用查询集 `EXTERNAL_CORPUS_DEFAULT_QUERIES`,可覆盖);RESULTS.md 段落带 `Corpus (external, anti-self-referential)` 行、机器 JSON `inputs.corpus.kind: "external"` + 语料根路径。同时脚本改造为可编程入口 `runTokenBenchmark({corpusRoot?, resultsPath?})` + **import 不再自跑 main**(直接执行守卫 `import.meta.url === pathToFileURL(argv[1])`),并修复 corpus 模式缺 `existsSync` 导入的崩溃;`docs/benchmark-standards.md` §2.2 补外部语料条目。 - **Fixed — `audit --privacy` 双重打印**:分支内手动 `console.log` 与 `main()` 统一的 `formatCliResult(legacyText)` 打印路径叠加,summary 输出两遍。现合并为单一 `legacyText` 返回,JSON 模式交由 main 输出 `data`。 - **测试 199→203 文件 / 1480→1498 条全绿**:新增 privacy-audit(2 条)与 skill-markdown-interop 4→6(spec frontmatter 往返 + 非法 name 拒绝)、embedding-backend 默认语义断言(9 条);本轮再增 skill-markdown-progressive(5 条:bundle 拆分/指针/常量/目录名/规格布局导入导出往返 + references 防误收)、token-benchmark(4 条:savings 数学/--corpus 解析/通用查询集/外部语料端到端含机器 JSON 出处)、efficiency-evidence(4 条:空态门禁/qualifying 开门/能力回归关门/写盘字段+boundary+gate)。端到端冒烟:`audit --privacy` 净空/含产物两态正确;空工作区 `efficiency export` 产出 gated 文件(版本号取自 GraphFlow 包自身而非工作区)。 - **已知边界**:R7-a 剩余 skills-ref 校验门禁(ROADMAP 标注);R7-h 剩余随包发布管线与 mechanism 生命周期联动;独立复现破零仍需外部贡献者(外部语料模式已把工具备好)。语义召回默认开意味着首次查询可能触发一次模型下载(默认缓存于 `~/.cache/huggingface`,可经 `GRAPHFLOW_EMBEDDING_CACHE_DIR` / `embeddingPolicy.modelCacheDir` 重定向、`HF_ENDPOINT` 镜像;显式 `"fnv"` 可完全关闭下载)——已在 threat-model 与 README 标注。 ## [1.23.2] - 2026-09-19 ### Fixed — 健壮性双修:文件锁死锁 + 夜间学习崩溃(覆盖率深挖) - **`src/utils/file-lock.ts` 陈旧锁死锁**:进程在 `openSync` 成功、`writeSync` 写入 pid **之前**崩溃会留下空 lock 文件;旧逻辑 `parseInt("")` 得 NaN 永远走不到清理分支,后续所有 `acquire` 只能空转到 30s 超时(且 `withFileLock` 直接抛错)。修复:空/非数字 pid 视为崩溃残留,文件年龄超过 10s 宽限窗口(避免与正在写 pid 的创建者竞态)即清理重试;`writeSync` 失败时不再泄漏 fd、不留半写锁文件。 - **`src/learning/learning-events.ts` 损坏行崩溃**:`readFeedbackEvents` 对每行裸 `JSON.parse`,崩溃残留的半行数据会让整个夜间学习任务挂掉。修复:fail-open 跳过无法解析/形状不符的行(写入方仅产 `{query, passed, tokenCost, retries}`,已核实无误伤)。 - **`src/routing/provider-executor.ts` skillHints 去重**:`formatPromptWithContext` 对重复 skill 提示不去重,重复词句白白消耗 prompt token;现保序去重后再截断。 - **测试 195→199 文件 / 1435→1480 条全绿**:新增 m101(file-lock 8 条:互斥/超时/ESRCH 死进程回收/陈旧空锁回收/新建竞态保护)、m102(learning-events + nightly-trainer 双签名 + reflector 聚类 12 条:损坏行跳过、10MB 轮转、lesson 节点与 improves 边)、m103(5 个 provider 适配器 stub fetch 13 条:无 key 降级、strict 抛错、HTTP 错误、abort 传播、thinking 模式请求体、usage 解析)、m104(provider-executor + deepseek 工具循环 15 条:重试预算、401 不重试、断路器开启短路、中止传播、上下文通道上限、工具结果回填、轮数耗尽强制终答)。 ## [1.23.1] - 2026-09-18 ### Fixed — 潜伏自 v1.19.1:完整 install 流程覆盖直连条目 - **legacy sweep 覆盖 bug**:`buildInstallReport` 在 HostAdapter 写完直连条目后,后续的全宿主 npx sweep 再写一遍,把直连覆盖回 npx——**zcode 直连在完整 `graphflow install` 里从未生效过**(单测全绿因为都绕过了完整流程;本机端到端复现定位)。修复:legacy sweep 加 `preferGlobalInstall: true` 与 adapter 一致。端到端验证:完整 install 后条目 = 稳定 node + 全局 server.js + cwd=包根。 - **新增 [docs/postmortem-windows-install.md](docs/postmortem-windows-install.md)**:v1.18.6→v1.23.1 六次安装故障的根因表 + **八条守则**(端到端冒烟非 existsSync / 配置只指向稳定目录 / 启动链优先级 / peer 显式声明 / install 带悬空修复 / 文档标 shell / 干净环境发版前演练 / registry 不可控自保)+ 支持排障速查表。 ## [1.23.0] - 2026-09-18 ### Fixed — Windows 双故障根因修复(v1.22.0 回归 + npx peer 丢失) - **稳定 runtime 布局 bug(v1.22.0 引入,本次修复)**:v1.22.0 把 vendor **内容**铺到 `~/.graphflow/runtime/` 根,但 launcher 按 `__dirname/vendor/graphflow/...` 定位 → `server not found: ...\runtime\vendor\graphflow\...`。现统一镜像扩展布局(`runtime/vendor/graphflow/dist/...`),且 launcher 增加**双布局回退**(vendor 布局 → 扁平布局),CLI 稳定探测同时接受两种布局(兼容 v1.22.0 已写入的扁平副本)。 - **npx 缓存 `Cannot find module 'ajv'`(peer 丢失免疫)**:`ajv-formats`(SDK 传递依赖)的 peer `ajv` 在镜像残缺/npx 解析下会丢失(现场:缓存里 ajv-formats 在、ajv 不在)。现将 **ajv + ajv-formats 显式声明为直接依赖**——任何解析路径下都强制存在。 - launcher 冒烟测试(vendored 布局定位 server);m100 更新双布局断言;全量 195 文件 / 1435 测试。 ## [1.22.1] - 2026-09-18 ### Fixed — 首次运行自动注册兜底(镜像残缺包 / ignore-scripts 环境的"一条命令"补洞) Windows 实战:用户从 npm 镜像装到**旧版(1.20.1)且包内容残缺**(skills 资产缺失、postinstall 静默)——注册从未发生且用户零感知。新增兜底:`graphflow` 命令**首次执行**时检测到版本标记文件不存在(postinstall 从未成功跑过)→ 自动执行完整安装注册(含悬空修复)并写入标记,仅此一次;help/version 保持只读不触发。输出中若出现 `Skill source not found` 会明确提示镜像包不完整并给出官方源重装命令。CI/GRAPHFLOW_SKIP_POSTINSTALL 环境不触发。 ## [1.22.0] - 2026-09-18 ### Fixed — VSIX 安装同样一键完成,且条目永不因升级悬空(三平台) 「再好的项目,安装不上也是扯淡」——两种安装方式现在都是一条命令全自动,且写入的 MCP 条目在任何升级路径下都不会悬空: - **稳定运行时目录 `~/.graphflow/runtime/`**:VSIX 激活时把自带 runtime + launcher 同步到该稳定目录(IDE 升级会删除带版本号的扩展目录——历史上所有 `Cannot find module mcp-launcher.cjs` 悬空报告的根源),MCP 条目全部指向稳定路径;每次激活刷新副本,升级 = 自动重写。同步失败 fail-open 回退扩展副本,下次激活重试。 - **CLI 直连候选链**:`preferGlobalInstall` 解析顺序变为 npm 全局包 → 稳定 runtime → npx 回退——只装 VSIX(没装 npm 包)的用户经 CLI 重装时也能拿到直连条目而非 npx。 - **三平台保证**:全部路径经 `os.homedir()` + `path.join`;`fs.cpSync` 跨平台复制;由既有 ubuntu(node20/22)/windows/macos CI 矩阵验证。npm 路径(v1.21.0 的 postinstall 全自动)不变。 - 测试 m100(3 条):稳定根路径(隔离 HOME)、探测命中/未同步 fail-open、直连候选链永不悬空(直连条目引用文件必须存在)。 ## [1.21.0] - 2026-09-18 ### Fixed — 一条命令承诺:`npm install -g @roarpeng/graphflow` = 安装 + 注册 + 检测 + 修复 Windows 实战暴露的链路缺陷:postinstall 全局安装时走的是旧的手工组装流程(只装部分宿主 + 强制 npx 条目),既不覆盖 20 宿主三件套也不做全局直连,更不会修复悬空条目——用户一条命令后仍需手动折腾。彻底收敛: - **postinstall 全局分支改为调用完整 CLI `install`**(单一事实来源):20 宿主 HostAdapter 三件套注册 + 全局安装直连条目 + 悬空修复 + doctor 摘要,一条命令全部完成;本地安装/CI 行为不变。 - **悬空 MCP 条目检测 + 自动修复**:新增 `repairDanglingGraphflowMcpEntries`——扫描所有检测宿主的 `graphflow` 条目,`command`/`args` 中的绝对路径指向已不存在的文件(典型:IDE 升级删除了旧扩展目录的 `mcp-launcher.cjs`)→ `graphflow install` 开头自动重写为当前最佳形态(全局直连优先)。`install` 输出新增 `[REPAIRED]` 行。 - **doctor 悬空可见性**:MCP 检查对条目启动目标做存在性校验,悬空标 `missing (dangling entry)` 并给出死路径与修复指引(`graphflow install` 一键重写);覆盖 legacy 与 HostAdapter 两条检查路径。 - 测试 m99(4 条):死扩展 launcher 检测 + doctor 标记、健康条目不误报、修复重写为可启动形态、无悬空时 no-op。 ## [1.20.1] - 2026-09-16 ### Docs — R9/R9 文档收口 - 新增 **[docs/closing-audit.md](docs/closing-audit.md)**:R9 承诺账本 + 收尾审计完整文档——三个触点(CLI / outcome 前置 / 跨会话提醒)、内置检查器矩阵、`graphflow.audit.json` 声明式规则示例(驱动加载 / 容器注入)、基线策略、诚实边界。 - README(英文)core capabilities 新增 R9 与 R8 两行 + CLI quick reference 补 `challenge` / `audit` 两行;README(中文)「本版要点」升至 v1.20 并新增 R9/R8 行。 ## [1.20.0] - 2026-09-15 ### Added — R9 承诺账本 + 收尾审计(Promise Ledger / Closing Audit) 针对 dogfood 实证痛点:agent 长任务"干着干着就忘了"——新依赖忘安装、新文件忘接线/注入容器、驱动忘加载、文档忘更新。问题本质是**承诺没有账本**:义务在任务中段产生、收尾时无人清点。R9 从可观测副作用登记义务并在三个触点对账(不猜意图、只对账事实、质询不阻断): - **检查器矩阵**:依赖 lock 一致性(npm v1/v3、pip+poetry/Pipfile.lock)、孤儿文件接线(图 inbound 边数为零即未接线)、文档一致性(CLI 变更 vs README、版本徽章 vs package.json)。 - **声明式规则引擎**:容器引用/驱动加载等项目特定义务由 `graphflow.audit.json` 配置(`filePattern` + `mustBeReferencedBy` glob),内置零项目类型假设;glob 引擎零依赖自研(`**`/`*`/`?`/`{a,b}`)。 - **基线策略**:默认 git 未提交工作区(agent 会话的天然收尾窗口);`--since ` 扩大;无 git 降级为纯状态检查。 - **`graphflow audit` CLI** + **outcome 前置审计**:`report_outcome success` 前自动跑审计——默认温和(findings 附进 episode 证据并提醒);`GRAPHFLOW_AUDIT_STRICT=1` 严格模式拒绝在有未决项时上报成功。 - **跨会话提醒**:会话结束未决项写入图上承诺账本(`promise-ledger:`);下次会话首次 `graphflow_context` 附带"上次会话有 N 项未收尾";审计清零自动 resolve。 ### Fixed - **m87 全局安装探测测试(Windows)**:`exists` mock 用 `path.includes("\\")` 猜平台。win32 上 `path.join("/usr/lib/node_modules", …)` 仍含反斜杠,POSIX 用例被当成 Windows 路径比较,导致 `found` 为 undefined、`validate-platforms (windows-latest)` 失败。现按用例传入明确 npm root。 ## [1.19.2] - 2026-09-15 ### Fixed — 跨平台加固(Windows / Linux / macOS) - **全局安装探测容错(v1.19.1 引入路径的加固)**:`npm root -g` 的 stdout 在 Windows 上可能带 UTF-8 BOM、CRLF 或混入 banner 输出——原 `trim()` 实现会被污染导致探测失败(安全回退 npx 但直连失效)。现剥 BOM + 按 CRLF/LF 切分 + 取**最后一个非空行**(npm 的路径输出在 stdout 末尾)。测试覆盖 BOM / banner 前置 / 空行三种污染形态。 - **Windows 平台门控直连验证**:新增 win32-only 测试——真实全局安装存在时,注入的直连条目 `command` 必须是磁盘上存在的 node 二进制(短路径形态允许或裸 `node`)、`args[0]` 必须是存在的全局 `server.js`。由 `validate-platforms (windows-latest)` CI 矩阵执行。 - 既有跨平台矩阵确认覆盖:CI 已在 ubuntu(node 20/22) / windows-latest / macos-latest 三平台跑全量测试;直连条目的空格路径加固(短路径化 / 裸 `node` 回退)复用 `sanitizeMcpServerNodeForWindowsClients` 既有逻辑并有 m63 win32 门控测试。 ## [1.19.1] - 2026-09-14 ### Fixed - **Windows ZCode「启动中」卡死(npx 冷启动超时)**:npx 条目首次需下载完整包及原生依赖(`onnxruntime-node`,Windows 上数百 MB),120s 连接超时内常无法完成。`install` 现对 ZCode 启用 `preferGlobalInstall`:探测到全局安装(`npm root -g` 下的 `@roarpeng/graphflow/dist/surfaces/mcp/server.js`)时自动写入 **node + server.js 直连条目**(`cwd`=包根,秒级启动、无网络依赖;复用既有 node-bundled 形状与 Windows 空格路径加固);无全局安装回退现行 npx 条目。探测失败(无 npm/路径不存在/空输出)一律 fail-open 回退。README(中英)注册小节补充 Windows 首启慢的说明与解法。测试 m87 扩至 6 条(npx 回退锁定 / 直连条目 / 探测函数三态 fail-open / adapter 三件套)。 ## [1.19.0] - 2026-09-14 ### Added — R8「省钱与靠谱双主线」(五模块齐发) 核心洞察:agent 最大的 token 黑洞是"找东西的探索轮次"(每轮探索都是带全量历史的完整模型调用——压缩 prompt 省加法,消灭探索轮省乘法);可靠性最便宜的形态是不跑测试的质量门。五项全部落地: - **R8-1 Working set 预取**:`src/graph/working-set.ts`——以 touched 文件为活跃工作集,沿 references/calls 边扩展 caller/callee/test-for 相关文件生成预取包;诚实计数 `potentiallyAvoidedReads`,不乘臆测系数(tests/m89)。 - **R8-2 图 diff 质询清单**:`src/graph/diff-challenge.ts` + `graphflow challenge --files`——改完代码后图谱生成三类质询(external-caller / requirement-link / deleted-symbol)还给 agent 回答;近零成本质量门,激活 Engineering KG 存量;不声称检测签名变更,只质询图上可证事实(tests/m90)。 - **R8-3 subagent 出生证**:`src/graph/spawn-receipt.ts` + `graphflow spawn-receipt`——父 agent 发紧凑收据(任务 + 图锚点 + 取回指令)替代背景文本复制;subagent 用 `graphflow_context` 按需展开(tests/m91)。 - **R8-4 时点事实查询**:`src/graph/temporal-facts.ts` + `graphflow facts ask`——对话图 bi-temporal 语义产品化:按 asOf 返回仍有效结论(effective)与已被取代历史(supersededAtPoint);白领"事实漂移"防线(tests/m92)。 - **R8-5 任务预算报价**:`src/learning/task-quote.ts` + `graphflow quote`——效率历史变事前决策工具;样本不足 confidence=insufficient-samples + 保守折半 + advisory 明说,绝不编造(tests/m93)。 ## [1.18.8] - 2026-09-14 ### Added - **R6 收官:efficiency for efficiency(效率反哺搜索,SoL-Pi 闭环最后一块)**:新增 `src/learning/efficiency-reinvest.ts` + `graphflow mechanism reinvest [--apply]`。合格配对节省(仅 qualifying——被 `no-efficiency-gain` / 能力回退取消资格的比较**不得为其验证搜索出资**)按 `efficiencyPolicy.reinvest.ratio`(默认 0.5,`maxBudgetTokens` 默认 200k)折算为机制试验预算;收据指纹记账于 `graphflow-out/efficiency-reinvest.json`(每条 efficiency.json 记录只出资一次,重复 apply 幂等,损坏账本 fail-open);输出下一步试验建议(`frozen`→held-out 优先、`in-trajectory`/`proposed` 次之,终态机制不再建议),**试验执行仍归操作者/宿主**(advisory 边界不变)。默认开启,可经设置页/配置关闭。测试 `tests/m88-efficiency-reinvest.test.ts`(7 条:预算推导/上限/disabled/建议排序/幂等 apply/dry-run 零写入/账本 fail-open)。至此 SoL-Pi 借鉴(R6)P0/P1/P2 全部 ✅。 ## [1.18.7] - 2026-09-14 ### Fixed - **MCP stdio 握手时序(严格客户端启动失败)**:stdio 服务器曾在 `initialize` 响应之前把 `notifications/message`(文件监视器启动日志)写到 stdout,严格按序等待响应的客户端(实测 ZCode)握手失败。`sendLogNotification` / `sendProgress` 现在以 SDK `oninitialized` 回调(客户端 `initialized` 通知到达)为门,握手完成前一律抑制,日志仅走 stderr。端到端实测:stdout 首行即 initialize 响应,`initialized` → `tools/list` 全链路干净。 - **测试不再重写/删除真实宿主配置与技能**:`buildInstallReport` 会重写所有检测到的宿主配置、`uninstallAllSkillsAndRules` 会扫除真实 HOME 下全部技能目录——此前 4 个 install 测试与 1 个 uninstall 测试未隔离 HOME,本机跑一次全量测试即静默撤销手工修复的 `~/.zcode/cli/config.json` 并删除 `~/.zcode/skills/graphflow/`。五个测试全部改用临时 HOME/APPDATA 隔离(uninstall 测试跑后以 md5 校验真实技能完好)。 ### Added - **ROADMAP R7 演化方向(2026-09 横向调研版)**:基于对云端记忆 API(Mem0/Zep-Graphiti/Letta)、索引派(codebase-memory-mcp/Continue+Ollama)、反索引派(Cline)、Agent Skills 开放标准生态(~40 平台、AGENTS.md 在野 57k+)与**效率机制赛道(NVIDIA SoL-Pi:绑 Pi 单宿主)**的横向对比,确定演化主线:R7-a 学习飞轮产物以标准 Agent Skills 包分发、R7-b 零配置本地语义召回默认开、R7-c 跨仓库/monorepo 图谱、R7-d 隐私威胁模型 + 审计面、R7-e 业界记忆基准接入、R7-f 团队记忆企业化。(发布后补充:R7-g 效率机制投影面宿主泛化、R7-h 效率证据可审计公开格式——补入第五赛道调研后新增,见 ROADMAP。) ## [1.18.6] - 2026-09-14 ### Added - **ZCode 宿主支持**:新增 `zcode` HostAdapter(capabilities: `mcp-stdio` + `skills` + `rules`)。`graphflow install` 现在会检测 `~/.zcode` 并完成三件事:(1) 向 `~/.zcode/cli/config.json` 的 **`mcp.servers`**(ZCode 嵌套结构,新增 `configFormat: "zcode"`)注入 `graphflow` stdio MCP 服务器;(2) 将 `skills/graphflow/SKILL.md` 复制到 `~/.zcode/skills/graphflow/`;(3) 向 `~/.zcode/AGENTS.md` 写入受管指令块(append-with-markers,不动用户内容)。工作区级 `.zcode/config.json` 目标同步支持,`doctor` / `uninstall` 均已覆盖(注入/检测/移除均为幂等操作;卸载时清理 `mcp.servers` 条目但保留其它服务器与顶层键)。新增测试 `tests/m87-zcode-host.test.ts`(3 条:注册表形状 / 安装+状态+幂等 / 预存配置保留)。 ## [1.18.5] - 2026-09-13 ### Added - **DSH 插件市场收录合规(按 [STANDARD](https://github.com/bradeGithub/DSH-Plugins-Marketplace/blob/main/STANDARD.md))**:`package.json` 的 `dsh` 块补齐显式声明(`plugin: true` / `kind: "server"`,`bundle.patch` → `cordis.patch.yml`,市场据此判为 **cordis-plugin**);补齐规范关键词(`dsh`、`dsh-plugins`、`deepseek-harness-plugin`、`cordis`、`cordis-plugin`);新增 **disclosure 披露块**(D1 云端依赖 + 端点、D3 凭据处理、D4 权限声明,另含 `offline_mode`/`jurisdiction`)——本地索引/压缩/召回/图存储全离线,仅配置了 LLM provider 时才访问云端端点。 - **README(中英)**:新增 DSH 徽章、插件市场一键安装与 `dsh plugin --profile web add github:Roarpeng/GraphFlow` 两种路径,并按 STANDARD §6.4 明确「**只选一条注册路径**」(市场/`dsh plugin add` 与 `npx @roarpeng/graphflow install` 的 home overlay 不要叠加,否则重复加载);披露摘要与市场类型说明(源码型 → 安装时询问并执行构建)。 ### Security - **全局配置以 0600 写入**:`~/.graphflow.config.json` 可能保存 `providers..apiKey`,现在创建/迁移/通过设置面板保存时都写为**属主可读写**,并会收紧已存在文件的权限(此前是 0600 &~ umask = 0644,同机其他用户可读)。这也是 disclosure 中 `api_keys[].storage: "file-0600"` 的依据;测试 `tests/m86-config-file-mode.test.ts`(新增 3 条)在 POSIX 上断言模式位。 ## [1.18.4] - 2026-09-13 ### Fixed - **Windows 平台验证失败(v1.18.3 的回归)**:1.18.3 让 Windows CI 的 `Test` 步骤失败——(1) `m83` 测试用 `"/"` 拼相对路径,在 Windows 上拿到绝对路径(已改为 `path.relative` + 正斜杠归一化);(2) 解析 worker 池在 TypeScript 源码(`tsx`/vitest)下用 `--import tsx` 启动 worker,Windows 上启动开销大且不稳定,拖慢到超时。现在 **worker 池只在编译产物(`file-parse-worker.js`)下启用**,源码/测试/`tsx` 运行一律走进程内解析(同一图,确定性);worker 池仍由 m84 的注入式调度测试与 dist 端到端实测覆盖。 - **worker 池门槛改为按规模**:线程切换有固定成本(worker 启动 ≈4×150ms + 结果克隆),实测 1.2k 小文件仅打平、5.5k 文件 / 50MB 源码 1.68×。门槛改为 `文件数 ≥ 200 且总字节 ≥ 1MB`(`graphPolicy.indexWorkers` 显式指定时同样遵守该门槛)。 - `git ls-files` 扫描加 `-c core.quotepath=false`,避免非 ASCII 路径被 C 风格转义后与真实路径不匹配。 > 说明:v1.18.3 的 npm 包已发布成功,但 Marketplace 发布被 Windows 验证阻塞(`publish-marketplace` 依赖 `validate`,后者失败即跳过),因此以 1.18.4 重新发布;功能改动与 v1.18.3 相同。 ### Fixed - **M83 Windows validate**:`walkFiles` 返回绝对路径,测试用 `root + "/"` 剥前缀在 Windows 上匹配失败(收到 `C:\\...\\src\\app.ts`)。改为 `normalizePath(relative(root, absPath))`,与 `walkScannableFiles` 一致。 ## [1.18.3] - 2026-09-13 ### Performance - **大型项目索引提速 3.7–4×(实测 ragflow:5,492 文件 / 78,160 符号)**:首建 **34.7–37.6s → 9.5s**(4 workers)/ 16.2s(单线程),图存储 **855–860MB → 193MB**。三处改动叠加: - **reference 边预算**:跳过"定义文件数 > N"的通用名(DF 停用词,`graphPolicy.referenceEdgeMaxDefinitionFiles`,默认 10;0=不限)并限制每文件引用边数(`referenceEdgeMaxPerFile`,默认 500)。实测 575 万 → **99 万条** references(−83%);此前 1.87 万个名字贡献了 575 万条边,`__init__` 一个名字就有 46.9 万条(定义于 414 个文件)。质量有验证:`ci-release-evidence` 三个 golden 探针 recall 保持 **1.00**,`fidelity-anchor-recall` 88 → **91**。 - **worker 池并行解析**(`worker_threads`,默认 cores−1、上限 8;`graphPolicy.indexWorkers`、`GRAPHFLOW_INDEX_WORKERS=0` 可关):解析阶段 fan-out,缓存/剪枝/写库仍在主线程;实测同仓库 **15.95s → 9.50s(1.68×)**,且图**逐项一致**(91,680 节点 / 1,113,739 边 / 989,218 refs)。worker 创建或单任务失败都会自动降级为进程内解析,绝不让索引失败。 - **索引扫描更聪明**:尊重 `.gitignore`(`git ls-files --cached --others --exclude-standard`,精确语义;`graphPolicy.respectGitIgnore: false` 可关,非 git 仓库自动回退目录遍历),并跳过 lockfile / minified bundle / source map / 生成代码(`*_pb2.py`、`*.pb.go`、`*.g.dart`、`*.generated.*` …)。 - **增量保存不再重写整库**:file 传输新增**追加式 delta 段**(`graphflow-graph.json.delta.jsonl`)+ 阈值压缩(默认 8MB)。仅当 base 存储 ≥ 4MB 才启用,小/中型项目保持"单个自包含 JSON、字节级不变"的历史布局。实测 11.2MB 图库:**单文件保存 0.27s 且 base 未被重写**(delta 3.5KB),无变更重跑 0.04s;`vacuum()` 与重建会把 delta 压缩回单文件。所有内部读取路径(`loadGraphStore` 等)都会合并 base + delta。 - **机械优化(消除 O(store) 放大)**:`upsertGraph()` 让节点+边**一次读写**(此前 `upsertNodes` + `upsertEdges` = 两次整库重写);**空批次完全不触碰存储**(watcher 空跑不再重写);**边键集合缓存**(增量写入不再每次重建百万级 key 集合);批量索引的 **per-file prune 合并为一次批量删除**(此前每个文件一次整库重写 —— 大型仓库增量索引会因此卡死;实测已修复:原先 >120s 卡死 → 13.1s)。 ### Added - **配置**:`graphPolicy.respectGitIgnore`(默认 true)、`referenceEdgeMaxDefinitionFiles`(默认 10)、`referenceEdgeMaxPerFile`(默认 500)、`indexWorkers`(默认 auto;0 = 关闭 worker 池)。 - **测试**:`m83-index-scan-budget`(DF 过滤、每文件上限、增量路径同预算、生成/锁文件识别、真实 git 仓库 `.gitignore` 生效与可关闭)、`m84-index-worker-pool`(worker 计数/门槛/入口解析、注入式调度与容错、共享解析核心)、`m85-incremental-store-delta`(追加不重写 base、阈值压缩、删除走 delta、vacuum、截断行容错、重建清理)、`m82` 扩到 10 条。 ## [1.18.2] - 2026-09-13 ### Fixed - **VS Code 扩展「GraphFlow MCP 自动安装失败: Invalid string length」(已完整复现并定位)**:扩展的 MCP 自动安装(`runMcpBootstrap`)会调用 `getSettingsPanelStatus()`,而它经 `inspectGraph` **自动索引整个工作区**;文件传输随后把整张图当作**一个 JSON 字符串**序列化(`JSON.stringify(store, null, 2)`)。对文档密集型仓库,索引器会产出约 **590 万条** `references` 边(实测 ragflow:5,939,794 边 / 91,684 节点),pretty-print 后的 payload 超过 V8 单字符串上限(64 位约 512 MB)→ `JSON.stringify` 抛 `RangeError: Invalid string length`,用户看到的就是安装失败(且图存储长期只有节点、`edges: 0`,因为边写入每次都死在这一步)。修复分四层: - **面板/状态路径改为只读**:`inspectGraph` 新增 `autoIndex`(默认 `true`,CLI 行为不变),`getSettingsPanelStatus()` 传 `false` —— “安装 MCP”/面板刷新不再建图(实测:打开大型仓库时从"索引到崩溃"变为 12ms 返回,且不写盘);建图仍由显式命令与激活后的自动索引负责。 - **写盘不再物化单个巨串**:小图(≤20k 元素)仍美观打印;大图改为**紧凑 + 分块写入**(4MB 缓冲区,逐元素序列化),写入前不再构造完整 payload。实测同一仓库 901 MB 图存储写入成功。 - **新增分块读取器**(`src/graph/graph-store-json-chunks.ts`):超过单字符串上限的 store 逐元素增量解析,跨任意 chunk 边界可恢复(含跨边界的多字节 UTF-8,截断文档报错而非半读)。实测 901 MB / 5,939,794 边 20 秒读完;`readFileGraphStore` 与 `GraphifyFileClient` 均自动路由到它。 - **扩展启动步骤互相隔离**:安装、探测、模型指南、面板统计各自捕获异常;面板统计失败不再被报成「MCP 安装失败」,失败时同时把 `err.stack` 写入 GraphFlow 输出通道(此前只有一行 `err.message`,本次 bug 正是因此难以定位)。 ### Added - **`tests/m82-graph-store-write-safety.test.ts`**:锁定四条保证——面板状态只读(不建图、不写盘)、`inspectGraph` 默认仍建图(CLI 行为不回退)、`autoIndex:false` 不触碰存储、小图美观打印 / 大图紧凑分块且可往返解析、超限存储走分块读取、跨 chunk 边界(含 1 字符 chunk 与多字节字符)解析一致、截断文档被拒绝。 ## [1.18.1] - 2026-09-12 ### Fixed - **跨宿主 unsafe workspace root 加固(dsh / opencode glue)**:dsh glue 的工作区此前只读 `payload/agent/session.cwd`,dsh 从 `$HOME` 启动时宿主进程 cwd 胜出,首轮 hint 因此把 `rootDir=/home/` 喂给模型(MCP 硬拒 → 整次调用失败)。现在优先取会话头 `session.header.cwd`(含 `subagent/*` 直接传入的裸 session 对象),遇到 home/AppData/未展开占位符会跳过;hint 自身也不再输出任何 unsafe `rootDir`——无法确定时直接省略,由服务端按 `GRAPHFLOW_WORKSPACE_ROOT` / 发现逻辑兜底。opencode 插件同理:改用宿主传入的 `{ directory, worktree }` 作为 CLI 子进程 cwd,不再继承宿主进程 cwd(此前在项目外启动会把回复记到错误工作区,被拒后静默丢弃)。 - **MCP 边界:unsafe workspace root 变成可恢复错误,不再 `-32603`**:显式 `rootDir` 或 cwd 落在 home/AppData 时,工具调用返回 `isError: true` 的结果,附 server cwd、当前 `GRAPHFLOW_WORKSPACE_ROOT` 与「改用项目绝对路径重试」的指引;此前作为协议错误抛出,整次调用对模型不可恢复。**安全策略未放宽:仍然拒绝 home/AppData,只是拒绝方式可操作。** - **新增 `CLAUDE_PROJECT_DIR` 工作区发现提示**:Claude Code ≥2.1.157 会把它注入 MCP stdio 子进程;从家目录启动的 Claude Code 现在能自动解析出会话项目,而不是让每个工具调用失败(unsafe 取值仍会被跳过)。 - **`sync:surfaces` 镜像映射错误**:此前把 Trae 规则同时写进 `.agent/rules`(属 Antigravity)与 `.claude/rules`(属 Claude Code),`sync:surfaces --check` 在 v1.18.0 上一直是 DIRTY;现按安装器真实来源映射,并补上 `.cursor/rules`、`.trae`/`.agent` skills、`.windsurfrules`、`AGENTS.md`,`--check` 通过。 - **规则/技能写入 `rootDir` 契约**:4 个规则模板、规范 SKILL.md、根 `CLAUDE.md`/`AGENTS.md` 与托管指令块(GEMINI.md、`.windsurfrules` 等)统一说明——`rootDir` 必须是项目绝对路径,禁止 home/AppData/未展开 `${workspaceFolder}`;遇到 `unsafe workspace root` 就省略 `rootDir` 重试。 - **新增跨宿主安装守卫测试**(`tests/m81-host-install-workspace-guard.test.ts`):沙箱 HOME 下安装全部已迁移宿主,断言任何写出的 `cwd` / `GRAPHFLOW_WORKSPACE_ROOT` 都不会指向安装者 cwd、HOME、AppData 或沙箱外路径(并校验 dsh 的 MCP 行保持 `!!js process.cwd()` 动态形式)。 ### Added - **插件 ON/OFF 配对效率 A/B harness**:新增 `benchmarks/plugin-ab-lib.ts`、`benchmark:plugin-ab`(DSH 插件开/关双臂,沿用 SoL-Pi 配对双臂 + 能力地板判据)与 `benchmark:real-task-ab`(离线、确定性、免 API Key 的真实任务「起步 token 成本」对比),并附设计文档 `docs/efficiency-ab-test-design.md` 与实测结果 `benchmarks/REAL-TASK-AB-RESULTS.md`。 - **`graphflow efficiency [show|reset]` CLI**:直接查看配对效率报告与能力地板判定(release-gate 读取同一份数据)。 - **机制试验写入效率报告**:`recordMechanismTrial` 新增 `onComparison` sink,配合新的 `appendEfficiencyRecord()` 把**已评估**的记录原样落进 `graphflow-out/efficiency.json`(不再被默认容差重算),机制 trial 因此对 release-gate 的能力地板可见,而不只存在于 mechanism Decision 节点里。 ## [1.18.0] - 2026-09-12 ### Added - **统一效率机制开关 efficiencyPolicy(SoL-Pi 借鉴,P0 收口)**:新增顶层配置 efficiencyPolicy.{observations,contextPressure,actionFusion},**默认全开(最佳配置)**;可在 graphflow-settings 页逐项关闭,或在此显式设 false。解析集中在纯函数 src/config/resolve.ts 的 resolveEfficiencyPolicy;数值非法回退安全默认,reduce.strategy="llm" 缺 provider+model 时降级为 fingerprint。显式调用(graphflow_context 传 content/handle、reduce:true)属于明确意图,不受开关限制。 - **GF-3 观测压力预算 + 压缩建议(Online Context Compact analog)**:graphflow_context 新增 contextPressure 入参(usedTokens/maxTokens/pressureRatio/remainingTurnsEstimate)。启用后打包预算由 deriveAdaptiveBudget("auto", observed) 决定(回退默认预算,绝不编造压力),结果新增 contextPressure 块:effectiveMaxContextTokens + 可选 compaction 经济性建议(cacheWriteReadRatio 默认 12.5,minSavingRatio 默认 0.2)。启用时绕过 context 缓存,避免跨压力复用陈旧预算。 - **GF-4 融合动作步骤(Action Fusion analog)**:graphflow_run bridge 模式的 executionDescriptor 新增 steps(fused: true)——plan 中 edit/write 紧跟的 run/test/validate 节点合并为一个动作单元(含 command 与 dependsOn),供宿主在一次调用内执行;执行权仍归宿主,GraphFlow 只做计划与证据。 - **GF-2 观测句柄策略来自配置**:graphflow_context 的 pack/recall/reduce 现按 efficiencyPolicy.observations 解析阈值、head/tail、TTL、脱敏与 reducer 路由(解析失败 fail-open 到内置默认)。SKILL.md 新增 Workflow 8,写明「归档大输出 → 保留 handle → 按页/区间精确召回 → reduce 出逐字核验收据」协议。 - **P1 配对效率报告 + 能力地板(SoL-Pi capability floor)**:新增 src/learning/efficiency-report.ts,按「基线臂 vs 打包臂」记录同一任务的 tokens/turns/toolCalls/responseCount/score 配对对比,落盘 graphflow-out/efficiency.json。token 未改善、或分数/响应数劣化超容差即判不合格——response-count 臂专门证明节省不是「少干活」。提供 evaluateEfficiencyFloor / evaluateFidelityFloor 供治理门禁使用。 - **P2 机制自动研究回路(SoL-Pi auto-research 方法论)**:新增 src/learning/mechanism-research.ts,把「候选机制」作为节点(mechanism:)走 proposed → in-trajectory → frozen → held-out → admitted|rejected。三条规则代码强制:准入必须有合格的 held-out 试验;冻结后不再接受 in-trajectory 试验(held-out 隔离);终态不再接受试验。新增 graphflow mechanism propose|trial|freeze|admit|reject|list CLI,并在 graphflow diagnose 暴露 mechanisms 汇总。 - **P1 工具结果投影(自动省 context)落地 dsh**:dsh 具备 surface-replace 原语(与原生 dsh-compaction-tool-result-pruner 同一 API),dsh/plugin.mjs 新增观察投影:在 session/event 的 tool/result 上先把原文归档到观察库(新增 CLI `graphflow observe pack|recall`),再用 handle 投影替换模型可见的表面节点(保留首尾 + 召回指令),并带 surfaceOp replace + sourceEventSeqs。默认开启(GRAPHFLOW_D_DSH_PROJECTION=0 关闭),全程 fail-open(禁用/低于阈值/打包失败/表面 API 缺失/append 抛错都退回原文)。与原生 pruner 的本质差别:原文精确可召回且逐字核验,而不是有损 marker。src/observations/host-hook.ts 的 projectToolResult 为进程内宿主的同一契约;HOSTS_WITH_TOOL_RESULT_PROJECTION 现为 ["deepseek-harness"]。其余宿主(opencode/Cursor/Codex/Gemini)暂无结果重写面,继续走 SKILL.md 显式 handle 协议。 ### Fixed - **toContextPressure 不再伪造 token**:仅提供 maxTokens(或仅 usedTokens)时此前会以默认 0 补齐并得出可用的压力比;现在要求「显式 ratio」或「used+max 双双有限且 max>0」,否则返回 undefined。 - **远端 reducer 路由不得静默降级**:reduceObservation 在 strategy="llm" 且未传入 reducer 时返回 reducer-route-missing 的 fail-open 摘录,而不是悄悄退回本地 fingerprint 选择器;配置解析层同时把缺 provider/model 的 llm 策略降级为 fingerprint。 ### Changed - **governance release-gate 新增能力地板阈值**(均可选,保持向后兼容):--min-efficiency-qualifying、--max-capability-regressions(默认 0)、--min-anchor-recall-percent、--min-body-coverage-percent。锚点召回/正文覆盖仅在存在样本时检查。 ### Documentation - 新增 docs/efficiency-mechanisms.md:SoL-Pi 借鉴的配置、四机制映射、效率/能力地板、机制自动研究 CLI、投影边界,以及「不要做」的负面清单。 ## [1.17.1] - 2026-09-10 ### Fixed - **插件说明页版本停滞两个 minor**:`vscode-extension/README.md` 就是发布到 VS Code Marketplace 与 Open VSX 的**说明页正文**(随 VSIX 打包并对外展示),却仍停留在 **1.15.3**——含 `graphflow-1.15.3.vsix` 安装命令、`npx @roarpeng/graphflow@1.15.3 install`、"升级到 1.15.3+",以及一整节 "v1.15.x 要点"。v1.16.0 与 v1.17.0 两次发版都没有更新它,用户看到的说明页因此落后两个 minor。已重写为 1.17.x 内容,并补上此前缺失的 v1.16.0(HostAdapter 全宿主、编排层拆分)与 v1.17.0(双口径 token 节省、对话图接入上下文引擎、对话密钥脱敏、provisional 准入)要点。 - **根 README 章节标题滞后**:`README.md` 的 `## Core capabilities (v1.15+)` 与 `README.zh.md` 的 `## 本版要点(v1.15)` 更新为 v1.17,并补上 v1.17 的能力行(打包后 token 记账、双口径节省、对话图注入位置与密钥脱敏)。 ### Tests - `tests/m48-doc-code-consistency.test.ts` 新增守卫,堵住这次漂移的根因——**插件说明页此前完全不在文档一致性检查范围内**: - `vscode-extension/README.md` 纳入 `DOC_FILES`(工具名一致性 + UTF-8 校验); - 新增 `README_SURFACES` 断言**所有面向用户的 README**(根 EN / 根 ZH / 扩展)都引用当前版本; - 断言插件说明页里每个 `graphflow-.vsix` 文件名与 `@roarpeng/graphflow@` 都等于当前版本——此前正是"这个页面的版本号没人管",用户才会照着 1.15.3 的命令去装。 ## [1.17.0] - 2026-09-09 ### Added - **Token 节省的现实对照臂**:`benchmarks/run-token-benchmark.ts` 新增 Arm B `baselineTopKFilesFullText`——把**同一排序器**的 top-K 锚点解析到真实源文件并按全文计数(每文件上限 1500 行,`--anchor-top-k=N` 可调)。原 Arm A 更名 `baselineGrepTopFilesFullText` 并明确标注 "upper bound by construction"。实测:Arm A 410,725 → 6,044(98.5%);**Arm B 136,265 → 6,044(95.6%)**。每查询的 `resolvedFiles` 落盘可复算。Arm B 无法自我膨胀——锚点越小它的节省率越低。 - **打包后 token 记账**:`src/surfaces/cli/runtime/graph.ts` 新增 `estimateSummaryLinesTokens` / `estimateUnbudgetedPayloadTokens` / `withPostPackageAccounting`。对话召回行、workbench `promptLines`、对话主线 `promptLines` 三处「打包后前插」现全部计入 `tokenEstimate` 与 `budgetUsedPercent`;`dialogueHits` 作为**不占 L1–L3 配额**的负载单独报在 `unbudgetedTokens`,并新增 `accountedTokens`(= 已预算 + 未预算)。`estimatedSavingsPercent` 改为对**真实总量**计算,`graphflow-out/token-savings.json` 的 ROI 不再系统性低报。 - **技能准入冷启动层**:`admitSkillToProvisional`(`src/learning/skill-admission.ts`)——`proven` 仍严格要求 `successCount >= 2` 的去重 pass episode;新增的 provisional 层要求名字像项目符号**或**至少 1 个成功 episode,且**无条件否决**结构性噪声(空名 / 纯停用词 / readme+update 融合)。文档明示:provisional 只是 hint,**绝不作为 proven 呈现、导出或同步**。 - **对话写入边界密钥脱敏**:`redactSecrets`(`src/learning/dialogue-thread.ts`)在**写盘前**清洗 `userQuery` / `assistantReply` / 派生 title+summary / 序列化的 `record` metadata / agent trace label。覆盖 PEM 私钥、含凭据的连接串(postgres/mysql/mongodb/redis/amqp/mssql)、Bearer 与 JWT、各家 API key 形态(sk-/ghp_/github_pat_/glpat-/xox[baprs]-/AKIA/AIza…)、以及 `KEY=value` 形式的凭据键。标记稳定可调试(`[REDACTED:api-key]` 等),幂等,默认开启,`GRAPHFLOW_DIALOGUE_REDACT=0` 可关闭(附团队同步风险警告)。误伤保护有 10 组反例测试(散文、路径、无凭据 URL、版本号、`process.env.X` 等原样通过)。 ### Fixed - **L3 对话打包在生产路径是死代码**:`injectDialogueTurns` 此前**只**被 `buildLayeredContextPackage` 调用,而生产路径 `previewContext`(MCP `graphflow_context`)走的是 `buildEnhancedContextPackage`——于是 v1.14.0 的头号能力「对话图进入上下文引擎 L3」对用户**从未生效**,而 5 个测试只覆盖非生产打包器所以 CI 全绿。现抽出共享阶段 `injectL3Stage`(`src/graph/context-package-core.ts`):治理技能/pin 与对话轮在**同一 budget、同一 L3 配额**下打包,两个打包器共用,不再漂移。`tests/m-dialogue-l3-packing.test.ts` 改为对**两个**打包器同时断言。 - **CI 发布证据同义反复**:`scripts/ci-release-evidence.ts` 此前用 `returnedAnchorIds.filter(...)` 反推 `expectedAnchorIds`,而 recall 的定义使 `expected ⊆ returned` 时恒为 1.0——该门禁在数学上不可能因检索质量失败。现期望锚点**先于检索**从提交在案的 golden 数据集独立导出(缺失的探针用显式 ground-truth 常量并在 recall < 1.0 时失败);同时传入 `expectedBodies`/`packagedBodies` 让唯一非同义反复的 `bodyCoverage`(LCS)**真正被度量**,为 0 即失败。 - **proven 技能证据可断言而非可观测**:`userConfirmed` 在 CI 场景改为 `false`(CI 不是人);`testResult` 不再硬编码 `"pass"`,改为按 `GRAPHFLOW_CI_TEST_RESULT` 环境变量 → 流水线结果文件 → GitHub Actions 步骤顺序推断,**缺失即 unknown 并明确失败**,不回退到断言;DOGFOOD_LESSONS 里陈旧的 "(149 files)" 改为运行时统计真实测试文件数。 - **`wouldDegradeLibrary` 忽略真实成功证据**:它调用 `admitSkillToProven(name)` 时不传 options,`successCount` 恒为 0,永远走不到 "success-evidence" 快路径——有真实成功 episode 的技能会被误判为"会污染库"。现接受可选 `AdmitSkillOptions` 并转发(1 参调用点保持兼容)。审计确认生产晋升路径本就直连 `admitSkillToProven`,故无生产调用点在丢失证据;`admitSkillToProvisional` 已从 `src/index.ts` 导出。 - **安全审计工作流连续 3 周静默失败**:`scripts/security-audit.cjs` 第 10 行用了 `join` 却未 import `node:path`,`ReferenceError` 使 2026-08-24 / 08-31 / 09-07 三次定时运行在 `npm audit` 运行前即崩溃。修复含 `node:path` 导入、Windows `shell` 处理、报告路径按仓库根解析;新增 `tests/security-audit-script.test.ts`(静态断言 import + 端到端跑假 npm 断言无 ReferenceError),随 `npm test` 进入 CI——坏脚本从此无法隐藏。 - **OIDC Trusted Publishing 的 `repository.url` 与失败诊断**:`package.json` 的 `repository.url` 从 `git+https://….git` 改为 provenance/OIDC 要求的规范形 `https://github.com/Roarpeng/GraphFlow`。OIDC 换票 404 `package not found` 时,发布脚本打印 Trusted Publisher 应对齐的字段(含 2026-09-03 之后默认只允许 `npm stage publish`)。 - **npm publish EOTP 不再被 `whoami` 预检漏掉**:`npm whoami` 只证明 token 能读身份;带 2FA 的用户 token 在 `npm publish` 时仍会要 OTP(CI 无法提供)。发布脚本改为先走 GitHub OIDC Trusted Publishing(`npx npm@11.6.2`,去掉 `_authToken` 以免 `setup-node` 的 dummy token 跳过 OIDC),失败再回退 `NODE_AUTH_TOKEN`;EOTP 时打印 Trusted Publisher / 自动化 token 的操作说明。 ### Tests - `tests/npm-publish-idempotent.test.ts`:EOTP / 已发布 / 缺鉴权分类、OIDC 环境剥 token、workflow 不再把 whoami 当成发版证明。 ### Changed - **README 的 token 节省改为双口径并列**,不再只报膨胀分母的单一数字;两项分别标注其回答的问题与不可互换性。 ## [1.16.0] - 2026-09-08 ### Added - **R4 集成层模块化收口(HostAdapter 全宿主)**:新增通用 profile 驱动切片 `src/integrations/profile-host-installer.ts`。`installViaHostAdapter` / `uninstallViaHostAdapter` / `getHostAdapterInstallStatus` 现覆盖全部 19 个注册宿主——4 个手写切片(DeepSeek Harness / Cursor / Claude Code / Kimi Code)+ 15 个 profile 宿主(Trae、VS Code、Windsurf、Cline、Roo Code、Kilo Code、PearAI、Gemini、Codex、Antigravity、Amazon Q、Zed、Continue、Qoder、Opencode)。 - **`skill-installer` 精确目标原语**:`installSkillToTargets` / `removeSkillFromTargets` / `installInstructionsToTargets` / `removeInstructionsFromTargets`——单宿主 install slice 只写自己的 `skills/graphflow/SKILL.md` 与受管指令块,不再顺带写其它已检测宿主。 ### Changed - **CLI 三处宿主硬编码改为注册表遍历**:`install` / `uninstall` / `doctor` 统一走 `HOST_ADAPTER_MIGRATED_IDS`;`uninstall` 先按宿主切片清理,再跑遗留清扫(工作区 MCP 条目、Trae 用户 Skill、项目级规则)。新增宿主不再需要改 `init.ts`。 - **`agent-profiles` 注册表并入 `buildAgentProfiles()`**:`opencode` 等仅在新注册表登记的宿主获得 MCP 安装/状态支持;遗留条目在同 id 时优先,已写入的 marker / target 路径不变。 - **`runOrchestration` 拆分**:新增 `src/core/orchestrator-phases.ts`,把 ~360 行大函数拆为 `runSimplePhase` / `resolvePlanPhase` / `runBridgePhase` / `runLlmDagPhase` + `makeDagNodeRunner`;`orchestrator.ts` 只保留模式解析、上下文装配与 triage。日志、图/技能同步顺序、`triageId` 传播(含 LLM 失败路径有意不带 `triageId`)逐字保持。 ### Fixed - **mcp-http 请求超时可配置**:新增 `GRAPHFLOW_MCP_TIMEOUT_MS`,`createGraphClient()` 据此设置 `GraphifyMcpClient.timeoutMs`(默认仍 15s)。当端点连接挂起(而非被拒绝)时,15s × 多次图操作会拖长单次运行;该开关让 CI / 测试可以快速失败。 - **临时目录残留图谱劫持工作区发现**:MCP 服务以 cwd 位于 `%TEMP%` 启动时会在那里写 `graphflow-out/graphflow-graph.json`,而 `hasProjectWorkspaceMarkers()` 把该文件当作项目标记,于是 `discoverWorkspaceRoot()` 对**所有**位于临时目录之下的项目都返回临时目录根,m49 工作区隔离用例随之失败。新增 `isSystemTempDirectory()` 作为向上遍历边界(不改动 `isUsableWorkspaceFallback`,保留显式 cwd 回退语义),并给 `discoverWorkspaceRoot()` 增加 `extraBoundaries` 测试钩子。 - **README.md / README.zh.md UTF-8 损坏**:v1.15.4 的版本号提交(`a8ae51d`)在改写两个 README 时把约 100 个多字节序列的第三字节替换成 `?`——中文、破折号、箭头、勾选全部变成乱码并随 npm 包发布。已按 `e7e429d`(v1.15.3 文档提交)逐行核对后重建,仅保留有意的版本号与 HostAdapter 文案改动;同时补齐 README.zh.md 落后一版的版本徽章(1.15.4 → 1.15.5)。 ### Tests - `tests/host-adapter-install.test.ts`:注册表完整性、通用切片 install / uninstall / status、未安装宿主零写入(+4 用例)。 - `tests/m-install-hooks-wiring.test.ts`:doctor hooks 检查改为按 agent 名匹配(DeepSeek Harness glue 与 Claude Code hooks 同属 `hooks` 类别,注册表顺序不是契约)。 - `tests/m48-doc-code-consistency.test.ts`:新增「文档必须是合法 UTF-8」与「README.zh.md 徽章与 package.json 一致」两个守卫(+2 用例)。 - `tests/m49-workspace-root-isolation.test.ts`:新增临时目录边界与「残留图谱不得捕获嵌套项目」回归用例(+2 用例)。 ## [1.15.5] - 2026-09-08 ### Added - **Kimi Code HostAdapter**:`installViaHostAdapter("kimi-code")` 写入 `~/.kimi-code/mcp.json`、Skill 与 `AGENTS.md`;doctor / uninstall 同步走注册表。Kimi Code 不展开 `${workspaceFolder}`,MCP env 省略该占位符。工具前缀 `mcp__graphflow__`。 ## [1.15.4] - 2026-09-06 ### Fixed - **DeepSeek Harness 安装不再弄挂 `dsh web`**:`graphflow install` 在 profile 未安装 `@roarpeng/graphflow` 时只写 MCP home overlay(不写 glue);profile 已有包时清空 home overlay,由 bundle 独占 MCP+glue,避免 `ERR_MODULE_NOT_FOUND` 与 `duplicate loader entry id: mcp-graphflow`。空 `cordis.patch.yml` 改为删除文件(dsh 拒绝空 YAML)。FAQ 补充对应排障。 ## [1.15.3] - 2026-09-05 ### Changed - **R4 context packaging 去重**:`buildLayeredContextPackage` / `buildEnhancedContextPackage` 抽出共享 `context-package-core`(keyword/vector 召回、L1–L3 配额打包、dialogue 与 neighbor expansion)。两条公开函数的签名与 MCP/CLI context preview 行为保持不变;enhanced 仍独占 adaptive budget、RepoMap、symbol boost、graph compression 与 same-file/import 扩展。 ### Tests - **m74/m75 测试隔离**:不再 `process.chdir()`,也不再向真实 `$HOME/.npm/_npx` 写文件。fake home 与项目根均落在 `os.tmpdir()`,通过 `fromDir` 注入与 `process.cwd` mock 覆盖 unsafe-cwd 路径。 ## [1.15.2] - 2026-09-05 ### Added - **飞轮公开复现包(path A)**:`npm run proof:flywheel` 串起已有的检索 / skill A/B / memory A/B 离线基准,打印机器可读摘要 + 人类 checklist;`--dry-run` / `--help` 不重跑基准。冻结数字目录 [`benchmarks/flywheel-proof-claims.json`](benchmarks/flywheel-proof-claims.json);第三方入口 [`docs/flywheel-reproduction.md`](docs/flywheel-reproduction.md)。不发明新数字,只接线仓库里已提交的自测 RESULTS。 - **GraphFlow + Serena 联合方案独立指南**:把 `docs/comparison.md` 里的 "better together" 提升为一等文档 [`docs/graphflow-serena.md`](docs/graphflow-serena.md) / [中文](docs/graphflow-serena.zh.md)——并列安装两个 MCP、谁做什么(context/plan → Serena 编辑 → `report_outcome`)、常见坑。README(EN/中文)与 comparison 互链;配置示例 [`examples/graphflow-serena.mcp.json`](examples/graphflow-serena.mcp.json)(仅 MCP 片段,不把 Serena 写入 `package.json`)。无运行时代码改动。 ## [1.15.1] - 2026-09-05 ### Changed - Cursor and Claude Code install / uninstall / doctor now go through the HostAdapter registry (`installViaHostAdapter("cursor")` / `installViaHostAdapter("claude-code")`), including Claude Code hooks. Remaining hosts (Trae, VS Code, Windsurf, Codex, Gemini, and others) still use the legacy installers. ### Tests - Extended `host-adapter-install` with Cursor / Claude Code install-uninstall-status slices and M16-style CLI doctor wiring. ## [1.15.0] - 2026-09-05 ### Added - **Team shared memory MVP (ROADMAP R3)**:`graphflow team serve` 提供带 tenant 隔离与 viewer/contributor/admin RBAC 的 Graphify JSON-RPC 团队图服务;非 loopback 默认强制认证。`graphflow team issue-token` / `team example-config` 覆盖发证与客户端配置。 - **HTTP RBAC**:JWT `role` / `memory:read|write|admin` scope 或 `--http-token role:token` bearer 角色表;写路径(图变更、skill sync push、artifact import、governance)对 viewer 失败关闭。MCP Streamable HTTP 在配置了凭据时对 `tools/call` 执行同一套角色。 - **客户端**:`graphPolicy.mcpTenant`;mcp-http 客户端发送 `X-GraphFlow-Tenant`;401/403 不再静默降级到本地文件。`skill sync push|pull` 在 MERGE 语义上复用既有 git 技能包。 - **Diagnose / doctor**:`graphflow diagnose`(`route diagnose` 别名)与 `graphflow_diagnose` 输出 team 连通、authMode、tenant、RBAC、degraded-to-local。 - **文档**:`docs/team-memory-security.md` 标为 shipped MVP,并附部署 / 发证 / 加入 / 同步 runbook。 ### Tests - 新增 team RBAC 单测与 team server 集成测:角色允许/拒绝、tenant 隔离、非 loopback 拒无认证启动、客户端鉴权失败。 ## [1.14.1] - 2026-09-05 ### Fixed - **#28 DSH first-turn hint**: the glue extends the `agent/pre-step` enter decision's `messages` after `next()`, so the hint rides in the same step as the user's first message. `agent.inject()` is no longer used (it landed in the next-step inbox and spawned a trailing step the model refused). WeakSet gating and plugin source tagging are unchanged. - **#26 `/gf/nodes` HTTP 405**: `/gf` RPC registration waits for the host `connection` service with `ctx.inject(["connection"])` (same pattern as DSH api-gateway) instead of a sync `ctx.get("connection")` that is often undefined at apply() time. Registration failures are logged instead of swallowed. ### Changed - package.json `description` / keywords match the README positioning: GraphFlow is a local-first memory & context harness for coding agents, not an orchestrating executor. - DSH home overlay install/uninstall goes through the HostAdapter registry (`installViaHostAdapter("deepseek-harness")`). Cursor and Claude Code installers are unchanged. ## [1.14.0] - 2026-09-02 ### Added - **W1 时间语义与类型化边**:dialogue-turn 新增 `supersedes` / `same_topic` 类型化边与 `validAt` / `invalidAt` 时间有效性(Graphiti 式);`detectSupersession` 离线修正检测(更正标记 + 主题重叠阈值,pending 轮不可被取代,nearest-N 截断);跨 session `same_topic` 语义连边;`effectiveTurns` 当前真值过滤与 `formatSupersessionLine` 修正链渲染。`GraphEdge.relation` 扩展 `same_topic` 并纳入 compression weights / snapshot 优先级。 - **W1 可选 LLM 轮蒸馏**:`distillTurnWithLlm`(economy tier 路由,严格 Title/Summary/Decision 标签输出,失败逐轮回退启发式);`isDecisionTurn` 决策轮标记为飞轮提供 turn 粒度学习信号;`dialogue distill --llm` CLI 旗标(仅 `hasUsableLlmProvider` 时生效)。 - **W2 对话图进入上下文引擎**:`context-slicer` L3 打包命中有效对话轮(≤3)并附修正链标注行——同 token 预算与 L3 quota,绝不豁免;`graph-search` 新增 `searchDialogueTurns`(默认隐藏被取代轮、`includeSuperseded` 回看历史、修正链注解),对话命中纯增量、永不挤掉代码 Symbol/File 结果。 - **W2b 对话轮检索接入生产链路**:`previewContext` 附加 `dialogueHits`(跨 session 历史问答召回,≤3 条、默认隐藏被取代轮;命中修正链时在 summary 顶部加一行 `Dialogue recall: ...`,`recordDialogue: false` 的只读召回也生效)——MCP `graphflow_context` 结构化结果与 CLI `graphflow context` 同步获得该字段;新增 CLI `dialogue search "" [--limit N] [--include-superseded]` 与 runtime `searchDialogueTurnsRuntime`,直接检索历史问答。 - **W3 多 Agent 轨迹**:dsh glue 监听 `subagent/start|end` 写 `agent-trace` Decision 节点(`GRAPHFLOW_CAPTURE_TRACE` 独立开关、kind+label+status+turn 哈希去重、in-process runtime 优先、缺失即静默 no-op、绝不抛入 harness 循环)。 - **W3 fork / 回放原语**:`forkDialogueSession` 显式分叉(跨 session `next_section` 主干边 + fork session↔源 session `same_topic` 溯源边 + seed parentTurnId);`walkDialoguePath` 回放路径 walker(jump/fork 边界标注);CLI `dialogue fork --from [--name]`、`dialogue list --path `、`dialogue traces [--session] [--limit]`。 - **W4 面板与导出**:`/gf` RPC `nodes` 通道与 web 面板 host half 新增 `dialogue traces` 快照;面板对话轮显示「跳转 / 修正过结论 / fork」徽章与「Agent 轨迹」区块(含启动/完成/失败状态);`artifact export-memory` 新增 `dialogues.md`——按 session 分组的对话子图(修正链与 superseded 历史标注、Agent 轨迹列表)。 - **发布管线真正可发版**:新增 `scripts/ci-release-evidence.ts` flywheel 自证步骤——在 CI 上对本仓库做真实 dogfood(真实索引 + 检索探针写入 context-fidelity 样本 + 两个真实 pass episode 绑定 proven skill),并生成确定性 `graphflow-out/ci.config.json` 供 gate 审计;`publish-npm.yml` 在 gate 前执行该步骤。此前 release gate 在全新 checkout 上恒为 `proven-skills 0 < 1; fidelity-samples 0 < 1`,v1.13 接入门禁后 npm 实际从未发版成功。 ### Fixed - **Windows release gate**:`scripts/release-gates.cjs` 改为直接 `node + tsx` 运行 gate CLI——Node ≥ 18 出于安全拒绝 spawn `npx`/`npx.cmd` shim(EINVAL),旧写法在 Windows 上静默失败且无任何输出。 ### Tests - 新增 5 个测试文件 28 个用例:`m-dialogue-temporal`(8,时间边与修正链)、`m-dialogue-llm-distill`(6,LLM 蒸馏回退)、`m-dialogue-l3-packing`(5,L3 打包预算与修正标注)、`m-dialogue-retrieval`(5,检索命中与 superseded 过滤)、`m-dialogue-fork-replay`(6,fork/回放/轨迹)、`m-memory-pack-dialogues`(4,对话子图导出);dsh glue 套件更新为 3 命令面板协议并新增 4 个轨迹用例(共 29)。 - 新增 `m-dialogue-search-recall`(2,preview 附加 `dialogueHits` 与 CLI runtime 检索回环);修复 README 版本徽章落后于 package.json 导致的 doc-code consistency 用例失败。 ## [1.13.0] - 2026-08-23 ### Added - **Evidence Runtime**:outcome report 支持 repository/commit/diff/test command/result/artifacts/user confirmation;episode 持久化 evidence package,并返回 `verified|partial|unverified` 结论。新增 `outcome backfill` 用 JSON/JSONL 证据批量关闭 pending episodes。 - **Governance Plane**:新增 ADR / Invariant / APIContract / Test 图节点、版本化 upsert、supersession、review queue 和 requirement traceability;artifact 支持三方合并、冲突队列、HMAC 签名验证、AES-256-GCM 加密、保留策略与 quarantine 传播。 - **Tamper-evident audit**:evidence 与 MCP HTTP 治理事件使用 sequence + prevHash + SHA-256 hash chain,可离线验证篡改。 - **Secure MCP HTTP**:Streamable HTTP 支持 bearer token、HS256/RS256 JWT、issuer/audience/scope 校验、tenant allowlist、per-tenant session key 和审计响应头。 - **Release gates**:`graphflow governance release-gate` 强制 proven skill、context fidelity sample 和 pending episode ratio;npm publish workflow 已接入该门禁。 - **Portable profiles & proof plane**:`governance profiles` 导出 Cursor/Claude/Codex/DSH 配置;`benchmarks/run-proof-plane.ts` 支持多仓库 fidelity/token 评测。 - **Host adapter registry**:新增 DSH/Cursor/Claude 能力模型,作为 installer 后续拆分的稳定接口。 ### Changed - 统一 canonical embedding model 为 `Xenova/bge-base-zh-v1.5`,消除 graphPolicy 默认值与 transformers loader 的模型 split-brain。 - Graph node 类型扩展 ADR / Invariant / APIContract / Test;edge 扩展 `supersedes` / `governed_by` 并纳入 compression weights。 ### Tests - 新增 P0-P2 governance foundation suite,覆盖 evidence verification、knowledge supersession、artifact merge/signing/retention、encrypted snapshot 与 JWT claims。全量回归随发布流水线执行。 ## [1.12.2] - 2026-08-22 ### Fixed - **Windows release gate**:MCP structured-result 测试显式使用 file graph backend,避免 SQLite 连接仍在打开时清理临时目录导致 `EBUSY`。这是 v1.12.1 Windows validate 失败的直接根因;Linux/macOS 本地矩阵未暴露该平台锁差异。 ## [1.12.1] - 2026-08-22 ### Added - **MCP Streamable HTTP transport**:新增 stateless JSON 与 stateful SSE 双模式;支持 MCP initialize、draft `server/discover`、ping、tools、resources 和 structured tool results。启动方式:`graphflow mcp serve --http` 或 `graphflow-mcp --http` - **HTTP 生命周期与安全默认**:显式 DELETE 关闭 stateful session;默认仅绑定 loopback,Host 校验防止 rebinding,浏览器 Origin 默认拒绝并可用 allowlist 显式放行 - **端到端 transport 矩阵**:SDK Client 分别验证 HTTP JSON 与 stateful SSE;raw 请求验证 discovery、未知路径、非法 Origin、DELETE 后 stale session 和非 loopback 保护 ### Changed - `@modelcontextprotocol/sdk` 固定到 1.30 runtime 面;stdio legacy handshake 继续兼容 ### Tests - 新增 `tests/mcp-streamable-http.test.ts`;全量回归 141 文件 / 956 用例通过,扩展 bundled runtime 冒烟 7/7 通过 ## [1.12.0] - 2026-08-22 ### Added - **dsh 知识节点面板静态化(R4 落地)**:新增预构建 CJS factory bundle `dsh/client.js`(`window.__ModuleLoader__.load({id:"@roarpeng/graphflow/dsh",factory})`,named 导出 apply+inject;注册 `conversation.session.header.utilities` 开关与 `shell.overlay` 面板两个 slot,PANEL_CSS 闭包内注入防重),随 bundle 层开机自动加载——**不再需要按会话手动激活动态插件**。数据通道走 Connection 通用 RPC:glue 注册 `/gf`(`ctx.connection.rpc.handle(…,{authority:"trusted-host"})`,自带 browser-trust fence),handler 返回 RpcResult 信封 `{ok,value:{workbench,dialogues}}`;浏览器端 `connection.rpc.call("/gf","nodes",{workspaceRoot})` 取数。package.json 叠加声明 `dsh.client{platform:"web"}` + `exports["./client"]`/`exports["./dsh/package.json"]`(后者让现有 glue 行原样成为 client 扫描条目,实测 Node 解析通过) - **Context Fidelity 指标流(R1)**:新增 `graphflow-out/context-fidelity.json`、anchor recall@k、missing anchors 和基于归一化 LCS 的 body coverage;`FlywheelReport.fidelity` 增加 sample / recall / coverage 聚合。token savings 与信息保真度从此是两条可审计指标 - **SKILL.md 双向互操作(R2)**:新增 `skill markdown export|import`;导出只带 portable 元数据与 playbook,不带走 GraphFlow 本地信任决策;导入一律保守标记 `import/correctable`,不继承 proven 或 canary 证据 - **Engineering KG 抽取落地(R3)**:新增确定性中英文 Concept/Requirement 抽取器;CLI `knowledge extract [--all|--session] [--dry-run]` 与 MCP `graphflow_index({knowledgeExtract:true})` 可把对话结论写入图谱并保留 dialogue-turn `derived_from` 审计链 - **MCP structured results + stateless discovery**:全部工具结果继续保留 `content[0].text` 兼容层,同时返回 `structuredContent`;tool schema 声明 JSON Schema 2020-12;SDK 升级到 1.30,stdio 兼容握手之外支持 `server/discover` - **O(1) 技能读路径 + 自适应遗忘**:`readSkillState` / `loadCompositeSkill` 优先 `getNodesByIds`;skill decay 改为陈旧度 × 失败压力 × 成功保持 × proven 保护的确定性曲线,只软衰减,不删除经验 - **学习飞轮真实证据链(R0)**:`proven` 准入从"原子出现次数 `uses>=2`"改为"成功 episode 绑定计数 `successCount>=阈值`"(默认 2,`GRAPHFLOW_SKILL_PROVEN_MIN_SUCCESS` 可覆盖;按 episodeId 去重,旧数据经 `linkedSuccess+provenance.episodeId` 自动迁移,已 proven 节点不降级);删除 `FALLBACK_GOLDEN_TOKENS` 硬编码闭集,golden 词集动态生成(检索 golden 数据集 `expectAny` + 运行时 pass episode/symbol 证据叠加 `registerGoldenEvidenceTokens`);golden-overlap/符号检查降为辅助条件,不再一票否决真实成功记录 - **dsh 对话 A 面真实回填**:修复 glue 监听器读错会话事件信封字段(assistant 消息在 `event.data.message`,旧代码读 `event.message` 恒为空)这一"回复永远待回复"的根因;重写为 `turn/end` 提交模型(`assistant/message` 按 step 只喂"本 turn 最后文本"缓冲;`turn/end` 按 (session, turn) 去重提交;interrupted/aborted 不填);回填管线 = 进程内 runtime(`captureAssistantReply`;命中 workbench topic 时追加 dialogue turn 填充,保证 A 面必闭)→ CLI 兜底(`context preview --reply` + `dialogue record --reply` 双幂等 tip 填);latest-wins 每 session 串行队列 + no-pending-turn 有界重试;`GRAPHFLOW_CAPTURE_REPLY=0` 一票关闭 - **对话节点噪声过滤扩展**:`SYSTEM_MESSAGE_SOURCE_KINDS` 黑名单新增 `subagent-settled`/`subagent-report`(子代理完成/汇报通知此前被记成用户提问的直接根因)及 `agent-instructions`/`session-reference`/`goal`/`skill-catalog`;`user` kind 白名单放行真人输入,未知来源维持 role 回退保守兜底 - **file 图存储进程内缓存(R1)**:`graphify-file-client` 按绝对路径缓存解析 store 与懒构建倒排索引(`queryByKeyword` 不再每次重建索引),mtime+size 校验失效、写路径 write-through(拷贝构建 + `readSnapshot` 浅拷贝防污染)、跨实例共享;导出测试钩子 ### Fixed - **MCP unsafe-cwd 下工具级 rootDir 被吞(工具全灭)**:`resolveConfig()` 内部无条件先执行 `bindRuntimeWorkspaceRoot`(只认配置文件 `workspaceRoot`),MCP 服务端 cwd=家目录时在调用方 rootDir 应用前就抛 `Refusing to index unsafe workspace root`——而服务端启动日志承诺 "Pass rootDir on tools"。现在 `resolveConfig(configPath, { rootDir })` 把 rootDir 传入内部绑定(优先级 rootDir > projectWorkspaceRoot > cwd 发现不变,unsafe 安全检查不放宽);`src/surfaces/cli/runtime/{graph,dialogue,routing}.ts` 全部持有 rootDir 的调用点已接线;`resolveRuntimeWorkspaceRoot` 支持注入 `fromDir`(测试免 `process.chdir`) ### Tests - `tests/resolve-config-rootdir.test.ts`(新增 6 用例):unsafe cwd + rootDir 不抛错且绑定生效;不传 rootDir 保持抛错;显式 configPath 分支;`fromDir` 注入向上发现 - `tests/dsh-plugin-glue.test.ts`:reply 断言重写到 turn/end 提交模型(信封形状、按 turn 去重重放无副作用、aborted/interrupted 跳过、CLI 兜底双 spawn 参数与 cwd) - `tests/graphify-file-client-cache.test.ts`(新增 9 用例)+ `auto-transport` / `auto-transport-fallback`(+5):缓存命中/外部变更失效/仅 mtime 失效/写透三方一致/交错读写、sqlite 不可用与初始化失败静默回退 - `tests/m-learning-success-evidence.test.ts`(新增 9 用例);更新 5 个编码旧 `uses>=2→proven` 规则的测试 - 全量回归:140 文件 / 953 用例全绿;`tsc --noEmit` 零错误 - v1.12 新增回归:context fidelity、SKILL.md round-trip、Engineering KG extraction、structuredContent/stateless discovery、O(1) skill read、adaptive decay ## [1.9.16] - 2026-08-21 ### Added - **dsh 对话自动闭环**:`dsh/plugin.mjs` 监听 `session/event` 的 `assistant/message`,自动把每轮回复填入 `dialogue-turn` 节点(`dialogue record --reply`),与 `agent/inbox/inserted` 提问记录配对;提问/回复均按 dsh 会话 id 隔离(`--session`),同工作区多会话不串 - **对话节点提炼**:新增 `src/learning/turn-distillation.ts`(离线启发式)——`deriveTurnTitle` 剥离问候/祈使前缀取首子句(30 字符),`deriveTurnSummary` 结论标记句优先/末段落回退(200 字符);`DialogueTurnRecord` 增加可选 `title/summary`,记录/回填时自动生成 - **CLI `graphflow dialogue distill [--all] [--session]`**:批量回填遗留轮次的 title/summary(幂等);`dialogue list` 输出 title/summary - **对话记录噪声治理**:`isUserOriginatedMessage` 按 `message.source.kind` 过滤 harness 系统注入(job 完成/子代理/Cordis 通知不再入图),未知来源回退 role 判断 - **web 知识节点栏源码种子**:`web/plugin.mjs`(Host+Client 双半部参考实现)+ `web/README.md`;`docs/dsh-install-guide.md` 新 harness 安装启用指南 - **ROADMAP 进化方向**:R0-R4 深度调研版(真实证据链 / 性能收敛 / MCP 2.0 与 SKILL.md 对齐 / 概念层落地 / 工程治理) ### Fixed - **CLI `dialogue record --reply` 解析 bug**:reply-only 填充此前被参数解析短路——`--reply` 的值被裸参数拼接当成 query,导致填充变成新建垃圾轮次;新增 `resolveDialogueRecordInput`(reply-only 优先、flag 值不泄漏进 query、兼容 `--flag=value`)+ 4 个回归用例 - **doctor 指令状态检查竞态**:`getAgentInstructionStatus` 的 `existsSync`+`readFileSync` 非原子,并行场景(测试/安装并发)下 ENOENT 会抛异常;读失败改为视为未安装 ### Tests - `tests/dsh-plugin-glue.test.ts`:回复补全(spawn 参数/三态跳过/session/event 接线去重)+ 消息来源过滤(plugin/tool/model 不入图) - `tests/turn-distillation.test.ts`(新增 14 用例):标题/摘要单元 + `dialogue distill` 端到端幂等 - `tests/dialogue-thread.test.ts`:`resolveDialogueRecordInput` 4 用例 ## [1.9.15] - 2026-08-20 ### Added - **Experience v2**:噪声技能按名字清理(含 legacy `kind: evolution` / `readme+update` 融合);held-out golden overlap 准入;ACE 式 playbook 增量计数;成功 DAG 蒸馏为 workflow skill;`forgetEpisode` 按 `provenance.episodeId` 软隐藏派生技能;L3 钉住 goal/alignment/deviation - **DeepSeek Harness glue 收口**:MCP 行 `cwd: !!js process.cwd()`;bundle ESM `@roarpeng/graphflow/dsh`(`dsh/plugin.mjs` 打进 npm `files` + `exports`);`dsh plugin add` 时 `ctx.skills.register`;`graphflow install` / `doctor` / `uninstall` 检测 home overlay、glue 行、`$DSH_HOME/skills/graphflow/SKILL.md` - File expand 返回全文(上限 20 万字符);`FlywheelReport.fidelity` 拆开 packaging ROI 与 `pendingRatio` ### Changed - SessionEnd / dsh `agent/disposed` **不默认把 pending episode 标成成功**。Claude Code 空 `$2`、dsh 未设 `GRAPHFLOW_HOOK_SUCCESS` 时保持 pending;显式 `true`/`false` 才调用 `graphflow outcome report` - Token savings 不再冒充信息保真度(`explainSavings()` / `kind: tokens-not-fidelity`) ### Docs - README 诚实矩阵:dsh 上 MCP 10 工具 + skill + 会话结束捕获可用;VS Code/Cursor UI 与 Claude Code Session* 文件 hooks 不移植 - [docs/context-contract.md](docs/context-contract.md) 写明 preview 是指针,精确编辑要 expand File ### Tests - `tests/dsh-plugin-glue.test.ts`:glue 不监听 `session/flush`;无 `GRAPHFLOW_HOOK_SUCCESS` 不默认 pass - `tests/m-skill-admission.test.ts` / `m-playbook-delta.test.ts` / `m-workflow-skill.test.ts` / `m-skill-revoke.test.ts` / `m-context-fidelity.test.ts` / `m-l3-constraint-pin.test.ts` ## [1.9.14] - 2026-08-15 ### Added - **工作台脉络**:`graphflow_plan` 按计划 DAG 播种功能主题容器(`workbench.topics`),画布单位是功能而不是一轮一节点;偏离主线时 Fork 孤立旁支;点击 `topicId` 注入 Goal + 祖先标题 + 该节点原文 - 按需唤醒大纲(默认收起):CLI `graphflow workbench tree`、VS Code 活动栏 **GraphFlow: Workbench Tree** / Chat `/tree`、MCP `graphflow_diagnose.graph.workbenchOutline`(不新增第 11 个工具) - `graphflow_context` 支持 `topicId` / `assistantReply`(可省略 query)两拍入图:提问记 Q,答完回填原文 A;标题只用于显示,不写入下一轮必读上下文 - 无计划时仍将对话记为 `dialogue-turn`;有工作台则写入当前主题容器 - **DeepSeek Harness (`dsh`) plugin**:`@roarpeng/graphflow` 声明 `dsh.bundle` + 根目录 `cordis.patch.yml`,可通过 `dsh plugin --profile add @roarpeng/graphflow` 装入 profile;MCP 经 in-box `@deepseek-ai/dsh-mcp-client` 暴露为 `mcp__graphflow__graphflow_*` - 中文 README([README.zh.md](README.zh.md))与 `plugin.json` / Skill 写明 dsh 用法与 10 项能力 - `graphflow install` 在检测到 `$DSH_HOME` / `~/.dsh` 时写入 home 级 `cordis.patch.yml` overlay,并把 Skill 装到 `~/.dsh/skills/graphflow/SKILL.md` - `graphflow uninstall` / `doctor` 同步清理与自检该 overlay ### Tests - `tests/workbench-topic.test.ts`:主线 DAG 拓扑序、旁支嵌套、原文注入不含 Summary - `tests/dialogue-thread.test.ts`:对话入图与 pending 回填 - `tests/m15-vscode-panel-observability.test.ts`:快照「工作台脉络」默认收起 + 在此继续 - `tests/m16-agent-integrations.test.ts`:MCP `topicId` / `workbench.outline` 描述 ## [1.9.13] - 2026-08-13 ### Changed - **GraphFlow: Settings 收成一页**:文档解析(Markdown / Office·PDF)、anydoc 安装状态、语义召回、MCP、模型、建图与功能入口都在同一面板配置;不再依赖 VS Code Settings 里的 `graphflow.downloadAnydoc` 作为主入口 - Settings 去掉「本版亮点」长文,保留状态条 + 芯片入口(图谱 / 上下文 / 技能 / 规划 / 运行) ### Tests - `tests/m53-include-extensions.test.ts`:Markdown / Office 索引开关 - `tests/m10-cli-runtime.test.ts`:settings 持久化 document flags + embeddingProvider - `tests/m15-vscode-panel-observability.test.ts`:Settings 新布局断言 ## [1.9.12] - 2026-08-12 ### Added - **Episode ↔ Engineering KG on outcome path**: `graphflow_report_outcome` / CLI `outcome report` accept optional `requirementIds` / `conceptIds` / `codeHints` and write episode → `derived_from` → eng nodes via `linkEpisodeToEngineeringNodes` - **Document-semantic insight ↔ episode provenance**: when `episodeId` is passed with a document-semantic submit, the same eng links are written for experience↔eng consistency - **ATP minimal producer atp-ir/1.2**: optional `memory-recall` / `memory-backfill` markers (host-managed); fixture + README updated; still runnable without GraphFlow MCP - **P0 skill consolidate apply**:`graphflow skill consolidate` 默认 dry-run;`--apply` / `--execute` 安全调用 `applySkillConsolidation`(未知 id skip) - **代码域检索评测公开数据集**:`benchmarks/datasets/retrieval-golden-v1.json`(+ `.jsonl`),含 schema / license / domainCounts / Hit@5·MRR·NDCG 映射说明;`npm run dataset:retrieval` 从 `benchmarks/retrieval-golden-data.ts` 再生,避免漂移 - **Agent Plugins 1.0** packaging at repo root: `plugin.json`, `mcp.json` (`type: stdio`), and canonical `skills/graphflow/SKILL.md` - README section for local plugin install (`~/.cursor/plugins/local`) and Team Marketplace / Git discovery - `npm run sync:surfaces` keeps `src/surfaces/trae-skill/graphflow/SKILL.md` aligned with the Agent Plugins skill source - Conformance test `tests/agent-plugins-1.0.test.ts` - **P1 Context Engineering contract**: [docs/context-contract.md](docs/context-contract.md) — budget fields, L0–L3 anchors/refill, positioning vs platform indexing / RL; links MCP `graphflow_context` and Agent Plugins - **P1 Experience memory guide**: [docs/experience-memory.md](docs/experience-memory.md) — Storage → Reflection → Experience; artifact / memory-pack / skill-sync; Agent Plugin vs `install` matrix - **Experience memory pack**: `exportExperienceMemoryPack` + CLI `graphflow artifact export-memory` → `graphflow-out/memory-pack/{README,skills,episodes}.md` - README: Agent Plugins as **primary** install; `graphflow install` as Rules / multi-agent fallback; links to the two new docs - **install/doctor 接入 Claude Code 飞轮 hooks**:`graphflow install` 在检测到 Claude Code home 时自动调用 `installClaudeCodeHooks`(SessionStart / SessionEnd / Stop);`doctor --json` 新增 `hooks` 类别自检;InstallReport 增加 `claudeCodeHooks`;`GRAPHFLOW_CLAUDE_HOME` 便于测试覆盖 ### Fixed - **扩展升级后 MCP launcher 路径失效**:`repairStaleGraphFlowMcpLaunchers` 在扩展激活时扫描用户级与工作区 MCP 配置;若 `graphflow` 仍指向已删除的旧版 `mcp-launcher.cjs/.cmd`(如 `roarpeng.graphflow-1.9.6`),自动改写为当前扩展启动器。修复 Cursor Agents 依赖项目级 `.cursor/mcp.json` 而 IDE 仍可用的不一致。 ### Changed - ATP/IR spec status line marks **`atp-ir/1.2` Stable**; §5 / §8 document optional Engineering KG link fields on `report_outcome` - ROADMAP P2 rows (ATP producer + Engineering KG episode chain; ATP/IR v1.2 protocol) → ✅ - **P0 Experience 飞轮可观测**:`getFlywheelReport` / `skill report` / `route diagnose` / `graphflow_diagnose` 的 `experience` 增加 dry-run `consolidation` 动作计数(UPDATE/DELETE/ADD)与建议 hint;ROADMAP P0 ✅ - Skill resolution (`resolveSkillSourcePath` / MCP `graphflow_skill_guide`) prefers `skills/graphflow` before legacy `trae-skill` paths - `package.json` `files` publishes `plugin.json`, `mcp.json`, and `skills/` - ROADMAP (2026-08-12): Experience-layer P0–P2 ✅ (skill consolidate --apply; retrieval golden dataset; ATP/IR v1.2 + episode↔eng KG) - **`graphflow uninstall`** now removes **MCP + Skills + Rules + hooks** (user + workspace MCP). After removing an Agent Plugin in Cursor, run `uninstall` so leftover `~/.cursor/skills/graphflow` cannot keep steering the agent. ### Tests - `tests/m-install-hooks-wiring.test.ts`:hooks status + install/doctor 接线 - `tests/m-stale-mcp-launcher-repair.test.ts`:失效 mcp-launcher 路径检测与改写 - `tests/atp-ir-v1.2-conformance.test.ts`:ATP/IR v1.2 memory markers + producer protocol - `tests/report-outcome-engineering-links.test.ts`:outcome / insight eng-link wiring - `tests/retrieval-dataset.test.ts`:公开检索数据集与 TS 真源条目数/内容一致 ## [1.9.11] - 2026-08-08 ### Added - **VSIX 激活时按需下载 anydoc**:设置 `graphflow.downloadAnydoc`(默认 true)→ `npm install @firecrawl/anydoc` 到 `~/.graphflow/optional-deps`;MCP launcher / `document-convert` 经 `GRAPHFLOW_ANYDOC_NODE_MODULES` 加载。失败则跳过 Office/PDF,源码索引照常 - README / 扩展 README 说明 VSIX 不内置、可自动下载、可关闭 - **emilkowalski/skills**:项目安装 design-eng 等 skill;扩展 webview 面板统一 soft elevation、`:active` scale(0.97)、`--ease-out`、reduced-motion ## [1.9.10] - 2026-08-08 ### Added - **Engineering KG 跨层边**:`documents`(文档 File→Concept/Requirement)、`implements`(代码→Requirement)、`derived_from`(语义节点→来源 File/insight) - **文档域一等节点**:`Concept` / `Requirement`;`document-semantic` insight submit 自动写入并尝试用 `relatedCodeHints` 链接已有 File/Symbol - **说明**:VS Code/Cursor **VSIX 不打包** `@firecrawl/anydoc`;自 v1.9.11 起扩展激活时可自动下载到 `~/.graphflow/optional-deps`(`graphflow.downloadAnydoc`)。CLI/`npm i` 仍可通过 optionalDependency 安装。无 anydoc 时跳过 Office/PDF,源码索引不受影响 ### Changed - 逻辑三分(code / doc / experience)落在**单图 + type/domain + 跨层边**,不拆物理三库 ## [1.9.9] - 2026-08-08 ### Fixed - **CI macOS ENAMETOOLONG**:`walkFiles` 深度目录测试从 400 段降至 80 段,保留迭代遍历断言,避免 APFS 路径过长导致 Action 失败 ### Added - **Office/PDF 文档建图**:可选依赖 `@firecrawl/anydoc`,将 PDF/DOCX/PPTX/XLSX 等转为 Markdown 后走既有 markdown 章节/链接图谱;缺省扩展名已包含办公文档;单文件上限约 5MB - **Document semantic bridge**:索引成功后返回 optional `document-semantic-*` `agentWorkItems`,由宿主 Agent 抽取关键实体/主张并经 `graphflow_insight(mode=submit)` 回写 ### Research note 文档→MD 选型:优先 Firecrawl **anydoc**(Node、多格式、本地);备选 Microsoft MarkItDown(Python)、Pandoc(系统依赖)。npm 上无关的旧包 `anydoc` 勿用。 ## [1.9.8] - 2026-08-08 ### Added - **P0 飞轮可观测性**:`getFlywheelReport` / `skill report` / `graphflow_diagnose` / `route diagnose` 暴露 `autoCaptureEnabled`、`sessionJournal`、`skills.byOutcomeKind`;`npm run backfill:episodes` 包装历史回填脚本 - **Skill-conditioned DAG**:plan 节点可选 `skillRefs` / `avoidPatterns`;bridge 指令要求执行前审阅 skills / 避开 anti-patterns - **SkillOpt-lite**:无 LLM 的有界 skill guidance 编辑(最多 3 次,严格提升才接受);接入 `applySkillLearning` lessons 路径 - **团队记忆 canary 门控**:`canary-gate.ts`——sync/import 技能须本地成功 N 次(或显式 validate)才可晋升 `proven`;anti-pattern 仅隔离 - **Codex Windows MCP**:安装写入 `NODE` / `NPX_CLI` 8.3 短路径,修复 Codex 注册失败 ### Changed - **图噪声**:引用边前缀 Trie 预过滤;子图 PageRank LRU 缓存键按节点集排序哈希 - **planAndBrainstorm** 异步化以在 flywheel 开启时注入 skill 条件 ### Tests - 新增 `tests/m81-skill-conditioned-dag.test.ts`、`tests/canary-gate.test.ts`;扩展 flywheel-report / graph-noise / mcp-resources / Codex MCP install ## [1.9.7] - 2026-08-03 ### Added - **综合能力 Benchmark(P1-P6 六维度)**:`benchmarks/run-comprehensive-bench.ts`,覆盖图谱索引、上下文压缩、规划与分诊、学习飞轮、Bridge 模式、端到端性能,总体得分 **92.9%** - **CodeGraph 风格独立 Benchmark**:`benchmarks/run-independent-bench.ts`,5 域(core/graph/learning/config/integrations)评测,Hit@5 96%、Token 节省 96.6%、总体 **96.2%** - **SWE-bench 风格上下文就绪评测**:`benchmarks/run-swe-bench-eval.ts`,12 实例(easy/medium/hard × bug-fix/feature/refactor/test),多查询策略下上下文就绪率 100%(非真实 SWE-bench,仅测量压缩上下文是否包含任务所需文件/符号) - **检索质量 IR 指标评测**:`benchmarks/run-retrieval-eval.ts`,132 条 golden 查询,Hit@5=100%、MRR=0.836、NDCG@5=0.601 - **符号提取模块**:`src/graph/symbol-extract.ts`,从任务描述提取 camelCase/PascalCase 符号名,补充图查询提升召回 - **同文件符号提升 + 导入图扩展**:`buildEnhancedContextPackage` 新增 Step 5,自动从已锚定文件提取同文件 Symbol 节点,并通过 import 关系扩展跨文件召回 - **Bridge+DAG 混合执行模式**:`enableBridgeDagExecution` 选项,bridge 模式下可选择同时本地执行 DAG(`tests/m81-bridge-dag-execution.test.ts`,5 个用例) ### Changed - **上下文压缩优化**:anchor 上限 15(`maxAnchors`)、L2 module 注入、L3 always-on 层;压缩得分 38.4% → 64.9% - **DAG 并行度提升**:单 clause 任务拆分 4 节点(实现∥测试设计),并行度 1.2x → 1.40x - **Skill hints 修复**:传入 evidence 通过 P0-2 质量门控,skill hints 从 0 恢复到正常生成 ### Tests - 99 测试文件 / 692 tests(+1 m81 bridge+DAG、m79 plan clause split 更新) ## [1.9.6] - 2026-08-03 ### Fixed - **Cursor/VS Code MCP 启动失败**:扩展 vendor 打包漏掉 `@modelcontextprotocol/sdk`,MCP launcher 加载 `vendor/graphflow/dist/surfaces/mcp/server.js` 时抛出 `Cannot find module '@modelcontextprotocol/sdk/server/index.js'`(Connection closed / -32000)。`sync-runtime.mjs` 已将 MCP SDK 纳入 `runtimeRoots`,并在同步后校验必选包存在;新增 `test:mcp` 烟雾测试防止回归 ## [1.9.5] - 2026-08-01 ### Fixed - **图谱索引排除 Agent 工具目录(P1)**:`IGNORED_DIRS` 新增 `.agent` / `.claude` / `.cursor` / `.gemini` / `.joycode` / `.trae` / `Cursor`——`.claude/worktrees` 为每个 worktree 保存完整仓库副本,此前被当作源码索引进图(本地实测 1421 个 File 节点中 1076 个来自 worktrees,占 76%),污染检索锚点、PageRank 与存储;修复后 `graph rebuild` 扫描文件数从 ~1500+ 降至 326,旧图可在下次增量/全量索引时自动清理 - **增量索引剪枝批量删除(P1,读写放大修复的伴生问题)**:排除目录后首次增量索引需从缓存差集剪除大量过期节点,而 `pruneFileFromGraph` 逐节点 `deleteNode`(file 后端每次全量读写 JSON,实测 62MB 图 × 1000+ 节点 → 305s 挂起);新增可选能力 `GraphClient.deleteNodes(ids)`(file 单次读+写、sqlite 单事务分块 IN、memory 批处理,均级联清理悬空边),剪枝改为单次快照读取 + 单次批量删除,mcp-http 试点保留逐节点回退路径 - **测试 95 文件 / 656**(+2 walker 排除、+1 剪枝批量删除、+1 file 批量删除用例) ## [1.9.4] - 2026-08-01 ### Changed - **扩展市场说明更新**:vscode-extension/README.md 重写为 v1.9.x 最新使用说明(记忆审计 CLI、飞轮归因面板、语义 embedding 配置、技能分类、skill sync、改名后市场身份 `roarpeng.graphflow` / `GraphFlow Context & Memory`);扩展 description 改为版本无关描述(消除版本钉死导致的文档腐化) ## [1.9.3] - 2026-08-01 ### Fixed - **Marketplace 发布(二次)**:`GraphFlow` 显示名亦被第三方占用(不出现在公开搜索,疑似下架/保留名),改为 `GraphFlow Context & Memory` ## [1.9.2] - 2026-08-01 ### Fixed - **Marketplace 发布**:新身份 `roarpeng.graphflow` 的 displayName 改为 **`GraphFlow`**(`GraphFlow Tool` 被旧列表 `roarpeng.graphflow-tool` 持有,VS Marketplace 拒绝重复 displayName;经 Marketplace 搜索 API 验证 `GraphFlow` 未被占用) ## [1.9.1] - 2026-08-01 记忆透明化版本:让「跨会话记忆」可度量、可审计、可归因。 ### Added - **记忆 ROI 基准(正式化)**:`npm run benchmark:memory`(`benchmarks/run-memory-ab.ts`)——62 任务(26 golden + 36 hard:跨模块影响面/消歧/间接形态),记忆开 vs 关双臂,实测 **ON 100.0% vs OFF 56.5%**(救回 27 任务、0 受损,其中 hard 域 17 个);**归因链**逐任务记录「哪条记忆救了哪个任务」(top episode + 相似度 + 注入文本),JSON 落 `benchmarks/.cache/memory-ab-results.json` - **记忆审计 CLI**:`graphflow memory list [--outcome pass|fail|pending]`(证据记录:id/任务/结局/lessons/staleGoal)、`memory search ""`(相似度排序命中)、`memory forget `(物理删除,未知 id 干净 no-op);runtime facade 暴露 `listEpisodes/searchEpisodes/forgetEpisode` - **飞轮报告归因区块**:`getFlywheelReport` 新增 `memoryAttribution`(memoryHits / staleEpisodes / confidence 分布 / topContributingMemories 证据链 / deviationBreakdown),全字段增量兼容 ### Changed - **VS Code 扩展改名**:`graphflow-tool` → **`graphflow`**(Open VSX 名称可用已验证;新身份 `roarpeng.graphflow`,VSIX 产物 `graphflow-.vsix`);扩展包名、agent 标识、CI 工件、文档同步 - **测试 94 文件/646 → 95 文件/652**,全量通过 ## [1.9.0] - 2026-08-01 技能质量与团队化版本:飞轮从「机制完整、效果未知」走向「A/B 实证 + 质量门禁 + 团队共享」。 ### Added - **语义 embedding 可选后端(P0)**:`graphPolicy.embeddingProvider: "fnv" | "transformers"`(默认 `fnv` 离线安全);`transformers` 时经 `@huggingface/transformers` 懒加载 all-MiniLM-L6-v2,任何失败(缓存缺失/超时/加载错误)永久降级 FNV-1a 并告警;`graphflow_diagnose` 新增 `embeddingBackend: semantic | off` 上报活动后端 - **技能结果分类(P0)**:单一分数升级为 `proven / correctable / anti-pattern / noise` 四类——noise 提取即拒、装载时清理(`cleanupNoiseSkills`);仅 anti-pattern 记负分(消灭「首次失败即 -20 下沉」);proven 需 ≥2 次使用或链接成功结局 - **检索 golden set 26 → 132(P1)**:10 域覆盖(含 PLC),12 负样本断言 + 132 Top-K 位置断言(rank 稳定性门),每域 ≥8 查询护栏 - **技能飞轮端到端 A/B 基准(P1)**:`npm run benchmark:ab` 以 golden 查询为任务集、真实学习路径跑双臂——实测飞轮开 **100.0% vs 关 61.5%**(救回 10 任务、0 受损),开销 33 tok/任务 - **CI 版本一致性门禁(P1)**:`scripts/ci-version-check.cjs` 断言 package.json / CHANGELOG 最新条目 / README 徽章三源一致;CI 新增 skill A/B 基准 job(文件存在性守卫) - **skill sync 双向 merge(P2)**:导入改为按技能 ID 合并——同 ID 取较新 `updatedAt`、平手保本地、本地独有保留;`--force` 恢复覆盖;包 schema 1.1 新增 `goldenQueries`,团队 golden 集随包同步(合并去重写 `.graphflow/team-golden.json`) - **VS Code 飞轮贡献面板(P2)**:新增「Flywheel · 学习飞轮贡献」区块——技能正/中/负分布、topUsed、episodes pass/fail/pending 结果条;`runtime.getFlywheelReport()` 暴露数据 - **Graphify mcp-http 团队后端试点(P2)**:`GraphifyMcpClient` 补齐完整 `GraphClient` 接口,所有操作 `withFallback` 失败降级本地 file 存储;端点校验 + 15s 超时 + `readSnapshot`/`ping`/`isDegraded`;README 试点说明 - **PLC 索引器加固(P0)**:PLCopen XML POU `returnType`(嵌套/inline 双形态)提取为 `POU.return` 符号;ST 分析器 CASE 数值分支(`1:` / `1..10:`)不再被误判为跳转标签;45 测试 + 双 fixture ### Changed - **测试 92 文件/489 用例 → 94 文件/646 用例**,全量 14.7s 通过 - `vitest.config.ts` 排除 `.claude/worktrees/**`,根治多 worktree 并行时测试互扫污染(m50 假失败) ### Fixed - skill 节点全负分(-2/fail)根因:浅层 n-gram 技能(update/readme)被提取——现按符号证据门禁拒绝 ## [1.8.0] - 2026-07-28 目标对齐(Goal Alignment)版本:让 Agent 在长时间、多步骤任务中始终记得为什么出发——治「需求理解不透」与「干着干着偏离」两大痛点。 ### Added - **Goal 锚点节点化(P0)**:`intent-analysis` / `simple-plan-intent` / `clarification` 提交自动把意图五元组(coreProblem / successDefinition / nonGoals…)固化为图一等公民节点(`goal:`,metadata `kind:"goal"`);`PromptContext.goalAnchors` 在每次打包时以最高优先级位置注入原始需求,orchestrate 各角色 prompt 全程可见 - **低置信度澄清门(P3)**:intent 载荷新增 `confidence`;有效置信度 < 0.6 时 merge 拒绝定稿(`complete=false` + `needsClarification=true` + `intentConfidence`),须先提交 `clarification` work item 澄清至 ≥ 0.6;无 confidence 字段的旧载荷按 1.0 处理(向后兼容) - **alignment-check 执行期回检(P2)**:新 work item(`kind:"alignment"`,optional)——子任务/计划完成后回检「产出是否服务 successDefinition、是否触碰 nonGoals」,附 drift 分类;simple bridge 与 full ATP 的 agentInstructions 均加入执行期协议说明;永不阻塞 merge - **deviation 偏离分类(P1)**:`report_outcome` / `outcome report --deviation` 接受 `none | misread-requirement | scope-creep | tech-drift`,持久化到 episode record;飞轮报告新增 `episodes.deviations` 聚合与 `goals`(active/superseded)统计;MCP `graphflow_report_outcome` schema 同步 - **Goal 版本链 + 变更 diff(P4)**:需求实质变更时旧记录快照为 `goal::v`(status `superseded`),active 节点版本 +1 并带 `changedFields` diff;同任务 pending episodes 自动标记 `staleGoal`;相同再提交仅刷新时间戳 - **ATP/IR 规范 v1.1**:`docs/atp-ir-spec-v1.md` 升级——§4.3 协议级 work items、§5.1 goal anchor / clarification gate / alignment check / deviation / goal versioning(纯增量,v1.0 兼容) ### Changed - **测试**:新增 `tests/goal-anchor.test.ts`(12 用例覆盖 P0–P4);m80 simple bridge 断言更新为「required 2 项 + optional alignment-check」;flywheel report 测试覆盖 deviation 聚合与 goal 统计;全套 **92 文件 / 455 tests** 通过 ## [1.7.15] - 2026-07-28 ### Added - **检索 golden set 回归测试**:`tests/retrieval-golden.test.ts` 固定 26 条代表性查询(orchestrator / context / skill flywheel / planner 等),断言关键源文件召得回且命中率 ≥ 80%,检索质量从此有回归护栏 - **词干匹配**:`rankNodesForContextQuery` 对 ≥ 6 字符的查询 token 做前缀词干匹配(如 `routing` 命中 `route`),修复 "orchestrate task routing" 类查询召不回 orchestrator 的盲区 - **PageRank LRU 缓存**:`computePageRank` 以全图指纹(节点 + 边 + 参数)为键缓存结果(上限 8 条),重复上下文打包零重算;导出 `pageRankCacheStats` / `resetPageRankCache` - **HNSW 向量索引持久化**:`getSharedVectorIndex(nodes, persistPath?)` 进程内 memo + 磁盘恢复(Float32 base64,上限 20k 向量);`OrchestrateOptions.hnswIndexPath` / `embeddingPolicy.vectorStorePath` 派生 `.hnsw` 路径,跨进程复用向量召回索引 - **`transport: "auto"`**:图存储自动选择——sqlite 优先(FTS5 检索、避免大仓库全文件读写放大),better-sqlite3 不可用时透明降级 JSON 文件存储;`graphflow.config.example.json` 默认改为 auto - **Skill A/B 基准**:`benchmarks/run-skill-ab-benchmark.ts`(`npm run benchmark:skills`)离线确定性度量 skill 飞轮价值——hint 注入率、episode 召回率、Jaccard 相关性代理、token 开销(实测注入 100% / 召回 100% / 25.6 tok 每任务) - **技能包团队共享**:`graphflow skill sync export|import [--path]` 双向同步技能包到可进 git 的 JSON 文件(默认 `.graphflow/skills/team-skills.json`),幂等再导入 - **飞轮贡献报告**:`graphflow skill report` / `graphflow_diagnose` 新增 flywheel 字段——skills 正/中/负分分布、topUsed、episodes pass/fail/pending/withLessons、insight decisions 计数 - **ATP IR 公开规范**:`docs/atp-ir-spec-v1.md` 定义 `atp-ir/1.0`——角色、AgentWorkItem/TaskNode 载荷 schema、full ATP vs simple-plan bridge ID 注册表、submit/merge 契约、兼容性规则 - **测试基建**:`tests/helpers/no-llm-config.ts` 隔离配置工厂(providers 空 + budget/learning/embedding/graph policy 完整,防 `loadConfigSafe` 静默回退默认配置);`tests/helpers/setup.ts` 注册进 vitest setupFiles,测试默认 2s provider/embedding 超时 ### Changed - **README 重写**:新定位「编码 Agent 的上下文与记忆层」,修复旧版中文乱码(0x3F 损坏);30 秒上手、能力矩阵、10 MCP 工具表、CLI 速查、基准与 ATP 规范链接 - **Bridge 模式省一次 LLM 调用**:orchestrate 在 bridge(agent-delegated)模式下跳过 `plannerDraft` 的纯装饰性 LLM 调用(其结果仅用于 feedback 字符串,无下游引用) - **引用边构建优化**:`file-indexer-edges` 改用 `matchAll` 流式扫描避免大中间数组,symbolIndex 为空时早退 - **测试环境隔离**:m7/m9/m10/m14/m16/m44/m48/m-bridge-cli-loop 全部改用显式隔离 configPath,本机 ambient 配置(真实 API key)不再把单测变成 30–60s 网络调用 ### Fixed - **sqlite FTS camelCase 盲区**:FTS5 不拆 camelCase,而查询侧经 `tokenizeForIndex` 拆成子词,后缀子词永远匹配不上;schema 升级 v2(`searchtext` 列 = 原文 + 拆分子词,含 ALTER/backfill/重建 FTS/trigger 迁移) - **m16 环境敏感断言**:agent 集成测试改用 mkdtemp 临时 config,`agent-delegated` 断言在任意本机环境下确定性通过 - **m48 文档一致性**:README 版本徽章回归,与 package.json 单一事实源对齐 - **lint**:`client-factory` auto 降级分支未使用变量、golden set 测试冗余 eslint-disable ## [1.7.14] - 2026-07-28 ### Fixed - **CI / m16**:无 LLM 时 `graphflow_plan` 返回 `mode=agent-delegated`,更新集成测试断言(修复 v1.7.13 构建失败) ## [1.7.13] - 2026-07-28 ### Changed - **`graphflow_plan` 无 LLM 也 Bridge**:默认 simple 模式在未配置 GraphFlow LLM 时返回 `mode=agent-delegated`,下发 `simple-plan-intent` + `simple-plan-decomposition` work items,由连接的 coding agent 理解任务并拆 DAG;本地启发式结果以 `suggestedNodes`(`nodesStatus=suggested`)附带,不作终稿 - **merge 协议**:识别 simple-plan work item ID,两步 submit 后即可 merge 出最终 plan(不与 insight 全量帽子协议混淆) ## [1.7.12] - 2026-07-28 ### Fixed - **`graphflow_plan` 误拆分析维度**:冒号后的评价维度列表(如 assumptions、failure modes、validation gates)不再被 `,`/`、`/`,` 拆成独立并行任务节点;仅当各子句都像可执行任务时才弱分隔 - **brainstormer** 共用同一 `splitTaskClauses`,避免目标澄清变成名词碎片 ## [1.7.11] - 2026-07-27 ### Changed - **Settings 工具页**:同步展示 v1.7.11 本版亮点(MCP home-cwd 修复、install/doctor JSON 自检、Bridge 飞轮、无需 LLM 能力) - **扩展 README / marketplace description**:对齐最新版本与 FAQ ## [1.7.10] - 2026-07-27 ### Fixed - **MCP home-cwd discovery**:安装后 Cursor 常以 `cwd=/home/` 启动 MCP;discovery 不再通过 IDE hint 把 home 当作工作区(修复 `Refusing to use unsafe workspace root from discovery: /home/...`) - **读取 `WORKSPACE_FOLDER_PATHS`**:优先使用 Cursor 注入的工作区路径;忽略未展开的 `${workspaceFolder}` 占位符 - **npx MCP 安装**:写入 `GRAPHFLOW_WORKSPACE_ROOT=${workspaceFolder}`,由 Cursor/VS Code 插值到真实项目根 ## [1.7.9] - 2026-07-22 ### Added - **Open VSX 自动发布**:`Build` workflow 在 `package-windows` 成功后幂等推送到 Open VSX(密钥 `open_vsx_token`,namespace `roarpeng`,与扩展 publisher 一致) - **Opencode agent 支持**:自动检测 `~/.config/opencode/` 并安装 MCP(`mcp` 键/数组 `command`/`enabled`/`type: "local"` 格式)、Skill(`~/.config/opencode/skills/`)和 AGENTS.md 指令;workspace 级 MCP 注入支持 opencode 格式 - **embedding 超时**:`pipelines()` 模型下载 60s 超时(`GRAPHFLOW_EMBEDDING_TIMEOUT_MS`),超时自动降级 hash - **HF 镜像**:`HF_ENDPOINT` / `GRAPHFLOW_HF_ENDPOINT` 环境变量配置 HuggingFace 镜像(如 hf-mirror.com) - **fallback 标注**:`ResilientLocalEmbeddingProvider.getFallbackReason()`,diagnose 输出当前 backend 和降级原因 - **全面健康检查**:`graphflow_diagnose` 增加 workspaceRoot 解析、graphFreshness、modelCache、connectivitySummary - **技能衰减**:`maybeDecaySkills`(七天内无活动分数向 0 衰减 ±1)、`resetSkillScore`、`pruneLowSkills`;CLI `skill decay/reset/prune` - **Episode 隐私**:`forgetEpisodes()` + `learn forget`;artifact export 默认排除 episode(`--include-episodes` 可还原) - **CI 矩阵**:`validate.yml` Node 20/22 矩阵 + `validate-platforms` job(win/mac Node 22) - **Surface sync 脚本**:`scripts/sync-surfaces.cjs` + `--check` 模式 + `npm run sync:surfaces` - **WASM 版本标记**:`wasm/.grammar-version` 版本校验,升级时强制重建 ### Changed - **迁移到 `@huggingface/transformers` v3**:`loadTransformersModule` 优先使用已在 `dependencies` 中的 v3,`@xenova/transformers` 保留为 legacy fallback - **`pino-pretty` 移到 devDependencies**:减小生产安装体积 - **README 测试数**:59→72 文件、280+→357+ tests(脚本化生成,避免再次漂移) ### Fixed - **macOS CI**:`m49-workspace-root-isolation` 测试通过 `realpathSync` 解析 `/var` → `/private/var` 符号链接 - **package-lock.json 同步**:与 `package.json` 依赖版本对齐 - **CI tsc 构建**:`@huggingface/transformers` 直接可解析,无需额外安装 ## [1.7.8] - 2026-07-19 ### Added - **Dart / Flutter 索引器**:新增 `.dart` tree-sitter 索引器(class/mixin/extension/enum/typedef/function/import);忽略 `.dart_tool`;`tree-sitter-wasms` 升至 0.1.13,`web-tree-sitter` 升至 0.25.10(支持 Dart ABI 15) ## [1.7.7] - 2026-07-19 ### Added - **npm 幂等发布**:`scripts/publish-npm-idempotent.mjs`,已发布版本不再因 E403 失败 - **技能飞轮卫生**:全 stopword 短语过滤、`pruneFailedSkills` 软隐藏毒技能、`reportOutcome` lessons 质量门 - **架构检索加权**:架构/CJK 查询优先 orchestrator / MCP / README,压低 types/errors/panels - **安装指令块**:统一为 10 工具面 + `graphflow_context` + CallMcpTool 契约 ### Changed - CI / publish workflows 升级 Node **22** - Marketplace:无密钥时 dispatch 跳过警告;tag 推送无密钥则明确失败;日志使用 GraphFlow Tool / `graphflow-tool` ## [1.7.6] - 2026-07-19 ### Changed - **VS Code 扩展更名**:`graphflow-vscode` → `graphflow-tool`,规避 Marketplace displayName 冲突;VSIX 文件名同步改为 `graphflow-tool` - **扩展 displayName**:更新为 `GraphFlow Tool` ## [1.7.5] - 2026-07-18 ### Added - **Qoder MCP / Skill 支持**:自动检测用户级 `~/.qoder/mcp.json`(Windows `%APPDATA%/Qoder/User/mcp.json`)与项目级 `.qoder/mcp.json`;Skill 安装至 `~/.qoder/skills/graphflow/SKILL.md` - **Agent Profile 模块化**:新建 `src/integrations/agent-profiles/` 目录与注册机制,各 IDE/Agent profile 独立成文件维护 - **统一错误类型**:新增标准化错误类型与处理函数 - **增量索引取消机制**:`file-indexer` 支持 `AbortController` 取消 - **Skill 健康检查**:新增 Skill 完整性检测 - **previewContext LRU 缓存**:新增 `src/graph/context-cache.ts` - **VS Code Marketplace 自动发布**:新增 `publish-marketplace.yml` workflow ### Changed - **自动执行模式**:LLM 仅在已配置且健康时启用,否则自动回退 bridge mode(`src/core/orchestrator.ts`) - **安装体验优化**:无项目打开时由报错改为友好提示并提供打开文件夹按钮;npm 与插件安装后的项目引导提示统一 ## [1.7.4] - 2026-07-13 ### Added - **DeepSeek 一等 provider**:`ProviderName` 新增 `deepseek`;默认模型 `deepseek-v4-pro` / `deepseek-v4-flash`;Settings 可选 deepseek - **配置→env 桥接**:`resolveConfig` 将 `providers.*.apiKey/baseUrl` 注入 `DEEPSEEK_*` / `OPENAI_*` 等(不覆盖已有环境变量) - **DeepSeek 能力**:思考模式(thinking + reasoning_effort)、JSON Output、`reasoning_content` 解析、KV cache usage 记录、可选只读 graph tool_calls ### Fixed - **LLM 配置无法联通**:此前适配器只读环境变量,忽略配置文件中的 apiKey/baseUrl ## [1.7.3] - 2026-07-12 ### Fixed - **无痛 Windows MCP**:扩展激活时调用 `repairUnsafeWindowsMcpCommands`,自动扫描 Trae / Trae CN / TRAE SOLO 等已有 `mcp.json`,把含空格的 `command` 就地改成短路径或 `node`(无需手动 Install) - **CI Test 挂死**:禁用 vitest/CI 下 embedding 后台预热(HuggingFace MiniLM 下载无超时可卡 30m+);`validate.yml` 设置 `GRAPHFLOW_SKIP_EMBEDDING_WARMUP=1` ## [1.7.2] - 2026-07-12 ### Fixed - **Trae/Windows MCP install**:`buildMcpServerNode` / 写入配置时统一将含空格的 `command`(如 `C:\Program Files\nodejs\node.exe`)转为 8.3 短路径或回退 `node`,避免 Trae Solo 经 cmd 无引号启动时出现 `'C:\Program' 不是内部或外部命令` ## [1.7.1] - 2026-07-12 ### Added - **Resilient local embedding**:`@xenova/transformers` 缺失或加载失败时自动降级到 `fnv1a-384` hash;支持从 workspace `node_modules` 解析 - **可选全图向量召回**:`embeddingPolicy.enableFullGraphVectorRecall`(默认 `false`),开启后对带 embedding 的图节点做 HNSW + RRF - **P2 transformers 离线缓存路径**:`embeddingPolicy.modelCacheDir` / `transformersCachePath` 或 `GRAPHFLOW_EMBEDDING_CACHE_DIR` - **测试**:`m77-embedding-fallback`、`m78-full-graph-vector-recall` ### Changed - **检索降噪**:架构查询提升 `src/graph`/`src/core` 等,降低 `vscode-extension`/`vendor`/`node_modules`/非 src `dist` 权重 - **Adaptive budget 日志**:`logger.info` → `logger.debug`,避免 MCP stderr 被 IDE 标成伪 error - **Installer surface 冻结**:当前 IDE/Agent 安装目标保持维护,不再继续扩展新的 IDE 自动安装面 - **VSIX / 扩展说明**:`graphflow-vscode@1.7.1` 描述与 README 同步上述行为 - **Windows MCP launcher**:优先 spawn `.cjs`,避免 `.cmd` + `shell:false` 的 EINVAL ### Notes (VSIX) - VSIX **仍不**捆绑 `@xenova/transformers`(体积与平台原生依赖) - 默认 hash embedding 可用;真语义请预置缓存目录 ## [1.7.0] - 2026-07-11 ### Added - **P0 向量召回修正**:引入 `@xenova/transformers` + `all-MiniLM-L6-v2`(384 维,约 22MB),实现真正的本地语义 embedding 召回 - **P2 ATP 自适应截断**:简单任务(低优先级、无约束、短描述)自动 short-circuit,跳过 First Principles / Decision Matrix / Reflection,节省 4-6 次 LLM 调用 - **P2 MCP 工具精简**:18 个工具合并为 10 个核心工具,降低 LLM 工具调用认知负荷 ### Changed - **embedding provider 默认改为 `transformers`**:替代原有的 FNV-1a hash embedding(伪语义) - **MCP 工具合并**: - `graphflow_context` = `preview_context` + `expand_anchor` - `graphflow_plan` = `plan` + `plan_insight`(mode 参数区分) - `graphflow_index` = `index` + `index_file` + `rebuild` - `graphflow_insight` = `submit_insight` + `merge_insight` - `graphflow_diagnose` = `diagnose` + `inspect_graph` + `stats` - `graphflow_artifact` = `export_artifact` + `import_artifact` ### Removed - **P1 移除 `hnswlib-node`**:彻底移除 C++ 编译依赖,向量召回统一使用纯线性扫描 - 移除 `graphPolicy.enableHnsw` 配置项及相关代码 - 移除 `hash` embedding provider 及相关函数 ## [1.4.4] - 2026-07-05 ### Added - **Antigravity IDE 安装**:MCP 写入 `~/.gemini/antigravity/mcp_config.json`;全局 Skill、项目 `.agent/rules` / `.agent/skills`;项目 `GEMINI.md` 受管块 - **Gemini CLI**:共享 MCP 路径 `~/.gemini/config/mcp_config.json` - **GitHub Copilot**:专用 `.github/copilot-instructions.md` 源文件(token-first,非 CLAUDE.md 副本) - **Trae CN 项目安装**:`.trae/rules/graphflow.md`(alwaysApply)与项目 Skill;doctor 自检 - **测试**:`m62-trae-cn-install`、`m63-agents-install` ### Fixed - **Antigravity MCP 路径错误**:不再写入 VS Code `Code/User/mcp.json` - **用户级 MCP 污染**:`install` 不再向用户配置注入 `GRAPHFLOW_WORKSPACE_ROOT`;切换策略时自动清除 stale env ## [1.4.3] - 2026-07-05 ### Added - **PascalCase/camelCase 拆词**:`BattlePage` → `battle` + `page`,`EnergyShield` → `shield` 等,英文子词可命中代码符号 - **合并 englishQuery 重排**:RRF 子查询使用中文 + englishQuery + 子查询共同打分 - **UI 路径加权**:含 avatar/shield/battle/camera 等 UI 意图时优先 `src/pages/`、`src/components/` ### Fixed - **TOKEN_SPLIT**:不再把大写字母误当分隔符(修复 `oldFunctionName` 等标识符被错误切碎) - **SQLite FTS**:ASCII 单词前缀匹配(`battle*` → `BattlePage`),多词短语仍用 AND ### Changed - **Agent 翻译提示 / Skill**:优先精确文件/类/组件名,避免泛化 `exercise` 误命中数据层 ## [1.4.2] - 2026-07-05 ### Added - **CJK 查询支持**:中文/日文/韩文分词与双字切分;FTS 对 CJK 查询使用 OR 匹配 - **Agent 委托翻译**:`graphflow_preview_context` 新增 `englishQuery`;当 CJK 查询锚点不足时返回 `agentWorkItems`(`query-translate-en`),由连接的 Agent 翻译为英文符号关键词后重试 - **多查询 RRF**:`expandSearchQueries` 合并原始查询、Agent 英文翻译与工作区路径提示进行检索 - **索引增强**:Symbol 节点 content 附加 JSDoc 摘要(≤160 字符),提升中文意图对英文符号的命中 ### Fixed - **自动索引**:`preview_context` 在图存储为空时即使 workspace 缓存已 warm 也会触发索引 ## [1.4.1] - 2026-07-05 ### Fixed - **CI Windows 构建**:`package-windows` 固定 `windows-2022`,修复 `windows-latest`(VS 2026)上 node-gyp 无法识别 VS 18 导致 `hnswlib-node` 编译失败 - **validate**:Linux CI 增加 `npm rebuild hnswlib-node`,确保 HNSW 原生模块在测试前就绪 - **文档一致性**:同步 MCP 工具列表(移除 v1.4 已删除的 `enrich_graph` / `model_download` / `metrics`;补充 `submit_insight` / `merge_insight` / `skill_guide`) ### Changed - **README / 扩展 README**:补充 VSIX 安装步骤(VS Code / Cursor)、MCP `install` 命令、`hnswlib-node` 原生编译环境说明 ## [1.4.0] - 2026-07-04 ### Changed - **奥卡姆剃刀精简**:移除未产生真实价值的模块,保留三条经过验证的闭环链路。 - 移除 OpenBMB 本地部署(`provider-adapters/openbmb.ts`) - 移除语义压缩模型(`compression-model.ts`、`semantic-compression.ts`) - 移除语义增强器(`semantic-enricher.ts`) - 移除技能进化(`skill-evolution.ts`) - 移除金丝雀门控(`canary-gate.ts`) - 移除本地嵌入模型(`local-embedding.ts`,改为零成本 hash embedding) - 移除向量存储(`vector-store.ts`,HNSW 直接内嵌) - 移除 `@xenova/transformers` 和 `node-llama-cpp` 依赖 - `hnswlib-node` 从 optionalDependencies 移到 dependencies - embedding 默认 provider 从 `"local"` 改为 `"hash"` ### Fixed - **HNSW 向量召回完全打通**(P0):`file-indexer` 现在为所有 File/Symbol/Module 节点附加 256 维 hash embedding(FNV-1a,零成本),HNSW 索引不再为空。 - **Orchestrator 向量召回激活**(P0):`orchestrator-context.ts:maybeBuildNearLosslessContext` 现在传递 `embeddingProvider` + `enableVectorRecall` 到压缩管道,`graphflow_run` 路径的向量召回不再被跳过。 - **HNSW 索引持久化**(P1):`buildEnhancedContextPackage` 现在从 `vectorStorePath` 派生 `.hnsw` 路径并传入 `HnswVectorIndex`,`save()`/`loadIndex()` 不再是空操作。 - **FileWatcher 接入 MCP 启动**(P0):`startFileWatcherIfEnabled` 此前是死代码,现已接入 MCP 服务器启动路径,`autoIndexOnSave: true` 时自动监听文件变化并增量索引。 - **skillHints 解耦**(P1):`buildPromptContext` 中 `skillHints` 不再依赖 `enableGraphContextInPrompt === true`,独立注入 worker prompt。 - **Dangling edges 修复**(P1):`applySkillLearning` 现在先创建 Decision 节点再连 `improves` 边,不再产生指向不存在节点的悬空边。 - **buildPlanFromInsight null 安全**(P0):`insight.ts` 异常时返回 `null` 而非 `[]`,orchestrator 正确检测并回退到 `planTasks`。 ### Added - **Agent MCP Installer 恢复并优化**:支持 15+ Agent 自动检测安装(Cursor、VS Code、Trae、Claude Code、Windsurf、Cline、Roo Code、Kilo Code、PearAI、Gemini、Codex、Antigravity、Amazon Q、Zed、Continue);WSL 检测修复(`platform()` → `release()`)。 - **Reflector 恢复并优化**:`reflectOnEpisodes` 贪心聚类 + Lesson 提取;`getLessonsForEpisode` 提取到 `episodic-memory.ts`;Lesson 自动注入 planner prompt。 - **HNSW 恢复并优化**:`HnswVectorIndex` 支持持久化加载/保存;大仓库自动 ANN,小仓库线性扫描。 - **Kotlin / Swift 索引器**:新增 `.kt` 和 `.swift` tree-sitter 索引器。 - **hash embedding**:零成本 FNV-1a 256 维向量,无需模型推理,作为 embedding 默认 provider。 ### Removed - `src/graph/compression-model.ts` - `src/graph/semantic-compression.ts` - `src/graph/semantic-enricher.ts` - `src/learning/canary-gate.ts` - `src/learning/local-embedding.ts` - `src/learning/skill-evolution.ts` - `src/learning/vector-store.ts` - `src/routing/provider-adapters/openbmb.ts` - `src/types/node-llama-cpp.d.ts` - 相关测试文件:m17、m17b、m17c、m20、m28、m29、m30、m31、m38、m47、m4m5 ## [1.3.4] - 2026-07-03 ### Fixed - **MCP / Windows EPERM**:修复 MCP 在 `AppData\Local` 等系统目录启动时误将系统路径当作工作区并扫描 `ElevatedDiagnostics` 导致 `EPERM` 的问题。 - 目录遍历对 `EPERM`/`EACCES` 静默跳过(`safe-fs`) - 忽略 `ElevatedDiagnostics` 等 Windows 受保护目录 - `ensureMcpWorkspaceEnv` 不再将 `LOCALAPPDATA` 根目录当作隐式工作区;优先使用 IDE 环境变量(`VSCODE_CWD` 等) ## [1.3.3] - 2026-07-03 ### Fixed - **VS Code 扩展(WSL)**:激活时默认仅写入用户级 MCP(`~/.config/Code/User/mcp.json`),不再自动创建项目级 `.vscode/mcp.json` 与项目 Rules,避免 WSL 下 GUI 提交触发 git hook 时与 pyenv 环境冲突。项目级安装改为显式执行 **GraphFlow: Install MCP to Agents**。 - **MCP 启动**:仅在原生 Windows 传入 `electronExecPath`,Linux/WSL 不再写入 IDE 可执行路径。 ## [1.3.1] - 2026-06-29 ### Added - **`graphflow_skill_guide` MCP 工具**:通过 MCP 协议直接提供 Skill 指南内容,不依赖外部文件安装,解决 C 盘权限不足导致 Skill 无法使用的问题。 ### Changed - **工作区级 Skill 回退安装**:当用户级目录(如 `~/.trae/User/skills/`)写入失败时,自动回退安装到项目目录 `.graphflow/skills/graphflow/SKILL.md`。 - **MCP 工具描述增强**:核心工具描述添加"Context First"原则: - `graphflow_preview_context`:强调"ALWAYS CALL THIS FIRST" - `graphflow_plan`:强调"USE AFTER graphflow_preview_context" - `graphflow_expand_anchor`:强调"USE THIS AFTER graphflow_preview_context" - `graphflow_index`:强调"CALL AFTER significant file changes" ### Fixed - **C 盘权限不足导致 Skill 无法使用**:通过 `graphflow_skill_guide` 工具和工作区级回退安装双重保障,确保即使没有 C 盘编辑权限也能正常使用 GraphFlow。 ## [1.3.0] - 2026-06-28 ### Added - **Agent Skill 安装**:`installAllSkills` 写入 Cursor / Claude Code / Codex 的 `skills/graphflow/SKILL.md`(非保留目录 `skills-cursor`)。 - **`graphflow doctor`**:自检各 agent 的 MCP 注册、指令文件与 Agent Skill 状态。 - **委托模式 5-Why**:`agentWorkItems` 新增 6 个可选 `five-whys` 项;merge 解析 `whyChain` 并填充 `rootCauses`。 - **Token benchmark**:`benchmarks/run-token-benchmark.ts` 与 `npm run benchmark`。 - **竞品分析**:`docs/comparison.md`。 - **测试**:`tests/m17b-agent-instructions.test.ts`(Claude MCP 路径 + 指令块安装)。 ### Changed - **启发式 `planTasks`**:支持中文连词拆分;单句任务生成分析→实现→测试三阶段 DAG。 - **`refinedTaskStatement`**:无 5-Why 根因时回退蓝帽综合,避免误显示「待探索」。 - **MCP 安装路径**:Claude Code → `~/.claude.json`;Gemini → `~/.gemini/settings.json`。 - **Windsurf / Codex / Gemini** 全局指令块(append-with-markers 安全写入)。 - **README** 快速上手与竞品对比表更新。 ### Fixed - Cursor 用户此前只能看到 Rule、看不到 Skill 的问题(现同时安装 Rule + Skill)。 ## [1.0.9] - 2026-06-26 ### Added - **Agent-delegated LLM(无 API 模式)**:未配置 provider API 时,`graphflow_plan_insight` / complex `graphflow_run` 返回 `agentWorkItems`,由连接的 coding agent 用自己的模型回答 Six Hats prompts。 - **MCP 闭环工具**:`graphflow_submit_insight`(回传每条 work item 分析)、`graphflow_merge_insight`(合并为完整 insight + DAG plan)。 - **Skill 质量**:`extractSkillAtoms` 过滤 stopwords / 路径噪声,保留短语与 head token。 - **Adaptive budget**:complex 任务默认启用自适应 token 预算;配置默认 `enableAdaptiveBudget: true`。 - **Calls 边增强**:caller 缺失时按行号回退解析;Snapshot 优先展示 `calls` / `defines` 边。 - **L2/L3 锚点**:Module 父节点与架构类查询的 Skill/Decision 注入。 - **Monorepo**:`discoverWorkspacePackages` + Snapshot `workspacePackage` 元数据。 - **语言索引**:Kotlin(`.kt`/`.kts`)、Swift(`.swift`)tree-sitter 索引器。 - **MCP 模块化**:拆分 `tool-definitions.ts` / `tool-handlers.ts` / `version.ts`。 - **VS Code**:Agent Work Items 面板、`graphflow.planInsight` 命令;Chat `/insight` 与 agent-delegated 闭环指引。 ### Changed - Bridge 文档强化:`report_outcome` / `submit_insight` 为必做步骤(AGENTS.md、Cursor rules)。 - `graphflow_inspect_graph` 支持 monorepo 包分组。 ### Fixed - `parseAgentInsightResponse` 优先解析 JSON 数组(plan-refinement)。 - Skill 融合测试与 stopword 过滤的平衡(m20 回归)。 ## [1.0.3] - 2026-06-24 ### Fixed - **CI**:`m17` 测试不再硬编码 `/usr/bin/node`,兼容 GitHub Actions hosted Node 路径。 - **图谱存储**:`graphify-file-client` 原子写入(temp + rename);损坏 JSON 时优雅降级为空 store 并提示 rebuild。 - **上下文检索**:`rankNodesForContextQuery` 降低 `.cursor/mcp.json`、`docs/integrations` 等配置噪声,优先 `src/` 与 Symbol 节点。 - **MCP metrics**:`graphflow_metrics` 支持 `rootDir` 并绑定工作区。 ## [1.0.2] - 2026-06-24 ### Fixed - **MCP ENOENT(fnm 临时路径)**:安装 MCP 时不再写入 fnm multishell 临时 `node` 绝对路径;优先使用 IDE 自带 Electron(`ELECTRON_RUN_AS_NODE`),否则回退稳定 `node`。 - **Trae CN 支持**:安装器识别 `~/.trae-cn` 并写入 `~/.config/Trae CN/User/mcp.json`。 ## [1.0.1] - 2026-06-24 ### Fixed - **多项目工作区隔离**:MCP / 扩展 / npm 包不再把图谱绑定到 vendor 目录或全局配置里的陈旧 `workspaceRoot`。 - **自动发现工作区**:新增 `discover-workspace`,从 cwd 向上查找项目根;仅在 runtime 目录(vendor、extensions)时回退到 IDE 环境变量。 - **MCP launcher**:子进程 `cwd` 与 `GRAPHFLOW_WORKSPACE_ROOT` 指向用户打开的项目,不再固定在扩展 vendor。 - **MCP 安装器**:默认写入 `GRAPHFLOW_WORKSPACE_ROOT: "${workspaceFolder}"`,merge 已有 env,扩展有工作区时同时写用户级与项目级配置。 - **MCP 工具**:`preview_context`、`inspect_graph`、`skill_insights`、`stats` 支持可选 `rootDir` 覆盖。 ## [1.0.0] - 2026-06-19 首个正式版本。在 0.6.x 基础上完成「诚实执行语义」收敛与「上下文压缩」体系,所有新增能力均端到端接线到 CLI / MCP / orchestrator。 ### Added - **混合压缩模型策略(compressor role)**:新增 `compressor` 角色,默认复用 economy tier(`backend: "inherit"`)——配置了外部 provider(OpenAI/Anthropic/百炼)就用其 economy 模型,纯离线则回退内嵌 minicpm。零额外配置。 - **内嵌模型首次自动下载**:无外部 LLM 时,`resolveCompressionModel` 复用既有断点续传下载器,首次按需拉取 minicpm GGUF 到 `~/.graphflow/models/`(类似 Playwright 浏览器下载)。 - **图结构压缩(零成本,默认开启)**:`graph-compression.ts` 提供边权重加权连通子图(`extractConnectedSubgraph`)、加权 PageRank 中心性(`computePageRank`)、检索序与中心性融合重排(`blendWithCentrality`)。preview / orchestrator 默认启用。 - **语义压缩(opt-in)**:`semantic-compression.ts` 通过 minicpm/economy LLM 对相似节点聚类合并(`clusterSimilarNodes` + `summarizeCluster`)、长节点改写(`densifyNodeContent`),由 `graphPolicy.compression.enabled` 开启。 - **RepoMap 概览模式(opt-in)**:`repo-map.ts` 在 token 预算紧张时返回模块级地图(每模块一行 exports 摘要),由 `compression.enableRepoMapFallback` 开启。 - **自适应 Token 预算(opt-in)**:`adaptive-budget.ts` 的 `estimateContextBudget` 按任务复杂度(refactor/多文件/架构/局部修复/加测试)动态调整预算,由 `compression.enableAdaptiveBudget` 开启。 - **HNSW 向量索引(可选依赖)**:`hnsw-index.ts` 在候选集 ≥200 节点时使用 hnswlib-node ANN 加速(10~100x),未安装时优雅降级线性扫描。`hnswlib-node` 列为 optionalDependency。 - **`buildEnhancedContextPackage`**:统一六步压缩 pipeline(RepoMap fallback → 关键词+向量召回 → 图压缩 → 语义压缩 → 分层配额 → 边扩展),preview 与 orchestrator 共用。 - **压缩诊断**:`route diagnose` 输出新增 `compression=:/` 行,可查当前压缩模型来源。 - 测试 m43(bridge 模式)、m44(增强压缩)、m45(真机 benchmark)。 ### Changed - **执行语义诚实化(bridge 模式)**:`graphflow_run` 默认进入 bridge 模式——规划 + 压缩上下文后输出 `executionDescriptor` 移交外部 coding agent 执行,状态为 `HUMAN_REVIEW_REQUIRED` 并标注 `[DELEGATED]`,不再伪造 `COMPLETED`。 - **校验启发式标注**:规则校验结果统一标注 `[heuristic]` 与 `heuristic_validation` riskTag;检测并拒绝 provider 占位符回显(`[openai:model] ...`)。 - `graphPolicy.compression` 配置项扩展:`enableGraphCompression` / `enableRepoMapFallback` / `enableAdaptiveBudget` / `enableHnsw`。 ### Fixed - worker 兜底分支不再返回 `"Simulated change..."` 伪造输出,无可用执行模式时抛出明确错误。 - README 版本号、测试数与失效文档引用同步至 1.0。 ### Added - MCP server 优雅停机:监听 `SIGTERM`/`SIGINT`,停止接收新的 stdin 输入并给在途请求短暂 flush 窗口后退出,避免长驻进程被硬杀导致状态丢失。 - `VectorStore.close()`:释放底层 SQLite 句柄,与 `SqliteClient.close()` 对齐,避免长驻进程文件描述符泄漏。 - MCP 工具入参长度上限(`MAX_STRING_FIELD_LENGTH`),防止超大 payload / prompt injection 风险。 ### Changed - `provider-executor` 改用结构化 `logger` 替换裸 `console.warn/error`,确保生产环境日志可被聚合采集。 - `orchestrate()` 增加顶层错误边界:上下文构建 / DAG 执行 / 图同步的未捕获异常统一收敛为结构化 `HUMAN_REVIEW_REQUIRED` 结果,不再裸抛给调用方。 ### Fixed - DAG 执行 timeout 定时器在任务成功路径未被清除,长驻进程下存在 timer 泄漏;改为 `finally` 中 `clearTimeout`。 - `m12-dynamic-routing` 测试不再依赖对 `api.anthropic.com` 的外网可达性:将 anthropic `baseUrl` 指向本地立即拒绝连接的地址,确定性触发非 strict 降级路径。 ## [0.6.13] - 2026-06-14 ### Fixed - 知识图谱面板力导向布局在大量节点时坐标爆炸,导致 viewBox 过大、画布仅显示角落小点;布局后归一化到画布并收紧力模拟参数。 ## [0.6.12] - 2026-06-14 ### Added - `snapshot-view` 模块:图谱样本的可读标签(`displayLabel`、`displayPath`、`folderGroup`)、分层视图(代码层 / 学习层)、按目录多样性采样。 - 知识图谱面板:暗色主题、分层 Tab、目录聚类着色、关系线型区分、双击/按钮跳转源文件。 ### Changed - `inspectGraph` 默认样本上限提升至 96 节点 / 160 边;VS Code「查看图谱」命令使用 120 / 200。 - 节点摘要预览长度由 96 提升至 160 字符。 ## [0.6.11] - 2026-06-14 ### Changed - 默认开启 `autoIndexOnSave`:保存/变更文件后 debounce 增量索引,实现项目更新时持续静默建图。 - 路由就绪校验要求开启 Auto index on file save。 - 旧配置中遗留的 `maxContextTokens: 400` 自动升级到 1500。 - `graphflow.config.example.json` 同步 `autoIndexOnSave` 与 `maxContextTokens: 1500`。 ## [0.6.10] - 2026-06-14 ### Added - `runtime/` 子模块:`env`、`settings`、`graph`、`routing`、`panel`、`helpers`、`facade`。 - `GraphFlowRuntimeModule` 与 `assertGraphFlowRuntime()`:扩展动态加载时使用统一类型校验。 - VS Code 扩展 esbuild 单文件打包(`dist/extension.js`)。 ### Changed - `runtime.ts` 改为薄 re-export 层;业务逻辑拆分到子模块。 - 扩展移除手写 `GraphFlowRuntime` 接口,改用 core 导出的类型。 ## [0.6.9] - 2026-06-14 ### Added - `loadConfigSafe`:损坏/缺失配置文件时回退默认配置并记录告警。 - `hasPendingGraphIndexWork`:无文件变更时跳过 preview/run 的自动索引。 - `runtime/types.ts`:CLI/MCP 公共类型集中导出。 - `vscode-extension/src/workspace.ts`:可测试的工作区 cwd 解析。 - 测试 `m41-optimization-hardening`。 ### Changed - `postinstall` 默认不再自动 init/MCP 注入;需 `GRAPHFLOW_ENABLE_POSTINSTALL=1` 显式开启。 - CI 根依赖安装改为 `npm ci`,提升可复现构建。 - 默认 `maxContextTokens` 从 400 提升到 1500,避免宽查询预览为空。 - 文件索引器合并 stat 遍历,减少重复 I/O。 - VSIX `.vscodeignore` 裁剪 vendor 中的 map/d.ts/tests/docs。 ### Fixed - 损坏的全局/项目 JSON 不再导致 GraphFlow 启动失败。 ## [0.6.8] - 2026-06-14 ### Fixed - 扩展在无工作区文件夹时也可打开 Settings 并保存全局模型配置;首次安装自动弹出 Settings 面板。 - `showSetupGuide` 不再因未打开项目而失败;图谱建立/路由测试在无工作区时给出中文提示。 ## [0.6.7] - 2026-06-14 ### Added - 全局配置优先:`resolveWritableConfigPath` 默认将 Settings 保存到 `~/.graphflow.config.json`。 - MCP 安装范围:`installScope: "user" | "all"`,默认仅写入用户级 Agent 配置(如 `~/.cursor/mcp.json`)。 - 测试 `m40-config-global-first`:覆盖全局读取/写入与 MCP 用户级默认行为。 ### Changed - 扩展首次安装只 scaffold 全局 `~/.graphflow.config.json`,不再自动创建 `.graphflow/config.json` 工作区覆盖层。 - `resolveConfig` 以全局配置为底,项目 `graphflow.config.json` / `.graphflow/config.json` 作为可选覆盖层合并。 - `npm postinstall` / `graphflow init` 改为全局配置 + 用户级 MCP;README 说明更新为一次配置、所有项目可用。 - 配置指南(`formatModelConfigGuide`)优先展示全局配置路径。 ### Fixed - `saveGraphFlowSettings` 补全 `resolveGlobalConfigPath` 导入,修复扩展打包 TypeScript 编译错误。 ## [0.6.6] - 2026-06-11 ### Added - Settings 面板:**建立图谱(无需 LLM)** — 仅需图谱存储路径即可扫描工作区并生成结构图谱(文件、符号、依赖)。 - Settings 面板:**路由连通性测试(可选)** — LLM 配置就绪后探测 Smart / Economy 路由,连通通过后自动索引并可运行语义提取。 - Runtime API:`indexGraphFromSettings`、`testRoutingAndIndexGraph`、`validateSettingsForGraphIndex`、`validateSettingsForRouting`。 ### Changed - 配置指南明确双路径:无 LLM 结构索引与可选 LLM 路由验证并存;语义提取失败时仍保留结构图谱。 ## [0.6.5] - 2026-06-11 ### Added - Settings 面板:图谱状态(节点/边数、上次索引时间)、配置覆盖层 diff、一键路由诊断。 - `graphPolicy.autoIndexOnSave`:保存文件后 debounce 增量索引(Extension 可选开关)。 - `getSettingsPanelStatus` / `listConfigOverlayKeys`:Settings 与 CLI 共用状态 API。 - Husky pre-push:`lint-staged` 在推送前自动跑 ESLint。 - CI:`validate.yml` 可复用工作流;PR 与 main 发布分离;`v*` tag 触发 Build / npm publish。 - `postinstall` 完成后轻量 bootstrap `indexGraph`(非 CI 环境)。 ### Fixed - Settings 面板 HTML 模板中反引号导致 ESLint 解析失败,阻断 0.6.5 GitHub Actions 与 Release。 ### Changed - 收紧多处 `any` 类型;提交 `vitest.config.ts` 排除 extension 测试。 - README 更新至 v0.6.5,补充 Release 与本地 `npm run ci` 说明。 ## [0.6.4] - 2026-06-10 ### Added - `graphPolicy.semanticEnrichment.backend`: `inherit` | `network` | `local`,明确区分网络模型与本地 OpenBMB。 - 语义提取可单独配置网络 API Key / Base URL(`semanticEnrichment.apiKey` / `baseUrl`)。 - Settings 面板「语义提取后端」:继承 Economy(网络)/ 自定义网络模型 / 本地 OpenBMB。 ### Changed - 语义富化运行时注入独立网络凭证(`applyEnrichmentProviderEnv`);任务编排后增量富化同步应用。 - MCP `graphflow_enrich_graph` 描述更新为支持云端或本地后端。 ## [0.6.3] - 2026-06-10 ### Added - `src/config/secrets.ts`: API Key 支持环境变量名、`${VAR}` 占位符、或直接 `sk-...` 明文;运行时按类型自动解析。 - Settings 面板新增 **Graph Semantic Enrichment**(知识图谱语义提取):可单独配置 provider/model,或留空继承 Economy 层。 - `graphPolicy.semanticEnrichment.provider` 可选字段,允许语义提取使用与 Worker 不同的 provider。 ### Changed - Smart / Economy 模型改为可选;未配置时由 `model-router` 默认表按 provider 回退。 - 语义提取模型不再默认 `minicpm5-1b`;可配置 DeepSeek(`openai` + `baseUrl` + 模型名)或其它云端/本地模型,也可留空。 - OpenBMB 设置与语义提取解耦;OpenBMB 区块仅用于本地 MiniCPM。 - `formatModelConfigGuide` 与初始化文档补充 API Key 规则与图谱更新说明。 ## [0.6.2] - 2026-06-10 ### Fixed - MCP install on Windows now uses `mcp-launcher.cmd` / `mcp-launcher.cjs` so `server.js` is never the MCP `command` (fixes Cursor opening the file as an editor tab). - Vendor bundle skips Linux-only `onnxruntime-node`; GitHub Release VSIX is built on `windows-latest`. - CI: Ubuntu runs full tests; Windows job only packages the VSIX. SQLite tests skip when optional `better-sqlite3` is unavailable. ## [0.6.1] - 2026-06-10 ### Fixed - MCP auto-install now uses system `node` (or Cursor/Electron with `ELECTRON_RUN_AS_NODE`) instead of writing `process.execPath` from the extension host, which broke MCP stdio on other machines. - MCP server logs are redirected to stderr so JSON-RPC on stdout is not corrupted. - Bundled MCP `cwd` points at the extension vendor runtime root for reliable module resolution. - Extension first-install now scaffolds `~/.graphflow.config.json` (global) and workspace `.graphflow/config.json` when a folder is open. ## [0.6.0] - 2026-06-09 ### Added - Agent MCP auto-installer: sniffs Cursor, VS Code, Trae, Claude Code, and Windsurf; writes GraphFlow MCP to user and workspace config (creates missing files). - VS Code extension auto-installs bundled MCP on first install/upgrade (`onStartupFinished`). - New extension commands: `GraphFlow: Install MCP to Agents`, `GraphFlow: Model Setup Guide`. - Post-install model configuration guide in Output panel and `.graphflow/README.md`. ## [0.4.2] - 2026-06-01 ### Fixed - VS Code extension host `Cannot find module 'typescript'`: `typescriptIndexer` now loads `typescript` via `createRequire` lazily and falls back to the regex extractor when unavailable. - `sync-runtime.mjs` now bundles `typescript` and `gpt-tokenizer` into `vendor/graphflow/node_modules/` so the extension runtime can resolve them; `.vscodeignore` explicitly whitelists `vendor/**`. ## [0.4.1] - 2026-06-01 ### Fixed - VS Code extension host `Cannot find module 'better-sqlite3'`: `sqlite-client` switched to dynamic `createRequire`; `client-factory` catches the load failure and degrades the `sqlite` transport to `GraphifyFileClient` with a single warning instead of crashing. - Moved `better-sqlite3` from `dependencies` to `optionalDependencies` so installs without native build tooling still succeed. ## [0.4.0] - 2026-05-31 ### Added - StdIO MCP server entrypoint (`graphflow-mcp`) for Cursor, Claude Code, and other MCP-capable agents. - JSON CLI mode for all primary commands via `--json`. - Agent guidance files: `AGENTS.md`, `CLAUDE.md`, and `.cursor/rules/graphflow.mdc`. - Integration config samples under `docs/integrations/`. - CLI help/version entrypoints (`--help`, `--version`). - AST-based workspace indexer (TypeScript Compiler API) emitting real Symbol nodes (function/class/interface/type/enum/variable/method) and cross-file `references` edges, with regex fallback on parse errors. - LLM-driven agent variants: `planTasksLlm`, `brainstormTaskLlm`, `validateTaskResultLlm`, each with deterministic JSON fallback. - Orchestrator options `enableLlmAgents`, `enableDriftReplan`, `maxReplanRounds` — failed DAG triggers a planner re-plan loop with `previousPlan` + `failureFeedback` before HUMAN_REVIEW. - Skill fusion: composite Skill nodes synthesized when `coOccurCount >= 2 && successCount >= 2`; `prerequisite` edges A→C and B→C; `suggestSkillHints` prioritizes composite skills when both parents match. - Prompt context injection: `executeRolePrompt` accepts `PromptContext`; orchestrator option `enableGraphContextInPrompt` threads `summaryChannel` + `skillHints` into planner / brainstormer / worker / validator prompts; `TaskRunResult.promptContextLines` records actual injected lines. - Node content compression: Symbol content is a signature line (`function planTasks (exported) @src/agents/planner.ts:14`), File content adds `# exports: ...` suffix, raw JSON moved to optional `GraphNode.metadata` (~1.76× byte reduction per Symbol). - Real tokenizer (`gpt-tokenizer` / o200k_base, lazy-loaded with graceful fallback) replaces `length/4` token estimate. - Inverted-index keyword lookup + adjacency lists on memory and file graph clients; new `getNodesByIds` and `getNeighbors` (optional on MCP client). - `expandSubgraph` BFS along `references / imports / depends_on / prerequisite` edges; `buildLayeredContextPackage` pulls 1-hop neighbors of top hits into the same token budget (opt-out via `LayeredPackageOptions.enableEdgeExpansion=false`). - SQLite + FTS5 graph backend (`transport: "sqlite"`) via `better-sqlite3`: WAL mode, idempotent CREATE schema, FTS5 sync triggers, edges PK + from/to/relation indexes; implements `getNodesByIds` and `getNeighbors`. - Vector recall with reciprocal-rank fusion: `src/learning/embeddings.ts` provides deterministic `hashEmbedding` + `createOpenAiEmbeddingProvider` + `reciprocalRankFusion`; `buildLayeredContextPackage` accepts `enableVectorRecall` / `embeddingProvider` / `vectorTopK` / `vectorMinSimilarity` for semantic+keyword fusion. - Episodic Memory + Reflection: `src/learning/episodic-memory.ts` persists Episode nodes per task run; `src/learning/reflector.ts` clusters similar episodes and synthesizes Lesson nodes with `improves` edges; orchestrator `enableEpisodicMemory` injects past keyDecisions into PromptContext.extraInstructions; nightly-trainer optionally runs reflection when given a graph client. - Cross-language workspace indexer: TypeScript / JavaScript (AST via TS Compiler API) + Python / Rust / Go / C / C++ (regex-based) via dispatch in `src/graph/language-indexers/`; uniform Symbol / Module / defines / imports / references output across all languages. - Tests: m16 agent integrations, m17 release readiness, m18 AST indexer, m19 LLM agents + drift, m20 skill fusion, m21 prompt context injection, m22 node compression, m23 graph retrieval, m24 SQLite backend, m25 vector recall, m26 episodic memory, m27 multi-language indexer. ### Changed - Root package metadata now matches Apache-2.0 and publishes `graphflow` / `graphflow-mcp` binaries. - Default router and example config models now use `gpt-4.1` and `gpt-4.1-mini`. - Config loader now resolves `${ENV_VAR}` placeholders from the process environment. - Failed `runTask` executions now append negative feedback events for the learning flywheel. - File indexer skips symbolic links while crawling a workspace. - `GraphClient` interface extended with optional `getNodesByIds` / `getNeighbors`; MCP client degrades to `[]` on unsupported endpoints. - `graphPolicy.transport` accepts `"sqlite"` in addition to `"memory" | "file" | "mcp-http"`. ### Verified - `npm run ci` - `npx vitest run` — 25 test files / 95 tests passing ## [0.3.0] - 2026-05-28 GraphFlow 在 `0.3.0` 完成了从“可跑的多智能体原型”到“可安装、可观测、可分发产品版”的收敛: - CLI、VS Code 命令面板、`@graphflow` chat 三个入口全部打通 - 图谱存储切到本地持久化默认路径,支持观测与复用 - 学习飞轮、动态路由、夜跑训练、扩展打包与 CI 已形成闭环 - 正式使用测试已沉淀到 `docs/testing/2026-05-28-formal-usage-test-report.md` ### Added - Core orchestration pipeline with simple/complex routing and DAG execution. - Validator retry loop with human review fallback state. - Criteria-based validation with matched/missing requirement reporting. - Model tier routing and provider fallback path (OpenAI, Anthropic, 百炼, 豆包). - Graph client factory with file, memory and Graphify MCP HTTP transports. - Automatic graph sync after successful run. - Near-lossless context packaging: - summary + anchor dual channel - L1/L2/L3 quotas - dynamic refill manager with de-dup anchors - Workspace file indexer for File/Symbol graph nodes. - CLI commands: - `run` - `plan` - `context preview` - `graph index` - `graph inspect` - `skill insights` - Learning flywheel baseline: - feedback collector - sample builder - learning dataset exporter - canary gate - VS Code extension scaffold integrated with GraphFlow runtime. - VS Code extension command added: `GraphFlow: Plan & Brainstorm`. - VS Code chat participant added: `@graphflow` with `/run`, `/plan`, `/history`. - Dynamic routing health evaluation and configurable provider priority (`routingPolicy`). - GitHub Actions CI workflow for lint/build/test/extension-build. - CLI routing diagnostics command: `graphflow route diagnose`. - CLI nightly learning command: `graphflow learn nightly`. - Learning event persistence and nightly summary generation. - File indexer now captures `Module` nodes and `imports/defines` graph edges. - Skill flywheel module with skill extraction, skill scoring, and skill co-occurrence graph updates. - Orchestrator integration for learned skill hints in planning and execution feedback. - New chat slash commands: `@graphflow /diagnose` and `@graphflow /learn`. - New chat slash commands: `@graphflow /graph` and `@graphflow /skills`. - VS Code extension now bundles GraphFlow runtime, removing dependency on workspace `npm run start`. - VS Code extension interactive observability panels: - Graph Snapshot with search, type filter, node focus, relation highlight - Skill Insights with search, outcome filter, and score/uses/time sorting - Config template: `graphflow.config.example.json`. - Formal usage test plan and final pass report under `docs/testing/`. ### Changed - README updated to match implemented features and runnable commands. - Release notes updated to reflect bundled runtime, observability panels, and formal validation artifacts. - Config schema expanded with graph and near-lossless controls. - Default graph transport updated to `file` for persistent local usage testing. - Config schema expanded with `skillPolicy` controls. ### Verified - `npm run lint` - `npm run build` - `npm test` (40 tests passing) - CLI smoke checks for `graph index` and `context preview` - CLI smoke check for `plan` - CLI smoke checks for `route diagnose` and `learn nightly` - CLI smoke checks for `graph inspect` and `skill insights` - VS Code extension build - VS Code extension package (`artifacts/graphflow-vscode-0.3.0.vsix`)