fix: 审阅建页写入溯源信息并在卡片上展示可点击来源#523
Conversation
- 新增纯函数 buildReviewPageContent:从审阅项构造页面内容, frontmatter 写入 sources(原始源文件身份)与 related(受影响页面 slug), 与 ingest 直接生成页面的约定保持一致,修复审阅建页溯源链断裂 - ReviewCard 新增 "Source:" 行,点击经 openPathInPreview 在预览面板 打开原始文档,无需先 Create Page - 复用 path-utils 的 getFileStem/getFileName,杜绝 slug 派生写法漂移 - 补充 4 个单元测试(sources 写入 / related 派生 / 空值省略 / 引号转义) - .gitignore 忽略本地代码分析缓存目录 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Hugo <shen.lan123@gmail.com>
- 前置条件补充 protobuf(LanceDB 编译依赖) - 新增 mcp-server 预构建步骤(Tauri 打包资源硬性依赖,缺失则编译失败) - 补充 rustup 刚装完 Rust 需重开终端或 source ~/.cargo/env 的提示 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Hugo <shen.lan123@gmail.com>
There was a problem hiding this comment.
Pull request overview
This PR aligns “Create Page” from the Review flow with the ingest-generated wiki frontmatter conventions by writing source provenance into sources, deriving related from affectedPages, and improving review UX by letting users open the original source document directly from the review card.
Changes:
- Add
buildReviewPageContent()to generate full wiki page content (frontmatter + body) includingsourcesand derivedrelated. - Update Review “Create Page” to use the new builder and add a clickable “Source:” row on review cards.
- Update multilingual READMEs with additional build prerequisites and MCP-server build steps; update
.gitignorefor local analysis caches.
Reviewed changes
Copilot reviewed 7 out of 9 changed files in this pull request and generated 3 comments.
Show a summary per file
| File | Description |
|---|---|
| src/lib/review-create-page.ts | Introduces a page-content builder that writes sources and derives related from review metadata. |
| src/lib/review-create-page.test.ts | Adds unit tests for buildReviewPageContent() behavior (sources/related/escaping/omission). |
| src/components/review/review-view.tsx | Uses the builder when creating pages; adds clickable source link to ReviewCard. |
| README.md | Updates build-from-source prerequisites and steps (protobuf, rustup PATH note, MCP server build). |
| README_CN.md | Same build-from-source doc updates (Chinese). |
| README_JA.md | Same build-from-source doc updates (Japanese). |
| README_KO.md | Same build-from-source doc updates (Korean). |
| package-lock.json | Lockfile updates from dependency resolution changes. |
| .gitignore | Ignores local code-analysis cache directories. |
💡 Add Copilot custom instructions for smarter, more guided reviews. Learn how to get started.
| <button | ||
| onClick={() => useWikiStore.getState().openPathInPreview(sourcePath)} | ||
| className="underline decoration-dotted underline-offset-2 hover:text-foreground" | ||
| title={sourcePath} | ||
| > | ||
| {getFileName(sourcePath)} | ||
| </button> |
There was a problem hiding this comment.
已在后续推送中解决:来源按钮现拼接项目根后传绝对路径——原始来源走 ${projectPath}/raw/sources/${identity}(review-view.tsx 当前 L501),wiki 研究页走 ${projectPath}/${provenance.wikiSourcePage}(L515),不再直接透传 item.sourcePath。
| * :returns: 可直接写盘的页面全文 | ||
| */ | ||
| /** 把字符串转为带双引号的 YAML 标量(转义内部双引号)。 */ | ||
| const yamlStr = (value: string) => `"${value.replace(/"/g, '\\"')}"` |
There was a problem hiding this comment.
c15835f 起已修复:yamlStr 先转义反斜杠再转义双引号(review-create-page.ts L90),并有针对含 \ 标题的测试。换行/制表符方面:YAML 双引号标量中字面换行折叠为空格、字面 tab 合法,不会破坏解析;且标题来源为单行输入,现有转义已覆盖实际输入域。
| * :param draft: 页面草稿(标题/类型/目录) | ||
| * :param item: 审阅项(提供正文描述与 affectedPages) | ||
| * :param date: 页面 created 日期(YYYY-MM-DD) | ||
| * :param sourceIdentity: 原始源文件身份;为 null 时省略 sources 行 | ||
| * :returns: 可直接写盘的页面全文 |
There was a problem hiding this comment.
核实了基线(c03c6be)的现状:src/lib/ 下仅 mineru.ts 一个文件用 @param,无文件用 :param,尚不构成既有规范。本 PR 新增代码(review-create-page.ts、finance-naming.ts 等)内部统一用 :param;只改这一处反而会造成 PR 内部两种风格并存。如维护者希望统一为 JSDoc @param,我可以一次性转换本 PR 全部新增 docstring。
- yamlStr 先转义反斜杠再转义双引号,杜绝标题含 \ 时 frontmatter 被 js-yaml 解析损坏或整块解析失败 - 新增 rawSourceIdentityOrNull:sourcePath 不在 raw/sources 下时 (如 deep-research 产生的审阅项)不再把 wiki 页文件名误写为来源身份 - sources 改为多来源并集:审阅项自身来源 + 各受影响页面 frontmatter 中的来源,跨来源矛盾建页后可直接核对全部原始文档 - related slug 去重并剥除 [[wikilink]] 包裹,消除重复与悬空引用 - yamlStr 移出 docstring 与函数之间,文档正确挂载到导出函数 - Source:/Pages: 标签接入 react-i18next(含既有 Pages 的补翻译) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Hugo <shen.lan123@gmail.com>
|
已推送 c15835f,修复自查(8 角度 code review + 独立验证)发现的问题:
测试:新增/更新 7 个单测, 一个留给 maintainer 的设计问题:审阅建页现在携带 🤖 Generated with Claude Code |
- 提取 collectReviewSourceIdentities 共享函数(注入 readFile 保持可测): 审阅项自身来源 + 各受影响页面 frontmatter 来源的并集, 建页写入与卡片展示共用同一逻辑 - 审阅卡片"来源"行改为并集列表,逐个可点击预览, 跨来源矛盾无需建页即可核对全部原始文档 - wiki-store 新增 previewHistory 后退栈(上限 20)与 goBackInPreview, 预览面板头部出现返回按钮,建页跳转后可直接回退 - ingest 提示词强制 PAGES 必须逐字复制索引中现存页面路径, 禁止翻译/转写/臆造 slug(修复 LLM 输出英文 slug 导致 受影响页面无法解析、来源并集失效的问题) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Hugo <shen.lan123@gmail.com>
- 新增 affected-pages-resolver:ingest 解析 REVIEW 块后、写入 review-store 前,把 PAGES 引用逐条解析为真实存在的页面路径—— 精确路径(含补 wiki/ 前缀与 .md 后缀)→ 文件名主干 → frontmatter 标题(NFKC 宽松匹配),臆造引用丢弃并记入 ingest-warnings.log。 持久化的 affectedPages 从此永远指向真实页面,提示词约束失效时 下游(来源并集/related/级联删除)也不会消费脏引用 - decidePageFate 来源匹配改用 NFC + 小写身份键:macOS 文件系统 以 NFD 存储文件名,跨平台同步后 NFC 形式的 frontmatter 记录 此前会匹配失败;刻意不用 NFKC 以免全角/半角折叠导致误删 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Hugo <shen.lan123@gmail.com>
|
补充推送 a9c3165 + e9d2060,围绕"LLM 页面引用不可靠"做了两层加固与两项体验改进: 问题背景:实测发现 LLM 在 REVIEW 块 PAGES 行会把中文文件名翻译成英文 kebab-case slug(如 第一道闸(提示词,概率性):PAGES 指令要求逐字复制索引中现存路径(含非 ASCII 文件名),禁止翻译/转写/臆造 slug。 第二道闸(写入时校验,确定性,e9d2060):新增 Unicode 身份加固: 体验改进(a9c3165):
测试:累计新增 20+ 单测, 🤖 Generated with Claude Code |
- collectReviewProvenance:在来源并集基础上区分三类断链原因—— sourcePath 为 wiki 研究页(证据是网络文献)/ 引用页面不存在 (旧审阅项臆造引用)/ 页面存在但未记录来源 - 审阅卡片:来源为空时不再隐藏,显示"来源不可追溯:<具体原因>"; deep-research 链路的审阅项显示 🌐 可点击的研究报告入口 (其 References 即网络证据终点) - deep-research 时效加固(金融纪要等时效敏感库的关键): 综合提示词注入当天日期,要求逐条标注来源发布日期、冲突时 优先最新信息、超 6 个月或无日期的数据显式标注"时效存疑"; References 标题记录检索日期;查询改写提示词要求时效敏感 主题在检索词中带当前年份 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Hugo <shen.lan123@gmail.com>
- 新增 Finance Research 模板:个股实体页 frontmatter 必带 ts_code/industry,finding 页带 as_of 日期,schema 写明来源命名 规范与时间感知的矛盾处理规则(同标的冲突按来源日期判定超越 而非开放矛盾) - 新增 finance-naming 命名引擎(纯函数+15 个测试): 日期三级提取(yyyymmdd/yymmdd/mmdd,含月日合法性校验防止 股票代码误判);个股前缀分级匹配(全称→递减前缀,取最长 唯一命中,歧义不猜落 NA);对已规范化名称幂等 - importSourceFiles 导入钩子:项目启用时(建项目复选框写入 .llm-wiki/source-naming.json)导入前重命名为 yyyymmdd-<ts_code|NA>-<简称>-<标题>.<ext>,个股表读取项目根 约定位置 stock_basic.csv;改名审计追加 .llm-wiki/rename-map.json (original/renamed/date/dateSource/tsCode/matchedBy,仅供排错) - 建项目对话框:选金融模板时显示规范化复选框(默认开启) - 设计文档 plans/finance-source-naming.md(含 v1 范围外事项) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Hugo <shen.lan123@gmail.com>
正确性: - NFC 身份键提为 source-identity.ts:sourceIdentityKey 并接入真实 删除级联(deleteSourceFiles 的 deletingNames/deletingIdentities 与 sourceNameMatchesAny)——此前只加在无生产调用方的 decidePageFate 上; decidePageFate 改为消费共享键,语义测试保留 - 日期提取加固:yymmdd 层限定 20-39 年份窗口(裸代码 600519 不再 被命名成 2060 年);mmdd 层仅认主干结尾(1206 等型号不再误判); 构名只剥"实际采用"的日期片段,标题中 2028/1600V 等有效数字保留 - previewHistory:关闭预览(null)与外部引用预览不入栈; reset-project-state 切项目清空历史,杜绝跨项目 Back 泄漏 - rename-map 审计:改名计算移到过滤检查后,记录仅在复制成功后追加 且以实际落盘文件名(含唯一化后缀)为准 性能/复用: - PAGES 解析改两阶段 PageResolver:路径/主干索引零逐页读取, 仅存在未解析引用时才补建标题索引(每 ingest 最多一次), 消除每源全库 readFile 扫描 - 标题提取改用 parseFrontmatter 宽容解析(消除第三份正则副本); flattenMdFiles 导出共享,sweep-reviews 删除本地副本(统一大小写 不敏感行为);getRelativePath 替换手写前缀剥离 i18n: - 补 templates.finance name/description(en/zh),金融模板卡片不再 只显示英文;审阅卡片全角标点(():;)改为通用分隔符 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Hugo <shen.lan123@gmail.com>
|
已推送 affaeab:第二轮自查(8 角度 + 独立验证,覆盖金融模板/溯源诊断/预览导航等新增提交)发现 10 项问题并全部修复: 正确性
性能:PAGES 解析改两阶段——路径/主干索引零逐页读取,仅有未解析引用时才补建标题索引(每 ingest 至多一次),消除了每源全库 readFile 扫描(1000 页库批量导入 20 源 = 从 ~2 万次 IPC 读降到通常 0 次) 复用/i18n:标题提取统一走 parseFrontmatter(消除第三份正则副本);flattenMdFiles 共享(修复 .MD 大小写行为分叉);补 templates.finance 中英文案;清理硬编码全角标点 测试:111 文件 / 1690 测试全部通过,类型检查零错误。 🤖 Generated with Claude Code |
覆盖用户最常见的疑问:stock_basic.csv 放在项目根目录、 必需列结构(ts_code/name,可选 cnspell)、tushare 导出脚本、 命名与日期提取规则、rename-map.json 审计字段排错、 范围限制与存量文件改名警告。README 中英文版特性列表加入口链接。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Hugo <shen.lan123@gmail.com>
前一提交只含 README 链接,本提交补入被 .gitignore 拦下的 docs/finance-source-naming.md 本体;已跟踪后后续修改不受忽略规则影响。 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Hugo <shen.lan123@gmail.com>
- loadStockBasic 额外读取项目根可选的 hk_basic.csv(tushare hk_basic 导出),与 A 股表合并;解析器同时识别 cnspell(A 股)与 cn_spell (港股)两种拼音列名 - 新增 mergeStockRecords:按简称去重、靠前的表优先——A+H 两地上市 公司(如中芯国际)稳定解析到 A 股代码,不再因同名歧义落 NA - 使用指南更新港股章节:单独文件约定(两表列结构不同不可直接合并)、 导出脚本、双重上市优先级说明 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Hugo <shen.lan123@gmail.com>
- loadStockBasic 按"项目根 → 应用数据目录"顺序取表:全局放一份 即可供所有金融项目共享(更新一处全部生效),项目根同名文件覆盖; 不打包成分股数据(tushare 再分发限制 + 数据时效问题) - 建项目复选框下新增提示:成分股随上市/退市变化,建议定期自行更新 - 解析器兼容 pandas to_csv 未加 index=False 产生的首列无名索引 (按表头定位列,实测用户真实导出) - 使用指南更新:三平台全局目录路径、时效提醒、索引列兼容说明 Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Hugo <shen.lan123@gmail.com>
用户的主工作流是整文件夹导入纪要,v1 把文件夹路径排除在改名外 不符合预期。现在文件夹导入仅规范"叶子文件名": - 目录结构原样保留(v1 排除的原始动机不受影响) - 过滤检查(敏感文件/大小/监听规则)仍按原始文件名进行,通过后才改名 - 改名后可能与同批/磁盘文件碰撞,仅在发生改名时做落盘去重 - 审计记录同样写入 rename-map.json,以实际落盘名为准 - 新增 2 个测试(改名+结构保留、开关关闭时原样) Co-Authored-By: Claude Fable 5 <noreply@anthropic.com> Co-Authored-By: Hugo <shen.lan123@gmail.com>
京东方A 与 京东方精电 同以「京东方」(长度3)命中时曾判歧义落 NA; 现将命中恰等于基名(去掉尾部 A/B/A/B 市场后缀)视为完整名命中, 同长度平局时唯一完整名命中者胜出,纯前缀平局仍维持歧义规则。 Co-Authored-By: Hugo <shen.lan123@gmail.com>
前缀 ST/*ST/SST/S*ST 与未股改 S、连字符标记 -U/-W/-UW/-WD/-SW、 裸 A/B 后缀均剥为基名参与匹配;全角折半角、大小写不敏感,逐字符 1:1 归一化保证命中区间可切回原文供构名剥除。全名(含标记)直接 包含仍为最强命中;SOHO中国类拉丁开头名不受 S 前缀剥除误伤。 Co-Authored-By: Hugo <shen.lan123@gmail.com>
摘取自 main 7f3b240 中适用于本分支的部分:stripStockMarkers 的 连字符后缀由宽泛的 -[A-Z]{1,3} 收紧为枚举集 U/W/B/S/UW/WD/SW (tushare 命名实际存在的标记)。此前 -AI/-ESG 类纯大写缩写会被 当作市场标记剥除,使该股在同前缀平局裁决中被误判为基名整名命中 而错误胜出;现维持歧义落 NA,宁可不猜。 main 提交中其余部分(parseNormalizedFinanceName 解析端、MCP 批 量超时、无 URL 来源去重键)依赖本分支不存在的功能,未摘取。 Co-Authored-By: Hugo <shen.lan123@gmail.com>
8 角度自查(正确性 + 静默失败双线,独立验证)结果:正确性线无 确认发现;静默失败线确认 4 项,修复如下: - BOM 剥除:Excel「CSV UTF-8」保存的个股表带 ,首列头失配 导致整表静默解析为空、导入全部退化 NA;parseStockBasicCsv 现 先剥 BOM(新增测试) - 空表告警与位置回退:个股表文件可读但解析出 0 条记录时 console.warn 并继续尝试下一位置,坏表不再静默压制好表 - rename-map.json 损坏告警:既有审计文件 JSON 损坏时明确告警 后覆盖,与「文件不存在首次写入」区分 - README 四语对齐:JA/KO 补上金融来源命名条目(此前仅 EN/CN 有); 使用指南中去重后缀描述改为与实现一致的 -日期/-日期-序号 形式 另核实:文件夹重复导入的静默覆盖为上游基线既有行为(非金融路径 从不查重),不在本 PR 范围内扩改 Co-Authored-By: Hugo <shen.lan123@gmail.com>
|
已推送 134640d..a307f2b,共 4 个提交——第三轮加固(回移 + 8 角度自查): 回移的匹配修复(此前只落在 fork 主线,现补进本 PR):
本轮自查发现并修复(正确性 + 静默失败双线独立评审;正确性线无确认发现):
验证: |
问题
从审阅区(Review)通过 Create Page 创建的 wiki 页面,frontmatter 只有
type/title/created/tags/related五个字段,缺失sources——尽管审阅项本身携带sourcePath(触发审阅的原始源文件)和affectedPages。这导致此类页面(尤其 queries 下的矛盾/疑问页)无法追溯到原始文档,与 ingest 直接生成页面的溯源约定不一致。此外,审阅卡片上只显示
Pages:(受影响的 wiki 页面),想查看原始文档必须先 Create Page 再层层跳转。修改
src/lib/review-create-page.ts:新增纯函数buildReviewPageContent(),从审阅项构造建页全文——sources写入原始源文件相对raw/sources/的身份(经sourceIdentityForPath转换),related写入affectedPages派生的裸 slug(复用getFileStem,与现有 wiki 页面约定一致)src/components/review/review-view.tsx:getFileName),点击经openPathInPreview直接在预览面板打开,无需建页README*.md(四语版):修正"从源码构建"说明——补充 protobuf 前置依赖(LanceDB 编译需要)、mcp-server 预构建步骤(tauri.*.conf.json将其 dist/node_modules 声明为打包资源,缺失则编译期报错)、rustup 安装后 PATH 生效提示测试
review-create-page.test.ts):sources 写入、related 派生、无来源时省略、标题引号转义npm run typecheck通过;npm run test:mocks109 文件 / 1646 测试全部通过sources/related🤖 Generated with Claude Code