{"id":51302345,"url":"https://github.com/killop/ai-harness","last_synced_at":"2026-06-30T21:01:57.691Z","repository":{"id":352536815,"uuid":"1213389047","full_name":"killop/ai-harness","owner":"killop","description":null,"archived":false,"fork":false,"pushed_at":"2026-04-20T02:36:26.000Z","size":1284,"stargazers_count":18,"open_issues_count":0,"forks_count":3,"subscribers_count":0,"default_branch":"main","last_synced_at":"2026-04-20T04:41:38.403Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Python","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/killop.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null,"notice":null,"maintainers":null,"copyright":null,"agents":null,"dco":null,"cla":null}},"created_at":"2026-04-17T10:26:17.000Z","updated_at":"2026-04-20T02:56:42.000Z","dependencies_parsed_at":null,"dependency_job_id":null,"html_url":"https://github.com/killop/ai-harness","commit_stats":null,"previous_names":["killop/ai-harness"],"tags_count":null,"template":false,"template_full_name":null,"purl":"pkg:github/killop/ai-harness","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/killop%2Fai-harness","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/killop%2Fai-harness/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/killop%2Fai-harness/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/killop%2Fai-harness/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/killop","download_url":"https://codeload.github.com/killop/ai-harness/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/killop%2Fai-harness/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":34983171,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-26T15:22:16.424Z","status":"online","status_checked_at":"2026-06-30T02:00:05.919Z","response_time":92,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":[],"created_at":"2026-06-30T21:01:55.766Z","updated_at":"2026-06-30T21:01:57.678Z","avatar_url":"https://github.com/killop.png","language":"Python","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Harness Workspace\n\n`harness-workspace/` 是这个项目的本地记忆工作区。\n\n它不是游戏运行时代码，也不是共享数据库，而是一套围绕 `MemPalace` 搭起来的“知识缓存 -\u003e 本地 palace -\u003e MCP 查询”产品化壳层。\n\n它的目标很直接：\n\n- 让团队把项目知识沉淀成 Markdown，而不是散落在对话、脑子和聊天记录里\n- 让每个人都能从同一份共享知识源生成自己的本地 palace\n- 让 MCP 在不打断正在使用的情况下，安全刷新到新版本\n- 让刷新尽量增量化，而不是每次全量重建\n\n---\n\n## 0. Windows 用户先看这里\n\n如果你是人在 Windows 上手工执行，这个 README 最重要的就是下面这几条。\n\n绝大多数人平时只需要认这 4 个入口：\n\n```powershell\n第一次安装：\npython .\\tools\\mempalace_tools.py setup\n.\\tools\\mempalace-install-agent-mcp.bat --agent codex\n\n平时开 daemon：\n.\\tools\\mempalace-daemon.bat\n\n需要强制全量重建：\n.\\tools\\mempalace-rebuild.bat\n\n需要手工停 daemon：\n.\\mempalace-github-code\\.venv\\Scripts\\python.exe .\\tools\\mempalace_tools.py daemon-stop\n```\n\n直接理解成：\n\n- `setup`：新机器第一次安装时执行一次\n- `mempalace-install-agent-mcp.bat`：把本地 agent 接到当前项目\n- `mempalace-daemon.bat`：平时就开这个，持续监听知识目录\n- `mempalace-rebuild.bat`：只有你明确要强制全量重建时才跑\n\n注意：\n\n- 如果你用 Claude Code，把 `--agent codex` 改成 `--agent claude-code`\n- 日常优先用 `.bat`，不要自己手敲长 Python 命令\n- 刚 `rebuild` 完再开 `daemon`，现在不会再无意义地重刷一遍\n\n## 0.1 阅读地图\n\n这份 README 同时写给两类读者：\n\n- 人手工操作时看：`0`、`10`、`11`、`14`\n- AI / 维护者 / 想理解设计时看：`1` 到 `9`、`12` 到 `16`\n\n如果你现在只是想“把这套东西跑起来”，不要从第 `1` 节开始读。\n\n### 0.2 macOS / Linux 人工执行速查\n\n```bash\n首次安装：\nbash ./tools/mempalace-setup.sh\nbash ./tools/mempalace-install-agent-mcp.sh --agent codex\n\n日常全量重建：\nbash ./tools/mempalace-rebuild.sh\n\n日常常驻监听：\nbash ./tools/mempalace-daemon.sh\n\n手工停止 daemon：\n./mempalace-github-code/.venv/bin/python3 ./tools/mempalace_tools.py daemon-stop\n```\n\n注意：\n\n- macOS / Linux 这里用 `bash ./tools/*.sh`\n- 不要用 `sh ./tools/*.sh`\n- `daemon-stop`、`daemon-status`、`daemon-restart` 这类高级控制目前还是直接走 Python CLI\n\n### 0.3 人工执行时怎么选脚本\n\n- `setup`：新机器第一次安装时执行一次\n- `mempalace-install-agent-mcp`：把本地 agent 接到当前项目的 MemPalace\n- `mempalace-rebuild`：立刻做一次全量重建\n- `mempalace-daemon`：前台跑 daemon，持续监听知识目录\n- `daemon-stop`：手工停掉后台或前台 daemon\n- macOS / Linux 对应的是同名 `.sh`，用法统一写成 `bash ./tools/\u003cname\u003e.sh`\n\n---\n\n下面从 `1` 开始，主要是设计和实现说明，偏 AI / 维护者阅读。\n\n## 1. 给 AI / 维护者看的产品定位\n\n这套东西的定位不是“文档仓库”，也不是“直接共享数据库”。\n\n它更接近一个本地知识索引产品，分成两层：\n\n- 共享层：团队维护 `knowledges-cache/` 里的 Markdown\n- 本地层：每个人在自己的机器上生成 `.mempalace_local/palace/`\n\n也就是说：\n\n- 团队共享的是“知识源文件”\n- 每个人本地拥有的是“索引产物”\n\n这样做的原因是：\n\n- 数据库文件不适合多人共享提交\n- 本地 palace 可以按个人机器环境独立运行\n- 本地 MCP 可以直接连本地 palace，查询快，风险低\n- 刷新、回滚、切版本都可以只在本地完成\n\n### 1.1 这个产品解决什么问题\n\n- 项目知识分散，靠口口相传\n- AI 工具每次都要重新读代码和文档，成本高\n- 文档更新后，查询系统不能安全热切换\n- Windows-only 的脚本体系太重，不利于跨平台运行\n\n### 1.2 这个产品不做什么\n\n- 不把 `.mempalace_local/` 当成团队共享产物\n- 不直接改游戏运行时代码\n- 不把所有外部目录做复杂同步编排\n- 不试图做“中心化远程 palace 服务”\n\n---\n\n## 2. 产品总览\n\n从产品视角看，可以把它理解成 4 个部件：\n\n```text\n+----------------------+      +----------------------+      +----------------------+\n| Shared Knowledge     |      | Local Build Layer    |      | Query Layer          |\n| Source               |      |                      |      |                      |\n| knowledges-cache/    +-----\u003e+ mempalace_tools.py   +-----\u003e+ MCP / tools / agent  |\n| Markdown + config    |      | refresh / daemon     |      | query active palace  |\n+----------------------+      +----------------------+      +----------------------+\n                                         |\n                                         v\n                              +----------------------+\n                              | Local Palace         |\n                              | .mempalace_local/    |\n                              | versions + current   |\n                              +----------------------+\n```\n\n你可以把它记成一句话：\n\n```text\nMarkdown 是事实源\nPalace 是本地索引\nMCP 只读当前 active palace\nrefresh/daemon 负责把源变成新版本\n```\n\n---\n\n## 3. 目录结构\n\n```text\nharness-workspace/\n|-- .mempalace_local/          # 本地运行产物，不提交\n|   |-- palace/\n|   |   |-- current.json       # 当前 active 版本指针\n|   |   |-- versions/          # 蓝绿版本目录\n|   |   `-- ...                # chroma/sqlite/index 数据\n|   `-- refresh-daemon/        # daemon 锁、日志、状态\n|\n|-- knowledges-cache/          # 团队共享知识源\n|   |-- \u003cwing\u003e/\n|   |   |-- mempalace.yaml     # wing 配置\n|   |   |-- manual/            # 手写知识\n|   |   `-- generated/         # 脚本生成知识\n|   `-- README.md\n|\n|-- mempalace-github-code/     # MemPalace 源码副本\n|\n|-- tools/\n|   `-- mempalace_tools.py     # 跨平台统一入口\n|\n`-- README.md\n```\n\n---\n\n## 4. 核心概念\n\n### 4.1 Wing\n\n`wing` 是知识分区，不是物理数据库。\n\n一个 wing 通常代表一个知识域，例如：\n\n- `game_client`\n- `game_server`\n- `game_design`\n- `game_shared`\n\n每个 wing 目录下都有一个 `mempalace.yaml`，用于定义：\n\n- wing 名称\n- room 划分\n- 关键词路由\n\n### 4.2 Manual 和 Generated\n\n- `manual/`：人手维护，优先放长期稳定、需要表达判断的知识\n- `generated/`：脚本提炼出来的知识，适合大量同步型内容\n\n这两类内容都会被挖掘进 palace，但维护方式不同。\n\n### 4.3 Palace\n\n`palace` 是本地索引库，不是共享源。\n\n它里面保存的是：\n\n- drawer / closet 等检索数据\n- chroma / sqlite 等底层索引\n- 当前 active 版本指针\n\n所以 palace 的本质是“可再生缓存”。\n\n### 4.4 Active Version\n\n`current.json` 指向当前激活版本。\n\nMCP 不直接绑定某个固定版本目录，而是读取：\n\n```text\n.mempalace_local/palace/current.json\n```\n\n然后跳到：\n\n```text\n.mempalace_local/palace/versions/\u003ctimestamp\u003e\n```\n\n这就是蓝绿切换的基础。\n\n---\n\n## 5. 设计原则\n\n### 5.1 共享源和本地产物分离\n\n```text\nteam edits markdown\n        |\n        v\nknowledges-cache/     \u003c- shared, versioned, reviewable\n        |\n        v\n.mempalace_local/     \u003c- local, generated, disposable\n```\n\n这样可以让团队真正 review 的是知识本身，而不是二进制索引文件。\n\n### 5.2 统一入口，全面 Python 化\n\n这套工具只保留一个主入口：\n\n```text\ntools/mempalace_tools.py\n```\n\n所有常用动作都从这里进：\n\n- `setup`\n- `install-agent-mcp`\n- `refresh`\n- `rebuild`\n- `start-mcp`\n- `daemon`\n\n这样做的好处：\n\n- 跨平台\n- 文件少\n- 行为集中\n- 文档和命令一致\n\n### 5.3 蓝绿切换，而不是原地覆盖\n\n如果 MCP 正在使用 palace，直接原地刷新有几个风险：\n\n- 刷到一半被查询\n- 文件锁冲突\n- 索引状态不一致\n- 刷新失败后没有回退点\n\n所以这里采用蓝绿模型：\n\n```text\nactive version A\n      |\n      | build new version\n      v\ncandidate version B\n      |\n      | success\n      v\ncurrent.json -\u003e B\n```\n\nMCP 永远只读 active 版本，不读构建中的半成品。\n\n### 5.4 增量优先，不无脑全量\n\n最开始的蓝绿实现虽然安全，但每次都新建空版本，再全量 mine 所有 wing。\n\n问题是：\n\n- `file_already_mined` 的缓存只在“当前 palace 数据库”里有效\n- 新版本如果是空的，就等于所有文件都第一次挖\n\n现在改成了真正增量：\n\n```text\nold active palace\n      |\n      +--\u003e copy to new version\n               |\n               +--\u003e purge deleted files\n               +--\u003e reset changed-config wings\n               +--\u003e re-mine changed wings only\n               |\n               +--\u003e current.json cutover\n```\n\n这样就同时满足：\n\n- 查询安全\n- 刷新可回退\n- 未改的文件可以直接命中已有索引\n\n---\n\n## 6. 产品架构\n\n### 6.1 逻辑架构图\n\n```text\n                         +----------------------+\n                         | User / Agent         |\n                         | asks memory question |\n                         +----------+-----------+\n                                    |\n                                    v\n                         +----------------------+\n                         | MCP Server           |\n                         | start-mcp            |\n                         +----------+-----------+\n                                    |\n                                    v\n                         +----------------------+\n                         | current.json         |\n                         | resolve active path  |\n                         +----------+-----------+\n                                    |\n                                    v\n                         +----------------------+\n                         | active palace        |\n                         | versions/\u003cts\u003e        |\n                         +----------------------+\n\n\nShared knowledge update path:\n\n+----------------------+      +----------------------+      +----------------------+\n| knowledges-cache/    | ---\u003e | mempalace_tools.py   | ---\u003e | new palace version   |\n| markdown + yaml      |      | refresh / daemon     |      | candidate build      |\n+----------------------+      +----------------------+      +----------------------+\n                                                                      |\n                                                                      v\n                                                           +----------------------+\n                                                           | current.json cutover |\n                                                           +----------------------+\n```\n\n### 6.2 启动和查询关系\n\n```text\n\u003crepo .venv python\u003e tools/mempalace_tools.py start-mcp\n                |\n                v\n      mempalace.mcp_server --palace \u003clogical root\u003e\n                |\n                v\n      read current.json\n                |\n                v\n      attach active version\n                |\n                v\n      serve queries\n```\n\n### 6.3 刷新关系\n\n```text\nrefresh\n  |\n  +-- if unmanaged path:\n  |      mine directly into target palace\n  |\n  `-- if managed root:\n         run blue-green refresh\n             |\n             +-- compare source snapshot\n             +-- if no change -\u003e no-op\n             +-- else build candidate version\n             +-- cutover current.json\n```\n\n---\n\n## 7. 刷新设计\n\n### 7.1 为什么需要 daemon\n\n`refresh` 适合手动触发。\n\n`daemon` 适合常驻监听 `knowledges-cache/`，在文件变化后自动刷新。\n\n它的职责非常克制：\n\n- 只看 `knowledges-cache/*`\n- 只做快照对比\n- 只做去抖和触发刷新\n- 不负责复杂跨目录同步编排\n\n### 7.2 Daemon 工作方式\n\n```text\nloop every N seconds\n    |\n    +-- scan knowledges-cache snapshot\n    |\n    +-- diff with previous snapshot\n    |\n    +-- if changed:\n    |      record pending changes\n    |      reset debounce timer\n    |\n    `-- if debounce elapsed:\n           run blue-green incremental refresh\n```\n\n### 7.3 蓝绿增量刷新流程\n\n```text\n1. read active palace\n2. load previous source_snapshot.json\n3. scan current knowledges-cache\n4. compute changed files / changed wings\n5. if nothing changed:\n      keep current active version\n6. else:\n      copy active palace -\u003e candidate version\n      purge deleted files\n      reset wings whose mempalace.yaml changed\n      re-mine changed wings only\n      write candidate source_snapshot.json\n      update current.json\n      prune old versions\n```\n\n### 7.4 哪些情况会触发什么行为\n\n| 变化类型 | 行为 |\n| --- | --- |\n| 某个 Markdown 改了 | 只重挖所属 wing |\n| 某个 Markdown 删除了 | 先 purge 旧 drawer，再重挖该 wing |\n| `mempalace.yaml` 改了 | 整个 wing reset，再全量重挖该 wing |\n| 没有变化 | 直接 no-op |\n| 第一次没有快照 | 做一次 full refresh 建基线 |\n\n### 7.5 为什么现在 refresh 会很快\n\n如果日志出现：\n\n```text\nNo knowledge changes detected. Keeping current active palace.\n```\n\n说明：\n\n- 当前知识源和上次快照一致\n- 没有进入真实 mine\n- 也没有新建候选版本\n\n这是预期行为，不是异常。\n\n---\n\n## 8. 数据流\n\n### 8.1 从知识源到可查询记忆\n\n```text\nauthor writes markdown\n        |\n        v\nknowledges-cache/\u003cwing\u003e/\n        |\n        v\nmempalace_tools.py refresh / daemon\n        |\n        v\nMemPalace mine\n        |\n        v\npalace versions/\u003ctimestamp\u003e\n        |\n        v\ncurrent.json points to active version\n        |\n        v\nMCP query reads active version\n```\n\n### 8.2 团队协作模型\n\n```text\n                +----------------------+\n                | Git repository       |\n                | knowledges-cache/    |\n                +----------+-----------+\n                           |\n        +------------------+------------------+\n        |                                     |\n        v                                     v\n+----------------------+           +----------------------+\n| Developer A          |           | Developer B          |\n| local palace A       |           | local palace B       |\n| .mempalace_local/    |           | .mempalace_local/    |\n+----------------------+           +----------------------+\n        |                                     |\n        v                                     v\n   local MCP A                           local MCP B\n```\n\n重点是：\n\n- 大家共享同一份知识源\n- 但每个人都构建自己的本地索引\n\n---\n\n## 9. 核心目录说明\n\n### 9.1 `.mempalace_local/palace/`\n\n- 本地生成的 palace 数据目录\n- `current.json` 指向 active version\n- `versions/` 保存历史版本\n- candidate version 构建期间会写 `.build-state.json`\n- `source_snapshot.json` 记录上次构建对应的源文件快照\n- 这是运行产物，不是人工编辑区\n\n### 9.2 `.mempalace_local/refresh-daemon/`\n\n- `daemon.lock`：防止同一工作区启动多个 daemon\n- `daemon.log`：守护进程日志\n- `state.json`：当前快照状态、pending 数量、最近刷新状态\n- `stop-request.json`：优雅停止请求文件，`daemon-stop` 会先写它\n\n### 9.3 `knowledges-cache/`\n\n- 这是团队共享事实源\n- 每个 wing 是一个知识域\n- `mempalace.yaml` 决定这个 wing 怎么被 mine\n- `manual/` 适合手工沉淀知识\n- `generated/` 适合脚本生成知识\n\n### 9.4 `mempalace-github-code/`\n\n- MemPalace 源码副本\n- `setup` 会在这里创建 `.venv`\n- `setup` 之后，其余命令默认都应该走这里的 `.venv` Python\n- `start-mcp` 和 `refresh` 最终都依赖这里的 Python 环境和 CLI\n\n### 9.5 `tools/mempalace_tools.py`\n\n这是整个产品的控制台入口。\n\n你可以把它理解成：\n\n```text\noperator shell\n      |\n      v\nmempalace_tools.py\n      |\n      +-- setup\n      +-- install-agent-mcp\n      +-- refresh\n      +-- rebuild\n      +-- start-mcp\n      `-- daemon\n```\n\n---\n\n## 10. 给人看的常用命令（详细版）\n\n在 `harness-workspace/` 目录下执行。\n\n约定：\n\n- 首次在新机器 bootstrap 时，用系统 Python 跑一次 `setup`\n- `setup` 成功后，后续命令统一走 `mempalace-github-code/.venv` 里的 Python\n\n如果你是人在手工执行，先记住这一条：\n\n- Windows 优先用 `.bat`\n- macOS / Linux 优先用 `bash ./tools/*.sh`\n- 除非排障，不需要自己拼 `mempalace_tools.py` 参数\n- 顶部 `0` 节是最短路径，这一节是详细版\n\nWindows 推荐优先用这些批处理入口：\n\n- 安装本地 Agent MCP：`.\\tools\\mempalace-install-agent-mcp.bat`\n- 全量重建：`.\\tools\\mempalace-rebuild.bat`\n- 常驻 daemon：`.\\tools\\mempalace-daemon.bat`\n\n最常见的人手工操作可以直接记成：\n\n```text\n第一次安装 -\u003e setup\n接入本地 agent -\u003e mempalace-install-agent-mcp.bat\n强制重建一次 -\u003e mempalace-rebuild.bat\n持续监听刷新 -\u003e mempalace-daemon.bat\n```\n\n### 10.1 安装和初始化\n\nmacOS / Linux:\n\n```bash\nbash ./tools/mempalace-setup.sh\n```\n\nWindows:\n\n```powershell\npython .\\tools\\mempalace_tools.py setup\n```\n\n说明：\n\n- 这里只是第一次创建 `.venv`\n- 后续 `refresh`、`daemon`、`start-mcp`、`rebuild` 都优先用 repo 内 `.venv` Python\n\n作用：\n\n- 创建专用虚拟环境\n- 安装 MemPalace 依赖\n- 校验 MCP 依赖能否正常导入\n\n### 10.2 安装本地 Agent MCP\n\n这个命令现在支持两个本地 target：\n\n- `codex`：写当前项目根目录的 `.codex/config.toml`\n- `claude-code`：调用 `claude mcp add -s local`，写 Claude Code 的本地项目作用域配置\n\nmacOS / Linux:\n\n```bash\nbash ./tools/mempalace-install-agent-mcp.sh\n```\n\nWindows:\n\n```powershell\n.\\tools\\mempalace-install-agent-mcp.bat\n```\n\n作用：\n\n- 如果没传 `--agent`，会在终端里让你选择 `codex` 或 `claude-code`\n- `--agent codex` 时，会自动创建或更新当前项目的 `.codex/config.toml`\n- `--agent claude-code` 时，会调用本机 `claude` CLI 安装到 Claude Code 本地项目配置\n- `codex` 安装模式下，只会定点写入 `mcp_servers.mempalace`，不会重写无关 section\n- Windows 下日常推荐直接用 `.\\tools\\mempalace-install-agent-mcp.bat --agent codex` 或 `.\\tools\\mempalace-install-agent-mcp.bat --agent claude-code`\n\n### 10.3 手动刷新\n\nmacOS / Linux:\n\n```bash\nbash ./tools/mempalace-refresh.sh\n```\n\nWindows:\n\n```powershell\n.\\mempalace-github-code\\.venv\\Scripts\\python.exe .\\tools\\mempalace_tools.py refresh\n```\n\n作用：\n\n- 如果是 managed root，就走蓝绿增量刷新\n- 如果没有变化，会直接 no-op\n\n### 10.4 全量重建\n\nmacOS / Linux:\n\n```bash\nbash ./tools/mempalace-rebuild.sh\n```\n\nWindows:\n\n```powershell\n.\\tools\\mempalace-rebuild.bat\n```\n\n适合：\n\n- 你要强制做一次全量重建\n- 默认 managed root 上会走蓝绿全量重建\n- 需要验证从零开始的构建链路\n- Windows 下日常推荐直接用 `.\\tools\\mempalace-rebuild.bat`\n\n不适合：\n\n- 日常在线刷新\n\n### 10.5 启动 MCP\n\nmacOS / Linux:\n\n```bash\nbash ./tools/mempalace-start-mcp.sh\n```\n\nWindows:\n\n```powershell\n.\\mempalace-github-code\\.venv\\Scripts\\python.exe .\\tools\\mempalace_tools.py start-mcp\n```\n\n作用：\n\n- 启动本地 MemPalace MCP server\n- 让查询跟随 `current.json` 指向的 active version\n\n### 10.6 启动守护进程\n\nmacOS / Linux:\n\n```bash\nbash ./tools/mempalace-daemon.sh\n```\n\nWindows:\n\n```powershell\n.\\tools\\mempalace-daemon.bat\n```\n\n说明：\n\n- `daemon-run` 会先安全停掉旧 daemon，再在当前终端里直接跑前台 daemon\n- `mempalace-daemon.bat` / `mempalace-daemon.sh` 现在默认执行 `daemon-run`\n- 前台模式下，你会一直看到日志；按 `Ctrl+C` 就会关闭 daemon\n- `daemon-start` 会把 daemon 脱离当前终端，后台常驻\n- 如果 active palace 的 `source_snapshot` 已经和当前知识源一致，daemon 启动时不会再额外跑一轮 refresh；刚执行完 `rebuild` 再起 daemon，会直接进入监听态\n- `daemon-stop` 默认先请求优雅停止，等当前 refresh 收尾；超时后才会 force kill\n- 关闭当前 Codex / Claude Code / 终端后，后台 daemon 仍然继续轮询\n- 如果你就是想看前台实时输出，才直接用 `daemon`\n- `daemon-restart` 默认先等当前 refresh 空闲，再重启；只有传 `--force` 才会中断正在进行的 refresh\n- Windows 下日常推荐直接用 `.\\tools\\mempalace-daemon.bat`\n\n常用参数：\n\nmacOS / Linux:\n\n```bash\nbash ./tools/mempalace-daemon.sh --debounce-seconds 3 --keep-versions 3\n```\n\nWindows:\n\n```powershell\n.\\mempalace-github-code\\.venv\\Scripts\\python.exe .\\tools\\mempalace_tools.py daemon-start --debounce-seconds 3 --keep-versions 3\n```\n\n### 10.7 只跑一次守护刷新\n\nmacOS / Linux:\n\n```bash\n./mempalace-github-code/.venv/bin/python3 ./tools/mempalace_tools.py daemon --run-once\n```\n\nWindows:\n\n```powershell\n.\\mempalace-github-code\\.venv\\Scripts\\python.exe .\\tools\\mempalace_tools.py daemon --run-once\n```\n\n适合：\n\n- 手动验证刷新链路\n- CI 或临时操作\n- 不想常驻 daemon\n\n### 10.8 查看或关闭守护进程\n\nmacOS / Linux:\n\n```bash\n./mempalace-github-code/.venv/bin/python3 ./tools/mempalace_tools.py daemon-status\n./mempalace-github-code/.venv/bin/python3 ./tools/mempalace_tools.py daemon-stop\n./mempalace-github-code/.venv/bin/python3 ./tools/mempalace_tools.py daemon-restart\n```\n\nWindows:\n\n```powershell\n.\\mempalace-github-code\\.venv\\Scripts\\python.exe .\\tools\\mempalace_tools.py daemon-run\n.\\mempalace-github-code\\.venv\\Scripts\\python.exe .\\tools\\mempalace_tools.py daemon-status\n.\\mempalace-github-code\\.venv\\Scripts\\python.exe .\\tools\\mempalace_tools.py daemon-stop\n.\\mempalace-github-code\\.venv\\Scripts\\python.exe .\\tools\\mempalace_tools.py daemon-restart\n```\n\n---\n\n## 11. 给人看的推荐使用方式\n\n### 11.1 新机器首次接入\n\n```text\ngit pull\n   |\n   v\nbash ./tools/mempalace-setup.sh\n   |\n   v\nbash ./tools/mempalace-install-agent-mcp.sh --agent codex\n   |\n   v\nrepo .venv python -\u003e mempalace_tools.py daemon --run-once\n    |\n    v\nbash ./tools/mempalace-start-mcp.sh\n```\n\n对应命令：\n\n- Windows `setup`：`python .\\tools\\mempalace_tools.py setup`\n- Windows 安装本地 Codex MCP：`.\\tools\\mempalace-install-agent-mcp.bat --agent codex`\n- Windows 安装本地 Claude Code MCP：`.\\tools\\mempalace-install-agent-mcp.bat --agent claude-code`\n- Windows 启动常驻 daemon：`.\\tools\\mempalace-daemon.bat`\n- Windows 全量重建：`.\\tools\\mempalace-rebuild.bat`\n- Windows 其他高级命令：`.\\mempalace-github-code\\.venv\\Scripts\\python.exe .\\tools\\mempalace_tools.py \u003ccommand\u003e`\n- macOS / Linux `setup`：`bash ./tools/mempalace-setup.sh`\n- macOS / Linux 安装本地 Codex MCP：`bash ./tools/mempalace-install-agent-mcp.sh --agent codex`\n- macOS / Linux 安装本地 Claude Code MCP：`bash ./tools/mempalace-install-agent-mcp.sh --agent claude-code`\n- macOS / Linux 启动常驻 daemon：`bash ./tools/mempalace-daemon.sh`\n- macOS / Linux 全量重建：`bash ./tools/mempalace-rebuild.sh`\n- macOS / Linux 启动 MCP：`bash ./tools/mempalace-start-mcp.sh`\n- macOS / Linux 其他高级命令：`./mempalace-github-code/.venv/bin/python3 ./tools/mempalace_tools.py \u003ccommand\u003e`\n\n### 11.2 日常写知识\n\n```text\nedit markdown under knowledges-cache/\n        |\n        v\nrun refresh or let daemon detect it\n        |\n        v\nquery through MCP\n```\n\n### 11.3 推荐工作流\n\n#### 模式 A：手动模式\n\n适合低频更新。\n\n```text\n改文档 -\u003e refresh -\u003e 查询\n```\n\n#### 模式 B：守护模式\n\n适合你持续维护知识源。\n\n```text\n开 daemon-run 占住当前终端\n    |\n    +-- 改文档\n    +-- 等去抖\n    `-- 自动刷新\n```\n\n---\n\n## 12. 典型场景\n\n### 12.1 项目知识沉淀\n\n把一次需求理解、方案总结、排错经验放进 `manual/`，让后续 agent 和开发都能查询。\n\n### 12.2 自动知识编译\n\n把脚本分析、设计文档提炼、代码结构总结放进 `generated/`，作为可再生知识层。\n\n### 12.3 本地 AI 查询\n\n通过 MCP 直接问：\n\n- 这个系统入口在哪\n- 某个模块依赖谁\n- 某类逻辑通常放在哪\n\n---\n\n## 13. 关键设计取舍\n\n### 13.1 为什么不共享 palace 数据库\n\n因为它不适合做代码评审和多人协作源。\n\n共享数据库的问题：\n\n- 二进制不可读\n- 冲突难处理\n- 不同平台和环境容易不一致\n- 很难看出“知识到底改了什么”\n\n### 13.2 为什么不原地 refresh\n\n因为在线查询时不够安全。\n\n原地刷新意味着：\n\n- 构建中的状态可能被读到\n- 索引中间态可能暴露\n- 出错时难回退\n\n现在是 blue-green：\n\n- 新版本先在 `versions/\u003ctimestamp\u003e/` 里单独构建\n- 只有构建成功才切 `current.json`\n- 如果中途异常或被强杀，active palace 仍然保持旧版本\n- 未完成 candidate 会带 `.build-state.json`，下次 `refresh` / `rebuild` / `daemon` 启动时会自动清理\n\n### 13.3 为什么只监听当前文件夹\n\n因为产品边界需要稳定。\n\n这套工作区现在刻意不做“全仓库复杂同步编排”，而是只对 `knowledges-cache/` 负责。\n\n优点是：\n\n- 行为简单\n- 可解释\n- 变更边界清楚\n- 出问题时容易排查\n\n---\n\n## 14. 给人看的故障排查\n\n### 14.1 `refresh` 没反应\n\n先看你改的是不是：\n\n```text\nharness-workspace/knowledges-cache/\n```\n\n如果你改的是项目别的目录，`refresh` 不会理它。\n\n### 14.2 `refresh` 很快结束\n\n如果日志是：\n\n```text\nNo knowledge changes detected. Keeping current active palace.\n```\n\n说明没有检测到知识源变化，属于正常。\n\n### 14.3 `refresh` 很慢\n\n重点看是不是以下情况：\n\n- 第一次建立基线\n- `mempalace.yaml` 改了，导致整 wing reset\n- `seed copy` 失败，回退成 full refresh\n- 本次真的有大 wing 发生改动\n- 如果报 `UnicodeEncodeError: 'charmap' codec can't encode characters`，通常是 Windows 非 UTF-8 终端在打印装饰分隔线。更新到最新 `tools/mempalace_tools.py` 后，子进程会强制 UTF-8；终端里分隔线可能显示成 `?`，但不会中断 `refresh` / `rebuild`\n\n### 14.4 daemon 启动失败\n\n检查：\n\n- 有没有旧 daemon 还活着\n- `.mempalace_local/refresh-daemon/daemon.lock` 是否残留\n- `.mempalace_local/refresh-daemon/stop-request.json` 是否被异常残留\n- `state.json` 里的 pid 是否还存在\n\n### 14.5 MCP 启动失败\n\n检查：\n\n- 是否先跑过 `setup`\n- `.codex/config.toml` 里的 Python 是否指向 `harness-workspace/mempalace-github-code/.venv`\n- `.codex/config.toml` 里 `mempalace_tools.py` 路径是否有效\n- `mempalace-github-code/.venv` 是否存在\n- 可以直接重新执行一次 `install-agent-mcp --agent codex` 或 `install-agent-mcp --agent claude-code` 修复本地 agent 配置\n\n---\n\n## 15. 维护约定\n\n- 优先更新已有知识文件，不要随意创建 `v2`、`final_final` 一类副本\n- 需要长期维护的人工知识放到各 wing 的 `manual/`\n- 由脚本重新生成的内容放到各 wing 的 `generated/`\n- 不要手改 `.mempalace_local/` 下的数据库和索引文件\n- 不要把本地 `.mempalace_local/` 当成共享源提交\n- 团队共享的事实源应始终是 `knowledges-cache/` 下的 Markdown\n\n---\n\n## 16. 一句话总结\n\n```text\nHarness Workspace = 用共享 Markdown 做事实源，\n在本地生成可蓝绿切换、可增量刷新、可被 MCP 查询的项目记忆工作区。\n```\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkillop%2Fai-harness","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fkillop%2Fai-harness","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fkillop%2Fai-harness/lists"}