diff --git a/product-source/hololake-clean-desktop/audit/FIDELITY-LEDGER-20260903.md b/product-source/hololake-clean-desktop/audit/FIDELITY-LEDGER-20260903.md index b2c56faa0..fc208e28f 100644 --- a/product-source/hololake-clean-desktop/audit/FIDELITY-LEDGER-20260903.md +++ b/product-source/hololake-clean-desktop/audit/FIDELITY-LEDGER-20260903.md @@ -14,3 +14,7 @@ 有意差异:概念图中的人格回复和日历执行是视觉示例;运行产品没有绑定人格模型和日历能力,因此不显示也不伪造这些结果。实现改为明确的 `WAITING_PERSONA` 回执。 首屏可见文字来自冰朔本轮要求或产品登记名,没有新增营销口号、指标、徽章或模型选择器。 + +## 知识库人类视觉渲染层纠正 + +冰朔指出首轮只有 Markdown 文本编辑器,不能称为完整知识库模块。现已从只读旧产品供体精确拆入 `knowledge-render` 切片,并在新壳中重新接线:目录、阅读渲染、frontmatter、标签、大纲、wikilink、callout、代码块、表格、来源证据、编辑/阅读切换均可见。验收截图为 `design/concepts/hololake-knowledge-human-render-1536x1024.png`;旧产品其他模块未合并。 diff --git a/product-source/hololake-clean-desktop/audit/HOLOLAKE-CLEAN-V1-LOCAL-ACCEPTANCE-20260903.json b/product-source/hololake-clean-desktop/audit/HOLOLAKE-CLEAN-V1-LOCAL-ACCEPTANCE-20260903.json index 13cae11fa..62d68c098 100644 --- a/product-source/hololake-clean-desktop/audit/HOLOLAKE-CLEAN-V1-LOCAL-ACCEPTANCE-20260903.json +++ b/product-source/hololake-clean-desktop/audit/HOLOLAKE-CLEAN-V1-LOCAL-ACCEPTANCE-20260903.json @@ -18,12 +18,13 @@ "rust_clippy_denied_warnings": "PASS_100", "production_dependency_audit": "0_VULNERABILITIES", "browser_channel_create_message_separation_knowledge_create_edit_save": "PASS_100", + "knowledge_human_visual_rendering_frontmatter_outline_wikilink_callout_table_code_evidence": "PASS_100", "responsive_viewports": ["1536x1024_PASS", "820x900_PASS"], "developer_id_signature": "PASS_100", "installed_application": "/Applications/HoloLake.app", "installed_version": "1.0.0", - "installed_binary_sha256": "f3cd899f99bf7667cd70a897c98ef82ea862567409f61ed6f0a485fe9bc3a96e", - "updater_archive_sha256": "87ae061b942e631a55d7a83002686f1be939431a4cfae62986e2d637c91ffefe", + "installed_binary_sha256": "50e6206be32ce7c70d42998b6217956aaa99687976e3d9ee383d3671e03c250d", + "updater_archive_sha256": "b126efa723415beacfad916621dbecceff7ea3ff24c79e6adacabd5bb343736a", "installed_process_readback": "PASS_100", "updater_artifact_signature": "PASS_100", "update_endpoint_http": 204, diff --git a/product-source/hololake-clean-desktop/audit/HOLOLAKE-CLEAN-V1-LOCAL-ACCEPTANCE-20260903.md b/product-source/hololake-clean-desktop/audit/HOLOLAKE-CLEAN-V1-LOCAL-ACCEPTANCE-20260903.md index 7e579e248..f512c8b90 100644 --- a/product-source/hololake-clean-desktop/audit/HOLOLAKE-CLEAN-V1-LOCAL-ACCEPTANCE-20260903.md +++ b/product-source/hololake-clean-desktop/audit/HOLOLAKE-CLEAN-V1-LOCAL-ACCEPTANCE-20260903.md @@ -2,7 +2,7 @@ 结论:新的独立干净产品根已经建立,HoloLake 1.0.0 已签名安装并在本机运行。它不是公众发行完成回执。 -已通过:TCS→GIR 编译与双语投影、模块编号唯一性、七种来源分流、前端生产构建、Rust 测试与严格 Clippy、生产依赖审计、频道建立、语言/回执分离、知识页新建编辑保存、1536×1024 与 820×900 视口、Developer ID 签名、更新包签名、`/Applications/HoloLake.app` 进程读回。更新入口现场返回 HTTP 204,即服务在线且暂无更新。 +已通过:TCS→GIR 编译与双语投影、模块编号唯一性、七种来源分流、前端生产构建、Rust 测试与严格 Clippy、生产依赖审计、频道建立、语言/回执分离、知识页新建编辑保存、完整人类视觉阅读渲染(frontmatter、大纲、wikilink、callout、表格、代码块、来源证据)、1536×1024 与 820×900 视口、Developer ID 签名、更新包签名、`/Applications/HoloLake.app` 进程读回。更新入口现场返回 HTTP 204,即服务在线且暂无更新。 企业服务器读回:蓝环境保存 5 个中央仓和 5 个负责人工作仓;团队域权限尚未分配,公共切换尚未发生。冰朔语言主控工作仓没有独立编号与登记,因此本轮没有猜名创建。 diff --git a/product-source/hololake-clean-desktop/design/concepts/hololake-knowledge-human-render-1536x1024.png b/product-source/hololake-clean-desktop/design/concepts/hololake-knowledge-human-render-1536x1024.png new file mode 100644 index 000000000..6a9609500 Binary files /dev/null and b/product-source/hololake-clean-desktop/design/concepts/hololake-knowledge-human-render-1536x1024.png differ diff --git a/product-source/hololake-clean-desktop/docs/ARCHITECTURE.md b/product-source/hololake-clean-desktop/docs/ARCHITECTURE.md index 7648246d6..565951112 100644 --- a/product-source/hololake-clean-desktop/docs/ARCHITECTURE.md +++ b/product-source/hololake-clean-desktop/docs/ARCHITECTURE.md @@ -18,7 +18,7 @@ HoloLake 是公众个人初始化频道语言驱动操作系统。第一版只 - 对话和执行事实使用不同来源类型,不把系统文字塞进用户或人格消息。 - 公共四域由企业门户和企业服务器承载,不嵌入个人频道。 - 第五域、冰朔私人核 `TCS-iZero∞` 及私人语料不进入公众发行。 -- 当前知识库可处理 Markdown 和纯文本文件夹;PDF、Office、网页结构化转换尚未实现。 +- 当前知识库具备人类视觉阅读层:安全 Markdown 渲染、frontmatter、页面大纲、callout、表格、代码块与 wikilink 跳转;可处理 Markdown 和纯文本文件夹。PDF、Office、网页结构化转换尚未实现。 - 当前外部 AI 入口是本机来源明确的 inbox/outbox;实时加密通信尚未实现。 - 更新客户端只信任光湖控制的 HTTPS 清单与签名;服务器发行清单尚未发布。 diff --git a/product-source/hololake-clean-desktop/package-lock.json b/product-source/hololake-clean-desktop/package-lock.json index 491a181e2..257625876 100644 --- a/product-source/hololake-clean-desktop/package-lock.json +++ b/product-source/hololake-clean-desktop/package-lock.json @@ -12,6 +12,8 @@ "@tauri-apps/plugin-dialog": "2.7.2", "@tauri-apps/plugin-process": "2.3.1", "@tauri-apps/plugin-updater": "2.10.0", + "dompurify": "^3.4.13", + "marked": "^16.4.1", "react": "19.2.0", "react-dom": "19.2.0" }, @@ -1509,6 +1511,13 @@ "@types/react": "^19.2.0" } }, + "node_modules/@types/trusted-types": { + "version": "2.0.7", + "resolved": "https://registry.npmjs.org/@types/trusted-types/-/trusted-types-2.0.7.tgz", + "integrity": "sha512-ScaPdn1dQczgbl0QFTeTOmVHFULt394XJgOQNoyVhZ6r2vLnMLJfBPd53SB52T/3G36VI1/g2MZaX0cwDuXsfw==", + "license": "MIT", + "optional": true + }, "node_modules/@vitejs/plugin-react": { "version": "5.1.1", "resolved": "https://registry.npmjs.org/@vitejs/plugin-react/-/plugin-react-5.1.1.tgz", @@ -1630,6 +1639,15 @@ } } }, + "node_modules/dompurify": { + "version": "3.4.13", + "resolved": "https://registry.npmjs.org/dompurify/-/dompurify-3.4.13.tgz", + "integrity": "sha512-2vmYIoqjze2d+kakP8S/nS5shfsl587kzwEjcGlTdiksUVgFHnFCsLYDVj/JNqJVOQZGSYBTmuycv0PodwmnMQ==", + "license": "(MPL-2.0 OR Apache-2.0)", + "optionalDependencies": { + "@types/trusted-types": "^2.0.7" + } + }, "node_modules/electron-to-chromium": { "version": "1.5.420", "resolved": "https://registry.npmjs.org/electron-to-chromium/-/electron-to-chromium-1.5.420.tgz", @@ -1775,6 +1793,18 @@ "yallist": "^3.0.2" } }, + "node_modules/marked": { + "version": "16.4.1", + "resolved": "https://registry.npmjs.org/marked/-/marked-16.4.1.tgz", + "integrity": "sha512-ntROs7RaN3EvWfy3EZi14H4YxmT6A5YvywfhO+0pm+cH/dnSQRmdAmoFIc3B9aiwTehyk7pESH4ofyBY+V5hZg==", + "license": "MIT", + "bin": { + "marked": "bin/marked.js" + }, + "engines": { + "node": ">= 20" + } + }, "node_modules/ms": { "version": "2.1.3", "resolved": "https://registry.npmjs.org/ms/-/ms-2.1.3.tgz", diff --git a/product-source/hololake-clean-desktop/package.json b/product-source/hololake-clean-desktop/package.json index 086a8b2d3..de623511e 100644 --- a/product-source/hololake-clean-desktop/package.json +++ b/product-source/hololake-clean-desktop/package.json @@ -14,6 +14,8 @@ "@tauri-apps/plugin-dialog": "2.7.2", "@tauri-apps/plugin-process": "2.3.1", "@tauri-apps/plugin-updater": "2.10.0", + "dompurify": "^3.4.13", + "marked": "^16.4.1", "react": "19.2.0", "react-dom": "19.2.0" }, diff --git a/product-source/hololake-clean-desktop/registries/donor-registry.json b/product-source/hololake-clean-desktop/registries/donor-registry.json index db371de29..34a4c35bc 100644 --- a/product-source/hololake-clean-desktop/registries/donor-registry.json +++ b/product-source/hololake-clean-desktop/registries/donor-registry.json @@ -9,6 +9,6 @@ {"donor_id":"HLP-DONOR-GROK-BUILD-0001","path":"/Volumes/JZAO/HoloLake/reference-materials/grok-build-v-780d138","allowed_use":"BUILD_EXECUTOR_RESEARCH_ONLY","imported":false}, {"donor_id":"HLP-DONOR-GUADA-0001","path":"/Volumes/JZAO/HoloLake/reference-materials/guada-v0.5.6","allowed_use":"KNOWLEDGE_UX_BEHAVIOR_ONLY","imported":false}, {"donor_id":"HLP-DONOR-OUTLINE-0001","path":"/Volumes/JZAO/HoloLake/reference-materials/outline","allowed_use":"KNOWLEDGE_MODEL_AND_IMPORT_RESEARCH_ONLY","imported":false}, - {"donor_id":"HLP-DONOR-HOLOLAKE-LEGACY-0001","path":"product-source/hololake-native-desktop","allowed_use":"TAURI_SIGNING_UPDATE_AND_ACCEPTANCE_ORACLE_ONLY","imported":false} + {"donor_id":"HLP-DONOR-HOLOLAKE-LEGACY-0001","path":"product-source/hololake-native-desktop","allowed_use":"TAURI_SIGNING_UPDATE_ACCEPTANCE_ORACLE_AND_KNOWLEDGE_RENDER_SLICE_ONLY","imported":true,"extracted_slices":["src/modules/knowledge-render/index.tsx","src/modules/knowledge-render/manifest.ts"],"whole_product_merge":false} ] } diff --git a/product-source/hololake-clean-desktop/registries/module-registry.json b/product-source/hololake-clean-desktop/registries/module-registry.json index 2a1a16893..2e210533e 100644 --- a/product-source/hololake-clean-desktop/registries/module-registry.json +++ b/product-source/hololake-clean-desktop/registries/module-registry.json @@ -7,7 +7,7 @@ "module_id": "HLP-MOD-CHANNEL-0001", "name_zh": "个人初始化频道", "kind": "SYSTEM_FOUNDATION", - "state": "LOCAL_INSTALLED_VERIFIED", + "state": "LOCAL_INSTALLED_VERIFIED_WITH_HUMAN_VISUAL_RENDERING", "source": "src-tauri/src/lib.rs#create_channel", "data_owner": "CURRENT_LOCAL_USER" }, @@ -17,7 +17,7 @@ "kind": "PREINSTALLED_USER_MODULE", "state": "LOCAL_INSTALLED_VERIFIED", "source": "src-tauri/src/lib.rs#knowledge", - "capabilities": ["CREATE", "READ", "EDIT", "IMPORT_FOLDER", "EXPORT", "MOVE_TO_TRASH", "PRIVATE_GIT_COMMIT"] + "capabilities": ["CREATE", "READ", "EDIT", "HUMAN_MARKDOWN_RENDERING", "FRONTMATTER", "OUTLINE", "WIKILINK_NAVIGATION", "IMPORT_FOLDER", "EXPORT", "MOVE_TO_TRASH", "PRIVATE_GIT_COMMIT"] }, { "module_id": "HLP-MOD-GLP-BRIDGE-0001", diff --git a/product-source/hololake-clean-desktop/scripts/audit-clean-v1.py b/product-source/hololake-clean-desktop/scripts/audit-clean-v1.py index cac2213a0..0e99dea14 100644 --- a/product-source/hololake-clean-desktop/scripts/audit-clean-v1.py +++ b/product-source/hololake-clean-desktop/scripts/audit-clean-v1.py @@ -25,6 +25,12 @@ package = json.loads((ROOT / "package.json").read_text()) for forbidden in ("openai", "anthropic", "@google/generative-ai", "langchain"): if forbidden in package.get("dependencies", {}): errors.append(f"internal model dependency forbidden: {forbidden}") +for required in ("marked", "dompurify"): + if required not in package.get("dependencies", {}): + errors.append(f"knowledge human renderer dependency missing: {required}") +renderer = ROOT / "src/modules/knowledge-render/index.tsx" +if not renderer.exists() or "MarkdownDocument" not in renderer.read_text(): + errors.append("knowledge human visual renderer missing") tauri = json.loads((ROOT / "src-tauri/tauri.conf.json").read_text()) endpoints = tauri["plugins"]["updater"]["endpoints"] diff --git a/product-source/hololake-clean-desktop/src/App.tsx b/product-source/hololake-clean-desktop/src/App.tsx index 14ea28703..e1b0cfeb1 100644 --- a/product-source/hololake-clean-desktop/src/App.tsx +++ b/product-source/hololake-clean-desktop/src/App.tsx @@ -4,6 +4,12 @@ import { relaunch } from "@tauri-apps/plugin-process"; import { Icon } from "./icons"; import * as api from "./runtime"; import type { KnowledgeDocument, SourceKind, SystemSnapshot } from "./types"; +import { + MarkdownDocument, + documentOutline, + jumpToHeading, + splitFrontmatter, +} from "./modules/knowledge-render"; type View = | "channel" @@ -248,9 +254,10 @@ function Channel({

