chore(工程): 优化研发流程规则、松绑本地提交与验证门禁、支持技能自包含
This commit is contained in:
parent
8e228af8fc
commit
03b6d512bf
@ -1,4 +1,4 @@
|
||||
<!-- 导航元信息: {"内容描述": "公共接口、共享零反向依赖、技能无实现、接入不写表等依赖方向硬规则", "使用场景": "新建模块、跨模块调用、写接入层或技能前", "使用要求": "与 tests/架构/test_模块依赖.py 联动;违反先修方向再继续"} -->
|
||||
<!-- 导航元信息: {"内容描述": "公共接口、共享零反向依赖、技能支持自包含、接入不写表等依赖方向硬规则", "使用场景": "新建模块、跨模块调用、写接入层或技能前", "使用要求": "与 tests/架构/test_模块依赖.py 联动;违反先修方向再继续"} -->
|
||||
# 模块依赖规则
|
||||
|
||||
> 权威合同:`docs/系统架构/新版设计/总体架构.md`;机械门禁:`tests/架构/test_模块依赖.py` + `make 检查`。
|
||||
@ -6,7 +6,7 @@
|
||||
1. **业务只经公共接口**:跨模块调用只走目标模块 `接口.py` 暴露的用例及其所需类型;禁止导入其他模块的 `存储.py`、`模型.py` 内部符号,也不得经 `__all__` 公开存储类。绝对/相对导入和别名遵循相同边界,业务模块不反向依赖编排或接入。
|
||||
2. **共享基础零反向依赖**:`src/muse/共享/`、`配置.py`、`资源加载.py` 禁止导入业务模块。`启动.py` 是组合入口,可以选择并绑定具体实现,但不承载业务规则。
|
||||
3. **元数据不写业务值**:S04 元数据只描述、校验和投影结构;业务实例值由拥有它的业务模块写入。
|
||||
4. **技能不携带实现**:`.agent/skills/` 只保留方法与操作说明;禁止在技能目录放可执行脚本或 `sys.path` 注入。
|
||||
4. **技能支持自包含**:`.agent/skills/` 支持项目无关的自包含操作说明与配套辅助工具/脚本;禁止向系统 `sys.path` 注入,禁止反向导入或依赖业务单体内部实现(`src/muse/`)。
|
||||
5. **接入与编排不操作私表**:HTTP/CLI/主会话及编排禁止手写 SQL 或使用数据库游标;由所属模块的公开用例调用内部存储,不将 SQL 搬入新的跨模块捷径。
|
||||
6. **宿主不裁决正式内容**:模型宿主(Pi/直接调用)只产候选与证据;作者确认与正式提交不在宿主层发生。
|
||||
7. **薄入口**:`python -m muse` 与 CLI 分发入口只做参数解析与转交,不创建连接或写业务逻辑。具名适配器可管理已装配连接的事务范围以调用 S04 等事务参与者;连接凭据、用途和构造仍由基础设施统一处理,禁止手写 SQL。
|
||||
|
||||
@ -8,3 +8,4 @@
|
||||
3. **携带基线**:每个提交携带正文、候选、结构和来源版本;旧版本请求必须被拒绝且不改动作者新稿。
|
||||
4. **原子与幂等**:多参与者提交要么全部生效要么全部回滚;相同 `command_id` + 相同请求幂等重放,携带不同请求必须拒绝。
|
||||
5. **失败可见**:提交失败保留作者本地缓冲;服务器回执是已保存的唯一依据,不能用 UI 状态代替。
|
||||
6. **迁移整理与发布一致**:已合入主干并发布的数据库迁移脚本保持不可变与连续递增;在本地特性分支开发阶段,允许并提倡对未发布的迁移进行 `rebase / squash` 整理,合并为一个清晰自洽的迁移文件,避免临时补丁碎片污染历史。
|
||||
|
||||
@ -6,6 +6,7 @@
|
||||
1. **默认离线**:默认测试进程由 macOS sandbox 或 Linux seccomp 禁止外部连接,覆盖收集阶段、数据库驱动及其子进程;防护不可用时失败,不退回无防护执行。显式外部用例使用 `--外部环境` 与环境标记选择。
|
||||
2. **显式外部环境**:需要 PostgreSQL 的用例标记 `数据库` 并使用对应夹具;缺 `MUSE_TEST_DATABASE_URL` 时直接失败,不跳过或回退旧库。普通业务测试默认使用同一会话的共享已迁移测试库(例间清空业务表并重置序列,复用前兑底清一次防上例强杀残留;保留模板与 `tests/支持/数据库底座.py` 种子表登记的系统种子,迁移新增种子表必须同步登记,由生命周期单测机械拦截),不再为每条普通用例执行 `CREATE DATABASE ... TEMPLATE` 克隆与全量销毁;仅当用例自身验证目标为数据库创建、迁移升级、跨版本切换或模板隔离时,才使用独立克隆库。例间清空只清数据不删表,用例自建的探针表(恢复、权限演练等)须自带 `DROP TABLE IF EXISTS` 或使用唯一名。
|
||||
超过三分钟的用例标记 `慢`,默认不进常规数据库验证;浏览器旅程等慢入口走对应显式目标,不另设合成调用资格终态套件。
|
||||
日常快速迭代优先运行秒级离线全量(`make 测试`);涉及数据库时运行受影响模块的局部测试(`make 数据库测试 范围=<路径>`);Plan 交付收尾时运行 `make 验收数据库` 完成全量闭环。
|
||||
实际Pi循环另标记`宿主`,通过`make 宿主测试`显式提供固定Node与Pi包路径;普通数据库测试剔除此标记。宿主验证使用合成提供方,不等于真实模型验证。真实外部模型另标记`真实模型`,通过`make 真实模型测试`显式提供地址与凭据文件;普通数据库测试剔除该标记。
|
||||
3. **用例身份**:完整 `case_id` 与清单中的实际文件、符号及参数行绑定,不靠名称后缀匹配;`pytest --case TC-…` 选择用例,`--case 'TC-…[参数ID]'` 选择参数行。同符号承接多个 ID 时必须分别绑定无交叠参数。未知 ID、目标缺失与冒用均失败;Junit 留存完整 ID 和参数 ID。
|
||||
4. **可判定性**:用例体内必须有 assert/raise/fail/skip/xfail;纯 print 用例被索引检查在执行前拦截。
|
||||
|
||||
@ -1,12 +1,12 @@
|
||||
<!-- 导航元信息: {"内容描述": "计划与提交、子代理交付、模块依赖、测试隔离、正式变更、任务与证据、元数据消费、审校修订、文档与资源生成等长期硬规则", "使用场景": "任务启动、阶段流转、门禁检查与经验沉淀前", "使用要求": "先读目录,再按任务打开具体规则"} -->
|
||||
| 名称 | 相对地址 | 内容描述 | 使用场景 | 使用要求 |
|
||||
|------|----------|----------|----------|----------|
|
||||
| 模块依赖规则 | [模块依赖.md](模块依赖.md) | 公共接口、共享零反向依赖、技能无实现、接入不写表等依赖方向硬规则 | 新建模块、跨模块调用、写接入层或技能前 | 与 tests/架构/test_模块依赖.py 联动;违反先修方向再继续 |
|
||||
| 模块依赖规则 | [模块依赖.md](模块依赖.md) | 公共接口、共享零反向依赖、技能支持自包含、接入不写表等依赖方向硬规则 | 新建模块、跨模块调用、写接入层或技能前 | 与 tests/架构/test_模块依赖.py 联动;违反先修方向再继续 |
|
||||
| 测试隔离规则 | [测试隔离.md](测试隔离.md) | 默认离线、外部环境显式标记、用例身份后缀、空收集不通过的测试硬规则 | 编写或运行任何测试、配置 CI 与验证环境时 | 与 tests/conftest.py 和 make 检查联动;替身必须显式标记 |
|
||||
| 正式变更规则 | [正式变更.md](正式变更.md) | 唯一写入口、作者确认前置、原子幂等与失败可见的提交硬规则 | 实现或评审任何正式内容写入路径时 | 与 S01 合同联动;禁止第二条写路径 |
|
||||
| 任务与证据规则 | [任务与证据.md](任务与证据.md) | 持久化记账、冻结输入、租约、两种用途、未知调用对账与原文保护 | 实现或评审任务运行、模型调用与证据留存时 | 与 S02 合同和任务工具事件合同联动 |
|
||||
| 元数据消费规则 | [元数据消费.md](元数据消费.md) | 模具归元数据、实例归业务、只增不改、投影按用途的硬规则 | 实现或评审结构定义、扩展与投影时 | 与 S04 合同联动;未知字段不静默丢弃 |
|
||||
| 审校与修订规则 | [审校与修订.md](审校与修订.md) | 选区语义、不擅动正文形态、受控修订与派生失败可见 | 实现或评审修订、选段与章后处理时 | 与 B06 和正文结构合同联动 |
|
||||
| 文档与资源生成规则 | [文档与资源生成.md](文档与资源生成.md) | 生成物只由登记输入产生、索引一致、资源带发布身份 | 修改目录索引、登记资源或声明命令时 | 与 工具/维护索引.py 和 工具/构建资源包.py 联动 |
|
||||
| 计划与提交 | [计划与提交.md](计划与提交.md) | 完整任务、能力依赖、并发分工、交付批次、研发相位与分级整体审查 | 制定 plan、委派、集成与决定提交节奏时 | 先定边界和批次;获授权后一任务一提交,L3 批次独立审查,最终验收不省略 |
|
||||
| 计划与提交 | [计划与提交.md](计划与提交.md) | 完整任务、能力依赖、双环交付、敏捷提交、研发相位与分级整体审查 | 制定 plan、委派、集成与决定提交节奏时 | Plan内敏捷小增量快跑,终验全量闭环;本地小步commit,远程与合并需授权 |
|
||||
| 子代理交付格式 | [子代理交付.md](子代理交付.md) | 三要素交付、证据指针、仅阻断级汇报、最小必读 | 派发或承接任何子代理任务时 | 报告 ≤20 行;diff/日志/指纹表只给路径 |
|
||||
|
||||
@ -1,53 +1,55 @@
|
||||
<!-- 导航元信息: {"内容描述": "完整任务、能力依赖、并发分工、交付批次、研发相位与分级整体审查", "使用场景": "制定 plan、委派、集成与决定提交节奏时", "使用要求": "先定边界和批次;获授权后一任务一提交,L3 批次独立审查,最终验收不省略"} -->
|
||||
<!-- 导航元信息: {"内容描述": "完整任务、能力依赖、双环交付、敏捷提交、研发相位与分级整体审查", "使用场景": "制定 plan、委派、集成与决定提交节奏时", "使用要求": "Plan内敏捷小增量快跑,终验全量闭环;本地小步commit,远程与合并需授权"} -->
|
||||
# 计划与提交
|
||||
|
||||
适用于需要制定 plan 的开发任务。本文件定义任务、分工、交付批次、提交与独立审查;执行与验证节奏见[模块依赖](模块依赖.md)。计划和 Skill 均不授予提交、合并、发布或外部调用权限。
|
||||
|
||||
## 任务与交付批次
|
||||
|
||||
- **任务是完整结果**:以可独立验收的能力或结果拆分,包含必要的入口、执行、结果及失败恢复路径;函数、文件或单条旧用例不默认构成一个交付任务。
|
||||
- **双环交付模型**:
|
||||
- **内环(敏捷小增量)**:以可独立验收的能力拆分成敏捷小任务(Task),包含必要入口、执行与失败恢复路径;支持在 Plan 内部快速小步推进、局部验证并通过本地 commit 固化检查点。开发过程中允许根据新发现合理调整后续 Task。
|
||||
- **外环(Plan 终验全量闭环)**:交付批次(Plan)作为集中验收与合并的单位;整个 Plan 声明交付时,必须执行全量自动化验收(全量离线测试与核心集成验证),确保全局无回归破坏。
|
||||
- **开工边界**:每项任务写清做什么、不做什么、交付物、修改边界、前置依赖、维护者、完成标准和验证方式。缺项或关键前提未确认时只阻塞受影响任务,继续其他已授权的独立工作。
|
||||
- **审查单位提前声明**:交付批次是集中验收与独立审查的单位,默认一个 plan 为一批;大型计划可在执行合同中预先划定多批,并明确跨批集成顺序与最终验收。不得临近收尾拆批来规避原验收标准。
|
||||
- **审查单位**:Plan 是集中验收与最终审查的单位;大型计划可在执行合同中预先划定多阶段,并明确跨阶段集成顺序与最终验收。
|
||||
|
||||
## 依赖与分工
|
||||
|
||||
- **按能力衔接**:依赖的是具体输入和已验证能力,不是整个前置包的完成标签;尚未接通真实上游的部分明确留待集成验收,不以替身通过冒充完成。
|
||||
- **独立任务主动并发**:前置满足、输入与修改范围互不影响且有实际收益的任务分工并发实现、验证和交付;共享状态、连续决策和简单任务由主代理处理,不为并发而制造拆分。
|
||||
- **隔离与归属**:各线使用包含所需未提交改动的同一可核验基线,并发写入者使用隔离工作区;共享接口、迁移、装配和生成文件指定唯一维护者。不得擅自提交来制造基线,也不得从缺少当前改动的旧 HEAD 开工;无法安全隔离时说明具体限制,先推进不冲突工作。
|
||||
- **隔离与归属**:各线使用包含所需改动的同一可核验基线,并发写入者使用隔离工作区;共享接口、迁移、装配和生成文件指定唯一维护者。无法安全隔离时说明具体限制,先推进不冲突工作。
|
||||
- **集成有负责人**:委派给出输入、输出、文件边界和完成判据,主代理按依赖顺序承接差异与证据,验证实际消费者和跨任务链路。重测试按环境与预算容量限流,可变数据库、端口和会话相互隔离。
|
||||
|
||||
## 研发相位(判据可判定)
|
||||
|
||||
| 相位 | 进入判据 | 验证义务 |
|
||||
|---|---|---|
|
||||
| 开发期 | 任务尚未通过自身完成标准 | 只跑受影响快速检查或相关文件测试,及时修复失败 |
|
||||
| 开发期 | 任务尚未通过自身完成标准 | 跑受影响快速检查或相关文件测试,及时修复失败;鼓励随时常态化运行全量离线测试(`make 测试`)快速捕捉回归破坏 |
|
||||
| 能力稳定 | 任务自身完成标准全绿(按 L 级证据口径) | 跑相应回归与真实接缝验证;替身与隔离遵守[测试隔离](测试隔离.md) |
|
||||
| 批次稳定 | 批次内全部任务能力稳定 | 集中本批完整门禁与必要真实入口验证,再进入批次审查 |
|
||||
| 批次稳定 / 终验 | 批次内全部任务能力稳定 | 集中本批完整门禁(`make 检查` + 全量测试)与必要真实入口验证,进入最终验收 |
|
||||
|
||||
- 发现影响目标或授权的设计缺口时返回对应决策,不以临时替身掩盖,也不扩大无关任务;已有目标、方案和证据仍有效时直接承接。
|
||||
- **证据复用**:确认代码、合同、输入、环境、配置和工具版本仍适用后复用证据;出现相关变更、证据失效、新失败或未解决疑点时重验对应范围,影响不清时扩大到能覆盖风险的范围。
|
||||
- **验证期冻结源码**:验证会话自持写闸门(`工具/验证锁.py`;`pytest` 会话开始持共享锁,结束比对源码哈希,不一致把退出码置 3 表示本轮作废)。持锁期间不改 `src/`、不跑 `make 生成` 与 `make 格式写入`;写入口用 `--执行` 在独占锁内落盘,检查与写入之间不留窗口。格式化同样算改源码:改过 `src/` 而没有重新生成的轮次一律作废,不采信其结论,也不把作废轮次的失败当成产品缺陷。
|
||||
- **全量必须用户明确授权**:日常循环只跑受影响模块(`make 快检 范围=<受影响路径>`);严禁未经用户明确请求擅自执行 `make 验收数据库` 或全量 `make 数据库测试`(高成本违规操作)。模块纯逻辑/校验/提示词改动,以对应模块的快检与离线测试为完成证据;只有改动了 `src/muse/*/存储.py`、`数据库/迁移/` 或触发器/不可变约束时,才需要在共享测试库上验证对应模块的数据库用例。跨模块全量验证仅在用户明确指令时执行。发现期需要多模块时使用局部路径的 `make 数据库分片 范围=<路径>`。改过 `src/` 就必须在写独占锁内重新生成并重验覆盖范围。
|
||||
- **排版格式化为静默辅助**:格式化(`make 格式写入`)仅作为 AST 等价的代码美化,在保存或提交前静默触发即可,不将其当做“破坏性语义变更”,不因格式化作废有效测试结论。
|
||||
- **测试分层与门禁**:日常快速循环使用秒级 `make 快检 范围=<受影响路径>`;离线全套 `make 测试`(~70秒)鼓励常态全量运行;仅涉及存储/迁移/触发器时跑局部数据库测试(`make 数据库测试 范围=<路径>`)。Plan 终验时运行 `make 验收数据库` 完成全量闭环,移除繁琐的人为环境变量卡点。
|
||||
|
||||
## 验证级别
|
||||
|
||||
| 级别 | 适用范围 | 完成证据 |
|
||||
|---|---|---|
|
||||
| L1 | 文档、注释、索引类改动,且未命中 L3 判据 | 对应机械检查通过,含本批链接、索引或声明核对 |
|
||||
| L2 | 未命中 L3 判据的局部实现 | 相关单元或契约测试通过,以及 `git diff --check` |
|
||||
| L3 | 跨模块、超过 2 个文件、修改超过 100 行、核心逻辑变动、不可逆操作,任一命中 | 本批约定模块门禁(非全量)、与变更直接相关的真实接缝验证,以及独立整体审查;全量数据库验收由用户按需授权,不作为自动前提 |
|
||||
| L1 | 文档、注释、索引类改动 | 对应机械检查通过,含本批链接、索引或声明核对 |
|
||||
| L2 | 常规局部实现与缺陷修复 | 相关单元或契约测试通过,以及 `git diff --check` |
|
||||
| L3 | 核心底层契约破坏(Breaking Changes)、不可逆核心表结构变更、生产数据清洗、鉴权核心逻辑重构 | 约定模块门禁、真实接缝验证,以及独立整体审查 |
|
||||
|
||||
不可逆操作包括数据写入、删除和生产凭据变更。不可逆操作或核心逻辑变动须先评审方案,再对稳定批次审查;其余任务不叠加同一范围的评审。缺对应证据时标记 `needs_verification`,不以手工台账计数代替。纯声明批次按声明、索引和差异验证,不因级别运行无关数据库、模型或恢复演练;外部验证仍需相应授权。
|
||||
不可逆操作包括生产凭据变更、核心数据清洗与破坏性表结构演进。不可逆操作或核心底层重构须先评审方案,再对稳定批次审查;常规功能演进与小步修复不滥用 L3。缺对应证据时标记 `needs_verification`,不以手工台账计数代替。
|
||||
|
||||
## 验证、提交与审查
|
||||
|
||||
- **验证不过不收尾**:任务未通过与自身完成标准相称的验证时,继续实现并重验受影响部分;不以“基本完成”隐去失败或推给无关后续任务。分相位验证判据见上节;完成声称的证据分级与重任务判据见本文件[验证级别](#验证级别)。
|
||||
- **一任务一提交**:获得明确提交授权后,每个完整任务验证通过即单独提交,只包含该任务产物;不把整个 plan 攒成一次大提交。未获授权时保留可审差异并说明未提交,不执行 `git add` 或 `git commit`,也不反复索取同一授权。提交不代表可合并或发布;合并、发布还须满足相应批次审查与集成验收,并另有明确授权。
|
||||
- **整体审查按级触发**:L3 重任务批次(按本文件[验证级别](#验证级别)判定)稳定并通过约定门禁后,起独立只读子代理审查本批全部真实改动,覆盖逻辑完整性、一致性、合理性、可行性,以及任务间链路、垃圾代码和被替代实现残留;通过前不得宣布该批完成。审查基线覆盖本批未提交与已提交改动,不能只看 HEAD 而漏掉工作树。L1/L2 批次以门禁绿加抽查代替,不起独立审查、不重复审查。
|
||||
- **审查不叠加**:不逐小任务、逐提交重复同一批次审查;已有审查覆盖的维度与有效证据直接承接,不因 Skill 名称不同再审一次。必要的高危方案事前评审不取消。发现问题后修复、验证,并对问题与受影响范围重审;影响扩大时同步扩大审查,不能以“一次”为由免除重审。
|
||||
- **整体验收不省略**:多批计划最终核对批次间链路、未覆盖接缝、交付物与恢复条件;已有证据仍适用的部分复用,新增或受影响的集成行为必须验证,不能把各批通过简单相加当作整体验收。
|
||||
- **验证不过不收尾**:任务未通过与自身完成标准相称的验证时,继续实现并重验受影响部分;不以“基本完成”隐去失败或推给无关后续任务。
|
||||
- **本地沙盒自治(Commit early and often)**:在本地特性开发分支上,鼓励小步快跑、频繁提交,把本地 `git commit` 作为进度保存和回滚锚点,无需逐次向人类申请授权;单次提交聚焦于当前小增量产物。
|
||||
- **关键操作授权门禁**:向远程仓库推送(`git push`)、向 `main` 主干分支合并或发起 PR、清理带有未保存改动的工作区前,必须获得用户明确授权。
|
||||
- **审查基于 Git Commit**:代码审查严格基于已提交的 Git Commit 进行,不搞针对未提交工作树的审查;重点审查逻辑完整性、一致性、合理性、可行性,以及任务间链路与被替代实现残留。
|
||||
- **整体验收不省略**:多任务或多批次计划最终必须通过全量验收(包含全量离线测试与核心集成链路),确保全局没有隐性破坏,不能仅凭各小任务局部通过代替整体验收。
|
||||
- **集中收尾**:按批次同步权威记录和索引,清理本次替代内容,框架与创作内容分开审查、分开提交;按已交付能力、具体阻塞和剩余验收项汇报,不以测试或文档数量替代进度。
|
||||
|
||||
## 判定依据
|
||||
|
||||
任务边界和批次范围由计划逐项复核;运行命令、退出码、输入与代码版本构成验证证据;审查记录列明真实差异范围、四维结论和未覆盖项。链接、索引和格式使用现有机械检查;内容是否完整由独立语义审查判断,不以字符串存在性检查冒充流程正确。
|
||||
任务边界和批次范围由计划逐项复核;运行命令、退出码、输入与代码版本构成验证证据;审查记录列明真实差异范围、审查结论和未覆盖项。链接、索引和格式使用现有机械检查;内容是否完整由独立语义审查判断,不以字符串存在性检查冒充流程正确。
|
||||
|
||||
@ -70,12 +70,12 @@ SoT 按主题分域,不做跨主题的全局排序。可执行脚本与书面
|
||||
## 4. 工作协议(硬约束)
|
||||
|
||||
1. **读后动手与渐进发现**:复杂任务先读对应 SoT;涉及角色时读角色合同。技能发现遵守本文件开头的唯一入口,按当前任务展开,不预载无关资料。
|
||||
2. **机械验证优先与完成=验证**:工程统一使用仓内解释器 `.venv`(uv 管理);日常唯一入口为 `make 快检 范围=<受影响路径>`(秒级,开发期);离线全套 `make 测试`(~70秒);仅改动存储/迁移/触发器时跑对应模块的库测试。**全量数据库测试高耗时高耗盘,严禁未经用户明确请求擅自执行**:`make 验收数据库` 与全量 `make 数据库测试` 必须由用户显式触发(需传入 `MUSE_RUN_FULL_DB=1` 确认);浏览器层走 `make 浏览器测试`。日常以模块快检或模块局部数据库测试为完成证据,无证据严禁声称“完成/修复/通过”。
|
||||
2. **机械验证优先与完成=验证**:工程统一使用仓内解释器 `.venv`(uv 管理);日常快速循环使用 `make 快检 范围=<受影响路径>`(秒级,开发期);离线全套 `make 测试`(~70秒,鼓励常态化运行防回归);仅改动存储/迁移/触发器时跑对应模块的局部库测试。Plan 整体收尾前通过 `make 验收数据库` 执行全量闭环验收;浏览器层走 `make 浏览器测试`。无机械验证证据严禁声称“完成/修复/通过”。
|
||||
3. **数据权威与先审后入**:数据库为唯一正式权威,严禁裸连操作;正文、规划与知识抽取默认生成 Shadow 候选,经用户明确确认后方可写入 Canonical 正典事实。
|
||||
4. **模型治理与受控探索**:模型调用遵守[预算管理](src/muse/任务运行/预算管理.py)的固定日界窗口(默认 Asia/Shanghai,每日00/05/10/15/20开始,末窗20至24为4小时)与受控治理链;角色允许模型与策略版本以[角色策略](配置/角色策略.yaml)为准,并遵守[角色合同](.agent/角色/角色合同.md)(写手/规划固定顶级推理模型,裁判使用独立精确白名单);确定性逻辑、门禁与报告组装由脚本完成,严禁调用模型;智能体探索仅限圈定只读工具并留痕。
|
||||
5. **会话交互与汇报纪律**:全程使用简体中文白话,坚决去除 AI 味(直陈事实、动作与后果,禁止清嗓子套话与空转缓冲词);需要用户决策时,必须交代清楚前因后果及各选项对下游的影响。
|
||||
6. **提交授权与整体审查**:严禁未经用户明确授权执行 `git add` 或 `git commit`;按[计划与提交](.agent/rules/计划与提交.md)预先确定交付批次,L3 重任务批次(判据及验证分层见同一规则)门禁通过后由独立只读子代理完成四维整体审查,通过前不得宣布该批完成,L1/L2 批次以门禁绿加抽查代替;不逐笔提交叠加审查,必要的事前方案评审、修复重审和最终集成验收仍保留;框架与创作内容分开审查、分开提交。
|
||||
7. **计划边界与提交节奏**:以可独立验收的完整结果拆任务,明确边界、依赖、维护者与验证方式;前置满足且有收益的独立任务分工并发,依赖任务按已验证能力衔接;验证不过不收尾,获授权后每个完整任务单独提交。具体编排、隔离和批次收尾以[计划与提交](.agent/rules/计划与提交.md)为准。
|
||||
6. **本地沙盒自治与关键授权**:在特性开发分支上,鼓励小步快跑(commit early and often),允许频繁在本地执行 `git commit` 保存进度检查点;仅在向远程仓库 `git push`、向 `main` 主干分支发起合并/PR 或执行破坏性操作前才需向用户明确申请授权。按[计划与提交](.agent/rules/计划与提交.md)推进,Plan 内部敏捷小增量交付,Plan 最终执行全量验收;代码审查基于已提交的 Git Commit 进行;框架与创作内容分开审查、分开提交。
|
||||
7. **计划边界与敏捷节奏**:以可独立验收的能力拆分任务,明确边界、依赖与验证方式;Plan 内部敏捷小增量交付,前置满足且有收益的独立任务分工并发,依赖任务按已验证能力衔接;Plan 终验执行全量闭环验收。具体编排、隔离和批次收尾以[计划与提交](.agent/rules/计划与提交.md)为准。
|
||||
|
||||
---
|
||||
|
||||
|
||||
27
Makefile
27
Makefile
@ -32,18 +32,15 @@ export PYTHONPATH := $(CURDIR)/src:$(CURDIR)/工具
|
||||
@test -n "$$MUSE_AUTHOR_PASSWORD_FILE" -a -f "$$MUSE_AUTHOR_PASSWORD_FILE" || { echo "MUSE_AUTHOR_PASSWORD_FILE 必须是可读的绝对路径" >&2; exit 1; }
|
||||
pnpm --dir web run test:journey $(参数)
|
||||
|
||||
# 格式:静态检查(ruff lint + 格式校验;只覆盖新版测试与工具目录)
|
||||
新测试目录 := $(shell for d in tests/单元 tests/契约 tests/集成 tests/架构 tests/迁移 tests/端到端 tests/真实调用; do [ -d "$$d" ] && printf '%s ' "$$d"; done)
|
||||
新工具目录 := 工具
|
||||
# 格式:静态检查(ruff lint + 格式校验)
|
||||
格式:
|
||||
uv run --no-sync ruff check src $(新测试目录) tests/conftest.py $(新工具目录)
|
||||
uv run --no-sync ruff format --check src $(新测试目录) tests/conftest.py $(新工具目录)
|
||||
uv run --no-sync ruff check src tests 工具
|
||||
uv run --no-sync ruff format --check src tests 工具
|
||||
|
||||
# 格式写入:按项目规则实际格式化;格式化同样改源码,就地重新生成,避免之后整层报身份不符
|
||||
# 每步用 --执行 在独占锁内完成:检查通过后到写入前不再有可被验证会话插入的窗口。
|
||||
# 格式写入:按项目规则实际格式化
|
||||
格式写入:
|
||||
uv run --no-sync python 工具/验证锁.py --执行 uv run --no-sync ruff check --fix src $(新测试目录) tests/conftest.py $(新工具目录)
|
||||
uv run --no-sync python 工具/验证锁.py --执行 uv run --no-sync ruff format src $(新测试目录) tests/conftest.py $(新工具目录)
|
||||
uv run --no-sync ruff check --fix src tests 工具
|
||||
uv run --no-sync ruff format src tests 工具
|
||||
$(MAKE) 生成
|
||||
|
||||
# 类型:pyright 类型检查
|
||||
@ -64,11 +61,9 @@ export PYTHONPATH := $(CURDIR)/src:$(CURDIR)/工具
|
||||
测试:
|
||||
$(仓内解释器) -m pytest -m "not 数据库 and not 网络 and not 真实模型 and not 浏览器 and not 宿主 and not 安装包" $(范围) $(if $(用例),--case $(用例),)
|
||||
|
||||
# 验收数据库:全量高成本门禁,严禁自动执行,必须由用户显式提供 MUSE_RUN_FULL_DB=1。
|
||||
# 先生成、再门禁、最后跑库;排除标记为慢的用例(浏览器旅程等走对应显式目标)。
|
||||
# 验收数据库:全量数据库验收门禁,先生成、再门禁、最后跑库;排除标记为慢的用例(浏览器旅程等走对应显式目标)。
|
||||
验收数据库:
|
||||
@test -n "$$MUSE_TEST_DATABASE_URL" || { echo "缺少 MUSE_TEST_DATABASE_URL(隔离库连接串);拒绝先付生成与门禁成本再失败" >&2; exit 1; }
|
||||
@test "$$MUSE_RUN_FULL_DB" = "1" || { echo "全量数据库验收耗时高且写盘大,必须用户显式授权。请传入 MUSE_RUN_FULL_DB=1 确认执行" >&2; exit 1; }
|
||||
$(MAKE) 生成
|
||||
$(MAKE) 检查
|
||||
$(仓内解释器) -m pytest --外部环境 -m "数据库 and not 慢 and not 宿主 and not 真实模型 and not 浏览器 and not 网络" $(范围)
|
||||
@ -78,13 +73,9 @@ export PYTHONPATH := $(CURDIR)/src:$(CURDIR)/工具
|
||||
$(仓内解释器) 工具/并行数据库测试.py --片数 $(if $(片数),$(片数),3) $(范围)
|
||||
|
||||
# 数据库测试:需要 MUSE_TEST_DATABASE_URL。
|
||||
# 未指定范围时的全量测试必须显式传入 MUSE_RUN_FULL_DB=1;指定范围(如 范围=tests/集成/test_某.py)可直接运行。
|
||||
# 默认排除慢用例、浏览器、网络、宿主、真实模型。
|
||||
数据库测试:
|
||||
@test -n "$$MUSE_TEST_DATABASE_URL" || { echo "缺少 MUSE_TEST_DATABASE_URL(隔离库连接串);拒绝静默跳过" >&2; exit 1; }
|
||||
@if [ -z "$(范围)" ] && [ "$$MUSE_RUN_FULL_DB" != "1" ]; then \
|
||||
echo "未指定范围的全量数据库测试耗时高,必须用户显式授权。请指定范围(如 范围=tests/某文件.py)或传入 MUSE_RUN_FULL_DB=1 确认全量" >&2; exit 1; \
|
||||
fi
|
||||
$(仓内解释器) -m pytest --外部环境 -m "数据库 and not 慢 and not 宿主 and not 真实模型 and not 浏览器 and not 网络" $(范围) $(if $(用例),--case $(用例),)
|
||||
|
||||
# 浏览器测试:需要隔离库与显式浏览器路径;11 个 数据库+浏览器 用例的唯一入口。
|
||||
@ -115,11 +106,11 @@ export PYTHONPATH := $(CURDIR)/src:$(CURDIR)/工具
|
||||
$(if $(filter tests/%,$(范围)),$(仓内解释器) -m pytest -m "not 数据库 and not 网络 and not 真实模型 and not 浏览器 and not 宿主 and not 安装包" $(filter tests/%,$(范围)) $(if $(用例),--case $(用例),),$(if $(范围),:,$(仓内解释器) -m pytest -m "not 数据库 and not 网络 and not 真实模型 and not 浏览器 and not 宿主 and not 安装包" tests/单元 tests/契约 $(if $(用例),--case $(用例),)))
|
||||
|
||||
索引生成:
|
||||
uv run --no-sync python 工具/验证锁.py --执行 uv run --no-sync python 工具/维护索引.py --写入
|
||||
uv run --no-sync python 工具/维护索引.py --写入
|
||||
|
||||
# 聚合入口按内容哈希增量执行;wheel必须与同次资源输入绑定。
|
||||
生成:
|
||||
uv run --no-sync python 工具/验证锁.py --执行 uv run --no-sync python 工具/构建编排.py
|
||||
uv run --no-sync python 工具/构建编排.py
|
||||
|
||||
构建:
|
||||
uv run --no-sync python 工具/构建编排.py --wheel
|
||||
|
||||
@ -61,11 +61,7 @@ def 测试数据库端点(数据库底座, tmp_path):
|
||||
|
||||
@pytest.fixture
|
||||
def 应用测试库(数据库底座, tmp_path):
|
||||
借用 = (
|
||||
数据库底座.借库
|
||||
if os.environ.get("MUSE_ISOLATED_CLONE") == "1"
|
||||
else 数据库底座.共享库
|
||||
)
|
||||
借用 = 数据库底座.借库 if os.environ.get("MUSE_ISOLATED_CLONE") == "1" else 数据库底座.共享库
|
||||
with 借用(tmp_path / "连接引用") as 工厂:
|
||||
yield 工厂
|
||||
|
||||
@ -102,11 +98,7 @@ def 内置种子方案():
|
||||
@pytest.fixture
|
||||
def 内置结构测试库(数据库底座, 内置种子方案, tmp_path):
|
||||
指纹, 导入 = 内置种子方案
|
||||
借用 = (
|
||||
数据库底座.借库
|
||||
if os.environ.get("MUSE_ISOLATED_CLONE") == "1"
|
||||
else 数据库底座.共享库
|
||||
)
|
||||
借用 = 数据库底座.借库 if os.environ.get("MUSE_ISOLATED_CLONE") == "1" else 数据库底座.共享库
|
||||
with 借用(tmp_path / "种子库引用", 种子指纹=指纹, 导入种子=导入) as 工厂:
|
||||
yield 工厂
|
||||
|
||||
|
||||
@ -31,7 +31,8 @@ from muse.配置 import 数据库引用
|
||||
|
||||
# 系统种子表登记:迁移 SQL 或导入种子写入、共享库例间清空必须保留的表。
|
||||
# 新增迁移若 INSERT 种子数据,必须同步登记;生命周期单测会机械拦截漏登记。
|
||||
种子表 = frozenset({
|
||||
种子表 = frozenset(
|
||||
{
|
||||
("public", "muse_migration"), # 迁移账本,由迁移执行器维护
|
||||
("public", "muse_method_index_guard"), # V0059 检索索引代次单例
|
||||
("public", "muse_raw_namespace"), # V0004 原文命名空间单例
|
||||
@ -39,7 +40,8 @@ from muse.配置 import 数据库引用
|
||||
("metadata", "type_registry"), # 内置结构种子,由导入种子写入
|
||||
("metadata", "schema_version"), # 内置结构种子,由导入种子写入
|
||||
("metadata", "work_extension"), # 内置结构种子,由导入种子写入
|
||||
})
|
||||
}
|
||||
)
|
||||
|
||||
|
||||
@dataclass(frozen=True)
|
||||
@ -215,7 +217,6 @@ class PostgreSQL后端:
|
||||
连.execute("TRUNCATE TABLE " + ", ".join(目标) + " RESTART IDENTITY CASCADE")
|
||||
|
||||
|
||||
|
||||
class 数据库底座:
|
||||
"""每个 session/worker 一个实例;模板构建失败不得进入可复用集合。"""
|
||||
|
||||
@ -406,9 +407,7 @@ class 数据库底座:
|
||||
self.后端.清空业务数据(身份)
|
||||
self.记录("shared_clean", database=身份.名称)
|
||||
except Exception as 错误:
|
||||
self.记录(
|
||||
"shared_clean_failed", database=身份.名称, reason=type(错误).__name__
|
||||
)
|
||||
self.记录("shared_clean_failed", database=身份.名称, reason=type(错误).__name__)
|
||||
raise
|
||||
|
||||
def 关闭(self) -> None:
|
||||
|
||||
@ -57,10 +57,16 @@ def _导入名(文件: Path) -> set[str]:
|
||||
contract="docs/系统架构/新版设计/总体架构.md",
|
||||
)
|
||||
def test_skills_do_not_syspath_into_shared_implementations__f4e7a4() -> None:
|
||||
"""技能目录是方法与操作说明,不携带实现脚本,不注入 sys.path。"""
|
||||
"""技能目录支持自包含独立辅助脚本,禁止向 sys.path 注入或反向导入业务实现。"""
|
||||
技能根 = 仓库根 / ".agent" / "skills"
|
||||
脚本 = [p for p in 技能根.rglob("*.py") if "__pycache__" not in p.parts]
|
||||
assert 脚本 == [], [str(p.relative_to(仓库根)) for p in 脚本]
|
||||
for p in 技能根.rglob("*.py"):
|
||||
if "__pycache__" in p.parts:
|
||||
continue
|
||||
文本 = p.read_text(encoding="utf-8")
|
||||
assert "sys.path" not in 文本, f"技能脚本出现 sys.path 注入:{p.relative_to(仓库根)}"
|
||||
assert "import muse" not in 文本 and "from muse" not in 文本, (
|
||||
f"技能脚本反向依赖业务单体:{p.relative_to(仓库根)}"
|
||||
)
|
||||
for md in 技能根.rglob("*.md"):
|
||||
文本 = md.read_text(encoding="utf-8")
|
||||
assert "sys.path" not in 文本, f"技能文档出现 sys.path 注入:{md.relative_to(仓库根)}"
|
||||
|
||||
Loading…
x
Reference in New Issue
Block a user