我给 codex-windows-bot 加 project id、enabled、deny_paths 和只读检查,把它能看的项目范围收紧。
windows-bot-memory/project-registry
我最早踩过的坑,是把“能读到很多项目”误当成“更懂当前任务”。
实际情况往往相反。一个 Windows 机器上会有课程报告、机器人项目、部署脚本、图像工具、实验数据、公开仓库和私人记忆。它们都在本地,但它们不属于同一个上下文。
如果助手只靠关键词召回,很容易发生串台:把一个项目的部署规则套到另一个项目,把实验报告的参数记忆带进聊天机器人,把云端群机器人当成本地私聊机器人。
所以 codex-windows-bot 里我后来更看重一件很朴素的东西:项目注册表。
注册表不是目录清单
项目注册表看起来只是一个 JSON:
{ "id": "daily-brief", "name": "daily-open-source-brief", "enabled": true, "kind": "daily_brief_generator", "tags": ["daily-brief", "plugins", "rss"], "entry_files": ["AGENTS.md", "README.md"], "markers": ["app", "plugins", "config"]}它首先要定住一个稳定的 project id。后面的项目动作、报告查找、上下文打包和记忆召回,都先按这个 id 选范围。
绝对路径会随着机器状态变化,project id 更适合表达“现在说的是哪个项目”。
enabled 是健康判断的一部分
本地项目会移动、删除、迁移、暂时缺失。
如果 health 检查把所有历史注册目录都当成必须存在,结果会很吵。一个已经暂时不用的旧工具目录缺失,也会让整体健康状态失败。
更合理的做法是:注册表保留这个项目,但把它标成 enabled: false。
这样它仍然被记录在系统里,说明这个项目曾经存在、为什么暂时不可用、以后恢复时该看哪些入口文件;但项目动作不会选它,健康检查也不会因为它的本地根目录缺失而失败。
这点很小,但会影响日常维护。health gate 应该反映当前可用能力,而不是被历史目录拖成常红。
只允许 project id,不允许随便传根目录
本地助手最容易失控的入口,是“给我读一下这个路径”。
一旦 action 接受任意绝对路径,就等于绕过了注册表。模型可以从一个看似合理的路径跳到别的工作区,也可能误读不该进入的目录。
所以项目动作应该长这样:
projects.read_text(project="a1", path="README.md")而不是:
files.read(path="某个绝对路径")项目 id 负责选择工作区,path 只能是相对路径。再往下,本地脚本拒绝 ..、UNC、URL、隐藏敏感目录、依赖缓存、构建成果和注册表里明确 deny 的路径。
这个限制会让助手少一点“灵活性”,但换来的是可预测范围。
deny paths 比事后脱敏更靠前
有些目录不该进入项目动作。
比如云端群机器人项目里,代码和文档可以作为工程上下文,但群聊记忆、私有运行数据、账号状态和本地缓存不该被私聊助手当成普通项目文件读取。
所以注册表里需要 deny_paths。
deny_paths 解决的是读取前的问题。能不读的目录就不要读,能用元数据交代的内容就不要把正文塞进上下文。
项目动作应该默认只读
注册表连接的第一批动作都应该是只读的:
- 列出项目。
- 描述项目。
- 看项目状态。
- 读取注册入口文件。
- 固定字符串搜索。
- 生成 handoff brief。
- 列出允许的检查。
- 跑枚举好的只读检查。
- 查找报告成果元数据。
这里我会把可运行项提前登记好。projects.run_check 不接受任意命令、脚本、URL、cwd 或 args,只能跑静态目录里的检查。
这样注册表只负责项目内的受控动作,不扩展成通用 shell。
记忆召回也要先过项目范围
长期记忆最容易显得“聪明”,也最容易误导。
同一个关键词在不同项目里可能含义完全不同。“发布”可能是 GitHub release,也可能是静态站点部署;“健康检查”可能是机器人 action selftest,也可能是容器探活;“报告”可能是 DOCX,也可能是仿真截图。
所以记忆召回的顺序应该是:
当前 workspace 或 project id-> 任务关键词-> 当前文件和命令证据跨项目命中的记忆只能当背景材料,不能直接当结论。只有用户明确要求迁移、同步或对比时,才把不同项目的规则放在同一个决策里。
这个规则能避免很多隐蔽错误。尤其是多个机器人、多个实验项目、多个公开仓库都在同一块盘上时,路径范围比关键词相似度更可信。
app registry 不等于 project registry
另一个容易混淆的东西是应用注册表。
本地助手可以知道有哪些常用工具:编辑器、浏览器、仿真软件、运行时。不过应用目录不是项目根目录,也不该因为“我知道这个 app”就获得读取 app 安装目录的权限。
项目注册表管理的是工作区,应用注册表管理的是工具元数据。
这两者分开之后,助手可以回答“某个工具是否在运行、是否已登记、是否适合某类任务”,但不会把应用安装目录当成内容来源。
现在我的判断
现在回看,项目注册表真正有用的地方,是每次开工前先圈定工作区:用 id 选项目,用 enabled 处理暂时缺失,用 deny_paths 拦住不该读的目录,再让长期记忆按项目分桶。
这样助手不会因为能访问整块磁盘,就把所有东西都当成当前上下文。
继续读