公共更新

- {data.publicDistributionState === "SIGNED_UPDATE_FEED_READY_NO_RELEASE" - ? "更新入口在线 · 暂无发行" - : data.publicDistributionState} + {data.publicDistributionState === + "SIGNED_UPDATE_FEED_READY_NO_RELEASE" + ? "更新入口在线 · 暂无发行" + : data.publicDistributionState}

只接收签名发行,不自动执行普通 Git 拉取。

@@ -310,12 +317,15 @@ function Knowledge({ [doc, setDoc] = useState(null), [body, setBody] = useState(""), [query, setQuery] = useState(""), - [newTitle, setNewTitle] = useState(null); + [newTitle, setNewTitle] = useState(null), + [editing, setEditing] = useState(false), + [inspectorOpen, setInspectorOpen] = useState(true); useEffect(() => { if (selected) api.readDocument(selected).then((d) => { setDoc(d); setBody(d.body); + setEditing(false); }); }, [selected]); const list = useMemo( @@ -337,6 +347,8 @@ function Knowledge({ const save = async () => { if (doc) { await api.saveDocument(doc.path, body); + setDoc({ ...doc, body }); + setEditing(false); refresh(); } }; @@ -348,6 +360,20 @@ function Knowledge({ refresh(); } }; + const parsed = useMemo(() => splitFrontmatter(doc?.body ?? ""), [doc?.body]); + const outline = useMemo(() => documentOutline(doc?.body ?? ""), [doc?.body]); + const stats = useMemo(() => { + const chars = parsed.content.replace(/\s/g, "").length; + return { chars, minutes: Math.max(1, Math.ceil(chars / 450)) }; + }, [parsed.content]); + const openWiki = (target: string) => { + const normalized = target.replace(/[\s·•・\-_|*`]/g, "").toLowerCase(); + const hit = data.documents.find( + (item) => + item.title.replace(/[\s·•・\-_|*`]/g, "").toLowerCase() === normalized, + ); + if (hit) setSelected(hit.path); + }; return (
@@ -368,8 +394,14 @@ function Knowledge({
-
-