MOSS Architecture

Phase 1a → v2 架构全景图

从书签校准工具到个人上下文工作台。通用 content_items 模型 + 规则引擎 + Today、Knowledge、Governance、Calibration 四个路由。7 张图覆盖系统分层、组件树、路由迁移、规则引擎、SSR 数据流、实施计划和安全边界。

① 系统架构分层

6 层纵向架构,绿色已有、橙色新增、蓝色核心重构、灰色外部依赖。

分层 系统纵向架构 — 从数据源到浏览器
6浏览器
React 19 Client Components Tailwind CSS 4 Design Tokens Inspector Context force-dynamic SSR → 无客户端数据获取
↕ serialized props
5SSR 层
page.tsx (workbench)/layout.tsx today/page.tsx knowledge/page.tsx governance/page.tsx calibration/page.tsx
↕ 同步调用 (no await)
4计算层
规则引擎 Runner 5 条声明式规则 Signal 生成 输入版本驱动 · append-and-publish · 失败保留旧批次
↕ better-sqlite3 同步 API
3数据访问
getDatabase() importContentItems() addFeedback() getCalibrationItems() getLatestSignals() getDomainCoverage() getAuditEvents() getContentFlowStats()
↕ WAL mode · lazy-init singleton
2存储
SQLite moss.db 6 张表 · WAL 模式 · (source, source_id) 唯一 · active run 部分唯一索引
↕ 文件系统读取
1数据源
data/phase-1a-input/*.md parsers/x-bookmarks.ts parsers/x-date.ts import CLI 内部 ID + source_id · 新增使用 UUID · 同源幂等 upsert

② 组件架构

从单体 moss-workbench.tsx (20KB) 拆分为共享壳 + 独立视图组件。通用 ContentItem 替代 BookmarkItem。

当前 Current — 单体结构
layout.tsx 根布局 · Fraunces 字体加载
page.tsx SSR 入口 · 4 个 DB 查询 · force-dynamic
MossWorkbench 20KB 单体 · 含 Sidebar/Nav/3 views/ContextPanel
FeedbackControl 5 种反馈按钮
ThemeToggle 亮/暗模式切换
目标 Target — 共享壳 + 独立视图
layout.tsx 根布局(不变)
(workbench)/layout.tsx 路由组布局 — 组装共享壳
shell/Sidebar 导航 · 4 个视图入口 + 6 域列表
shell/Topbar 面包屑 + 操作按钮
shell/Inspector 右侧上下文面板 · 数据驱动 · 各页面注入不同内容
today/page.tsx SSR → runSignalEngine() + getLatestSignals() + getDomainCoverage()
today/HeroSection 日期 · 标题 · 状态芯片 · 日概览
today/FocusStack 优先处理列表 · urgency=warn|danger
today/SignalCards 信号卡片网格 · 域色编码
today/CoverageMeter 六域覆盖度仪表
knowledge/page.tsx SSR → getContentFlowStats() + getCategoryBreakdown()
knowledge/ModuleGrid 5 个模块卡片(Content Flow 实数据 + 4 placeholder)
governance/page.tsx SSR → getAuditEvents(20)
governance/PolicyList 策略卡片(静态数据)
governance/AuditBox 审计事件列表
calibration/page.tsx 迁移自根 page.tsx · 逻辑不变
MossWorkbench 重构:去掉壳,只保留校准逻辑,ContentItem 替代 BookmarkItem
FeedbackControl 不变
api/feedback POST · 调用 Feedback + Audit 原子事务
api/signals/refresh POST · nonce 触发安全发布新批次

③ 路由结构迁移

从单页面扩展为路由组,共享 Sidebar + Topbar + Inspector 壳。

路由 src/app/ 目录变更 — 左当前 · 右目标
当前 (Phase 1a)
src/app/
layout.tsx
page.tsx ← 单页面入口
globals.css
api/
feedback/
route.ts
目标 (v2 子集)
src/app/
layout.tsx
globals.css
(workbench)/
layout.tsx ← 共享壳
page.tsx ← redirect → /today
today/
page.tsx
knowledge/
page.tsx
governance/
page.tsx
calibration/
page.tsx ← 从根迁移
api/
feedback/
route.ts ← +audit · contentId
signals/
refresh/
route.ts
URL URL 映射表
URL 视图 状态
/ → redirect /today 新增
/today Today — Hero + FocusStack + Signals + Coverage 新增
/knowledge Knowledge — Content Flow + 模块网格 新增
/governance Governance — 策略 + 审计事件 新增
/calibration 书签校准工作台(从 / 迁移) 迁移
POST /api/feedback 事务提交 Feedback 与 Audit Event 扩展
POST /api/signals/refresh 通过 nonce 发布新信号批次 新增

④ 规则引擎执行流程

由本地日期、导入、反馈和规则版本共同驱动;新批次发布失败时继续提供旧 active 结果。

流程 runSignalEngine() 执行逻辑
1
SSR 页面请求到达
Next.js Server Component 调用 runSignalEngine()
today/page.tsx → runSignalEngine(db)
2
计算 generation key
先组合本地日期、最近导入 ID、最近反馈 ID和规则版本形成 base key;强制刷新只在 generation key 中额外加入 nonce
baseKey = date + import + feedback + rules · generationKey = baseKey + nonce
3
检查 active run
只读取 status = 'active' 的稳定批次;普通访问比较 base key,强制刷新绕过命中
SELECT id, base_key, generation_key FROM signal_runs WHERE status = 'active'
✓ 一致
直接读取 active run 的 signals,跳过重新计算
✗ 变化
保留旧 active run,继续计算候选结果
4
构建 RuleContext
注入 db 实例、当前时间、最新导入记录
{ db, now: new Date(), latestImport: getLatestImportRun(db) }
5
在事务外评估全部规则
收集候选 Signal[];任一规则失败时不修改当前 active run
rules.flatMap(rule => rule.evaluate(ctx))
6
事务内 append-and-publish
再次检查 generation key;旧 run 降级、新 active run、signals 与 audit event 共同提交
transaction(() => { supersedeOld(); insertActiveRun(); insertSignals(); insertAudit(); })
7
返回 active 信号列表
事务失败则回滚并继续读取旧 active run;成功则返回新批次
规则 5 条初始规则 — 输入 → 查询 → 判断 → 输出
规则 ID SQL 查询概要 触发条件 紧急度
uncalibrated-categories 按 json_extract(metadata, '$.category') 统计内容数、反馈数 总数 >20 且覆盖 <10% Knowledge normal → warn
stale-import 查最近 import_runs 的 created_at 与 now 的天数差 差 >7 天 Knowledge warn → danger
feedback-coverage COUNT(DISTINCT content_id) / COUNT(content_items) 覆盖率统计 Governance normal → warn
author-review 按 json_extract(metadata, '$.author_handle') 聚合,LEFT JOIN 正向反馈 高频作者无正向 Knowledge normal
category-skew 按 json_extract(metadata, '$.category') COUNT / 总数 占比 >30% Governance normal

⑤ SSR 数据流

每个视图的 Server Component 调用什么查询、传给哪些客户端组件。

SSR 页面 → 查询 → 组件 映射
/today
runSignalEngine() getLatestSignals() getDomainCoverage()
HeroSection FocusStack SignalCards CoverageMeter
/knowledge
getContentFlowStats() getCategoryBreakdown()
ModuleGrid
/governance
getAuditEvents(20)
PolicyList AuditBox
/calibration
getCalibrationItems() getProfileSnapshot() getFeedbackEvents() getImportRuns()
MossWorkbench FeedbackControl

⑥ 实施时间线

编号对应架构模块;9A/10A 先恢复数据重构后的编译,5+9B 再原子完成路由和共享壳。

计划 10 步实施顺序 — 依赖从上到下

Step 1 · 重构数据模型

内部 ID + UNIQUE(source, source_id) · 新增使用 UUID · user_version=2 · 严格日期解析 · 事务失败整体回滚

src/lib/db.ts src/lib/parsers/x-bookmarks.ts src/lib/parsers/x-date.ts src/lib/types.ts

Step 2 · 新增类型定义

ContentItemRecord, ContentItem, XBookmarkMeta, SignalRun, Signal, AuditEvent, DomainCoverage 等

src/lib/types.ts

Step 3 · 实现规则引擎

依赖 Step 4.1 getLatestSignals() · generation key + append-and-publish runner + active run 回退 + 5 条规则

src/lib/rules/types.ts src/lib/rules/index.ts src/lib/rules/*.ts ×5

Step 4 · 新增数据库查询

getLatestSignals(), getDomainCoverage(), getAuditEvents(), getContentFlowStats(), getCategoryBreakdown()

src/lib/db.ts

Step 5 · 路由组 + 共享 Layout

(workbench)/ 路由组 + 从 moss-workbench.tsx 提取 Sidebar / Topbar / Inspector

src/app/(workbench)/layout.tsx src/components/shell/*.tsx ×3

Step 6 · Today 视图

HeroSection + FocusStack + SignalCards + CoverageMeter · 域色编码

src/app/(workbench)/today/page.tsx src/components/today/*.tsx ×4

Step 7 · Knowledge 视图

Content Flow 模块(实数据)+ 4 个 placeholder 模块卡片

src/app/(workbench)/knowledge/page.tsx src/components/knowledge/*.tsx

Step 8 · Governance 视图

策略卡片(静态)+ 审计事件列表(实数据)

src/app/(workbench)/governance/page.tsx src/components/governance/*.tsx

Step 9 · 迁移书签校准

9A:先在根页面完成 ContentItem 兼容 · 9B:与 Step 5 同提交迁移 /calibration 并拆除旧壳

src/app/(workbench)/calibration/page.tsx src/components/moss-workbench.tsx

Step 10 · 信号刷新 API

10A:先更新事务化 Feedback API · 10B:规则引擎完成后新增 signals refresh API

src/app/api/signals/refresh/route.ts src/app/api/feedback/route.ts

⑦ 安全边界

local-first 架构的核心约束:数据不出本机、不写远端、不暴露公网。

🔒 安全与隐私约束

🚫
无公网暴露
Web API 无认证,仅在本机运行;不直接暴露到公网或多用户网络
📖
X.com 只读
不使用 X API;后续仅允许只读操作;禁止点赞、转发、关注、发消息、修改书签
🏠
数据本地化
兴趣画像、反馈、推荐历史和浏览行为均为敏感个人数据;本地保存,可查看/修正/删除,默认不进入云端模型
📝
Feedback 独立事件流
反馈不改写原始内容;Feedback 与对应 Audit Event 在同一事务中提交或回滚
⚠️
数据文件可见范围
data/phase-1a-input/*.md 含书签正文、作者与链接;推送仓库前确认数据可见范围
🗄️
审计 append-only
应用层不提供更新和删除入口;导入、反馈和信号发布的业务写入与审计写入保持原子性