From fce6c4de68d568f6556b8d996d9fcfde2461ec8b Mon Sep 17 00:00:00 2001 From: Research Assistant Date: Wed, 6 May 2026 23:28:34 +0800 Subject: [PATCH] feat(35-01): update pf-paper.md with discussion recording step MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit - Add step 8 (保存讨论记录) with Q&A accumulation and CLI invocation - Add prerequisite check for discussion.py module - Add output mention of automatic recording - Per D-05: explicitly exclude pf-deep from recording --- .../skills/literature-qa/scripts/pf-paper.md | 40 +++++++++++++++++++ paperforge/worker/__verify_task2.py | 27 +++++++++++++ 2 files changed, 67 insertions(+) create mode 100644 paperforge/worker/__verify_task2.py diff --git a/paperforge/skills/literature-qa/scripts/pf-paper.md b/paperforge/skills/literature-qa/scripts/pf-paper.md index 8f8e3f6f..f1388e53 100644 --- a/paperforge/skills/literature-qa/scripts/pf-paper.md +++ b/paperforge/skills/literature-qa/scripts/pf-paper.md @@ -32,6 +32,7 @@ paperforge sync # 生成正式笔记和 library-records - [ ] 正式笔记已生成(`paperforge sync` 生成) - [ ] library-record 存在(用于定位论文) - [ ] `fulltext.md` 存在(推荐,用于基于原文回答;如不存在则基于元数据回答) +- [ ] discussion.py 模块可用(`python -m paperforge.worker.discussion --help` 可执行) > **注意**:与 `/pf-deep` 不同,`pf-paper` **不强制要求** OCR 完成。没有 OCR 时基于论文元数据和公开信息回答。 @@ -70,6 +71,8 @@ Zotero Key: [key] 请问有什么问题? ``` +会话结束后,讨论记录将自动保存至论文工作区 `ai/discussion.json` 和 `ai/discussion.md`。 + ### 回答原则 - **严格基于** `fulltext.md` 中的文本内容回答 @@ -92,6 +95,43 @@ Zotero Key: [key] - **表现**:`fulltext.md` 不存在 - **处理**:Agent 基于元数据和公开信息回答,并告知用户"OCR 文本不可用,回答基于元数据" +## 8. 保存讨论记录 + +在 Q&A 会话结束时,Agent 必须将本次讨论记录保存到论文工作区的 `ai/` 目录中。 + +**操作步骤:** + +1. 在会话中积累所有 Q&A 对 —— 每次用户提问和 Agent 回答都记录为一对: + ```json + { + "question": "用户的问题", + "answer": "Agent 的回答", + "source": "user_question", + "timestamp": "2026-05-06T12:00:00+08:00" + } + ``` + 其中 `source` 为 `"user_question"`(用户提问)或 `"agent_analysis"`(Agent 主动分析)。 + +2. 会话结束时,将 Q&A 对序列化为 JSON 字符串,调用 CLI: + ```bash + python -m paperforge.worker.discussion record \ + --vault "" \ + --agent pf-paper \ + --model "" \ + --qa-pairs '' + ``` + +3. CLI 返回 JSON: + ```json + {"status": "ok", "json_path": "Literature/{domain}/{key} - {title}/ai/discussion.json", "md_path": "Literature/{domain}/{key} - {title}/ai/discussion.md"} + ``` + 如果 `status` 为 `"error"`,记录错误信息但不中断会话流程。 + +**注意:** +- 仅 `/pf-paper` 记录讨论。`/pf-deep` 不记录(精读内容已写入正式笔记)。 +- 如果论文没有 library-record(无法解析 domain/title),记录会失败但不影响正常使用。 +- 所有 Q&A 内容以 UTF-8 编码写入,支持中文。 + ## See Also - [pf-deep](pf-deep.md) — 完整三阶段精读 diff --git a/paperforge/worker/__verify_task2.py b/paperforge/worker/__verify_task2.py new file mode 100644 index 00000000..130164e9 --- /dev/null +++ b/paperforge/worker/__verify_task2.py @@ -0,0 +1,27 @@ +"""Verify Task 2 acceptance criteria for pf-paper.md.""" +from __future__ import annotations +import re +import sys + +content = open('paperforge/skills/literature-qa/scripts/pf-paper.md', encoding='utf-8').read() +checks = [ + ('grep: 保存讨论记录', bool(re.search('保存讨论记录', content))), + ('grep: paperforge.worker.discussion record', bool(re.search(r'paperforge\.worker\.discussion record', content))), + ('grep: 仅.*pf-paper.*记录', bool(re.search('仅.*pf-paper.*记录', content))), + ('grep: pf-deep.*不记录', bool(re.search('pf-deep.*不记录', content))), + ('grep: ai/discussion.json >= 1', content.count('ai/discussion.json') >= 1), + ('grep: ai/discussion.md >= 1', content.count('ai/discussion.md') >= 1), + ('grep: user_question', 'user_question' in content), + ('grep: agent_analysis', 'agent_analysis' in content), + ('grep: ## See Also preserved', '## See Also' in content), + ('grep: prerequisite discussion.py', 'discussion.py 模块可用' in content), + ('grep: output recording mention', '会话结束后,讨论记录将自动保存' in content), +] +all_pass = True +for name, result in checks: + status = 'PASS' if result else 'FAIL' + if not result: + all_pass = False + print(f'[{status}] {name}') +print(f'\nAll checks: {"PASS" if all_pass else "FAIL"}') +sys.exit(0 if all_pass else 1)