feat(knowledge): 项目名改 zncm + 去除元链接噪音 + 创建人显示人名

- project_name 默认 deerflow → zncm(config.yaml + 配置默认 + 模块内字面量)
- related_links() 返回空:笔记 Related 不再注入 index/_meta/taxonomy/hub 结构链接,
  只保留真实相关笔记的可点 [[标题]];无相关笔记且无来源时不再渲染 ## Related 段
- 移除随之多余的项目 hub 页脚手架(index.md/_meta/taxonomy.md 仍由 obsidian 脚手架保留,可解析)
- GET /notes/{id} 用 auth provider 把 created_by/updated_by(UUID) 解析为邮箱
  (created_by_name/updated_by_name),前端 footer 显示人名、解析不到才显示短 id
- 仅对新沉淀笔记生效,现有笔记不动

Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
This commit is contained in:
AdministratorandClaude Opus 4.8 committed 2026-06-08 21:50:56 +08:00
1 parent df3fac1032
commit e7ff07debd
11 files changed
+83 -61

No files matched your search

@@ -104,26 +104,33 @@ def _summary(turns: list[dict[str, str]], *, limit: int = 280) -> str:
return ""
def related_links(project_name: str | None) -> list[str]:
"""Structural wikilinks every note carries (wiki-capture requirement).
def related_links(project_name: str | None) -> list[str]: # noqa: ARG001
"""Structural wikilinks every note used to carry.
These point at vault meta/hub pages (``index`` / ``_meta/taxonomy`` / the
project hub) that always exist, so they resolve to navigable pages. Content-
specific "related notes" are injected separately by the service layer (which
has DB access) on top of these.
Product decision: notes no longer auto-link the vault meta/hub pages
(``index`` / ``_meta/taxonomy`` / the project hub) — they were noise in every
note's ``## Related``. Only real, content-specific related notes (injected by
the service layer, which has DB access) are linked now. Kept as a function
(returns empty) so existing callers and the wiki-capture contract stay intact.
"""
from deerflow.knowledge.markdown_vault import slugify
links = ["[[index]]", "[[_meta/taxonomy]]"]
if project_name:
links.append(f"[[projects/{slugify(project_name)}/synthesis/product-knowledge-base]]")
return links
return []
# Backwards-compatible internal alias.
_related_links = related_links
def _related_section_md(related_lines: list[str], source_lines: list[str]) -> str:
"""Render the ``## Related`` section, or ``""`` when there is nothing to show."""
if not related_lines and not source_lines:
return ""
inner = "\n".join(related_lines)
if source_lines:
sources_block = "### Sources\n\n" + "\n".join(source_lines)
inner = (inner + "\n\n" + sources_block) if inner else sources_block
return f"## Related\n\n{inner}\n"
def _build_body(
*,
title: str,
@@ -155,12 +162,9 @@ def _build_body(
implications = "- 后续可在相关问答中参考本页知识。\n- 如内容过期或冲突,请编辑或归档。"
related = "\n".join(f"- {link}" for link in _related_links(project_name))
if sources:
related += "\n\n### Sources\n\n"
for s in sources[:20]:
label = s.title or s.url or "来源"
related += f"- {label}" + (f" — {s.url}" if s.url else "") + "\n"
related_lines = [f"- {link}" for link in _related_links(project_name)]
source_lines = [f"- {s.title or s.url or '来源'}" + (f" — {s.url}" if s.url else "") for s in sources[:20]]
related_section = _related_section_md(related_lines, source_lines)
return (
f"# {title}\n\n"
@@ -168,7 +172,7 @@ def _build_body(
f"## Finding / Decision\n\n{finding}\n\n"
f"## Reasoning\n\n{reasoning}\n\n"
f"## Implications\n\n{implications}\n\n"
f"## Related\n\n{related}\n"
f"{related_section}"
)
@@ -180,7 +184,7 @@ def extract_thread(
mode: str = "summary",
title: str | None = None,
tags: list[str] | None = None,
project_name: str | None = "deerflow",
project_name: str | None = "zncm",
sources: list[SourceDraft] | None = None,
max_messages: int = 80,
) -> NoteDraft | None:
@@ -193,7 +197,7 @@ def extract_thread(
sources = sources or []
body = _build_body(title=final_title, turns=turns, mode=mode, project_name=project_name, sources=sources)
base_tags = list(tags or [])
for default in (project_name or "deerflow", "knowledge-base"):
for default in (project_name or "zncm", "knowledge-base"):
if default and default not in base_tags:
base_tags.append(default)
return NoteDraft(
@@ -216,7 +220,7 @@ def extract_search(
sources: list[SourceDraft],
*,
thread_id: str | None = None,
project_name: str | None = "deerflow",
project_name: str | None = "zncm",
title: str | None = None,
tags: list[str] | None = None,
) -> NoteDraft:
@@ -240,7 +244,7 @@ def extract_search(
*[f"- {link}" for link in _related_links(project_name)],
]
base_tags = list(tags or [])
for default in (project_name or "deerflow", "knowledge-base", "reference"):
for default in (project_name or "zncm", "knowledge-base", "reference"):
if default and default not in base_tags:
base_tags.append(default)
return NoteDraft(