# MemRelay 完整实施计划 ## 2026-08-19 Git 来源增量收集与无变化任务短路(已实施) 背景:`_collect_git` 每次对仓库 HEAD 全量 `ls-tree` 提取全部文件,与游标增量(memory/file)不对称;Git-only 项目(无 agent 活动,`auto` 策略每次兜底收集 git)即使一个字未改,每次任务也全仓重提取、重压缩、重写全部文档(实测 274 文件 → 40 次调用、约 115 万 Token)。定时任务每日空转消耗。 契约: 1. `_collect_git` 接受 `base_commit`(上次成功整理写入 CurationSource 的 git 来源 revision):与当前 HEAD 相同 → 零收集(`git_coverage.mode=unchanged`);不同 → `git diff --name-status` 只提取变更文件并为删除文件生成 SOURCE_REMOVED 声明(`mode=diff`);基线不可用(首次、浅克隆丢失)→ 回退全量(`mode=full`)。full 模式任务不传基线,始终全量。 2. 任务级短路:可用来源只剩 `curated_baseline`/全局指导(无任何主来源)且现有文档的 prompt_version 均为当前版本时,任务记录 `no_primary_changes` 事件并零调用完成(stats 带 `skip_reason`);提示词版本升级时放行重建。 3. 未变文件的信息由 curated_baseline 文档承载,与既有"基线 + 新证据重写"语义一致;diff 空集不再误标 GIT_SOURCE_EMPTY。 4. 验收:`_collect_git` 全量/unchanged/diff(含删除声明)/无效基线回退四态回归;端到端"第二次无变化任务零调用短路"回归;完整后端套件 + 前端门禁通过后发布 ARM,生产实测同一项目从"40 次调用/115 万 Token"降为"零调用完成"。 ## 2026-08-19 调用预算自适应工作量(已实施) 背景:BDYG18Pro 积压 293 个来源产生 27 个证据批次,任务约需 43 次模型调用,配置上限 `task_max_calls=30` 使每天 18:30 定时任务连续 7 天在第 31 次调用(合并 4/7)处失败,每次白烧 31 次调用;失败导致增量游标不推进、积压继续膨胀,形成每日必败循环。 契约: 1. 批次准备完成后按工作量估算所需调用上界:证据每批 1 次(单批不计)+ 合并树每层 ceil(n/4) 收敛至单份 + 文档每 4 份 1 批 × 2(含 repair 预留)。 2. 估算超过配置上限时,本任务内自动放宽调用上限至估算值,并记录 `budget_calls_auto_raised` 事件(configured/required)供审计;Token 预算保持硬顶不放宽,真实成本仍受控。 3. `CURATION_BUDGET_EXCEEDED` 错误信息附带用量与上限明细(调用 X/Y,Token A/B)。 4. 验收:估算函数数学回归(27 批 10 文档=43)、调用上限 1 + 五文档两批的端到端放宽回归(事件唯一、任务完成)、Token 硬顶既有回归不变;完整后端套件 + 前端门禁通过后发布 ARM,生产实测放宽事件触发且任务越过 30 次调用关口。 ## 2026-08-13 时间字段统一 UTC-aware 序列化(已实施) 背景:SQLite 存储 datetime 丢弃时区,ORM 读回 naive UTC,isoformat 序列化不带偏移,Web 前端与 MCP 客户端把它误当本地时间,全站时间显示偏差 8 小时;散落各服务的 `_ensure_utc` 补丁未覆盖序列化路径。该偏差还让静默期去抖中的整理任务(next_retry_at 为未来时刻)看起来像"卡死数小时不执行"。 契约: 1. `models.UTCDateTime`(TypeDecorator)在读取时为 naive 值补回 UTC tzinfo;全部模型时间列使用该类型,存储格式不变、无需迁移。 2. REST(FastAPI)输出 `+00:00` 偏移、MCP(pydantic)输出 `Z` 后缀;前端 `new Date().toLocaleString()` 自动转本地时区,前端零改动。 3. 任务调度语义不变:source_change 任务的 `next_retry_at` 仍是静默期去抖到期时刻,"计划执行"列语义正确。 4. 验收:REST 往返断言时间带 UTC 偏移;修正依赖"读回 naive"旧行为的存量断言;完整后端套件通过后发布 ARM,容器内 ORM 读回 aware、公网 MCP 时间带 `Z` 实测确认。 ## 2026-08-13 MCP GET /mcp 返回 405 兼容新版客户端(已实施) 背景:无状态 Streamable HTTP 下 fastmcp 只注册 POST/DELETE,GET /mcp 落入 SPA 兜底返回 404;新版 Cursor 在 initialize 后主动 GET 打开服务端通知 SSE 流,把 404 视为会话失效,连续重试后墓碑化整个连接导致 MCP 不可用。 契约: 1. `/mcp` 显式注册 GET(含自动 HEAD)返回 405 + `Allow: POST, DELETE`,符合 MCP Streamable HTTP 规范"不支持服务端主动 SSE 流必须回 405";客户端(官方 TS SDK 及 Cursor)对 405 静默容忍。 2. 该处理不做鉴权(405 优先于 401,无信息泄露);POST/DELETE 行为不变。 3. 验收:回归覆盖 GET /mcp 为 405 且带 Allow 头;完整后端套件通过后发布 ARM,内外网实测 405/200。 ## 2026-08-12 操作列收纳与生命周期筛选默认全部(已实施) 背景:全局记忆操作列在 132px 内排 3 个图标按钮导致换行错乱;用户希望各生命周期筛选组默认即显示"全部"。 契约: 1. 全局记忆操作列改为"编辑直达 + 更多下拉":标记待整理/移入回收站/永久删除收入 `el-dropdown`,永久删除以危险色标识(下拉挂载于 body,样式入全局 styles.css),列宽收窄为 104px 单行。新增 `common.moreActions` 文案。 2. 生命周期筛选默认值统一为 `all`:全局记忆、项目记忆(原 `pending`)、搜索页(原 `current`);项目记忆"全部"视图混入检查点与回收站记录,与手动选择"全部"语义一致。历史契约中"默认显示待整理内容"自本节起由本契约取代。 3. 验收:Vitest 覆盖搜索默认 `lifecycle=all` 请求;ESLint、Prettier、vue-tsc 构建通过;发布 ARM 后确认站点提供新构建资源。 ## 2026-08-12 整理输出语言设置(已实施) 背景:文档生成提示词未指定输出语言,整理文档语言隐式跟随来源主导语言,混合语言来源下可能漂移甚至 revision 间不一致;英文习惯的使用者需要确定性保证。 契约: 1. `CurationSettings` 新增实例级 `output_language`:`auto`(默认,跟随来源主导语言且单份文档内保持一致)、`zh-CN`、`en-US`;迁移 `20260812_0015` 为存量行回填 `auto`。不做工作区级覆盖(auto 已天然按项目来源自适应)。 2. 文档生成提示词按设置注入确定性语言指令;显式语言时无论来源语言一律按目标语言书写标题与正文。`PROMPT_VERSION` 升级触发下轮全量重生成。 3. REST/MCP 设置读写自动携带该字段;Web 整理设置页新增下拉(自动/中文/English)。 4. 验收:提示词三种模式的指令注入回归、设置读写回归;完整门禁后发布 ARM。 ## 2026-08-12 提示词页多场景形态(已实施) 背景:提示词页目前只展示一段通用工作流,用户需要自行摸索"规则文件放哪、如何让 AI 遵守、已有项目如何迁移到 MemRelay 记忆"。 契约: 1. 提示词页改为三个场景:`通用工作流`(现状保留)、`新项目接入`、`已有项目迁移`;语言切换对全部场景生效。 2. 新项目接入:提供各客户端规则文件位置表(Cursor:项目根 `AGENTS.md` 或 `.cursor/rules/*.mdc`;Codex CLI:项目根 `AGENTS.md`,全局 `~/.codex/AGENTS.md`;Claude Code:项目根 `CLAUDE.md`,全局 `~/.claude/CLAUDE.md`;VS Code Copilot:`.github/copilot-instructions.md`;其他客户端:项目根 `AGENTS.md` 事实标准),每行附路径复制按钮;三步流程文案——创建规则文件并粘贴工作流提示词(复制按钮)、说明客户端会自动注入每次会话、新会话验证 AI 已解析 MemRelay 项目。 3. 已有项目迁移:后端新增 `build_migration_prompt`(中英文,随密码库/AI 整理启用状态裁剪),指导 AI 完成——解析或创建项目 → 通读 README/docs/脚本/既有 AI 规则文件 → 按 rule/fact/decision/experience 分类精炼写入(凭证只入密码库、记忆只存条目名)→ 建立迁移基线检查点 → 搜索与上下文抽查校验 → 转入标准工作流;明确只迁移确定的长期知识、原文档保留。`/api/v1/system/prompt` 增加 `variant` 参数(workflow/migration)。 4. 验收:后端覆盖 variant 参数与迁移提示词中英文关键内容、功能开关裁剪;前端覆盖场景切换、位置表渲染与迁移变体请求;完整门禁后发布 ARM。 ## 2026-08-12 模型分配的双模式交互重做(已实施) 背景:模型页的"候选模型链"编辑器(自由列表 + 任务类别多选 + 顺序语义)对人不直观;用户期望配置完连接后,模型选择支持两种心智模型:全部任务统一使用一个模型(区分文本与视觉),或按任务类型分别指定。 契约: 1. 连接表单保留"文本模型 + 视觉模型"两个字段不变;其下新增"模型分配"分段开关:`统一模型` 与 `按任务分配`。 2. 统一模型:不显示任何链配置,保存时提交空候选链(后端链自动回落文本模型);提示文案说明所有任务用文本模型、涉图内容用视觉模型。 3. 按任务分配:三个带标签的单选下拉——全局整理、开发项目、高频增量,均可留空表示"跟随文本模型";一个"通用兜底"有序多选(任一模型失败冷却后按顺序尝试);一个冷却秒数输入。视觉模型保持连接级单字段,不按任务拆分。 4. 保存映射:任务专属模型各生成一条对应类别候选,文本模型生成一条通配候选,兜底列表按顺序生成通配候选;该结构与既有后端候选链语义完全兼容,无后端改动。加载时按同样结构反解;无法精确表示的历史高级链(同类别多候选、default 标签等)折叠为"任务槽 + 兜底",提示文案说明保存将按简化结构重写。 5. 候选健康(冷却中标签、最近错误)继续展示在对应的任务槽上。 6. 验收:Vitest 覆盖两种模式的保存载荷映射与历史链反解;ESLint、Prettier、TypeScript/Vite 构建通过;发布 ARM 后浏览器确认两种模式交互与现有生产配置的正确回显。 ## 2026-08-09 模型连接测试的可见性与抗中断改造(已实施) 背景:保存/测试模型连接会同步执行完整能力探测(模型列表、双协议文本生成、结构化输出、流式、视觉),受超时与重试影响可达数分钟。现状按钮无加载状态、过程无反馈、结果仅一次性 toast,用户离开页面即错过结果;HTTP 请求被反向代理超时或客户端断开时探测协程可能被取消,依赖状态停留在 `checking`(生产已出现,靠探测循环 5 分钟后自愈)。 契约: 1. 探测单飞与抗中断:`CurationManager` 持有单个探测任务,保存/测试/自动探测统一入口;测试与自动探测复用运行中的任务,保存新配置则取消旧任务后重启。请求侧以 `asyncio.shield` 等待,客户端断开或代理超时不再取消探测,依赖状态必定被写入终态。 2. 启动自愈:服务启动时若依赖状态遗留 `checking`,将 `next_probe_at` 置为当前时间,由探测循环在 30 秒内重新探测,不再依赖旧的探测计划时间。 3. `model_status` 增加 `probe` 字段(running、started_at、trigger),Web 轮询可见探测进行中状态。 4. Web 模型页:保存与测试按钮增加加载状态;探测进行中显示驻留面板——本次将依次验证的项目清单(模型列表、Responses/Chat Completions 文本生成、结构化输出、流式输出、视觉模型)、已耗时秒数、"可离开页面,结果会保留"提示,期间每 2 秒轮询模型状态;完成后面板转为驻留的结果横幅(成功/失败 + 错误码文案 + 检查时间),不再依赖一次性 toast。测试按钮旁增加帮助图标说明测试内容。 5. 探测语义不变:仍使用连接配置的协议、流式与超时设置端到端验证;不改动模型网关。 6. 验收:后端覆盖探测单飞复用、保存替换旧探测、请求取消后状态仍到终态、启动 `checking` 自愈;前端覆盖加载状态、探测面板轮询与结果驻留;完整门禁后发布 ARM。 ## 2026-08-08 输出截断显式检测与预算默认值提升(已实施) 背景:生产首个全局 full 整理失败于 `MODEL_OUTPUT_INVALID`。三批文档(4+4+2)的最后一批被旧公式 `max(4096, 2048*n)` 压到 4096 输出上限,推理模型的思考 Token 计入输出导致 JSON 截断,repair 调用同上限再次截断后任务失败;实例配置的 80000 输出上限对小批次不生效,属代码缺陷。已先行以 `62fa810` 将下限提高到 `max(8192, 4096*n)` 并发布。标准 OpenAI 兼容协议无法可靠读取模型最大输出值(`/v1/models` 不含该字段),因此不做"自动读取模型上限",改用协议内的确定性截断信号。 契约: 1. 网关显式检测输出截断:Chat Completions `finish_reason=length`,或 Responses `status=incomplete` 且 `incomplete_details.reason=max_output_tokens`,抛出确定性 `MODEL_OUTPUT_TRUNCATED`(非 transient),不再把截断文本交给 JSON 解析产生误导性的 `MODEL_OUTPUT_INVALID`;配置候选链时按既有语义顺延下一候选。 2. Responses 流式 `response.incomplete` 是正常终止事件:计入流完成标记并作为终态响应参与截断判定,不再被误判为 `MODEL_STREAM_INCOMPLETE` 而按临时故障重试;Chat 流式装配保留 `finish_reason`。 3. 能力探测使用 16/32 Token 微预算,推理模型可能带 length 标记仍返回可用文本;全部探测调用豁免截断检测(`fail_on_truncation=False`),不因该标记把依赖判成配置错误。 4. 文档生成输出预算下限提升为 `max(32768, 4096*文档数)`;实例默认 `context_output_tokens` 从 8000 提升为 32000(SQLAlchemy 客户端默认,仅影响新实例,存量配置值不变)。 5. 暂不实施、观察真实运行后再定:截断后自动折半文档批次重试;对"max_tokens 过大"的 400 自适应钳制并按模型记忆实际上限(可存 `curation_model_candidate_states`);机会式读取 `/models` 非标上限字段。 6. 验收:网关回归覆盖非流式/流式截断、探测豁免与 `finish_reason` 装配;预算与批次断言更新;完整后端门禁通过后发布 ARM。 ## 2026-08-08 整理覆盖状态与统计修复(已实施) 生产诊断(192.168.32.100 实例,2026-08-08):26 条活动记忆中 22 条待整理(含 7 条检查点),30 份活动整理文档存在且内容正常。确认以下原因,前两条为实现缺陷: 1. `_apply_documents` 写新 revision 时,文档元数据的 `cited_source_ids` 与 `source_revisions` 只包含本次运行的引用与来源;随后 `rebuild_memory_curation_states` 按“当前活动文档元数据”全量重建生命周期,上一轮已覆盖但本轮未再次引用的记忆整体翻回待整理。生产证据:任务 `ed8aa16d`(18:42)将约 10 条记忆置为已整理,任务 `ce73902c`(23:50)写入 revision 6(每份文档仅引用 1 条新来源)后这些记忆全部回到待整理。 2. 增量任务只收集变化来源,`source_revisions` 缺少未变化旧来源的 key;即使模型再次引用旧来源,revision 匹配也会失败。 3. 检查点计入待整理统计,但整理文档几乎不会逐条引用检查点,统计长期虚高。 4. 附带缺陷:`rebuild_memory_curation_states` 赋回原 `updated_at` 时值未变化、不进入 UPDATE 集合,`onupdate=utcnow` 仍触发,生命周期翻转会污染记忆的 `updated_at`。 修复契约(已按以下最终形态实现): 1. 覆盖元数据跨 revision 累计:`_apply_documents` 写新 revision 时继承活动文档现有 `cited_source_ids`、`source_revisions` 与 `supersedes` 并与本次合并(`_merge_document_coverage`);已删除记忆对应的历史引用在合并时剔除。本次重新引用的来源把 `source_revisions` 更新到新 revision;未再次引用的旧来源保留原 revision,因此被引用记忆再次编辑(revision 变化)仍自动回到待整理,现有 revision 匹配逻辑不变。元数据新增 `job_cited_source_ids` 记录本次任务实际引用,便于追溯;累计规模受范围内记忆数量约束,不会无界增长。 2. 模型对本批次每个来源声明处置:`cited`、`redundant`、`no_action`(文档生成调用的 JSON Schema 新增顶层 `source_dispositions`,Prompt/修复 Prompt 同步说明;PROMPT_VERSION=2026-08-08.1、SCHEMA_VERSION=3)。处置为宽松解析:未知来源 ID 或非法值直接忽略,模型输出缺少该字段时保持现状语义,不阻断任务。实现偏差(等价且更可靠):`redundant`/`no_action` 不写入文档元数据,而是作为持久审阅标记落在 `MemoryReference.reviewed_revision`/`reviewed_job_id` 列——审阅可能不伴随任何文档变化,文档元数据无法承载;重建时 `reviewed_revision == revision` 且未被引用/替代的记忆计为已整理,`covered_reason` 区分 `cited` 与 `reviewed`。来源在收集后被再次编辑(revision 不匹配)时跳过标记,保持待整理。 3. 检查点与“待整理”统计分离:仪表盘 `memory_lifecycle`、AI 整理状态与 rebuild 统计不再把 `checkpoint` 计入 pending/covered/superseded,检查点单独计数(rebuild 返回 `checkpoints`);记忆生命周期筛选新增 `checkpoint` 值,Web 记忆页与项目页提供该筛选;`memory_search` 的 `current` 语义保留检查点可搜索。检查点作为整理来源的行为不变。 4. 修复 rebuild 的 `updated_at` 保留:`_preserve_updated_at` 用 `flag_modified` 强制把原值纳入 UPDATE 集合,杜绝 `onupdate` 覆盖(与 Core update 等价、改动更小)。`reset_memory_curation` 同步修复并清除审阅标记。 5. 迁移 `20260808_0014`:`memory_references` 新增可空 `covered_reason`、`reviewed_revision`、`reviewed_job_id` 列,存量 `covered` 记忆回填 `covered_reason='cited'`。历史活动文档元数据为旧格式,已丢失的跨轮覆盖关系无法凭空恢复;发布后由用户手动触发整理,以新累计语义重建覆盖。 6. 验收:回归覆盖“第二轮重写不翻回已覆盖来源 + 处置声明落库 + revision 变化后审阅失效”(`test_document_rewrite_keeps_previous_citations_and_review_marks_cover_sources`)、“检查点统计分离与筛选”(`test_checkpoints_have_their_own_lifecycle_bucket`)、“updated_at 保留”(同前者断言);生产发布后由用户手动执行整理复测收敛。 ## 2026-08-08 AI 整理模型退避链与场景路由(已实施) 背景:当前 `CurationModelConfig` 为单连接单文本模型,模型不可用时任务进入 `waiting_dependency` 等待探测恢复。外部网关(如 Sub2API)能在同一模型的多个账号之间切换,但不做跨模型降级;跨模型退避由 MemRelay 自身实现。 契约(已按以下最终形态实现): 1. 保持单连接(一个 Base URL、Token、协议),`CurationModelConfig` 新增 `candidates_json`(有序候选:模型名、任务类别、启用开关)与 `candidate_cooldown_seconds`(默认 600 秒)。不引入多连接或多 Base URL;候选链为空时回落 `text_model` 单模型链,向后兼容。视觉模型维持单独字段不变。 2. 任务类别与链(实现为集合匹配,与优先级方案等价且更简单):每个任务派生类别集合 `_job_task_classes`——恒含 `default`,`scope=global` 加 `global`,`trigger=source_change` 加 `incremental`,项目 `workspace_type=development` 加 `development`。候选按声明顺序参与匹配:类别为空的候选匹配全部任务,否则要求与任务类别集合有交集;因任务恒含 `default`,标记 `default` 的候选天然充当所有链的兜底。任务内选择粘性:候选一旦成功即服务同一任务后续全部调用,保证证据/合并/文档批次的一致性。 3. 退避语义:单次请求保持现有最多 3 次有界重试(`OpenAICompatibleClient` 不变);候选调用抛出任何 `ModelGatewayError` 时把该候选置入共享冷却(`CurationModelCandidateState.cooling_until`),同一任务内顺延到链上下一候选并记录切换事件;`MODEL_AUTH_FAILED` 属连接级错误,不触发切换。整链耗尽或全部冷却时抛出 `MODEL_CANDIDATES_EXHAUSTED`(transient,`retry_after` 取最近冷却剩余时间),任务进入 `waiting_dependency`。 4. 候选健康是运行时状态,存储于独立表 `curation_model_candidate_states`(按模型名主键),不进配置 revision 快照、不被配置保存重置;配置 revision 快照包含完整候选链,失败任务重试按现有语义使用当前配置,或 `use_original_config` 复用原链。 5. 探测按需进行:不做全候选周期轮询;连接保存时仍只端到端验证 `text_model`。候选可用性由真实任务调用驱动(成功清除冷却、失败进入冷却),冷却到期后自动重新参与选择。 6. 可观测性:`ModelCall.requested_model` 记录每次实际请求的候选模型(每个候选尝试一条记录);执行输出新增 `model_candidate_switched` 事件(原候选、错误码、新候选),不含 Prompt 与秘密值;任务 usage 记录 `model_used`,文档元数据与来源指纹使用实际产出模型。 7. REST/MCP:`ModelConnectionSaveRequest` 新增 `candidates`(模型名去重校验)与 `candidate_cooldown_seconds`;`model_status` 的 connection 返回候选链及每候选健康(冷却状态、最近错误、最近成功/失败时间);MCP `curation_model_connection_save` 同步扩展参数。Web 模型页提供链编辑(增删、类别多选、启用开关)与健康标签展示。 8. 验收:单元覆盖类别路由(`test_job_task_classes_follow_scope_trigger_and_workspace`)、冷却/跨任务共享/整链耗尽(`test_candidate_chain_routes_falls_back_and_cools_failed_models`)、任务内退避与调用记录/切换事件(`test_call_model_switches_candidates_and_records_each_attempt`);真实网关跨模型退避留待生产观察(用户手动触发整理验收)。未配置 AI 的零配置模式行为不变。 交付顺序:先交付“整理覆盖状态与统计修复”(生产可见的正确性问题),再交付“模型退避链与场景路由”。两份方案已在同一提交中实现并通过完整前后端门禁;发布到 ARM 生产实例后不自动触发整理任务,由用户手动执行一次整理观察新逻辑(冗余文档处置、未整理残留收敛)作为最终验收。 ## 2026-08-07 AI 整理长请求断线修复 - 生产任务在来源收集和批次准备完成后,长时间非流式 Responses 请求间歇出现 `Server disconnected without sending a response.`;短模型探测仍可成功,因此该问题属于长请求传输稳定性,而不是 SQLite、Basic Memory 或文档写回故障。 - `httpx.RemoteProtocolError` 属于 `TransportError` 而不是 `NetworkError`。模型网关必须统一捕获全部 `httpx.TransportError`,映射为可恢复的 `MODEL_UNAVAILABLE`,让任务进入 `waiting_dependency`、按有界退避等待探测恢复,而不是被最外层误标记为永久 `CURATION_FAILED`。 - 模型调用记录必须在所有异常路径结束;已知模型异常保存稳定错误码,未知异常保存 `MODEL_CALL_FAILED` 后继续向上抛出。服务启动时将上个进程遗留的 `running` 模型调用标记为 `MODEL_CALL_INTERRUPTED`,避免 Web/MCP 长期显示不存在的运行中调用。 - 回归测试覆盖模型列表与生成请求的远端协议断线、请求内重试、整理任务进入依赖等待、未知调用异常收尾和启动清理遗留调用。完整后端门禁通过后才允许发布。 - 正式实例发布前创建一致性备份,只原生重建 ARM64 `memrelay` 服务;模型连接启用已验证可用的流式 Responses,使用当前活动模型配置重试每个范围最新的一条传输失败任务,不批量重放已经被后续成功任务覆盖的旧失败记录。 - 生产重试进一步发现实例并发值为 3 时,多个任务会同时读取本地 Basic Memory 并触发 `BASIC_MEMORY_TIMEOUT`。并发降低或停用整理时现有 worker 必须在当前任务结束后自动退休,不能只增不减;Basic Memory 的超时和暂时不可用必须按任务级有界退避重新排队,不得永久失败,也不得错误污染模型依赖状态。 - 流式模型请求发生网络、协议断线或服务端临时故障时,只重试当前流式模式;只有服务明确拒绝流式参数或协议时才允许退回非流式,避免一次逻辑调用被放大为多轮长超时。配置的模型超时必须直接作为每次流式读取超时,不能隐式翻倍。 - 长模型调用每 60 秒写入一次不含 Prompt 或响应正文的安全进度事件;成功事件显示底层请求尝试次数和端到端总耗时。服务停止或 worker 取消时立即结束模型调用记录,避免依赖启动清理才能修正状态。 - 修复以提交 `c3304bf` 发布到正式 ARM64 实例。发布前一致性备份为 `memrelay-20260807T140405Z.tar.gz`,新镜像摘要为 `sha256:050b38618ae05c9ae8161b79252bd27e45cd983785d8e02a868d0970f609994a`,旧镜像保留为 `memrelay:pre-curation-recovery-20260807`。发布后两个容器健康,LAN/公网 readiness 均为 200,运行时 worker 为 `1 / 1`,队列、活动任务和运行中模型调用均为 0。 - 正式实例通过受控故障实验验证本地依赖恢复:停止 Basic Memory 后重试旧超时任务,新任务以 `BASIC_MEMORY_UNAVAILABLE`、`retries=1` 和未来 `next_retry_at` 回到 `queued`,尝试状态为 `waiting_dependency`,执行输出为 `local_dependency_waiting`;测试任务随后取消,Basic Memory 恢复健康,模型依赖未被污染。 ## 2026-08-07 全链路复审结果 - 对照设计初衷重新核验记忆/项目上下文、检查点与时间线、外部密码库 CRUD/TOTP、目录化文件仓储、签名上传下载、MCP、动态提示词、可选 AI 整理和可选记忆 Git;Web、REST 与 MCP 仍共用同一服务层,AI/Git 未配置时基础模式可以独立运行。 - 修正能力发现的一致性:语义搜索状态根据 Basic Memory 实际健康状态返回,不再固定宣称已启用;`memrelay://capabilities` 与 `capabilities_get` 复用同一完整能力清单;MCP `dashboard_get` 补齐数据库、整理、记忆 Git 和 Basic Memory 运行状态。 - ARM64 线上验收发现 AI 整理状态包含时间字段时 `memrelay://capabilities` 无法直接 JSON 序列化;资源输出统一经过 FastAPI `jsonable_encoder`,并增加带真实 `datetime` 状态的 Streamable HTTP MCP 回归测试。 - 修正桌面文件仓储目录按钮的可访问名称,并让 Playwright 只定位本次创建的目录,避免多设备/历史目录存在时出现歧义。 - 本轮门禁:后端 `153 passed, 18 skipped`、Ruff 通过;前端 `34 passed`、ESLint、Prettier、TypeScript/Vite 构建通过;真实桌面 Playwright `1 passed`;隔离 Docker 实例的 Streamable HTTP MCP 实测 `95` 个工具、`3` 个资源。 - 本地审计数据、测试 Token、测试文件和临时容器只存在于隔离目录,正式数据不在本轮本地测试中修改;线上发布必须在提交后重新备份并只重建 `memrelay` 服务。 - ARM64 发布后公网 HTTPS、REST 登录、95 个 MCP 工具、3 个 MCP Resources、外部 Vaultwarden 解锁、Basic Memory 语义搜索、SQLite WAL 和记忆 Git 均通过真实验证;OpenResty 只缓存带哈希的 `/assets/`,API 与 MCP 不进入代理缓存。AI 上游短暂 503 时任务保持有限合并队列,探测恢复后会自动重新排队并继续执行。 ## 持续交付审计修正 - 密码库连接兼容私有网络和反向代理环境中的 HTTP/HTTPS Vaultwarden/Bitwarden 地址,不把是否启用 TLS 作为功能前置条件。 - AI 自动保存凭证时,只在名称相同且请求中提供的用户名、URI 等身份字段与已有条目吻合时自动更新;多个候选必须返回歧义,不能因“同名或任一 URI 相同”误覆盖其他账号。 - 文件元数据更新采用真正的局部更新语义,未提交字段保持原值;MCP 同时提供明确清空可空字段和解除项目关联的能力。 - 文件说明、版本、用途、标签或项目归属变化必须生成新的整理活动版本,不能因为文件正文校验值未变化而被静默去重。 - 一次性上传任务必须持久保存发起来源和记忆档案;上传完成、元数据更新、移动与删除由 Web 或 MCP 发起时,都必须以正确的 `origin` 和 `usage_profile_id` 进入同一整理事件流。 - 整理来源达到文件数量或字符预算时,未入选但仍存在的文件只能标记为未覆盖,不能生成删除墓碑;仅 MCP 来源策略不得把活动仓储文件误判为已删除。 - 文件扫描与密码库同步周期在运行中启用、停用或修改后必须生效,不要求重启服务,也不得在周期设为 `0` 时形成高频空转。 - 启动、周期、Web 和 MCP 文件扫描发现的外部新增、修改、恢复或丢失文件必须生成准确的整理活动;目录变化只维护目录表,不作为正文来源。 - 未显式指定 `scope` 但指定 `project_id` 的 `memory_search` 必须同时搜索该项目和当前记忆空间可见的全局记忆/整理文档,与 `context_get` 的全局规则继承语义保持一致;显式 `scope=project` 或 `scope=global` 时仍严格限定范围。 - MCP 必须提供写权限保护的 `project_resolve_or_create`:优先按 Git remote、设备目录和项目名称解析,找不到时仅用已提供的标识创建项目,并返回项目与 `created` 标记;动态提示词和能力清单必须引用真实存在的工具,避免新项目首个会话依赖两次非原子调用。 - 上述行为必须同时由 REST 与 MCP 回归测试覆盖,并继续保持 Web、REST、MCP 共用同一服务层。 ## 原始记忆生命周期与稳定整理文档优化 > 执行状态:已完成。原始 Markdown 和完整来源追溯保持不变,默认浏览、搜索和上下文只关注尚未整理或重新发生变化的内容;数据库层保证同一范围、记忆空间、项目和文档类型只有一个活动整理文档。 1. 为原始记忆增加可重建的整理状态:`pending`、`covered`、`superseded`。记录被哪些活动整理文档覆盖、覆盖时的原始记忆 revision、整理任务和整理时间;原始 Markdown 仍是正文来源,整理状态属于可由活动整理文档元数据和变化游标重建的 SQLite 派生索引。 2. 新建或编辑原始记忆时自动回到 `pending`,清除旧覆盖关系;成功整理后,仅把被模型明确引用的记忆标记为 `covered`,把 `supersedes` 明确指出的旧记忆标记为 `superseded`,未被引用的来源继续保持 `pending`,避免静默隐藏未处理内容。 3. 全局和项目整理文档继续按稳定文档更新 revision,不为同类型内容反复创建文件。增加基于 `scope + COALESCE(project_id) + COALESCE(usage_profile_id) + document_type` 的活动文档唯一索引;迁移时保留最新活动文档并把历史重复项标记为已替代,不删除历史 revision。 4. `context_get` 优先读取稳定整理文档,并补充所有类型的 `pending` 原始记忆、整理游标之后发生变化的内容和最近检查点;为待整理来源和最新进度保留独立上下文预算,避免超长整理文档独占返回内容。`memory_search` 默认使用 `current`,同时搜索活动整理文档和待整理来源,排除 `covered`、`superseded` 与回收站内容;Web/MCP 可以显式检索这些历史来源。 5. 全局记忆页和项目记忆页提供“待整理、已整理、已替代、回收站、全部”筛选和状态数量,默认显示待整理内容;AI 未启用时所有现有活动记忆保持 `pending`,页面和基础记忆工作流不受影响。 6. REST 与 MCP 返回整理状态、覆盖文档、覆盖 revision 和整理时间;`memory_list`、`memory_search` 支持生命周期筛选,并提供把已整理或已替代记忆重新放回待整理队列的能力。重新整理只更新派生状态并记录新的变化事件,不复制正文。 7. 仪表盘和 AI 整理状态增加待整理、已整理、已替代和活动整理文档统计;整理任务详情记录本次覆盖、替代和仍待整理的记忆数量。 8. 启动时检查并修复缺失或过期的派生状态;迁移、备份恢复和旧实例升级后无需手工整理数据库。覆盖状态重建不得调用外部 AI,也不得修改原始 Markdown。 9. 验收覆盖:同类型整理多次只增加 revision、不增加活动文件;被引用记忆退出默认列表和搜索;编辑后重新变为待整理;未引用来源不被隐藏;已替代来源可追溯;AI/Git 均未配置时基础模式保持原行为;Windows AMD64 与 ARM64 正式实例迁移、备份和公网 Web/MCP 均正常。 > 生命周期优化验收:后端 Ruff 与全量 pytest 通过,结果为 `141 passed, 18 skipped`;前端 33 项 Vitest、ESLint、Prettier、TypeScript/Vite 构建和桌面浏览器布局通过。Windows Docker Desktop AMD64 和物理 Armbian ARM64 均完成原生镜像构建;正式实例迁移到 `20260806_0012`,启动重建得到 19 条待整理、4 条已整理、1 条已替代和 13 份活动整理文档,LAN readiness、公网 HTTPS 页面和生命周期筛选均正常。 > 执行状态:已完成。AI 整理与记忆 Git 保持默认关闭、彼此独立且完全可选;两者均未配置时不探测、不排队、不初始化仓库,基础 Web、REST、MCP、记忆、项目、搜索、密码库和文件仓储完整可用。Responses 非流式、SSE、原生 JSON Schema、真实整理、历史/差异/回滚、Windows AMD64、Armbian ARM64、备份恢复、正式迁移、公网 HTTPS/MCP 和重启恢复均已通过验收。 > 零配置基础模式是正式支持的完整运行方式,不是降级或试用模式。初始化、创建项目、使用 Web/MCP、健康检查和部署均不得要求填写模型或 Git 配置;AI 整理与记忆 Git 只能由用户分别显式启用,未启用时不产生后台探测、队列、工作区 clone、`.git` 目录、错误告警或额外外部请求。 ## 最终验收结果 - 后端完整环境回归、Ruff、真实 Responses、真实 Git、并发、备份冷恢复和迁移链均通过;当前无外部凭证回归为 `145 passed, 18 skipped`,跳过项已在带真实依赖的独立验收中覆盖。 - 前端 `27 passed`,ESLint、Prettier、TypeScript、Vite 和桌面浏览器验收全部通过。 - Windows Docker Desktop 在所有可选构建加速参数为空时成功构建 `linux/amd64` 镜像;物理 Armbian 原生构建并运行 `linux/arm64` 镜像。 - 正式实例部署于 `192.168.32.100:/opt/1panel/docker/compose/memrelay`,数据位于 `/data/memrelay-stack`,数据库迁移至 `20260806_0013`;容器重启后项目、记忆、密码库、MCP 以及中断的 AI 整理任务自动恢复。 - `https://mr.asio.asia` 的登录、REST、Streamable HTTP MCP 均通过;上一轮线上验收发现 93 个工具和 3 个资源,本轮源码与隔离实例已核对为 95 个工具和 3 个资源。OpenResty 只缓存 `/assets/`,动态 API/MCP 不缓存。 - 正式实例在 AI/Git 都未配置时模型配置、整理队列、Git 连接和记忆仓库均为空,现有 2 个项目、23 条记忆引用、文件与已连接密码库保持可用。 ## 完整交付审计与真实模型验收 1. 保留已通过的可选模式、SQLite WAL、多 worker、备份恢复、Windows AMD64 和 Armbian ARM64 能力,并对照两个正式计划逐项重新取证,不能用单元测试数量替代功能验收。 2. 修正项目源码 Git 地址的“身份规范化值”和“真实 clone URL”混用问题;补齐工作区来源策略、分支、密码库凭证引用、整理开关、Agent 最近同步和来源覆盖状态的 REST/MCP/Web 管理。 3. 修正项目归档与永久删除顺序:普通归档不得移动仍在使用的仓库;永久删除必须先删除 Markdown、生成本地 Git 删除提交,再归档 `per_workspace` 历史并保留可恢复的远程同步任务。 4. 补齐整理文档 revision 差异、调度默认恢复、间隔锚点、记忆空间统计与已有 MCP Token 重新绑定能力,并保持 Web、REST 与 MCP 同一服务层。 5. 扩展来源秘密过滤和提示注入验收,覆盖常见密码、Bearer/API Token、TOTP 种子、私钥、连接 URI 和常见平台 Token;测试凭证不得进入 Markdown、Git、日志、错误或临时产物。 6. 增加真实 Git 断网补推、服务重启、远程分叉、项目删除历史、Agent 优先/源码 Git 兜底、所有工作区模板、调度继承/恢复和真实 Streamable HTTP MCP 测试。 7. 使用运行时注入的新网关和 `gpt-5.6-sol` 完成 Responses 非流式、SSE、JSON Schema、模型探测、真实全局/项目整理、历史、差异、回滚及故障恢复;密钥只存在于进程环境或加密测试数据库。 8. 重新执行完整 pytest、Ruff、Vitest、ESLint、Prettier、TypeScript、Vite、Playwright、Windows Docker、备份冷恢复、ARM64 原生构建、正式数据迁移和公网 HTTPS/MCP 验收,最后清理测试环境并覆盖部署。 审计修正已经锁定以下契约:项目级关闭或归档会使其待处理整理任务停止;全局首次启用 AI 只为项目级启用的工作区建立基线;增量整理把已删除的记忆和文件作为来源墓碑处理;`auto` 来源策略在 Agent 数据新鲜且完整时不拉取源码 Git,过期或不足时才使用 Git 兜底;静默调度的 `inherit`、`override`、`disabled` 与周期调度保持一致;失败任务默认使用当前模型配置重试,也可显式复用任务原配置 revision。 ## 无人值守 AI 整理与可选 Git 版本管理完整交付 本轮以 `docs/ai-curation-plan.md` 为详细功能、公共接口、可靠性和验收标准的权威文档,所有能力一次完整实现,不发布缺少计划能力的中间版本。 执行顺序: 1. 增加整理任务、尝试、来源、变化日志、文档、模型连接、依赖状态、调度、记忆空间及 Git 连接/仓库/同步任务的 Alembic 迁移和服务层。 2. 实现有界任务合并、运行中单一后继、调度租约、来源游标、内部事件过滤、模型配置快照、预算分批和异常恢复。 3. 实现 OpenAI-compatible Responses 与 Chat Completions、SSE/非流式、结构化输出、能力探测、退避暂停和自动恢复;真实 Responses 验收使用运行时注入的测试凭证,不把密钥写入 Git、日志或快照。 4. 实现 MCP/文件/Git 来源收集、文本/PDF/Office/图片 OCR/压缩包提取、可信边界、秘密过滤和整理 Markdown 自动应用。 5. 实现默认关闭的记忆 Git、本地历史、可选 remote、双凭证存储、push-to-create、离线补推、分叉处理、删除归档、历史/差异/恢复及远程检查/导入/冷启动。 6. 完成 REST、MCP、中文/英文桌面 Web、动态 Agent 提示词、状态诊断和 README/许可文档;AI 与 Git 未配置时必须保持当前基础服务行为。 7. 完成后端单元/集成、真实 Responses、调度与并发、MCP、前端 Vitest/TypeScript/ESLint/构建、Playwright、Windows Docker Desktop AMD64 和 Armbian ARM64 验收。 8. 通过全部验收后备份并部署到 `192.168.32.100:/opt/1panel/docker/compose/memrelay`,沿用 `/data/memrelay-stack`、端口 `3003` 和 `mr.asio.asia`,验证 LAN、公网 HTTPS、MCP、数据迁移、重启恢复与资源状态。 交付门槛: - 模型长期不可用并积累大量变化时队列有界且不漏事件;恢复后自动补齐。 - AI 和 Git 可分别关闭,两者都未配置时不探测、不排队、不初始化仓库,也不影响现有功能。 - 所有模型、Git、Basic Memory 和文件外部 I/O 均不占用 SQLite 长事务;多 worker 不重复调度或领取。 - 测试密钥只通过进程环境或隔离的加密测试数据库使用;正式部署不包含测试连接、密钥或模型任务。 - Windows AMD64 与真实 Armbian ARM64 上全部测试和端到端工作流通过后才允许部署完成。 ## 完整 AI 开发记忆工作流与正式部署 ### 目标 - 让 Codex、Cursor、Claude Code 等客户端在新项目、新设备和新会话中,仅配置 MCP 与生成的 Agent 提示词即可识别项目、恢复上下文、持续记录开发历史、复用凭证和管理文件。 - Web、REST 与 MCP 共用同一套项目、记忆、检查点、密码库、文件仓储和系统能力,避免只在页面或单一客户端中可用的功能。 - 开发历史使用检查点统一记录,每条包含完成内容、原因、关键修改、验证结果、问题与解决方案及下一步,时间精确到秒并按最新在前展示。 - 对 MemRelay、Basic Memory、本地语义模型、Vaultwarden 连接、文件仓储、Web、REST、MCP、Docker 与反向代理进行完整能力和诊断审计,确认不存在静默降级、接口缺口或阻断主要工作流的问题。 ### 后端与数据 - 新实例首次启动自动创建管理员 `admin`,初始密码为 `242520`;已有实例管理员不受影响,初始化接口继续作为显式关闭自动初始化时的兼容入口。 - 增加记忆和检查点永久删除能力,同时删除 Basic Memory Markdown 与 SQLite 可重建引用;归档和永久删除保持为不同操作。 - 记忆 frontmatter 明确保存 `created_at` 与 `updated_at`,更新时保留创建时间;检查点默认生成秒级标题和结构化正文。 - 记忆搜索结果返回范围、项目 ID 和项目名称,全局记忆明确标记为全局。 - 增加项目文档 ZIP 导出,直接生成 `aidocs/project_context.md`、项目记忆、全局记忆与清单;不让 AI 逐条读取后重写。导出使用短期签名下载地址,Web 和 MCP 均可准备下载。 - 仪表盘接口提供记忆类型分布、近 14 天新增记忆趋势、项目记忆排行、最近检查点、检查点数量、文件容量、有效 Token 与密码库状态。 ### MCP 与 Agent 提示词 - 补齐项目创建、更新、归档、删除和文档导出;记忆列表、永久删除;检查点删除;密码库同步;仪表盘与系统设置查询/更新等 MCP 工具。 - 能力资源和 `capabilities_get` 返回实际可用工具、权限及推荐工作流;破坏性操作保留明确标记,但不人为削减读写 Token 的管理能力。 - 动态提示词提供中英文版本并锁定工作流:会话开始发现能力和解析项目,支持 Resource 的客户端继续读取 `memrelay://guide` 与 `memrelay://capabilities` 获取当前能力状态;工作前读取上下文与最新检查点,过程中保存规则、偏好、事实、决定和经验,获得凭证后立即写入密码库,重要节点和结束前保存结构化检查点。 - 提示词要求登录或连接前先查密码库,唯一匹配直接复用;通用文件进入仓储;需要本地项目文档时直接下载并解压 ZIP 到 `aidocs/`,同时确保 `.gitignore` 包含 `aidocs/`。 ### Web - 已有记忆的 Markdown 编辑器每次打开默认预览,新建记忆默认编辑。 - 项目列表增加搜索,项目名和 Git remote 分行显示;项目详情提供“项目记忆”和“开发时间线”标签及项目文档下载。 - 不设置独立进度页面;项目开发时间线显示秒级检查点并支持创建、编辑和删除;搜索与编辑页面显示每条结果所属项目或全局范围。 - 弹窗头部和底部操作区固定,正文按内容在内部滚动;Markdown、预览、日志和列表使用独立滚动区域并按桌面浏览器高度自适应。普通表单标签在左、控件在右,大型多行编辑器标签在上;提示文案使用标题旁帮助图标并在悬停时显示。 - MCP Token 页面同时管理记忆空间;默认提供共享/全部空间范围,全部记忆空间 Token 自动覆盖后续新增空间,具体空间 Token 仍可限制写入范围。 - 仪表盘使用原生 CSS、SVG 折线图和环形占比图展示聚合统计、趋势、依赖状态与最近活动,不新增重量级图表依赖;最近开发活动固定在依赖状态之后。 - 全局 AI 整理调度不显示或提交项目字段,项目调度才允许选择具体项目。 ### 正式数据、文档与部署 - 更新 MemRelay 正式全局记忆、BDYG18Pro 项目记忆及最新开发检查点,清理无效测试数据。 - 将当前仍有效且可明确定位的基础设施账号、密码、Token 和服务登录信息精确匹配写入已连接 Vaultwarden,避免重复;普通记忆仅保存条目名称和用途。 - README 补充部署、使用、MCP 工具、Agent 提示词、备份恢复、项目导出,以及 AI、MCP、MemRelay、Basic Memory、Vaultwarden 和文件仓储的 Mermaid 架构图、关系图与时序图。 - 在 Windows Docker Desktop 完成 AMD64 回归后,构建并部署到 `192.168.32.100` 的 `/opt/1panel/docker/compose/memrelay`,数据保存在 `/data/memrelay-stack`,主机端口使用 `3003`。 - 备份 OpenWrt FRPC 配置后新增 `mr.asio.asia` 到 `192.168.32.100:3003` 的 HTTP 映射,验证公网 HTTPS、MCP Streamable HTTP、登录 Cookie 和转发头;API、MCP、认证及签名下载禁用代理缓存,仅静态资源允许长期缓存。 - 正式服务、数据和公网访问验收通过后关闭本机 MemRelay Compose,保留源码与构建缓存。 ### 验收顺序 1. 后端迁移、单元测试、真实 Basic Memory、语义模型与 Vaultwarden 集成测试,并检查依赖健康、索引状态、降级状态和诊断信息。 2. MCP 工具发现、权限、完整新项目/新会话工作流与项目 ZIP 导出测试。 3. 前端 Vitest、TypeScript、ESLint、Prettier、Vite 构建和桌面 Playwright 验收。 4. Windows AMD64 镜像验收、Armbian ARM64 原生构建部署、FRP 与公网 HTTPS 验收。 5. 清理临时内容,更新时间线记忆、README 与第三方说明,检查 `.gitignore` 和全部工作树改动后提交独立中文 Commit。 ## 总体方案 - MemRelay 是单管理员、单共享工作区的自托管 AI 记忆、密码库接入和文件仓储服务。 - 后端:Python 3.12、FastAPI、FastMCP、Pydantic、SQLAlchemy 2、Alembic、SQLite,使用 `uv` 管理依赖。 - 前端:Vue 3、TypeScript、Vite、Pinia、Vue Router、Element Plus、Vue I18n,使用 `pnpm`。 - 记忆引擎:Basic Memory `v0.22.1`,通过 Git 子模块固定源码并构建定制镜像。 - 密码库:只连接用户已有的外部 Vaultwarden/Bitwarden,不部署密码库服务。 - 许可证:AGPL-3.0-only;同步提供第三方依赖和本地语义模型许可清单。 - 支持 Windows Docker Desktop 的 Linux 容器模式,以及 Linux 原生 Docker/Compose 部署;不支持 Windows 容器模式。 - 发布固定版本的 `linux/amd64`、`linux/arm64` Docker 镜像,不绑定特定 CPU 型号、核心数、内存容量或 Linux 发行版。 - 其他架构不作为正式发布和测试目标;不为缺少上游依赖的架构维护专用实现。 ## 执行顺序 ### 1. 同步计划与源码 - 任何代码实施前,先将本 Codex 计划完整同步到 `docs/implementation-plan.md`。 - 更新 `aidocs/project_context.md`,检查 `.gitignore`,提交 `docs: 同步完整实施计划`。 - 将 Basic Memory 添加为 `third_party/basic-memory` Git 子模块,固定到 `v0.22.1`,禁止跟随浮动分支。 - 提交 `.gitmodules` 和子模块引用,提交 `chore: 引入Basic Memory源码`。 - 后续所有实现必须同时遵循 Codex 计划和正式计划文档;决策变化时先同步两处。 ### 2. 阶段零验证 - 从本地 Basic Memory 子模块审查 MCP 工具、Markdown 格式、自定义元信息、项目、归档、索引和错误模型。 - 验证 Streamable HTTP MCP 的写入、读取、搜索、移动、归档、索引重建和并发行为。 - 构建定制 Basic Memory 镜像,预置 `sentence-transformers/paraphrase-multilingual-MiniLM-L12-v2`。 - FastEmbed 完全在本地运行,不配置 OpenAI/LiteLLM,不消耗外部 AI Token 或产生 API 费用。 - ONNX/FastEmbed 线程数根据容器可用 CPU 自动选择并允许环境变量覆盖,模型缓存持久化到 `/data/basic-memory/cache`。 - 在 Windows Docker Desktop 的 Linux 容器环境验证 `linux/amd64`,在真实 ARM64 Linux 设备验证 `linux/arm64`;两种镜像均须能够启动并提供完整能力。记录模型加载、首次索引、增量写入、查询延迟和内存占用,用于发布说明和后续优化,不设置特定硬件性能门槛,也不使用 QEMU 模拟替代正式 ARM64 验收。 - 模型故障时保留全文、标签、元数据和关系搜索,Web 显示语义搜索降级状态。 - 验证 Bitwarden CLI `2026.7.0` 在 AMD64/ARM64 下连接外部 Vaultwarden/Bitwarden、注册邮箱加主密码登录、个人 API 密钥登录、同步、TOTP、自动解锁、离线缓存和并发读取。 - 验证不通过时停止后续开发,先修正兼容版本或接口契约,不由实现者临时替换架构。 ### 3. 基础框架与数据 - 建立 `backend/`、`frontend/`、`deploy/`、`scripts/`、`third_party/` 目录。 - Web 使用 HttpOnly 服务端会话;管理员密码使用 Argon2id;MCP 使用 Bearer Token。 - 部署主密钥首次启动自动生成到持久化目录;可取回 Token 和密码库登录凭据使用 AES-GCM 加密。 - SQLite 保存管理员、会话、Token、项目、项目别名、记忆引用、幂等请求、密码库连接、凭证映射、文件目录、上传任务和系统设置。 - Alembic 管理迁移;迁移前备份数据库,失败时停止启动并保留旧数据。 - 后端统一错误码、超时、取消、健康检查和结构化日志;日志不保存密码、Token、TOTP 或文件上传地址。 ### 4. 记忆与项目 - Basic Memory Markdown 是记忆正文唯一来源,按 `global/`、`projects//`、`archive/` 组织。 - frontmatter 保存稳定 ID、范围、类型、项目、状态、revision、标签和时间;MemRelay SQLite 只保存可重建引用。 - 统一 SSH/HTTPS Git remote,结合目录、仓库名、人工别名和设备路径识别项目;歧义选择一次后保存映射。 - 明确规则、偏好、稳定事实、已确定决定和有效进度由读写 MCP 客户端自动保存。 - 推测、临时信息、冲突内容、普通闲聊及秘密值不自动保存;任务无实质变化时不生成空检查点。 - 记忆更新携带 revision;冲突返回最新内容;检查点只追加;创建使用请求 ID 保证幂等。 - Obsidian 可以直接读取 Markdown;第一版不保证外部编辑后的同步,所有正式写入统一通过 Web/MCP。 - 上下文依次组装全局规则、项目规则、偏好、事实、决定、最新检查点和相关经验,并限制返回长度。 ### 5. 外部密码库 - 一个 MemRelay 实例维护一个外部 Vaultwarden/Bitwarden 连接。 - Web 支持两种登录方式:注册邮箱加主密码,或个人 API 密钥的 `client_id`、`client_secret` 加主密码;账号密码方式必须填写 Vaultwarden/Bitwarden 的注册邮箱,不能使用显示名称。 - API 密钥只负责 CLI 身份认证,主密码仍用于解锁密码库;账号、主密码、`client_id` 和 `client_secret` 均使用 AES-GCM 加密保存且不进入日志。 - 第一版不支持密码库账号二步验证;启用二步验证的账号使用个人 API 密钥方式连接。 - Bitwarden CLI 配置和加密缓存持久化,服务启动后自动登录和解锁。 - 默认每 5 分钟同步并支持 Web 手动同步。 - 外部服务不可达时允许读取最后一次成功同步的加密缓存,结果标明缓存状态和最后同步时间;恢复联网后自动刷新。 - 唯一凭证自动解析;多个候选选择一次并保存非秘密映射;未找到时才创建或询问用户。 - Web 和 MCP 支持登录条目的完整列表、详情、新建、修改和删除,字段覆盖账号、密码、多个 URI、备注、TOTP 和自定义字段。 - MCP 在 AI 获得、生成或修改可复用凭证后自动保存;没有条目 ID 时先按名称匹配,并使用请求中实际提供的用户名和 URI 继续收窄,唯一匹配才更新,没有匹配则创建,多个匹配返回稳定歧义错误。 - 秘密结果不进入普通日志、记忆或文件目录表。 ### 6. 文件仓储 - 文件正文保存在配置目录;SQLite 文件目录表保存路径、名称、可空说明、可空版本、用途、标签、项目、MIME、大小、校验值、状态和时间。 - 启动时扫描,默认每 15 分钟周期扫描,Web/MCP 支持手动扫描;管理员可以调整或关闭周期扫描。 - Web/MCP 操作后立即更新目录表;外部新增、修改和丢失文件由扫描补齐。 - 文件版本只是可搜索字段,不保存历史版本。 - 只读 Token 可以搜索、列出和下载;读写 Token 可以更新说明、移动、重命名、删除及准备上传。 - 覆盖和删除只在用户明确要求时执行。 - MCP 不传输文件正文;`file_upload_prepare` 创建上传任务并返回一次性短期 HTTP PUT 地址。 - PUT 流写入临时文件,校验大小和可选哈希后原子移动,随后自动写入目录表;失败临时文件定期清理。 - 下载使用短期签名 GET 地址,支持 HTTP Range;上传和下载地址默认 10 分钟有效。 ### 7. Web、部署与恢复 - 页面包括初始化、仪表盘、全局记忆、项目、搜索编辑、外部密码库、文件仓储、MCP Token、客户端配置、提示词、系统与备份;检查点统一在项目开发时间线中管理。 - 中文为默认语言,可切换英文;只适配桌面浏览器。 - 为 Codex、Cursor、Claude Code、VS Code 和通用 Streamable HTTP MCP 客户端生成配置和动态提示词。 - Compose 只包含 `memrelay` 和定制 `basic-memory`,统一挂载 `/data`。 - 同一套 Compose 配置用于 Windows Docker Desktop 和 Linux Docker;宿主机差异只通过环境变量、卷路径和部署脚本处理。 - 支持 UID/GID、时区、公共 URL、扫描周期、文件容量、上传限制和外部密码库配置。 - HTTP 不附加加密;HTTPS 由反向代理提供 TLS;生成地址沿用公共 URL 协议。 - 提供 Linux Shell 和 Windows PowerShell 手动备份脚本:停止 Compose、归档 `/data`、生成版本清单与校验值、恢复服务。 - 不实现定时备份和 Web 备份调度;外部 Vaultwarden/Bitwarden 数据由其自身备份。 ## 公共接口 - REST 统一使用 `/api/v1`,覆盖认证、状态、项目、记忆、检查点、密码库、文件、上传任务、Token、客户端配置和系统设置。 - MCP 项目与记忆工具:`capabilities_get`、`project_create/update/archive/delete/resolve/resolve_or_create/list/export_prepare`、`context_get`、`memory_list/search/get/save/mark_pending/archive/delete`、`checkpoint_get/save/delete`。 - MCP 密码库工具:`secret_capabilities`、`secret_list`、`secret_item_get`、`secret_search`、`secret_resolve`、`secret_get`、`secret_totp`、`secret_save`、`secret_delete`。 - MCP 文件工具:`file_search/list/get`、`file_directory_create`、`file_upload_prepare/status`、`file_metadata_update`、`file_move`、`file_delete`、`file_scan`。 - MCP 整理工具:`curation_run/status/history/source_submit/cancel/retry`、`curated_document_list/get/update/history/diff/revert`、`curation_settings_get/update`、`curation_schedule_list/save/delete/reset_defaults/preview`、`curation_model_connection_status/save/test`、`curation_model_list`、`usage_profile_list/save/token_bind/delete`。 - MCP 记忆 Git 工具:`git_connection_get/save/test/delete`、`git_mode_migration_preview/execute`、`memory_repository_list/create/status/sync/history/diff`、`memory_version_get/restore`、`memory_snapshot_restore`、`memory_repository_remote_inspect`、`memory_remote_import/bootstrap`、`memory_repository_unbind/archive_purge`。历史查询支持时间、提交者、操作类型、工作区和资源 ID 筛选。 - MCP 系统工具:`dashboard_get`、`system_settings_get/update`、`token_list/create/reveal/revoke/delete`。 - MCP Resources:`memrelay://guide`、`memrelay://capabilities`、`memrelay://projects`。 - 读取和状态查询允许一次受控重试;写入不自动重试;超时、取消、冲突、候选歧义和依赖不可用返回稳定错误码。 ## 测试与验收 - pytest 覆盖权限、加密、项目归一、revision、幂等、自动记忆、密码库映射与条目 CRUD、签名 URL、扫描和错误映射。 - 使用真实 Basic Memory 和测试 Vaultwarden 进行集成测试,覆盖在线、断网、重启、离线缓存与索引重建。 - 使用固定中英文检索样本验证多语言语义搜索,并断言运行期间没有外部嵌入 API 请求。 - Vitest 覆盖状态、表单、国际化和组件;Playwright 覆盖桌面端完整工作流。 - 验证 MCP 完整文件管理、一次性 PUT、Range 下载、15 分钟扫描、目录表实时更新和说明/版本搜索。 - 验证 HTTP、反向代理 HTTPS、Windows Docker Desktop、Linux Docker、`linux/amd64`、`linux/arm64`、目录权限、迁移失败和完整备份恢复。 - 每个阶段完成后清理临时内容、更新 `aidocs/project_context.md`、检查 `.gitignore` 并提交独立中文 Git commit。 ## 已锁定默认值 - 单实例、单管理员、单共享工作区、单外部密码库连接。 - Element Plus、Vue I18n、AGPL-3.0-only。 - Basic Memory 以 Git 子模块固定在 `third_party/basic-memory`。 - Obsidian 只读兼容,不承诺外部 Markdown 编辑同步。 - 本地多语言 MiniLM 默认启用并预置镜像,不使用付费嵌入服务。 - 明确记忆自动保存;已有唯一凭证无感使用。 - 新获得或生成的可复用凭证由读写 MCP 客户端自动保存到外部密码库;唯一匹配条目直接更新,避免重复创建。 - 文件扫描默认 15 分钟;文件版本仅为元数据。 - MCP 完整管理文件,但上传只生成 HTTP PUT 地址。 - 密码库离线时允许使用最后同步缓存。 - 完整备份由手动短暂停机脚本触发。 - Windows 通过 Docker Desktop Linux 容器部署;Linux 通过原生 Docker/Compose 部署。 - 正式构建和测试 `linux/amd64`、`linux/arm64` 镜像,不针对 ARMv7 等缺少上游依赖的架构开发替代实现。