diff --git a/docs/proposals/2026-10-11-rdm-two-trees-trace-audit-integration.md b/docs/proposals/2026-10-11-rdm-two-trees-trace-audit-integration.md
new file mode 100644
index 0000000..a648011
--- /dev/null
+++ b/docs/proposals/2026-10-11-rdm-two-trees-trace-audit-integration.md
@@ -0,0 +1,391 @@
+---
+title: RDM 两树一网集成、完善与追溯审计展示方案
+type: feat
+date: 2026-10-11
+execution: code
+artifact_contract: ce-unified-plan/v1
+product_contract_source: ce-plan-bootstrap
+---
+
+# RDM 两树一网集成、完善与追溯审计展示方案
+
+修订:r1(2026-10-11 并入用户裁定);确认状态:用户评审通过(2026-10-11,需求拆解至实施计划五阶段一并,含 KTD4 双层管理员裁定);推进状态:方案已批准,业务实施、迁移、运行验收均为 NOT_RUN。
+需求负责人:weichen;方案编制:Codex;实施负责人:待实施立项时指定。
+来源:2026-10-11 用户要求检查两树一网现状,并设计简单直观的项目追溯、审计展示;同轮明确选择“完善 RDM,并补齐必要的基座能力”。
+目标仓:Agent-System-RDM;下文 `RDM:` 路径相对于该仓,`Dev:` 路径相对于 Agent-System-Dev;所有建议接口名均为候选契约。
+关联任务:Dev `.task/feature-rdm-two-trees-audit-plan.md`;本文件是本次方案唯一正文。
+
+## Goal Capsule
+
+推荐按**每项目一套笔记树、文档树和追溯网**管理,在现有 RDM 实现上补齐隔离、历史完整性和产品入口。
+项目创建者查看自己创建项目的追溯审计;RDM 域管理员与基座超管(基座 isAdmin)查看全部项目。
+管理员使用跨项目目录和筛选器进入各项目,默认不展示混合的全局关系大图。
+
+本轮只交付现状、方案和实施验收计划;方案已于 2026-10-11 获用户评审通过,业务实施与数据迁移仍须另行立项授权。
+项目独立是数据归属、授权、版本和查询范围独立,不要求每项目部署一套服务或建立一个数据库。
+先用一个项目跑通业务闭环,同时用第二项目验证隔离;管理员全项目目录与历史导出随后接入,本批默认范围为 U1–U5。
+
+---
+
+## Product Contract
+
+### Current State
+
+**结论:已经实现相当一部分,适合做集成与完善;尚不能认定为满足本次要求的完整产品。**
+
+调查基线(SELF·源码检查):
+
+| 对象 | 固定提交 |
+|---|---|
+| Dev 集成仓 | `5771d4f1e5b692bce95eb64cc30dc9931079ad12` |
+| Dev Backend | `ea4651b1f870d84ab9b72cfa79363b3432d113b3` |
+| Dev Frontend | `3ed10e122042a64180fb24a42d9cc6438cd2d2d6` |
+| RDM | `0081628a10ec48a36537c6eced11a57439c986fa` |
+| RDM 实际 Backend pin | `421fee81c314c05530bc809e224b5d0818ec3472` |
+| RDM 实际 Frontend pin | `84b73ab32848e623d0a0ab7ade552784dca8cf3c` |
+
+Dev 当前源码与 RDM 实际依赖不是同一组合,升级前须分别核验公开契约。
+本次没有运行业务测试、登录服务、读取业务数据库或进行浏览器验收;下列“已有”指源码存在,不能转换为“已部署/已验收”。
+命令、对象 SHA、原始输出和远端在途查询由工具保存于[调查收据](../records/2026-10-11-rdm-two-trees-source-receipt.json);收据为 SELF,不是 GATE 或独立 REPLAY。
+
+| 对象 | 源码现状 | 本次需要补齐 |
+|---|---|---|
+| 笔记树 | `RDM:internal/domain/notetree.go` 已有骨架、切片、锚点、标签、多点挂载、软删除;树是浏览骨架,切片可多挂载 | 独立浏览和详情读取接口;完整树导航;层级与挂载一致性 |
+| 文档树 | `RDM:internal/domain/doctree.go` 已有文档、章节、正文版本与依据、状态;已有基线和审签能力 | 树式浏览、真实版本元数据、来源与变更联动 |
+| 一般追溯网 | `tracenet.go`、`rdmapp/trace.go` 已有关系生命周期、邻域、多跳和图查询 | 端点完整性、同项目约束、版本定位及统一读模型 |
+| 受控合规图 | `compliance.go`、`chainviews.go`、`cgraph_export.go` 已有受控节点、版本边、链视图、矩阵及导出 | 与一般关系网整合展示;补重放一致性和历史快照 |
+| 项目分片 | `events.project`、`WorldFor`、按项目重放已经存在 | 清除外部入口的空项目全量回退;贯通基座项目与 RDM 项目;端到端鉴权 |
+| 结构历史 | `eventlog.go`、`replay.go` 已有 seq、操作者、时间、来源、payload 和重放 | 原子批次、幂等、完整状态还原、对用户可读的时间线 |
+| 现有界面 | `RDM:web/app.js` 有基线表、章节弹层、SVG 追溯图和多跳高亮 | 缺独立笔记树、统一审计页、完整项目上下文;合规图与导出尚未接入 Web |
+| 基座审计 | `Host.Audit`、`audit_events`、`command_audit` 已有通用记录 | 缺显式项目作用域、结构事件关联、跨项目管理员查询及稳定分页 |
+
+旧 `RDM:docs/design/data-model.md` 中“当前单 World、需求无产生路径”等结论已被后续代码改变,不作为当前缺口依据。
+旧追溯网和受控合规图目前是分别维护的边集合;共用事件日志不等于已有一张覆盖所有对象的完整网。
+
+### Material Gaps
+
+以下为源码事实及控制流推导,失败/越权场景尚未动态重放。
+
+| 编号 | 问题与依据 | 影响与处理 |
+|---|---|---|
+| G1 | `runtime.go:108` 空项目返回全库重放的 `rt.World`;`plugin.go:737` 的 trace/graph/hops 未检查 actor;实际 pinned Backend 的 `compiled.go:31` 和 `cmdbus.go:228` 没有领域项目授权 | 只隐藏页面入口无法隔离;旧命令、工具、图、计数、详情、导出均须使用同一服务端策略 |
+| G2 | `web/app.js:69,170` 使用基座项目,命令不自动注入领域项目;`projects_api.go:43` 列出全部 RDM 项目 | 必须先建立项目身份绑定及授权后的目录,不能依赖前端选择器过滤 |
+| G3 | `projects.go:18` 的 CreatedBy 与 `members.go` 的 owner 角色分离;`rdm_admins` 与基座 isAdmin 分离 | 按创建者事实授权;不能用“负责人”“成员”替代创建者;审计可见性按 KTD4 双层口径(基座超管+RDM 台账域管理员)执行,域管理员不因此获得平台管理权 |
+| G4 | `notetree.go:77` 的入库/挂载逐事件提交;`tracenet.go:67` 的 candidate/confirm 分开提交;`Retag` 等先改内存再写日志 | 中途失败可能遗留部分事件或内存/数据库不一致;先补事务批次和提交后投影 |
+| G5 | `compliance.go:170` 升版标 stale,但 `replay.go:230` 未对等重建;快照事件仅保存计数/hash;`replay.go:379` 正式版审签重建缺少时间/操作者 | 重启和历史回看可能与提交时不同;不得在修复前展示“历史已完整还原” |
+| G6 | `conclusions.go:264` 取提案只有 id 没有 project 条件;`tracenet.go:59` 未校验关系端点归属 | 全部节点、版本、提案和关系必须在同一项目作用域解析;跨项目对象拒绝 |
+| G7 | 成员/权限主要保存当前态;部分 `h.Audit` 错误被忽略;`review.go:95` 职责事件 Actor 使用受托编制人 | 补真实操作者与被操作主体分离、变更历史及可靠审计投递 |
+| G8 | `Dev:modules/backend/internal/store/platform.go:187` 审计无 project 字段;命令审计按 owner/会话读取 | 不能按 target 字符串猜项目,也不能把创建者自己的动作记录冒充整个项目审计 |
+
+### Requirements
+
+用户明确的范围与权限优先于旧方案:RDM 负责领域,基座只补通用能力(session-settled: user-directed — chosen over 所有基座项目内建两树一网:用户选择完善 RDM)。
+
+| ID | 需求 | 可判定验收条件 |
+|---|---|---|
+| R1 | 每项目独立两树一网 | A 项目查询、遍历、计数、详情、历史、导出均不出现 B 项目对象;跨项目建边被拒绝 |
+| R2 | 仅项目创建者和系统管理员查看追溯审计 | 创建者可读所建项目;RDM 域管理员与基座超管可读全部;非创建者负责人、成员、非成员均不能访问审计能力;域管理员不因此获得平台管理权 |
+| R3 | 展示来源与影响 | 任一支持的对象能查看来源、去向、版本与待确认关系,并打开有权限的证据 |
+| R4 | 操作记录直观可读 | 能回答谁、何时、改了什么、为什么、结果如何;未知信息明确标缺失 |
+| R5 | 历史真实且可重建 | 同一项目同一 seq 下,重启前后节点/关系/版本/审签/缺口一致;不可重建时明确报错 |
+| R6 | 提交与记录一致 | 单命令多事件全部提交或全部不生效;重试不重复生效;并发覆盖返回明确冲突 |
+| R7 | 简单、渐进展示 | 默认显示摘要、树和所选对象的一跳关系;不强制用户理解节点类型、内部事件码或原始 JSON |
+| R8 | 可导出可复核结果 | 导出绑定项目、截止 seq、对象版本、规则版本、身份与生成时间;文件下载再次鉴权 |
+| R9 | 复用现有能力和开发边界 | 保留 RDM 模型/计算/导出器,基座扩展经公开契约交付;无下游导入基座 internal |
+| R10 | 历史数据及私人资料有清楚边界 | 未归属记录不自动塞入默认项目;项目审计不绕过私人原文访问控制 |
+
+R2 约束项目审计中心及能返回等价审计数据的接口;普通文档阅读、协作、合法的引用展示继续遵守既有业务权限,不能顺手全部收紧为创建者专属。
+模型工具同样受调用者权限约束,不通过智能体转述绕过审计读取限制。
+
+---
+
+## Planning Contract
+
+### Key Technical Decisions
+
+以下为待评审的推荐技术决策;只有显式 session-settled 标注的用户选择已在本轮确认。
+
+- KTD1. **项目为隔离根,逻辑分区共享存储。** 查询及复合键携带实例域与 projectId;项目内对象采用稳定 ID,受控对象另带不可变版本。关系两端在同项目内解析,项目归属创建后不随意改动。共享模板/法规以固定版本引用或项目内快照进入,保留来源;第一版不建立项目 A 到项目 B 的业务边。
+- KTD2. **复用两套图,通过读适配器形成统一项目视图。** 一般事实关系与受控合规关系保留不同确认及版本规则,避免一次重写两套存储。统一对象引用包含项目、类型、ID、版本、图层,防止 ID 碰撞或把不同版本误并为一个节点。`candidate` 显示“待确认”、active 显示“已确认/已生效”、retired 显示“已废止”;stale 显示“依据版本已变更”。不将模型候选画成已生效事实。
+- KTD3. **一个服务端授权入口。** RDM 审计能力判定为“可信认证主体是 RDM 域管理员或基座超管(isAdmin),或等于项目 CreatedBy”。CreatedBy 固定;负责人调整不转移此权利。另设审计 read/export/history 能力映射,普通成员不能被项目负责人额外授予这些能力。权限异常拒绝读取,授权后的项目范围再进入存储,禁止先读全量后前端过滤。
+- KTD4. **双层管理员:基座超管保底+RDM 台账域管理员。**(session-settled: user-directed — chosen over 两套真值完全分离与基座 isAdmin 单层直通:用户 2026-10-11 评审裁定)基座提供认证身份;基座 isAdmin 作为超管始终可查看全部项目审计,是跨项目审计的保底入口。RDM 现有唯一管理员台账继续判定域审计管理员:域管理员可读全部项目,但不因此获得平台用户/插件等管理权。基座管理区承载的 RDM 审计分区对两类管理员开放;capability 仍由服务端下发,前端只消费、不自行合并角色。历史身份不一致需显式核对,不自动提升为域管理员。普通 project.create 不自动引导域管理员;首个域管理员经受信部署引导产生,初始化唯一性由事务及数据库约束保证。台账为空、多管理员或来源不明时,域管理员路径关闭等待授权核对,超管保底路径不受影响。超管的审计访问同样落入动作审计并标记身份层级。
+- KTD5. **基座项目与 RDM 项目显式一对一绑定。** 新增受约束的 hostProjectId 映射并带实例域;查询会话/工件所属基座项目后解析到 RDM 项目。不得用项目名称或默认第一个项目推断。两库创建无法单事务时用可恢复的 provisioning→ready/failed 流程和幂等标识,绑定未就绪不开放审计。EXT-8 共享资源检查使用映射后的领域项目,但不扩大成审计授权。
+- KTD6. **项目命令原子写,事件为结构历史依据。** 在 RDM 存储事务内验证预期版本、端点归属与幂等键,一次提交整批事件、必要台账和 outbox;提交后更新内存投影。缓存失效或更新失败时重建,不暴露半新状态。关键事件落库失败则命令失败;跨库基座审计通过可靠 outbox 补送,不能用两次独立写入冒充事务。
+- KTD7. **历史按项目+截止 seq 固定。** 可见水位只取已提交操作批次的结束 seq,时间按批次提交时间解析;显式 seq 落入批次内部时拒绝并提示可选的完整水位,不展示半次操作。保留当前全局 seq 的顺序语义,项目过滤后允许 seq 有间隙,不把它当作丢事件。快照保存完整节点/版本/边/审签/规则版本及哈希,含事件 schemaVersion;只有计数的旧快照不可作为恢复依据。未知事件版本须停止还原并说明缺口,不能静默跳过。
+- KTD8. **先沿用单实例,再与团队 PG 方案衔接。** RDM 当前领域库仍是 SQLite,基座配置 PG 不会迁移它。先修事务和项目串行写入;团队档上线前将 RDM 权威事件/台账纳入有唯一写入 owner 的 PG 存储适配。多实例需数据库发号/并发控制及缓存刷新验证,不因基座支持 PG 就宣称 RDM 支持多实例。
+- KTD9. **当前项目公开事实与私人过程分开。** 项目创建者能看项目审计,不因此得到成员私人会话/原件全文。内部重放载荷与对外审计 DTO 分离,原始 payload 不直接返回。摘要、正文、差异、历史快照和导出中的复制内容统一进行披露检查:当前来源 ACL 允许,或存在可核验的项目发布快照,方可输出。旧数据无来源/发布依据时默认遮蔽并标“来源受限/归属待核实”,不泄漏标题、摘要或路径。管理员看全部项目审计,仍不把凭证、模型隐藏推理或无关私聊放进审计输出。
+
+### Architecture
+
+```mermaid
+flowchart TB
+ U[创建者:自己项目 / 域管理员与基座超管:全部项目] --> A[认证身份 + 审计能力校验]
+ A --> P[解析当前项目绑定]
+ P --> Q[RDM统一审计读服务]
+ Q --> N[笔记树与文档树投影]
+ Q --> G[一般追溯与受控合规图适配]
+ Q --> H[事件历史与完整快照]
+ Q --> B[基座动作审计:经授权关联查询]
+ Q --> V[同一追溯审计工作区]
+```
+
+两树说明“资料怎样整理、文档怎样组织”;关系说明“依据来自哪里、影响到哪里”;审计说明“谁在什么时候作出了什么变更”。
+它们共用项目和对象身份,各回答一个问题,不要求用户先学习图数据库概念。
+
+### Data and Event Contract
+
+领域事件补足项目、operationId/requestId、真实 actor、actorType、被操作主体、对象版本、发生时间、提交 seq、原因、事件 schemaVersion,以及必要的前后差异。
+一个 operationId 关联多个结构事件和基座动作审计;前端按一次操作归组,技术明细按需展开。
+纠正错误通过新事件完成,保留更正者和原因;关系失效、软删除和权限变更不覆盖原历史。
+
+权限变更审计保留当时的政策版本/决策摘要,便于解释过去为何允许;**现在能否查看**仍按当前权限判断。
+前端自报审计只能标为客户端报告,不得伪装成服务端核实的批准或业务成功。
+普通 hash 用于校验导出/快照一致性,不宣称具备防数据库管理员篡改或电子签名保证。
+
+```mermaid
+sequenceDiagram
+ participant C as 调用者
+ participant A as RDM命令应用层
+ participant D as RDM存储
+ participant B as 基座审计
+ C->>A: 项目、操作、预期版本、幂等键
+ A->>A: 当前授权与同项目端点检查
+ A->>D: 原子提交事件批次、幂等结果、outbox
+ D-->>A: 已提交seq及结果
+ A-->>C: 业务结果与可追溯操作编号
+ A->>A: 刷新或重建项目投影
+ D->>B: outbox可靠补送关联审计
+```
+
+基座暂不可用时,已提交结构事实继续保存,动作审计显示“同步中”;恢复后幂等补送。
+关键业务规则需要同一库的证据记录才能放行时,在业务事务内保存;不将异步投递当作批准的前提已满足。
+导出需先固定截止水位、检查完整性;审计关联仍缺失时明确标为不完整,正式完整报告应阻止导出或要求用户选择带缺口的草稿。
+
+### Read Interfaces
+
+优先通过现有命令总线及页面 SDK 提供 RDM 查询,所有入口落到同一应用服务;不另建绕过权限的调试 API。
+
+| 候选读契约 | 返回内容与限制 |
+|---|---|
+| inspect.capabilities / inspect.projects | 可见项目、当前项目是否可审计、是否可跨项目;管理员全项目目录独立分页 |
+| inspect.summary | 两树规模、待确认关系、缺口、最新动作、数据截止水位;不把缺失当作零 |
+| inspect.tree / inspect.object | 树子节点分页;所选对象版本、出处、状态;只展开需要的分支 |
+| inspect.relations | 方向、图层、关系状态、版本、深度;默认一跳,后续点选扩展;有数量上限和截断提示 |
+| inspect.events | 按项目、对象、时间、操作者、动作、结果过滤,游标分页;可展开一次操作的差异 |
+| inspect.history | 固定 seq/基线下的对象、关系和当时规则;缺少重放材料返回明确不可还原状态 |
+| inspect.export | 导出同一筛选条件和截止水位;生成、取状态、下载都重新校验主体及项目权限 |
+
+分页游标绑定项目/筛选条件/排序/权限版本,不能拿 A 项目游标读 B。
+缓存、导出缓存及订阅键包含主体能力范围、项目和截止水位,撤权后不可复用旧授权结果。
+异步数据只有一个状态所有者:项目切换取消旧请求并递增 generation,过期响应丢弃;事件按 seq 去重、有序应用。
+
+### Base Extension Requests
+
+先验证现有注册点能否组合;不足部分按 RDM 的四要素扩展申请办理,保持公开面可选、向后兼容。
+
+| 场景 | 希望的通用能力 | 现有能力不足 | 兼容方式 |
+|---|---|---|---|
+| 创建者看项目内所有人的动作 | 审计 envelope 的 projectId、operationId、对象版本及按项目查询 | Host.Audit 只有 owner/action/target/evidence;按 owner 会遗漏其他成员动作 | 增加可选的结构化审计能力/接口,不直接强改所有 Host 实现;旧记录标项目未知 |
+| 宿主页面展示 RDM 审计入口 | 插件提供当前主体的审计能力和可见项目,宿主提供可信身份与项目上下文 | EXT-8 只有资源共享读取布尔判断;基座 AdminZone 仅看 isAdmin | 新增可选的动作级 capability/provider;不改变旧资源授权器含义 |
+| 私人来源与项目发布证据联动 | 已授权工件/版本链接与受限占位,导出后下载再校验 | 不能让全项目审计器任意扩大 owner-scoped Host | 复用现有工件访问契约,仅按实测缺口增加窄接口;禁止任意 owner impersonation |
+
+两树对象、边规则、合规矩阵和领域重放保留在 RDM,基座不内置这些领域表。
+
+---
+
+## Display Design
+
+### Entrances and Layout
+
+项目创建者从当前项目菜单进入“追溯与审计”;RDM 域管理员与基座超管从管理区“项目追溯与审计”进入项目目录,选定项目后复用同一页面。
+管理员选择项目后,审计工作区的项目上下文必须更新为实际被审计项目,所有请求与标题保持一致。宿主支持审计项目切换时,项目身份集中显示在宿主项目位置;宿主不能切至该项目时,审计页必须显示明确项目标题和“返回项目目录”,并避免让宿主旧项目标题被误认为审计范围。管理员目录显示项目名、创建者、最近活动、待关注数量。
+第一版为只读审计工作区,审批、确认关系和编辑仍跳回原受控业务流程,不在审计页面创造第二套写入口。
+
+页面保留四个入口:**概览、资料与文档、关联追溯、操作记录**。
+左侧按需显示笔记树/文档树导航;主区显示当前选择;对象详情在页面内展开,原件仍进入宿主唯一文件预览区。
+不叠加弹窗,不默认铺满全部节点。
+
+| 入口 | 默认看到什么 | 深入查看 |
+|---|---|---|
+| 概览 | 已收集资料、已形成文档、需要确认的关系、需要补齐的证据;最近几次重要变更 | 点击数字进入带筛选的列表;明确“统计截至…”和“不完整”状态 |
+| 资料与文档 | 笔记树:阶段→事项→主题→资料切片;文档树:阶段→文档→章节 | 同一资料多个挂载不重复计数;缺主题可显示未分类,不伪造层级 |
+| 关联追溯 | 所选对象居中,左右分别为“来源依据”和“影响对象” | 列表优先;切换为局部关系图;合规链/矩阵在此页按需切换 |
+| 操作记录 | 自然语言时间线,按一次业务操作归组 | 展开前后差异、批准依据、对象版本与技术记录 |
+
+### Human-readable Trace
+
+关系展示示意,实际节点与连线必须来自已保存数据:
+
+```mermaid
+flowchart LR
+ A[会议纪要中的原文] -->|支持| B[用户需求]
+ B -->|落实到| C[方案章节 v3]
+ C -->|由此验证| D[验证记录]
+```
+
+点选“方案章节 v3”后首先看到:这是什么、当前版本、依据哪几条材料、影响哪几项需求/验证、最近谁改过。
+缺少验证记录时显示“验证依据待补齐”,不画虚构的完整链;候选边使用虚线和文字“待确认”,不能仅靠颜色区分。
+“没有已知关联”与“尚未完成关系索引/本次查询被截断”分开呈现。
+关系被废止后可在历史模式中看到;跨版本关系明确标注版本,不让 v4 的证据替代 v3 的事实。
+
+### Audit Timeline
+
+时间线示意:
+
+- 10:32 张三将《需求说明》从 v2 更新为 v3;修改了“使用环境”章节,依据为评审纪要第 4 条。
+- 10:41 李四确认该章节与 UR-012 的关联;确认理由为“已覆盖用户场景”。
+- 11:05 王五批准 v3;点击可查看批准时的版本和证据。
+
+每条默认仅显示时间、操作者、动作、对象、结果;“查看变更”再展开前后差异与理由。
+后台归档、重试等技术事件默认归组收起,失败、拒绝、未知结果有文字说明;原始 JSON 不作为主界面。
+Actor 为真实执行者,Subject 为被分配职责或被变更权限的人,界面不混写两者。
+默认显示北京时间并注明时区,底层保留 UTC;历史模式顶部醒目标注“查看截至某时间/某基线的记录”。
+
+### Interaction Boundaries
+
+提供“当前/历史”切换,历史可选择时间或基线;从批准记录可直接打开批准时的版本。两树、关系与记录共用一个截止水位,“返回当前”恢复对象当前版本;对象已删除则显示删除说明,不切到同名对象。
+对象名称支持搜索;树节点懒加载;记录使用“加载更多”;关系默认一跳,上限和截断状态由服务端返回。
+加载、空项目、无权限、部分数据、同步中、历史不可还原、请求失败分别展示,不都渲染成“暂无数据”。
+首屏不显示 SQL、事件 opcode、内部 UUID、hash;复制技术编号放在详情中。
+推荐验收任务:创建者在三次主要点击内找到某章节的原始依据和最近修改原因;管理员能清楚确认当前查看哪个项目。
+
+实现遵循 `Dev:DESIGN.md`:颜色/圆角/字号消费 `@ui` 令牌;折叠用 Collapsible;动效只用 `mk-*`;键盘可导航,状态同时有文字与形状。
+优先在当前宿主工作区体系内以 RDM 插件页面提供,避免长期维护第二套静态工作台。
+旧 `web/app.js` 保留过渡兼容范围,但图与审计能力接同一授权服务;最终页面交付形式在 U4 固定,不能假设在途 Generative UI 已能直接承载。
+
+---
+
+## Implementation Units
+
+本批默认顺序:U1→U2→U3→U4→U5,按 `policy/delivery.md` 分增量评审。U6 是独立后续衔接项,不纳入本批完成条件。
+U1 是首选下一任务;这份方案不构成启动它的授权。
+
+### U1. 项目身份与读取授权闭环
+
+目标/需求:R1、R2、R9、R10;依赖:方案已批准(2026-10-11)、KTD4 已按双层口径裁定;剩余既有项目映射盘点在立项时完成。
+范围:`RDM:internal/projects`、`members`、`perms`、`rdmapp/runtime.go`、`projects_api.go`、`perms_api.go`、`plugins/rdm/plugin.go`、`web/app.js` 的旧客户端项目上下文;测试 `rdmapp/perms_test.go`、`sharding_test.go`、`plugins/rdm/plugin_test.go`;必要基座 capability 扩展单独申请。
+
+建立显式项目绑定;增加审计读取策略和管理员受信引导门禁;统一包裹旧/新 trace、cgraph、项目列表、历史和导出入口。
+U1 同批接通旧客户端的项目选择和命令封装,并解析可信会话/工件上下文到显式绑定;随后启用对外 projectId 必填门禁。无映射时显示“项目待绑定”,不回退全量世界。仅管理员专用迁移/调查路径能够处理未归属域,并单独留痕。
+检查结论提案、引用、关系两端和版本归属,不接受来自别的项目的 ID。
+普通文档协作仍使用原业务权限,避免用审计策略误封工作流程。
+
+验证:创建者、非创建者负责人、成员、非成员、RDM 域管理员、仅基座超管六类主体(后两类均为跨项目审计正例,域管理员访问平台管理分区须为负例);空项目、伪造项目、跨项目对象、旧命令/模型工具绕过、撤权后的新请求与下载均有正负例。
+增加首次启动、恢复后空台账、并发初始化、普通建项目不提权的验证。
+完成条件:至少两个项目、多用户、真实认证入口下全部读取边界可复核;不依赖隐藏按钮。
+
+### U2. 原子事件与历史还原
+
+目标/需求:R5、R6、R10;依赖:U1 的项目合同。
+范围:`RDM:internal/domain/{eventlog,notetree,doctree,tracenet,compliance,replay,persist,review}.go`、`domain/store/store.go`、`rdmapp/conclusions.go`、`upload.go` 及上传状态台账,对应 `persist_test.go`、`integrity_test.go`、`compliance_test.go`、`conclusions_test.go`、`upload_test.go`。
+
+补事件批次事务、项目内写入串行/预期版本和操作幂等;内存变更置于提交之后。
+上传原件先不可变留存,再由同一 RDM 数据库事务发布引用、状态、项目归属、切片关联、pending 关闭和幂等结果;meta.json 降为可重建镜像。上传确认/拒绝中断后按操作结果恢复,不重复入库;此项在 SQLite 首期完成,不等待 U6。
+修复升版 stale、正式版审签元数据和完整快照重放;记录成员/权限/职责变化及真实 actor。
+建立结构事件到基座审计的 outbox,显示投递状态;旧缺失事实明确为不可恢复,不能补造批准人或时间。
+
+验证:第二条/最后一条事件失败、提交后进程退出、投影刷新失败、相同请求重试、并发同版本更新;重启前后对节点/版本/边/审签/缺口深比较;旧快照与未知 schemaVersion 明确拒绝冒充完整;历史/导出截止落在批次中间时拒绝,上传发布/确认中断后状态与切片不重复、不矛盾。
+完成条件:命令结果、持久记录、重建投影一致,故障不造成不可解释的部分成功。
+
+### U3. 统一项目审计读服务
+
+目标/需求:R3、R4、R5、R8;依赖:U1、U2。
+范围:`RDM:internal/rdmapp/trace.go`、`baseline.go`、`cgraph_export.go`、拟增 inspection 读投影;`plugins/rdm/plugin.go`;测试 `trace_test.go`、`chainviews_test.go` 及新增 inspection 集成测试。
+
+把两树、一般关系、受控关系、结构事件和基座动作记录适配到统一对象详情及分页查询。
+为查询绑定项目、当前授权、截止水位及版本;返回覆盖状态和截断状态。
+补公开面需要的 project/operation 审计查询与能力 provider;不从字符串解析项目归属。
+
+验证:旧网和合规网的同名 ID 不冲突,历史 v3 与当前 v4 不串用;未知/受限来源在旧 payload、差异、快照及导出副本中也不泄漏;游标换项目拒绝,分页期间新增事件不重不漏;动作审计同步延迟可见。
+完成条件:无需读数据库即可通过受控接口回答来源、影响、变更与历史问题。
+
+### U4. 项目追溯审计工作区
+
+目标/需求:R2、R3、R4、R7;依赖:U3;页面载体在本增量设计评审时固定为宿主支持的 RDM 插件工作区。
+范围:RDM 页面资源及宿主注册声明;必要时 `Dev:modules/frontend/src/components/{Workspaces,AdminZone,adminSections}.tsx`、`store.ts`、`api.ts`;交互测试沿用 frontend test/e2e 体系,旧 Web 的兼容测试留在 `RDM:web/workbench_test.mjs`。
+
+实现四入口、两树导航、对象详情、一跳关系和自然语言记录;普通用户无入口且接口拒绝。
+管理员目录按授权后的项目查询,选项目复用页面;RDM 管理 capability 不解锁其他平台管理分区。
+沿用宿主文件预览、令牌和折叠;删除/替换旧重复图入口需另列兼容清单。
+
+验证:真实浏览器完成来源查询、选择历史时间/基线并返回当前、管理员从宿主 A 打开审计 B 后标题和请求一致;模拟慢请求后快速切项目无串页;键盘、窄屏、长标题、千级节点懒加载、空/失败/受限/不可还原状态可理解。
+完成条件:用户按三次主要点击任务完成取证,并人工评审界面是否直观;业务可用与视觉通过分别记录。
+
+### U5. 历史导出与正式集成验收
+
+目标/需求:R5、R8、R9、R10;依赖:U2、U3、U4。
+范围:`RDM:internal/rdmapp/{cgraph_export,docx,xlsx}.go`、页面导出入口、导出临时工件及下载授权;测试 `domain/export_test.go`、`plugins/rdm/xlsx_export_test.go` 和浏览器下载场景。
+
+复用 docx/xlsx 导出器,固定项目/版本/规则/截止 seq,补证据来源清单和完整性说明。
+导出按请求身份和范围生成,撤权后下载失败;历史受限来源不随导出泄漏。
+固定基座发布版本、RDM pins 与页面资源组合后,重放真实端到端流程。
+
+验证:导出中途有新写入不改变已固定内容;历史来源软删除仍可按授权追溯;未归属/缺失事件可见;跨项目下载、过期下载、权限撤销均拒绝。
+完成条件:同一版本在 UI 与报告中结论一致,并有正式 GATE/REPLAY 证据。
+
+---
+
+## Deferred Integration
+
+### U6. 团队部署存储衔接(独立后续任务)
+
+本项不纳入 U1–U5 的默认实施与验收范围,另经团队存储方案授权后立项。
+目标/需求:R1、R5、R6、R9;依赖:U2,以及[多人协作存储方案](2026-10-11-collaboration-storage-and-distribution.md)适用增量。
+范围:RDM 领域 store/迁移、项目/成员/权限/结论/慢通道台账、上传原件与导出清单;基座只补通用连接/生命周期公开契约。
+
+明确 RDM SQLite 与团队 PG 的适配和备份清单,避免一半事实在 PG、一半未受保护地留在本机文件。
+先验证单实例团队档;多实例的发号、执行所有权、缓存失效与故障恢复在独立验收前保持关闭。
+本次不复制基座在途 PG 档位和迁移能力,也不把基座 PR 完成当作 RDM 迁移完成。
+
+验证:真实 PG 的隔离/事务/重放、迁移前后对象与事件数及哈希对账、备份恢复含原件;PG 不可用不静默退回空 SQLite。
+完成条件:团队部署具备明确权威存储与恢复证据;若本批仅交付单实例 SQLite,验收报告必须声明该限制。
+
+---
+
+## Migration and Delivery
+
+历史归属先做只读盘点:未归属事件、缺少项目绑定、对象依赖闭包、旧快照和私人来源。
+现有 seq 区间迁移接口不能作为任意截取的安全保证;归属以完整对象及依赖闭包为单位校验,并保留批准映射和原因。
+不把存量自动分给首个项目,不根据当前 owner 猜历史创建者。
+
+迁移前保存备份和对账清单,在隔离副本上验证,再取得共享环境迁移授权。
+采用新增字段/投影、保留原事件、按项目启用;观察期内可关闭新页面和新读取投影,但不能恢复越权的全量读取入口。
+停止条件:发现跨项目泄漏、重放不一致、无法确定历史归属、投影滞后超出可解释范围或恢复失败;保留现场和失败证据。
+
+跨仓顺序为基座扩展申请→基座实现/测试/发布→RDM 升级固定版本→RDM 集成验证→Dev 文档与组合记录更新。
+必要令牌调整按 DESIGN.md 成对关联 UI 与 Dev 组合;仅消费令牌时不制造无关令牌 PR。
+
+在途核对(本次 Gitea API 只读,SELF;实施前须刷新):Dev #325 为团队 PG 档与迁移组合,#317 为服务启动 DSN;RDM #194 为已合入 xlsx 工作的任务卡闭合,不能重复安排 xlsx 从零实现;Backend、Documents 查询未返回开放 PR。
+关联规划为 RDM 阶段总案 P3/MS3、U0 项目共享合同、V2.2 合规图方案和上述团队存储方案;本案补充集成/授权/显示,不声称这些里程碑已验收。
+
+---
+
+## Verification Contract
+
+以下为实施时的验收计划,本轮结果均 NOT_RUN;文档自检另以任务收据记录。
+
+| 组 | 覆盖需求 | 最小可复核场景 |
+|---|---|---|
+| 授权/隔离 | R1、R2、R10 | 六类角色×两个项目;列表、统计、详情、关系、历史、工具、导出、下载、订阅均验证;普通文档协作无误封 |
+| 数据完整性 | R3、R5、R6 | 跨项目提案和边拒绝;多事件中途失败;重试/并发;重启及指定 seq 深比较;完整快照哈希 |
+| 真实业务闭环 | R3–R6 | 项目创建→纪要入库→切片→需求→章节 v1→依据变化→v2→审签→历史回看→报告;缺失链节明确显示 |
+| 可用性 | R4、R7 | 创建者找依据/变更原因,管理员选项目,键盘/窄屏/长文本,加载/失败/受限状态,过期响应丢弃 |
+| 导出 | R8、R10 | 同一 cutoff UI/报告一致;创建与下载分别鉴权;撤权/受限来源/不完整记录不泄漏或冒充完整 |
+| 组合与运行 | R9 | 固定 Backend/Core/Frontend/UI/RDM SHA;RDM 测试与构建、Dev 适用组合检查;部署后二进制身份和真实浏览器路径 |
+| 团队档(U6另行立项时) | R1、R5、R6 | 真 PG、迁移与恢复;单实例和多实例证据分别记录,无变量或无环境即 NOT_RUN/SKIP |
+
+性能建议作为待批准目标:单项目 1 万对象/5 万关系、100 万事件的样本;首屏仅取分页摘要与当前树分支;普通分页查询 P95≤1s,首屏可操作≤2s。
+记录实际硬件、数据分布、过滤条件和组件版本,不能以空库或缓存命中替代容量结论。
+正式审核先重放最小集再读作者证据;来源标记遵循 GATE/REPLAY/SELF,用户界面演示与正式验收分开。
+
+---
+
+## Definition of Done
+
+本方案阶段完成条件:现状依据可定位、原有能力不重复建设、项目和角色边界明确、展示可理解、工作项与验收对应;r1 已于 2026-10-11 经用户评审通过(五阶段一并,含 KTD4 双层管理员裁定)。
+实现阶段完成条件:R1–R10 对应证据齐备,固定组合通过正式测试和独立审核,部署与浏览器验收有独立记录;源码存在不等于完成。
+
+已裁定决策:KTD4 采用双层管理员——基座 isAdmin 超管保底+RDM 台账域管理员(session-settled: user-directed,2026-10-11)。剩余待定决策:RDM 宿主工作区入口的具体交付契约(U4 设计评审时固定);U6 如需提前并入本批,应另行批准范围及目标环境,默认不包含。
+推荐先批准 U1 的细化设计与测试范围;U2–U5 按依赖逐阶段评审,U6 单独立项,不把本轮范围确认当作连续实施授权。
+
+后续再考虑跨项目引用审批、全局关系图、电子签名/外部防篡改存证及复杂图分析;这些不属于首个可用闭环。
diff --git a/docs/proposals/INDEX.md b/docs/proposals/INDEX.md
index 3de6900..e762c5c 100644
--- a/docs/proposals/INDEX.md
+++ b/docs/proposals/INDEX.md
@@ -158,3 +158,7 @@ RDM 总案把库分期作为支撑与依赖,不覆盖库分期的原始范围
后续维护:主案或任务变化时先更新其唯一主记录,再更新这里的导航和核验快照。
更换 Docs/Dev 基线后重新核对 PR、版本与在途任务;新的索引状态不自动产生实施授权。
+
+## 2026-10-11 规划补充
+
+- [RDM 两树一网集成、完善与追溯审计展示方案 r1](2026-10-11-rdm-two-trees-trace-audit-integration.md):对应 P3/MS3,源码已有部分实现;优先补项目绑定、创建者/管理员读取隔离与历史完整性,再接统一展示。用户确认范围为 RDM 与必要基座能力;r1 已获用户评审通过(2026-10-11,五阶段一并,含 KTD4 双层管理员裁定),业务实施与运行验收 NOT_RUN,U1 起另行立项授权。
diff --git a/docs/records/2026-10-11-rdm-two-trees-source-receipt.json b/docs/records/2026-10-11-rdm-two-trees-source-receipt.json
new file mode 100644
index 0000000..916d868
--- /dev/null
+++ b/docs/records/2026-10-11-rdm-two-trees-source-receipt.json
@@ -0,0 +1,34 @@
+{
+ "schema": 1,
+ "source": "SELF",
+ "timestamp": "2026-10-11T03:51:00.492861+00:00",
+ "command": "python3 /tmp/rdm-two-trees-audit-20261011.py",
+ "command_sha256": "69b27cf0bf6a1f234f93ea7302fb2a4407bf78076f4af75a83118f386361b1e6",
+ "cwd": "/home/weichen/projects/Agent-System-Dev-wt-feature-rdm-two-trees-audit-plan",
+ "common_dir": "/home/weichen/projects/Agent-System-Dev/.git",
+ "before": {
+ "head": "a14882c62e1ad20f9d16ff204456be14965095ff",
+ "branch": "feature/rdm-two-trees-audit-plan",
+ "target_branch": "main",
+ "target_head": "5771d4f1e5b692bce95eb64cc30dc9931079ad12",
+ "status": " M modules/documents\n",
+ "tracked_diff_sha256": "f91a4e41ab1b5e0b2bcbec359f1e3596fb337b5c599d17a2e4de775182f3e392",
+ "untracked": {},
+ "submodules": " 4f583ca3eeeb07a56a714c5086de84dcd6ad2980 deps/agent-command (heads/main)\n ed2af3e6048928b1fd0ba6da1f9d0c1bafec82d4 deps/agent-command/deps/development-guidelines (remotes/origin/feature/delivery-mechanism-5-ged2af3e)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c deps/agent-intent (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/agent-intent/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/agent-intent/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n c348441691e8bdab784a03aa9be64d53dacff341 deps/agent-native (heads/main)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c deps/agent-native/deps/agent-intent (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-native/deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/agent-native/deps/agent-intent/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-native/deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/agent-native/deps/agent-intent/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-native/deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-native/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/agent-native/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-native/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/agent-native/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-native/deps/logging-system/deps/development-guidelines (26b562d)\n 490b0b2dfa1567cb16ff7a7230fd78e52bc2938e deps/agent-squad (heads/main)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c deps/agent-squad/deps/agent-intent (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/agent-squad/deps/agent-intent/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/agent-squad/deps/agent-intent/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n c348441691e8bdab784a03aa9be64d53dacff341 deps/agent-squad/deps/agent-native (heads/main)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c deps/agent-squad/deps/agent-native/deps/agent-intent (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-native/deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/agent-squad/deps/agent-native/deps/agent-intent/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-native/deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/agent-squad/deps/agent-native/deps/agent-intent/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-native/deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-native/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/agent-squad/deps/agent-native/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-native/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/agent-squad/deps/agent-native/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-native/deps/logging-system/deps/development-guidelines (26b562d)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/agent-squad/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/agent-squad/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/logging-system/deps/development-guidelines (26b562d)\n af199eeaa23c5b39e08b4649f2513d7572dc5274 deps/development-guidelines (heads/main)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/logging-system/deps/development-guidelines (26b562d)\n ea4651b1f870d84ab9b72cfa79363b3432d113b3 modules/backend (v0.3.0-28-gea4651b)\n 4f583ca3eeeb07a56a714c5086de84dcd6ad2980 modules/backend/deps/agent-command (heads/main)\n ed2af3e6048928b1fd0ba6da1f9d0c1bafec82d4 modules/backend/deps/agent-command/deps/development-guidelines (remotes/origin/feature/delivery-mechanism-5-ged2af3e)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c modules/backend/deps/agent-intent (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/agent-intent/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/agent-intent/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n c348441691e8bdab784a03aa9be64d53dacff341 modules/backend/deps/agent-native (heads/main)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c modules/backend/deps/agent-native/deps/agent-intent (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-native/deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/agent-native/deps/agent-intent/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-native/deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/agent-native/deps/agent-intent/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-native/deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-native/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/agent-native/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-native/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/agent-native/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-native/deps/logging-system/deps/development-guidelines (26b562d)\n 490b0b2dfa1567cb16ff7a7230fd78e52bc2938e modules/backend/deps/agent-squad (heads/main)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c modules/backend/deps/agent-squad/deps/agent-intent (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/agent-squad/deps/agent-intent/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/agent-squad/deps/agent-intent/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n c348441691e8bdab784a03aa9be64d53dacff341 modules/backend/deps/agent-squad/deps/agent-native (heads/main)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c modules/backend/deps/agent-squad/deps/agent-native/deps/agent-intent (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-native/deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/agent-squad/deps/agent-native/deps/agent-intent/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-native/deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/agent-squad/deps/agent-native/deps/agent-intent/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-native/deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-native/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/agent-squad/deps/agent-native/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-native/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/agent-squad/deps/agent-native/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-native/deps/logging-system/deps/development-guidelines (26b562d)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/agent-squad/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/agent-squad/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/logging-system/deps/development-guidelines (26b562d)\n a253a40b8e5563119b00c4e71fb61fe0d11d6d6a modules/backend/deps/agent-system-core (v0.3.0)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/logging-system/deps/development-guidelines (26b562d)\n a253a40b8e5563119b00c4e71fb61fe0d11d6d6a modules/core (v0.3.0)\n+3e2d8c90492c4d232c030a219885871fa5c98a0f modules/documents (heads/feature/rdm-two-trees-audit-plan)\n 3ed10e122042a64180fb24a42d9cc6438cd2d2d6 modules/frontend (v0.3.0-4-g3ed10e1)\n 76d6633736a7abb36ac1ecca42fe4e6f120d0558 modules/ui (v0.3.0)\n"
+ },
+ "after": {
+ "head": "a14882c62e1ad20f9d16ff204456be14965095ff",
+ "branch": "feature/rdm-two-trees-audit-plan",
+ "target_branch": "main",
+ "target_head": "5771d4f1e5b692bce95eb64cc30dc9931079ad12",
+ "status": " M modules/documents\n",
+ "tracked_diff_sha256": "f91a4e41ab1b5e0b2bcbec359f1e3596fb337b5c599d17a2e4de775182f3e392",
+ "untracked": {},
+ "submodules": " 4f583ca3eeeb07a56a714c5086de84dcd6ad2980 deps/agent-command (heads/main)\n ed2af3e6048928b1fd0ba6da1f9d0c1bafec82d4 deps/agent-command/deps/development-guidelines (remotes/origin/feature/delivery-mechanism-5-ged2af3e)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c deps/agent-intent (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/agent-intent/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/agent-intent/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n c348441691e8bdab784a03aa9be64d53dacff341 deps/agent-native (heads/main)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c deps/agent-native/deps/agent-intent (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-native/deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/agent-native/deps/agent-intent/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-native/deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/agent-native/deps/agent-intent/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-native/deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-native/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/agent-native/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-native/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/agent-native/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-native/deps/logging-system/deps/development-guidelines (26b562d)\n 490b0b2dfa1567cb16ff7a7230fd78e52bc2938e deps/agent-squad (heads/main)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c deps/agent-squad/deps/agent-intent (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/agent-squad/deps/agent-intent/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/agent-squad/deps/agent-intent/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n c348441691e8bdab784a03aa9be64d53dacff341 deps/agent-squad/deps/agent-native (heads/main)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c deps/agent-squad/deps/agent-native/deps/agent-intent (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-native/deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/agent-squad/deps/agent-native/deps/agent-intent/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-native/deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/agent-squad/deps/agent-native/deps/agent-intent/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-native/deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-native/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/agent-squad/deps/agent-native/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-native/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/agent-squad/deps/agent-native/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/agent-native/deps/logging-system/deps/development-guidelines (26b562d)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/agent-squad/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/agent-squad/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/agent-squad/deps/logging-system/deps/development-guidelines (26b562d)\n af199eeaa23c5b39e08b4649f2513d7572dc5274 deps/development-guidelines (heads/main)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 deps/logging-system/deps/development-guidelines (26b562d)\n ea4651b1f870d84ab9b72cfa79363b3432d113b3 modules/backend (v0.3.0-28-gea4651b)\n 4f583ca3eeeb07a56a714c5086de84dcd6ad2980 modules/backend/deps/agent-command (heads/main)\n ed2af3e6048928b1fd0ba6da1f9d0c1bafec82d4 modules/backend/deps/agent-command/deps/development-guidelines (remotes/origin/feature/delivery-mechanism-5-ged2af3e)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c modules/backend/deps/agent-intent (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/agent-intent/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/agent-intent/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n c348441691e8bdab784a03aa9be64d53dacff341 modules/backend/deps/agent-native (heads/main)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c modules/backend/deps/agent-native/deps/agent-intent (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-native/deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/agent-native/deps/agent-intent/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-native/deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/agent-native/deps/agent-intent/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-native/deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-native/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/agent-native/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-native/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/agent-native/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-native/deps/logging-system/deps/development-guidelines (26b562d)\n 490b0b2dfa1567cb16ff7a7230fd78e52bc2938e modules/backend/deps/agent-squad (heads/main)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c modules/backend/deps/agent-squad/deps/agent-intent (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/agent-squad/deps/agent-intent/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/agent-squad/deps/agent-intent/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n c348441691e8bdab784a03aa9be64d53dacff341 modules/backend/deps/agent-squad/deps/agent-native (heads/main)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c modules/backend/deps/agent-squad/deps/agent-native/deps/agent-intent (heads/main)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-native/deps/agent-intent/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/agent-squad/deps/agent-native/deps/agent-intent/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-native/deps/agent-intent/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/agent-squad/deps/agent-native/deps/agent-intent/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-native/deps/agent-intent/deps/logging-system/deps/development-guidelines (26b562d)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-native/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/agent-squad/deps/agent-native/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-native/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/agent-squad/deps/agent-native/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/agent-native/deps/logging-system/deps/development-guidelines (26b562d)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/development-guidelines (26b562d)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/agent-squad/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/agent-squad/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/agent-squad/deps/logging-system/deps/development-guidelines (26b562d)\n a253a40b8e5563119b00c4e71fb61fe0d11d6d6a modules/backend/deps/agent-system-core (v0.3.0)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 modules/backend/deps/error-code-system (a3ee67b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/error-code-system/deps/development-guidelines (26b562d)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 modules/backend/deps/logging-system (49b5d8b)\n 26b562d2e34fbc560711296a309c91c74ffc55b1 modules/backend/deps/logging-system/deps/development-guidelines (26b562d)\n a253a40b8e5563119b00c4e71fb61fe0d11d6d6a modules/core (v0.3.0)\n+3e2d8c90492c4d232c030a219885871fa5c98a0f modules/documents (heads/feature/rdm-two-trees-audit-plan)\n 3ed10e122042a64180fb24a42d9cc6438cd2d2d6 modules/frontend (v0.3.0-4-g3ed10e1)\n 76d6633736a7abb36ac1ecca42fe4e6f120d0558 modules/ui (v0.3.0)\n"
+ },
+ "after_error": null,
+ "exit_code": 0,
+ "output": "{\"source\": \"SELF\", \"kind\": \"read-only-source-inspection\", \"heads\": {\"Dev\": \"5771d4f1e5b692bce95eb64cc30dc9931079ad12\", \"RDM\": \"0081628a10ec48a36537c6eced11a57439c986fa\"}, \"status\": {\"Dev\": \"\", \"RDM\": \"\"}}\nDev pins\n4f583ca3eeeb07a56a714c5086de84dcd6ad2980 deps/agent-command (remotes/origin/HEAD)\n 343b1e6d9a5b58e47bf7e594826221036ae8175c deps/agent-intent (remotes/origin/HEAD)\n c348441691e8bdab784a03aa9be64d53dacff341 deps/agent-native (remotes/origin/HEAD)\n 490b0b2dfa1567cb16ff7a7230fd78e52bc2938e deps/agent-squad (remotes/origin/HEAD)\n af199eeaa23c5b39e08b4649f2513d7572dc5274 deps/development-guidelines (remotes/origin/HEAD)\n a3ee67bba269e1276c14e22c026171ecf2cf6190 deps/error-code-system (heads/main)\n 49b5d8be604d05e4246dffa0d10fa1c2b7ad45d7 deps/logging-system (heads/main)\n ea4651b1f870d84ab9b72cfa79363b3432d113b3 modules/backend (v0.3.0-28-gea4651b)\n a253a40b8e5563119b00c4e71fb61fe0d11d6d6a modules/core (v0.2.0)\n 3304efee154e218fa223419b624e8cefb4c762e1 modules/documents (remotes/origin/feature/generative-ui-research-1-g3304efe)\n 3ed10e122042a64180fb24a42d9cc6438cd2d2d6 modules/frontend (v0.3.0-4-g3ed10e1)\n 76d6633736a7abb36ac1ecca42fe4e6f120d0558 modules/ui (v0.3.0)\nRDM pins\n421fee81c314c05530bc809e224b5d0818ec3472 pins/agent-system-backend (v0.2.0-40-g421fee8)\n a253a40b8e5563119b00c4e71fb61fe0d11d6d6a pins/agent-system-core (v0.2.0)\n 84b73ab32848e623d0a0ab7ade552784dca8cf3c pins/agent-system-frontend (v0.2.0)\n 76d6633736a7abb36ac1ecca42fe4e6f120d0558 pins/agent-system-ui (v0.2.0)\n{\"repo\": \"RDM\", \"path\": \"internal/rdmapp/runtime.go\", \"sha256\": \"4b814b94b26672dc93c528e76084078aee6483efcb9d89e4eb32fb20d60f5205\"}\n75: // WorldFor 取项目分片世界(G1-2:只含该项目事件;重放自库、写穿带 project 戳)。\n76: // 空项目串非法(存量未归属域不经此入口暴露——先归属,后可见)。缓存按项目复用;\n77: // 存量归属执行后由调用方触发失效重建。\n78: func (rt *Runtime) WorldFor(project string) (*domain.World, error) {\n79: \tif project == \"\" {\n80: \t\treturn nil, fmt.Errorf(\"rdmapp: 项目 ID 必填(存量未归属数据须经 rdm.project.migrate 先归属)\")\n81: \t}\n82: \tps, err := rt.Projects()\n83: \tif err != nil {\n84: \t\treturn nil, err\n85: \t}\n86: \tif err := ps.MustExist(project); err != nil {\n87: \t\treturn nil, err\n88: \t}\n89: \trt.worldsMu.Lock()\n90: \tdefer rt.worldsMu.Unlock()\n91: \tif w, ok := rt.worlds[project]; ok {\n92: \t\treturn w, nil\n93: \t}\n94: \tw, err := domain.LoadWorldForProject(rt.Dict, rt.Store, project)\n95: \tif err != nil {\n96: \t\treturn nil, err\n97: \t}\n98: \tw.Log().UseSeqAllocator(rt.nextSeq)\n99: \tif rt.worlds == nil {\n100: \t\trt.worlds = map[string]*domain.World{}\n101: \t}\n102: \trt.worlds[project] = w\n103: \treturn w, nil\n104: }\n105: \n106: // worldForParam 命令层世界选择:非空 projectId → 分片世界(WorldFor 校验+缓存);\n107: // 空串=过渡期全量世界(命令面未迁移调用点的兼容档,切片 2 逐步收窄)。\n108: func (rt *Runtime) worldForParam(projectID string) (*domain.World, error) {\n109: \tif projectID == \"\" {\n110: \t\treturn rt.World, nil\n111: \t}\n112: \treturn rt.WorldFor(projectID)\n113: }\n114: \n115: // WorldForParam worldForParam 的导出面(G1-5:插件命令层按 projectId 选世界)。\n116: func (rt *Runtime) WorldForParam(projectID string) (*domain.World, error) {\n117: \treturn rt.worldForParam(projectID)\n135: // AuthorizeProjectResource EXT-8 适配器判定(供插件注册转发)。\n136: func (rt *Runtime) AuthorizeProjectResource(owner string, projectID core.ID) (bool, error) {\n137: \tms, err := rt.Members()\n138: \tif err != nil {\n139: \t\treturn false, err\n140: \t}\n141: \treturn ms.IsMember(owner, string(projectID)), nil\n142: }\n{\"repo\": \"RDM\", \"path\": \"internal/projects/projects.go\", \"sha256\": \"b857bf3db7e30616cd17ac68a4239cc9ed9baea5435e7135bd3277a1c7997e11\"}\n17: // Project 一条研发项目注册行。\n18: type Project struct {\n19: \tID string\n20: \tName string\n21: \tCreatedBy string\n22: \tCreatedAt time.Time\n23: }\n24: \n{\"repo\": \"RDM\", \"path\": \"internal/rdmapp/projects_api.go\", \"sha256\": \"87951d8f46f1e112e0591f79e670cf2c7bc0a34712fe1167746c606b0bc723ec\"}\n14: func CreateProject(name, by string) (projects.Project, error) {\n15: \trt, err := Get()\n16: \tif err != nil {\n17: \t\treturn projects.Project{}, err\n18: \t}\n19: \tps, err := rt.Projects()\n20: \tif err != nil {\n21: \t\treturn projects.Project{}, err\n22: \t}\n23: \tp, err := ps.Create(name, by)\n24: \tif err != nil {\n25: \t\tif errors.Is(err, projects.ErrNameTaken) {\n26: \t\t\treturn p, fmt.Errorf(\"项目名已占用:%s(研发项目名全局唯一,请换名)\", name)\n27: \t\t}\n28: \t\treturn p, err\n29: \t}\n30: \tpermStore, err := rt.Perms()\n31: \tif err == nil {\n32: \t\tif n, cerr := permStore.AdminCount(); cerr == nil && n == 0 {\n33: \t\t\t_, _ = permStore.BootstrapAdmin(by)\n34: \t\t}\n35: \t}\n36: \tif ms, merr := rt.Members(); merr == nil {\n37: \t\t_ = ms.AddRole(p.ID, by, \"owner\", by)\n38: \t}\n39: \treturn p, nil\n40: }\n41: \n42: // ListProjects 列出全部研发项目。\n43: func ListProjects() ([]projects.Project, error) {\n44: \trt, err := Get()\n45: \tif err != nil {\n46: \t\treturn nil, err\n47: \t}\n48: \tps, err := rt.Projects()\n49: \tif err != nil {\n50: \t\treturn nil, err\n51: \t}\n52: \treturn ps.List()\n{\"repo\": \"RDM\", \"path\": \"internal/domain/notetree.go\", \"sha256\": \"79b0e740da9156e97c80912972ac43aaa1326d1961e7425b913561c24cd7b15d\"}\n64: // 挂载点须已存在;空挂载允许(先入库后整理)。\n65: func (t *NoteTree) Ingest(content string, anchor Anchor, labels LabelSet, summary string,\n66: \tsrc Provenance, batch string, mounts []string, actor string) (*Slice, error) {\n67: \tif err := t.dict.Validate(labels); err != nil {\n68: \t\treturn nil, err\n69: \t}\n70: \tfor _, m := range mounts {\n71: \t\tif _, ok := t.spine[m]; !ok {\n72: \t\t\treturn nil, fmt.Errorf(\"domain: 挂载点 %s 不存在\", m)\n73: \t\t}\n74: \t}\n75: \ts := &Slice{ID: newID(KindSlice), Content: content, Anchor: anchor, Labels: labels,\n76: \t\tSummary: summary, Source: src, Batch: batch, IngestedAt: t.log.clock()}\n77: \t// 事件先行(含挂载事件),全部落库后才改内存——落库失败零结构变更。\n78: \tif _, err := t.log.Append(OpSliceIngest, actor, src, s.Ref(), nil,\n79: \t\tfmt.Sprintf(\"入库 %q(批次 %s)\", s.Summary, batch), marshalJSON(slicePayload{\n80: \t\t\tID: s.ID, Content: content, Anchor: anchor, Labels: labels,\n81: \t\t\tSummary: summary, Batch: batch,\n82: \t\t})); err != nil {\n83: \t\treturn nil, err\n84: \t}\n85: \tfor _, m := range mounts {\n86: \t\tref := t.spine[m].Ref()\n87: \t\tif _, err := t.log.Append(OpMountAdd, actor, src, s.Ref(), &ref, \"\", nil); err != nil {\n88: \t\t\treturn nil, err\n89: \t\t}\n90: \t}\n91: \tt.slices[s.ID] = s\n92: \tfor _, m := range mounts {\n93: \t\tt.mounts[s.ID] = append(t.mounts[s.ID], m)\n94: \t}\n95: \treturn s, nil\n96: }\n101: \tif !ok || s.Deleted() {\n102: \t\treturn fmt.Errorf(\"domain: 切片 %s 不存在或已删除\", sliceID)\n103: \t}\n104: \tif err := t.dict.Validate(next); err != nil {\n105: \t\treturn err\n106: \t}\n107: \tprev := s.Labels\n108: \ts.Labels = next\n109: \t_, err := t.log.Append(OpSliceRetag, actor, src, s.Ref(), nil,\n110: \t\tfmt.Sprintf(\"标签 %s → %s\", prev.Stage, next.Stage), marshalJSON(retagPayload{ID: s.ID, Labels: next}))\n111: \treturn err\n112: }\n113: \n114: // MoveMount 摘挂 + 挂入(迁移留痕);影响已基线内容时由上层触发变更流程(08 §8.3)。\n115: func (t *NoteTree) MoveMount(sliceID, fromSpine, toSpine, actor string, src Provenance) error {\n{\"repo\": \"RDM\", \"path\": \"internal/domain/tracenet.go\", \"sha256\": \"ee7422c3633719f41427dbf188b8a8db8f8c519612fd34c6ff24c4f706f385a2\"}\n55: \treturn &TraceNet{edges: map[string]*Edge{}, log: log}\n56: }\n57: \n58: // Link 建边:人工/规则直接生效;模型候选落 candidate 等待确认(SR-D1/E3)。\n59: func (n *TraceNet) Link(from, to Ref, typ EdgeType, src Provenance, conf float64, actor string) (*Edge, error) {\n60: \te := &Edge{ID: newID(KindEdge), From: from, To: to, Type: typ, Conf: conf,\n61: \t\tSource: src, At: n.log.clock()}\n62: \tif src == ByModel {\n63: \t\te.State = EdgeCandidate\n64: \t} else {\n65: \t\te.State = EdgeActive\n66: \t}\n67: \tif _, err := n.log.Append(OpEdgeCandidate, actor, src, e.Ref(), &to, string(typ),\n68: \t\tmarshalJSON(edgePayload{ID: e.ID, From: from, To: to, Type: typ, Conf: conf})); err != nil {\n69: \t\treturn nil, err\n70: \t}\n71: \tif e.State == EdgeActive { // 人工/规则的生效迁移也留痕\n72: \t\tif _, err := n.log.Append(OpEdgeConfirm, actor, src, e.Ref(), &to, string(typ), nil); err != nil {\n73: \t\t\treturn nil, err\n74: \t\t}\n75: \t}\n76: \tn.edges[e.ID] = e\n77: \treturn e, nil\n78: }\n79: \n80: // Confirm 候选 → 生效(R3:只有候选可确认)。\n81: func (n *TraceNet) Confirm(edgeID, actor string) error {\n82: \te, ok := n.edges[edgeID]\n83: \tif !ok || e.Retired() {\n84: \t\treturn fmt.Errorf(\"domain: 边 %s 不存在或已废止\", edgeID)\n85: \t}\n86: \tif e.State != EdgeCandidate {\n87: \t\treturn ErrNotCandidate\n88: \t}\n89: \tif _, err := n.log.Append(OpEdgeConfirm, actor, ByHuman, e.Ref(), &e.To, string(e.Type), nil); err != nil {\n90: \t\treturn err\n91: \t}\n92: \te.State = EdgeActive\n93: \treturn nil\n94: }\n95: \n96: // Retire 废止(软删,R2/R3):须理由与操作者。\n{\"repo\": \"RDM\", \"path\": \"internal/domain/compliance.go\", \"sha256\": \"3f118f21e0c4d58ca8584310e329615010b9b21a860d522f0e9b9e4fc1c015e0\"}\n162: func (w *World) AddCNodeBump(kind CNodeKind, id, title, payload, actor string) (CNode, error) {\n163: \tg := w.cgraphOf()\n164: \tver := 0\n165: \tfor v := range g.nodes[kind.String()+\":\"+id] {\n166: \t\tif v > ver {\n167: \t\t\tver = v\n168: \t\t}\n169: \t}\n170: \tn, err := w.addCNodeVer(kind, id, ver, title, payload, actor)\n171: \tif err != nil {\n172: \t\treturn n, err\n173: \t}\n174: \tw.markStaleEdges(kind, id)\n175: \treturn n, nil\n176: }\n177: \n178: func (w *World) addCNodeVer(kind CNodeKind, id string, prevVer int, title, payload, actor string) (CNode, error) {\n179: \tif title == \"\" || actor == \"\" {\n308: func (w *World) CSnapshots() []ComplianceSnapshot {\n309: \tg := w.cgraphOf()\n310: \tout := make([]ComplianceSnapshot, len(g.snaps))\n311: \tcopy(out, g.snaps)\n312: \treturn out\n313: }\n314: \n315: // TakeComplianceSnapshot 基线/正式版批准时生成合规快照(不可变;active 边+\n316: // 全部节点版本;内容哈希覆盖节点/边/规则版本——审计比对锚)。\n317: func (w *World) TakeComplianceSnapshot(scope, approver string) (ComplianceSnapshot, error) {\n318: \tif scope == \"\" || approver == \"\" {\n319: \t\treturn ComplianceSnapshot{}, fmt.Errorf(\"domain: 快照 scope/approver 必填\")\n320: \t}\n321: \tnodes := w.CNodes()\n322: \tedges := w.ComplianceEdges()\n323: \th := hashCGraph(nodes, edges, \"viewrules-v0\")\n324: \ts := ComplianceSnapshot{ID: fmt.Sprintf(\"csnap-%d\", w.log.clock().UnixNano()),\n325: \t\tScope: scope, Nodes: nodes, Edges: edges, ViewRules: \"viewrules-v0\",\n326: \t\tHash: h, Approver: approver, At: w.log.clock()}\n327: \tg := w.cgraphOf()\n328: \tg.snaps = append(g.snaps, s)\n329: \tpl := cSnapPayload{ID: s.ID, Scope: scope, Hash: h, Approver: approver,\n330: \t\tNodes: len(nodes), Edges: len(edges)}\n331: \tif _, err := w.log.Append(OpCSnapAdd, approver, ByHuman,\n332: \t\tRef{Kind: KindSection, ID: \"cgraph\"}, nil,\n333: \t\tfmt.Sprintf(\"合规快照 %s(%s):节点 %d 边 %d 哈希 %s\", s.ID, scope, len(nodes), len(edges), h[:12]),\n334: \t\tmarshalJSON(pl)); err != nil {\n335: \t\treturn ComplianceSnapshot{}, err\n336: \t}\n{\"repo\": \"RDM\", \"path\": \"internal/domain/replay.go\", \"sha256\": \"fe99bfb403b5f07b64338f1493feea798995ac20735f2e2e9d66c6041f87f3d2\"}\n230: \tcase OpCNodeAdd:\n231: \t\tvar p cNodePayload\n232: \t\tif err := json.Unmarshal(ev.Payload, &p); err != nil {\n233: \t\t\treturn err\n234: \t\t}\n235: \t\tg := w.cgraphOf()\n236: \t\tif g.nodes[p.Kind+\":\"+p.ID] == nil {\n237: \t\t\tg.nodes[p.Kind+\":\"+p.ID] = map[int]CNode{}\n238: \t\t}\n239: \t\tg.nodes[p.Kind+\":\"+p.ID][p.Ver] = CNode{\n240: \t\t\tCNodeVerRef: CNodeVerRef{Kind: CNodeKind(p.Kind), ID: p.ID, Ver: p.Ver},\n241: \t\t\tTitle: p.Title, Payload: p.Payload, At: ev.At, Actor: ev.Actor}\n242: \t\treturn nil\n243: \n244: \tcase OpCEdgeConfirm:\n245: \t\tvar p cEdgePayload\n246: \t\tif err := json.Unmarshal(ev.Payload, &p); err != nil {\n247: \t\t\treturn err\n248: \t\t}\n249: \t\tg := w.cgraphOf()\n250: \t\te := CEdge{Kind: CEdgeKind(p.Kind),\n251: \t\t\tFrom: CNodeVerRef{Kind: CNodeKind(p.FromKind), ID: p.FromID, Ver: p.FromVer},\n252: \t\t\tTo: CNodeVerRef{Kind: CNodeKind(p.ToKind), ID: p.ToID, Ver: p.ToVer},\n253: \t\t\tState: CEdgeState(p.State), Propose: p.Propose, By: p.By, At: ev.At}\n254: \t\t// 重放升版语义:若同端点旧状态存在(stale 标记由升版路径在写侧做),\n255: \t\t// 直接追加——stale 由 cnode.add 升版时按当前边集重算(见下)。\n256: \t\tg.edges = append(g.edges, e)\n257: \t\treturn nil\n258: \n259: \tcase OpCSnapAdd:\n260: \t\tvar p cSnapPayload\n261: \t\tif err := json.Unmarshal(ev.Payload, &p); err != nil {\n262: \t\t\treturn err\n263: \t\t}\n264: \t\tg := w.cgraphOf()\n265: \t\tg.snaps = append(g.snaps, ComplianceSnapshot{ID: p.ID, Scope: p.Scope,\n266: \t\t\tHash: p.Hash, Approver: p.Approver, At: ev.At})\n267: \t\treturn nil\n268: \n269: \tcase OpSectionVer:\n270: \t\tvar p versionPayload\n369: \tcase \"approve\":\n370: \t\tif rs.card != nil && p.Reviewer != \"\" {\n371: \t\t\tif _, is := rs.card.Reviews[p.Reviewer]; is {\n372: \t\t\t\trs.card.Reviews[p.Reviewer] = true\n373: \t\t\t}\n374: \t\t}\n375: \tcase \"reject\":\n376: \t\trs.card = nil\n377: \tcase \"final\":\n378: \t\tif p.Formal != nil {\n379: \t\t\tf := FormalRevInfo{Rev: p.Formal.Rev, Seq: p.Formal.Seq, At: time.Time{}, Actor: \"\"}\n380: \t\t\tif p.Formal.SupersedesRev > 0 {\n381: \t\t\t\tfor i := range rs.formal {\n382: \t\t\t\t\tif rs.formal[i].Rev == p.Formal.SupersedesRev {\n383: \t\t\t\t\t\tprev := rs.formal[i]\n384: \t\t\t\t\t\tf.Supersedes = &prev\n385: \t\t\t\t\t}\n386: \t\t\t\t}\n387: \t\t\t}\n388: \t\t\trs.formal = append(rs.formal, f)\n389: \t\t}\n390: \t\trs.card = nil\n391: \t}\n392: }\n393: \n394: // applyLegacyReviewDetail 解析旧实现(G0-2 之前)以 OpSectionState + 自由文本\n{\"repo\": \"RDM\", \"path\": \"internal/rdmapp/conclusions.go\", \"sha256\": \"e467cbecab7058b76258f1da7c8abc139c5f8540e48ea11abbfce212f39f2cd7\"}\n254: \trt, err := Get()\n255: \tif err != nil {\n256: \t\treturn domain.Conclusion{}, err\n257: \t}\n258: \tw, err := rt.worldForParam(project)\n259: \tif err != nil {\n260: \t\treturn domain.Conclusion{}, err\n261: \t}\n262: \tvar text, bucket, basisJSON, labelsJSON string\n263: \tvar labels domain.LabelSet\n264: \terr = rt.Store.RawDB().QueryRow(`SELECT text,bucket,basis_json,labels_json FROM rdm_conclusion_proposals\n265: \t\tWHERE id=? AND state='pending'`, proposalID).Scan(&text, &bucket, &basisJSON, &labelsJSON)\n266: \tif err == sql.ErrNoRows {\n267: \t\treturn domain.Conclusion{}, fmt.Errorf(\"rdmapp: 提议 %s 不存在或已决策\", proposalID)\n268: \t}\n269: \tif err != nil {\n270: \t\treturn domain.Conclusion{}, err\n271: \t}\n272: \t_ = json.Unmarshal([]byte(labelsJSON), &labels)\n273: \t// 依据:命令传入优先;回落提议自带。\n274: \tvar refs []domain.Ref\n275: \tfor _, b := range basis {\n276: \t\tfor i := 0; i < len(b); i++ {\n277: \t\t\tif b[i] == ':' {\n278: \t\t\t\trefs = append(refs, domain.Ref{Kind: domain.Kind(b[:i]), ID: b[i+1:]})\n279: \t\t\t\tbreak\n280: \t\t\t}\n281: \t\t}\n282: \t}\n283: \tif len(refs) == 0 {\n284: \t\tvar legacy []string\n285: \t\t_ = json.Unmarshal([]byte(basisJSON), &legacy)\n286: \t\tfor _, b := range legacy {\n287: \t\t\tfor i := 0; i < len(b); i++ {\n288: \t\t\t\tif b[i] == ':' {\n289: \t\t\t\t\trefs = append(refs, domain.Ref{Kind: domain.Kind(b[:i]), ID: b[i+1:]})\n290: \t\t\t\t\tbreak\n291: \t\t\t\t}\n292: \t\t\t}\n293: \t\t}\n294: \t}\n295: \tc, err := w.AddConclusion(text, refs, labels, \"trigger\", by)\n296: \tif err != nil {\n297: \t\treturn domain.Conclusion{}, err\n298: \t}\n299: \t_, err = rt.Store.RawDB().Exec(`UPDATE rdm_conclusion_proposals SET state='confirmed', decided_by=?, decision=? WHERE id=?`,\n300: \t\tby, \"confirmed:\"+c.ID, proposalID)\n301: \tif err != nil {\n302: \t\treturn domain.Conclusion{}, err\n303: \t}\n304: \treturn c, nil\n{\"repo\": \"RDM\", \"path\": \"internal/rdmapp/trace.go\", \"sha256\": \"76288d9cc879011341085b5dbbd1ef0769a3b7896c1a48d9f987aa00b6c05ae5\"}\n31: func Trace(_ context.Context, _ extension.Host, projectID, sectionID string) (*TraceResult, error) {\n32: \trt, err := Get()\n33: \tif err != nil {\n34: \t\treturn nil, err\n35: \t}\n36: \tw, err := rt.worldForParam(projectID)\n37: \tif err != nil {\n38: \t\treturn nil, err\n39: \t}\n40: \tsec, ok := w.Docs.Section(sectionID)\n41: \tif !ok {\n42: \t\treturn nil, errParam(\"章节不存在: \" + sectionID)\n43: \t}\n44: \tref := sec.Ref()\n45: \tres := &TraceResult{SectionID: sectionID, Title: sec.Title}\n46: \tfor _, e := range w.Net.EdgesWhere(func(e *domain.Edge) bool {\n47: \t\treturn e.To == ref || e.From == ref\n48: \t}) {\n49: \t\tother := e.From\n50: \t\tif e.From == ref {\n131: func Graph(projectID string) (*GraphResult, error) {\n132: \trt, err := Get()\n133: \tif err != nil {\n134: \t\treturn nil, err\n135: \t}\n136: \tw, err := rt.worldForParam(projectID)\n137: \tif err != nil {\n138: \t\treturn nil, err\n139: \t}\n140: \tres := &GraphResult{}\n141: \tfor _, s := range w.Notes.Query(domain.LabelCondition{}) {\n142: \t\tres.Nodes = append(res.Nodes, GraphNode{ID: s.ID, Kind: \"slice\",\n143: \t\t\tTitle: firstNonEmpty(s.Summary, truncate(s.Content, 18)), Col: 0})\n144: \t}\n145: \tfor _, d := range w.Docs.AllDocs() {\n146: \t\tfor _, sec := range d.Sections {\n147: \t\t\tif sec.Deleted() {\n148: \t\t\t\tcontinue\n149: \t\t\t}\n150: \t\t\tres.Nodes = append(res.Nodes, GraphNode{ID: sec.ID, Kind: \"section\",\n151: \t\t\t\tTitle: firstNonEmpty(sec.Title, sec.ID), Col: 1})\n152: \t\t}\n153: \t}\n154: \tfor _, ev := range w.Log().Snapshot() {\n155: \t\tif ev.Op != domain.OpOpenItemAdd {\n156: \t\t\tcontinue\n157: \t\t}\n158: \t\tif o, ok := w.Reg.Item(ev.Target.ID); ok && o.Open() {\n159: \t\t\tres.Nodes = append(res.Nodes, GraphNode{ID: o.ID, Kind: \"open-item\",\n160: \t\t\t\tTitle: truncate(o.Statement, 18), Col: 2})\n161: \t\t}\n205: func Hops(_ context.Context, _ extension.Host, projectID, refID string, depth int) (*HopsResult, error) {\n206: \trt, err := Get()\n207: \tif err != nil {\n208: \t\treturn nil, err\n209: \t}\n210: \tw, err := rt.worldForParam(projectID)\n211: \tif err != nil {\n212: \t\treturn nil, err\n213: \t}\n214: \tif depth <= 0 || depth > 5 {\n215: \t\tdepth = 2\n216: \t}\n217: \t// 判起点种类\n218: \tstartKind := \"slice\"\n219: \tif _, ok := w.Docs.Section(refID); ok {\n220: \t\tstartKind = \"section\"\n{\"repo\": \"RDM\", \"path\": \"internal/domain/persist.go\", \"sha256\": \"8655272bc532a927b224c25cb5a051ddfe0ae5414c53d80bbe739b01a1680b1e\"}\n108: \n109: // SaveWorldSnapshot / LoadWorldSnapshotAt:R5 加速层——序列化重放产物,\n110: // 读回 ≤at 最近快照。语义校验仍以事件重放为准(调用方按需比对)。\n111: func SaveWorldSnapshot(w *World, s *store.Store) error {\n112: \tevents := w.Log().Snapshot()\n113: \tat := time.Time{}\n114: \tif len(events) > 0 {\n115: \t\tat = events[len(events)-1].At\n116: \t}\n117: \tblob, err := json.Marshal(struct {\n118: \t\tAt time.Time `json:\"at\"`\n119: \t\tNotes int `json:\"notes\"`\n120: \t\tDocs int `json:\"docs\"`\n121: \t\tEdges int `json:\"edges\"`\n122: \t\tOpen int `json:\"openItems\"`\n123: \t\tLastSeq int64 `json:\"lastSeq\"`\n124: \t}{At: at, LastSeq: lastSeq(events),\n125: \t\tNotes: len(w.Notes.Query(LabelCondition{})),\n126: \t\tDocs: len(w.Docs.docs), Edges: len(w.Net.edges), Open: openItems(w)})\n127: \tif err != nil {\n128: \t\treturn err\n129: \t}\n130: \treturn s.SaveSnapshot(at, blob)\n131: }\n132: \n{\"repo\": \"RDM\", \"path\": \"plugins/rdm/plugin.go\", \"sha256\": \"364b0909a9f48597e375139d0b7248c9fcea72c3f1fc1a22b9c66808792b7df1\"}\n737: func rdmTrace(ctx context.Context, h extension.Host, req extension.Request) (any, error) {\n738: \tid, _ := req.Params[\"sectionId\"].(string)\n739: \tpid, _ := req.Params[\"projectId\"].(string)\n740: \treturn rdmapp.Trace(ctx, h, pid, id)\n741: }\n742: \n743: func rdmTraceGraph(ctx context.Context, h extension.Host, req extension.Request) (any, error) {\n744: \tpid, _ := req.Params[\"projectId\"].(string)\n745: \treturn rdmapp.Graph(pid)\n746: }\n747: \n748: func rdmTraceHops(ctx context.Context, h extension.Host, req extension.Request) (any, error) {\n749: \tid, _ := req.Params[\"ref\"].(string)\n750: \tdepth := 2\n751: \tif d, ok := req.Params[\"depth\"].(float64); ok && int(d) > 0 {\n752: \t\tdepth = int(d)\n753: \t}\n754: \tpid, _ := req.Params[\"projectId\"].(string)\n755: \treturn rdmapp.Hops(ctx, h, pid, id, depth)\n756: }\n757: \n758: func rdmTraceConfirm(ctx context.Context, h extension.Host, req extension.Request) (any, error) {\n759: \tid, _ := req.Params[\"edgeId\"].(string)\n760: \tpid, _ := req.Params[\"projectId\"].(string)\n761: \tres, err := rdmapp.TraceConfirm(ctx, h, pid, id, req.Actor)\n1390: \tpid, _ := req.Params[\"projectId\"].(string)\n1391: \treturn rdmapp.CGraphSummary(pid)\n1392: }\n1393: \n1394: func rdmCGraphView(ctx context.Context, h extension.Host, req extension.Request) (any, error) {\n1395: \tpid, _ := req.Params[\"projectId\"].(string)\n1396: \tview, _ := req.Params[\"view\"].(string)\n1397: \tif view == \"\" {\n1398: \t\treturn nil, rdmapp.ErrParam(\"view 必填(13485|sw0664|hardware|risk)\")\n1399: \t}\n1400: \treturn rdmapp.CGraphChainView(pid, view)\n1401: }\n1402: \n1403: func rdmCGraphMatrix(ctx context.Context, h extension.Host, req extension.Request) (any, error) {\n1404: \tpid, _ := req.Params[\"projectId\"].(string)\n1405: \tfrom, _ := req.Params[\"from\"].(string)\n1406: \tto, _ := req.Params[\"to\"].(string)\n1407: \tif from == \"\" || to == \"\" {\n1408: \t\treturn nil, rdmapp.ErrParam(\"from/to 必填(受控节点类型,如 UN/PR)\")\n1409: \t}\n1410: \treturn rdmapp.CGraphMatrix(pid, from, to)\n1411: }\n1412: \n1413: func rdmCGraphExport(ctx context.Context, h extension.Host, req extension.Request) (any, error) {\n1414: \tpid, _ := req.Params[\"projectId\"].(string)\n1415: \tformat, _ := req.Params[\"format\"].(string)\n1438: func rdmProjectCreate(ctx context.Context, h extension.Host, req extension.Request) (any, error) {\n1439: \tname, _ := req.Params[\"name\"].(string)\n1440: \tif name == \"\" {\n1441: \t\treturn nil, rdmapp.ErrParam(\"name 必填\")\n1442: \t}\n1443: \tp, err := rdmapp.CreateProject(name, req.Actor)\n1444: \tif err != nil {\n1445: \t\treturn nil, err\n1446: \t}\n1447: \t_ = h.Audit(\"rdm.project.create\", p.ID, \"name=\"+p.Name)\n1448: \treturn map[string]any{\"projectId\": p.ID, \"name\": p.Name, \"createdBy\": p.CreatedBy}, nil\n1449: }\n1450: \n1451: func rdmProjectList(ctx context.Context, h extension.Host, req extension.Request) (any, error) {\n1452: \tlist, err := rdmapp.ListProjects()\n1453: \tif err != nil {\n1454: \t\treturn nil, err\n1455: \t}\n1456: \tlegacy, err := rdmapp.LegacyStats()\n1457: \tif err != nil {\n1458: \t\treturn nil, err\n1459: \t}\n1460: \tout := []map[string]any{}\n1461: \tfor _, p := range list {\n1462: \t\tout = append(out, map[string]any{\"projectId\": p.ID, \"name\": p.Name,\n1463: \t\t\t\"createdBy\": p.CreatedBy, \"createdAt\": p.CreatedAt})\n1464: \t}\n1465: \treturn map[string]any{\"projects\": out, \"legacyUnattributedEvents\": legacy}, nil\n{\"repo\": \"RDM\", \"path\": \"web/app.js\", \"sha256\": \"37c7a0847ddc1903d7bf3679ddef71b5fed3c98fe268f621453456ff6eaa7a3f\"}\n69: async function command(id, params = {}) {\n70: const out = await api(`/api/commands/${encodeURIComponent(id)}`, { params, conversationId: state.conversationId || '' });\n71: const st = out?.receipt?.state;\n72: if (st === 'rejected') throw new Error(out.receipt.error || out.receipt.message || '命令被拒绝');\n73: if (out?.card) throw new Error('高危命令已生成确认卡——请点击右侧卡片上的「确认执行/取消」按钮');\n74: return out?.payload !== undefined ? out.payload : out;\n75: }\n76: \n77: // danger 命令 UI 触发的提示分流:确认卡≠失败——指引去卡片按钮完成闭环。\n78: const confirmHint = (e) => {\n79: if (String(e.message).includes('确认卡')) sys('已生成确认卡——请在右侧卡片上点「确认执行」。');\n80: else sys(`执行失败:${e.message}`);\n165: // ---- 命令分发与卡片渲染 ----\n166: const KNOWN = ['rdm.baseline', 'rdm.gap', 'rdm.draft', 'rdm.draft.compose', 'rdm.conflicts'];\n167: \n168: // ---- F1 上传五步(📎 与对话双入口同源:ensureProject → 基座 uploads → rdm.upload)----\n169: \n170: // GET /api/projects 兜底取/建项目:基座 uploads 是项目级落点,工作台无项目概念,取首个/建默认。\n171: async function ensureProject() {\n172: if (state.projectId) return state.projectId;\n173: const res = await fetch(state.baseUrl + '/api/projects', {\n174: headers: state.token ? { Authorization: `Bearer ${state.token}` } : {},\n175: });\n176: if (!res.ok) throw new Error(`projects ${res.status}`);\n177: const list = await res.json();\n178: const first = Array.isArray(list) ? list[0] : (list?.projects || [])[0];\n179: if (first?.id) {\n180: state.projectId = first.id;\n181: return state.projectId;\n182: }\n183: const created = await fetch(state.baseUrl + '/api/projects', {\n184: method: 'POST',\n185: headers: { 'Content-Type': 'application/json', ...(state.token ? { Authorization: `Bearer ${state.token}` } : {}) },\n186: body: JSON.stringify({ name: 'RDM 自身研发' }),\n911: async function openTraceOverlay() {\n912: closeOverlay();\n913: const g = await command('rdm.trace.graph', {});\n914: const ov = document.createElement('div');\n915: ov.className = 'overlay';\n916: ov.id = 'ov-trace';\n917: ov.addEventListener('click', (e) => { if (e.target === ov) closeOverlay(); });\n918: const panel = document.createElement('div');\n919: panel.className = 'ov-panel';\n920: const head = document.createElement('div');\n921: head.className = 'ov-head';\n922: const ht = document.createElement('div');\n923: const h1 = document.createElement('div');\n924: h1.className = 'ov-title';\n925: h1.textContent = '追溯网';\n926: const h2 = document.createElement('div');\n{\"repo\": \"Dev\", \"path\": \"modules/backend/pkg/extension/host.go\", \"sha256\": \"a8a8c05eaf2e611375bead39fe383c7a1bed251e547d3b526e7e88c509ec7db2\"}\n9: // Request 是进程内命令处理器收到的一次分发请求(cmdbus.Request 的子集)。\n10: type Request struct {\n11: \tID string\n12: \tParams map[string]any\n13: \tEntrance string // button | card | slash | chat | api(归一)\n14: \tActor string\n15: \tOwner string\n16: \tConversationID string\n17: }\n18: \n19: // Handler 是下游注册的进程内命令处理器:每次分发由基座构造 owner 作用域的\n20: // Host 句柄传入,处理器经句柄访问基座能力,不得自行越权持有 owner 凭证。\n21: type Handler func(ctx context.Context, h Host, req Request) (any, error)\n22: \n23: // Host 是基座在分发时构造的 owner 作用域宿主句柄(EXT-1 最小集 + EXT-5 解析)。\n24: // 所有能力的可见范围都以本次分发的 Owner 为准;artifacts 只读\n25: // (写入属完整集,另行评估)。实现由基座 internal 提供。\n26: type Host interface {\n27: \t// PluginID 返回注册处理器的插件标识(形如 rdm)。\n28: \tPluginID() string\n29: \t// Owner 返回本次分发的作用域 owner。\n30: \tOwner() string\n31: \n32: \t// KVPut/KVGet 插件 KV(按 pluginID+owner 隔离)。\n33: \tKVPut(key, value string) error\n34: \tKVGet(key string) (value string, ok bool, err error)\n35: \n36: \t// Audit 写一条 owner 名下的审计事件。\n37: \tAudit(action, target, evidence string) error\n38: \n{\"repo\": \"Dev\", \"path\": \"modules/backend/internal/store/platform.go\", \"sha256\": \"a565d901a9277d6724f6fe0d2fb0c13dd8d06ad084dda04e5e6fc78a781a2db0\"}\n187: type AuditEvent struct {\n188: \tID int64 `json:\"id\"`\n189: \tTime string `json:\"time\"`\n190: \tOwner string `json:\"owner\"`\n191: \tAction string `json:\"action\"`\n192: \tActor string `json:\"actor,omitempty\"`\n193: \tTarget string `json:\"target,omitempty\"`\n194: \tEvidence string `json:\"evidence,omitempty\"`\n195: \tTraceID string `json:\"traceId,omitempty\"`\n196: }\n197: \n198: func (s *Store) AppendAuditEvent(ev AuditEvent) error {\n199: \tif ev.Time == \"\" {\n200: \t\tev.Time = time.Now().UTC().Format(time.RFC3339)\n201: \t}\n202: \t_, err := s.db.Exec(s.q(`INSERT INTO audit_events(time,owner,action,actor,target,evidence,trace_id) VALUES(?,?,?,?,?,?,?)`),\n203: \t\tev.Time, ev.Owner, ev.Action, ev.Actor, ev.Target, ev.Evidence, ev.TraceID)\n204: \treturn err\n205: }\n206: \n207: func (s *Store) ListAuditEvents(owner string, limit int) ([]AuditEvent, error) {\n208: \tif limit <= 0 || limit > 200 {\n209: \t\tlimit = 50\n210: \t}\n211: \trows, err := s.db.Query(s.q(`SELECT id,time,owner,action,actor,target,evidence,trace_id FROM audit_events\n212: \t\tWHERE owner=? OR ?='' ORDER BY id DESC LIMIT ?`), owner, owner, limit)\n213: \tif err != nil {\n214: \t\treturn nil, err\n{\"repo\": \"Dev\", \"path\": \"modules/backend/internal/store/audit.go\", \"sha256\": \"54a7c6ab8315f3c0b3f0ec97ab857925a7a745453a2a41fb28051e54423ecf9a\"}\n32: \tif owner == \"\" {\n33: \t\treturn []agentcommand.AuditEnvelope{}, nil\n34: \t}\n35: \tif limit <= 0 || limit > 500 {\n36: \t\tlimit = 100\n37: \t}\n38: \tvar (\n39: \t\trows *sql.Rows\n40: \t\terr error\n41: \t)\n42: \tif conversationID == \"\" {\n43: \t\trows, err = s.db.Query(s.q(`SELECT payload FROM command_audit WHERE owner=? ORDER BY time DESC LIMIT ?`), owner, limit)\n44: \t} else {\n45: \t\trows, err = s.db.Query(s.q(`SELECT payload FROM command_audit WHERE owner=? AND conversation_id=? ORDER BY time DESC LIMIT ?`), owner, conversationID, limit)\n46: \t}\n47: \tif err != nil {\n48: \t\treturn nil, err\n49: \t}\n50: \tdefer rows.Close()\n51: \tout := []agentcommand.AuditEnvelope{}\n52: \tfor rows.Next() {\n53: \t\tvar raw string\n54: \t\tif err := rows.Scan(&raw); err != nil {\n55: \t\t\treturn nil, err\n{\"repo\": \"Dev\", \"path\": \"modules/backend/internal/app/compiled.go\", \"sha256\": \"5f7da627fedcac99ecc0f50b7ae0a593defa189f77e0e4250f0f5faef1a1b7bc\"}\n31: func (r pluginRegistry) AddCommandHandler(spec json.RawMessage, h extension.Handler) error {\n32: \tif r.bus == nil {\n33: \t\treturn nil\n34: \t}\n35: \tif h == nil {\n36: \t\treturn fmt.Errorf(\"extension: %s: nil command handler\", r.pluginID)\n37: \t}\n38: \tvar s agentcommand.CommandSpec\n39: \tif err := json.Unmarshal(spec, &s); err != nil {\n40: \t\treturn fmt.Errorf(\"extension: command spec: %w\", err)\n41: \t}\n42: \treturn r.bus.RegisterPluginCommand(s, func(ctx context.Context, req cmdbus.Request) (any, error) {\n43: \t\thost := inprocHost{caps: r.caps, pluginID: r.pluginID, owner: req.Owner}\n44: \t\treturn h(ctx, host, extension.Request{\n45: \t\t\tID: req.ID, Params: req.Params, Entrance: req.Entrance,\n46: \t\t\tActor: req.Actor, Owner: req.Owner, ConversationID: req.ConversationID,\n47: \t\t})\n48: \t})\n49: }\n{\"repo\": \"Dev\", \"path\": \"modules/backend/internal/cmdbus/cmdbus.go\", \"sha256\": \"843f31dd2fe23d1ebe0da0a896b95d3040f2a5d0ba0bf200d4146fccab41ffd9\"}\n228: func (b *Bus) Dispatch(ctx context.Context, req Request) Response {\n229: \tstart := b.now()\n230: \treq.Entrance = agentcommand.CanonicalEntrance(req.Entrance)\n231: \treceipt := func(state agentcommand.ResultState, op, reason string) Response {\n232: \t\treturn Response{Receipt: b.auditReceipt(req, state, op, reason, start)}\n233: \t}\n234: \tspec, _, err := b.reg.Resolve(req.ID)\n235: \tif err != nil {\n236: \t\treturn receipt(agentcommand.StateRejected, \"\", \"unknown or disabled command: \"+req.ID)\n237: \t}\n238: \tif err := validateParams(spec.ParamsSchema, req.Params); err != nil {\n239: \t\treturn receipt(agentcommand.StateRejected, \"\", \"params: \"+err.Error())\n240: \t}\n241: \t// 高危收口:非确认入口先落内联确认卡(committed 语义 = 卡已创建;确认后二次分发执行)。\n242: \tif spec.Danger == agentcommand.DangerHigh && !req.Confirmed {\n243: \t\tif b.cards == nil || req.ConversationID == \"\" {\n244: \t\t\treturn receipt(agentcommand.StateRejected, \"\", \"high-danger command requires conversation context for inline confirm\")\n245: \t\t}\n246: \t\tcard, err := b.cards.Create(req.Owner, confirmCard(spec, req), \"cmd:\"+spec.ID)\n247: \t\tif err != nil {\n248: \t\t\treturn receipt(agentcommand.StateUnknown, \"\", \"confirm card: \"+err.Error())\n249: \t\t}\n250: \t\tb.pendMu.Lock()\n251: \t\tb.pending[card.ID] = pending{req: req, cardID: card.ID}\n252: \t\tb.pendMu.Unlock()\n253: \t\tif b.pendingStore != nil {\n254: \t\t\traw, _ := json.Marshal(req)\n255: \t\t\t_ = b.pendingStore.SavePendingConfirm(card.ID, req.Owner, string(raw))\n256: \t\t}\n257: \t\tr := b.auditReceipt(req, agentcommand.StateAccepted, card.ID, \"awaiting explicit confirm\", start)\n258: \t\treturn Response{Receipt: r, Card: &card}\n259: \t}\n260: \th, ok := b.handlers[req.ID]\n261: \tif !ok {\n262: \t\treturn receipt(agentcommand.StateRejected, \"\", \"no host handler bound for \"+req.ID)\n263: \t}\n264: \tpayload, err := h(ctx, req)\n265: \tif err != nil {\n266: \t\treturn receipt(agentcommand.StateRejected, \"\", \"rejected: \"+err.Error())\n267: \t}\n268: \top := fmt.Sprintf(\"op_%s_%d\", strings.ReplaceAll(strings.TrimPrefix(req.ID, \"\"), \".\", \"_\"), b.now().UnixNano())\n269: \treturn Response{Receipt: b.auditReceipt(req, agentcommand.StateCommitted, op, \"\", start), Payload: payload}\n{\"repo\": \"Dev\", \"path\": \"modules/frontend/src/components/AdminZone.tsx\", \"sha256\": \"5b853ae339ffd61f5a88d1102b82c4f63f79390e1073d1519ddde08a57159c3b\"}\n23: const SECTIONS: AdminSectionDef[] = [\n24: { key: 'users', label: '用户管理', icon: 'users', desc: '建号、发放初始密码、重置密码(管理员发放制)', render: () => },\n25: { key: 'profiles', label: '智能体画像', icon: 'bot', desc: '系统级画像:系统提示、工具允许/确认/拒绝清单', render: () => },\n26: { key: 'plugins', label: '插件管理', icon: 'puzzle', desc: '已装载插件清单与热重载(装卸不影响核心)', render: () => },\n27: { key: 'workspaces', label: '插件工作区', icon: 'grid', desc: '插件声明面板与服务端声明工作区', render: () => },\n28: ]\n29: \n30: export function AdminZone() {\n31: const me = useStore(s => s.me)\n32: const [sectionKey, setSectionKey] = useState('users')\n33: // 双保险:入口已在菜单层门控(me?.isAdmin),此处再拦一次(纵深防御)。\n34: if (!me?.isAdmin) return null\n35: const section = SECTIONS.find(s => s.key === sectionKey) ?? SECTIONS[0]\n36: return (\n{\"version\": \"1.27.3\"}\nAPI token verification: authenticated\n{\"repo\": \"Agent-System-Dev\", \"open_prs\": [{\"number\": 325, \"title\": \"U1+U2: team PG tier, atomic migrations, connection budget, real-database CI gate (pin #137/#61)\", \"url\": \"https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/325\", \"head\": \"7134f83fde4634a37b45bb1ced40b35104fc2c1a\", \"base\": \"main\"}, {\"number\": 317, \"title\": \"Align the svc.sh startup precheck with binary auth semantics and keep the reused DSN\", \"url\": \"https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-Dev/pulls/317\", \"head\": \"cd05692e809f3751b30c1583bebbb859410ef172\", \"base\": \"main\"}]}\n{\"repo\": \"Agent-System-Backend\", \"open_prs\": []}\n{\"repo\": \"Agent-System-RDM\", \"open_prs\": [{\"number\": 194, \"title\": \"Close merged task card: feature-g3-native-xlsx (PR #193)\", \"url\": \"https://git-home.u1680832.nyat.app:30319/weichen/Agent-System-RDM/pulls/194\", \"head\": \"fe16a527722973cb8a84440e417f5ad0585c5ae8\", \"base\": \"main\"}]}\n{\"repo\": \"Agent-System-Documents\", \"open_prs\": []}\n{\"heads_after\": {\"Dev\": \"5771d4f1e5b692bce95eb64cc30dc9931079ad12\", \"RDM\": \"0081628a10ec48a36537c6eced11a57439c986fa\"}, \"same_heads\": true, \"business_tests\": \"NOT_RUN\", \"runtime_acceptance\": \"NOT_RUN\"}\n",
+ "output_sha256": "cb2e6ec66105777ba07b6441d395b2a9c5a948f8033caa95060cdcff74ac7d68",
+ "receipt_sha256": "26681e6036c5ccc9e1fc907511b4ebdfb87929b67af93ba1bdbba92ae78304e2"
+}