#!/usr/bin/env node "use strict"; const fs = require("node:fs"); const path = require("node:path"); const repoRoot = path.resolve(__dirname, ".."); const routePath = path.join(repoRoot, "rust/crates/mnote-web/src/routes/page_ai_openhub.rs"); const modPath = path.join(repoRoot, "rust/crates/mnote-web/src/routes/mod.rs"); const designPath = path.join( repoRoot, "design/07-ai/process/7-68-openhub-weknora-mnote-deep-fusion-checklist-v1.md" ); function read(filePath) { return fs.readFileSync(filePath, "utf8"); } function assertCheck(failures, name, passed, details = undefined) { if (!passed) failures.push({ name, details }); } const route = read(routePath); const routesMod = read(modPath); const design = read(designPath); const failures = []; assertCheck( failures, "MNote exposes artifact index API under Page AI OpenHub boundary", routesMod.includes('"/api/page-ai/openhub/artifact-index"') && routesMod.includes("get(page_ai_openhub::artifact_index_get).post(page_ai_openhub::artifact_index_upsert)") ); assertCheck( failures, "artifact index schema stores only lightweight locator fields", route.includes("mnote.page_ai_openhub_artifact_index_record.v1") && route.includes('"openhubSessionId"') && route.includes('"kind"') && route.includes('"providerId"') && route.includes('"path"') && route.includes('"citationPayload"') ); assertCheck( failures, "artifact index explicitly refuses OpenHub message fulltext fields", route.includes("reject_fulltext_message_fields") && route.includes("page_ai_openhub_artifact_index_forbidden_fulltext_field") && route.includes('"message"') && route.includes('"conversationMessages"') && route.includes('"assistantMessage"') && route.includes('"userMessage"') && route.includes('"content"') && route.includes('"transcript"') ); assertCheck( failures, "artifact index response documents no message fulltext copy", route.includes('"messageFulltextCopied": false') && route.includes('"openhub_message_fulltext"') && route.includes('"openhub_conversation_message_rows"') && route.includes('"assistant_text"') && route.includes('"user_prompt"') ); assertCheck( failures, "minimal persistence stays inside MNote/root metadata or explicit env path", route.includes("MNOTE_OPENHUB_ARTIFACT_INDEX_PATH") && route.includes('join(".mnote")') && route.includes('join("page-ai-openhub-artifact-index.json")') && route.includes("write_artifact_index_records") ); assertCheck( failures, "design checklist records completed artifact index boundary", design.includes("[x] MNote 只存 artifact index") && design.includes("task778-openhub-artifact-index-static-smoke.js") && design.includes("不是复制 OpenHub SQLite message 表") ); const result = { ok: failures.length === 0, task: "task778-openhub-artifact-index-static-smoke", failures, }; console.log(JSON.stringify(result, null, 2)); if (!result.ok) process.exit(1);