Files
Agent-System-Dev/policy/governance.md
T

169 lines
14 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# 开发门禁的执行与证据
本文件细化根 AGENTS.md 的启动、验证和回收规则。通用语义以固定的
`deps/development-guidelines` 为准;门禁实现及回归用例随本仓版本管理。
需求表、设计试验、迭代调整、阶段产物、人工决策及智能体 Review/合入按
[迭代交付](delivery.md) 执行。任务卡分别记录授权边界、必要人工决策点、
`agent-per-unit(配置:AGENT-EXECUTION.md)` 实施执行模式、逐单元 Agent 实施收据、
智能体审阅者及对象版本;权威验证与合入仍由 host/主模型执行,worker 局部自检不替代。
本地 evidence 仅记录 SELF 命令,不能证明授权/人工决策或提升为 CI/独立审阅证据。
### Agent 实施收据与来源
每次外部实施尝试须在任务卡「Agent 实施收据」记录:配置摘要(`AGENT-EXECUTION.md` digest)、
角色、声明候选顺序、attempt、CLI/模型、终态、transport、fallback(只表示该行是否为 Codex
紧急尝试),以及源码外原始收据路径。初始生成状态为 `NOT_RUN`。原始事件流与超限输出保留在
源码外;未知终态(`failed-unknown`)与 `scope-expansion` 的隔离工作区须保留待对账,不得静默丢弃。
清理须有精确恢复或保留现场的可复核证据。
候选、尝试上限、Codex 紧急尝试、fallback、fail-stop、尝试结束条件,以及 transport/admit
与 host 豁免路径,以[迭代交付](delivery.md#agent-实施单元与主模型职责)为唯一权威。
## 启动与恢复
从当前检出运行一次启动检查,使用每次唯一、仓外的绝对收据路径:
```bash
make task-triage REQ='<需求>' TRIAGE_RECEIPT=/tmp/my-task-triage.json
RECEIPT=/tmp/my-task-precheck.json CMD="make precheck" make evidence
make task-start NAME=feature/my-task TRIAGE_RECEIPT=/tmp/my-task-triage.json PRECHECK_RECEIPT=/tmp/my-task-precheck.json
```
分流以远端为准(见 [迭代交付](delivery.md) 的两级分支模型)。有候选时先运行
`make task-triage-decide TRIAGE_RECEIPT=… VERDICT=JOIN|NEW …` 写入显式决策与理由。子任务使用
`KIND=child INITIATIVE=feature/<大任务> NAME=feature/<大任务>-<子题>`,收据须为选中该大任务的 JOIN。
`task-start` 对 DECISION_REQUIRED、过期、远端不可核验(REMOTE_UNVERIFIED,退出码 6)或与所选 initiative 不一致的收据直接拒绝,且不建分支。
第一步先捕获原始执行,再创建任务卡;收据保存完整脱敏输出、退出码、执行位置和对象。
第二步核验收据与当前仓库/基线,再创建工作区并导入;不靠事后重跑冒充首次检查。
同一收据不可覆盖。首次检查失败时处理原因,使用新路径重新启动。主干在两步间前进时,
重新确认新的启动基线,不能把旧收据移花接木到新对象。
恢复已有登记任务先捕获本次启动检查,再在原任务 worktree 用
`make task-resume PRECHECK_RECEIPT=/tmp/my-task-resume.json` 验证并原样导入;不重新建分支。
默认 `TASK_WORK_MODE=delivery`,继续要求严格 READY 和当前目标一致。
工作区忙或落后时先由 owner 保存现场并同步。远端不可达时,delivery 恢复仍以 REMOTE_UNVERIFIED 拒绝;
显式 `TASK_WORK_MODE=local` 可在先核验收据、活动任务、原 R0/HEAD/工作区范围后导入 LOCAL_READY 收据,
继续已授权局部工作(子任务仅在远端不可查询时以已登记的本地父分支为参考,且须包含记录的 `parent_head_sha`)。
远端可达但目标或已登记父分支缺失(即使本地同名分支存在)、回退/分叉或无法比较时仍以 REMOTE_UNVERIFIED 拒绝,不导入收据。离线不得建任务、同步、PR 检查、Review/合入或交付,本地参考不视为最新或可交付。
局部恢复接口已具备,正式交付仍按[合入调度](delivery.md#合入调度)的单一最终窗口执行。
启用后,既有任务可以显式选择 local,保持原 R0,标记落后,继续已授权局部工作:
```bash
TASK_WORK_MODE=local RECEIPT=/tmp/my-local-resume.json CMD="make precheck" make evidence
TASK_WORK_MODE=local make task-resume PRECHECK_RECEIPT=/tmp/my-local-resume.json
```
LOCAL_READY 只用于局部恢复;新任务入口始终校验严格 READY,正式验收与合入另行同步。
恢复核验实际 worktree/卡片/分支、R0 祖先关系及源码外原始收据;脏现场、Git 操作和组件漂移仍拒绝。
`resume-local` 只接受 LOCAL_READY 收据,且须同时满足:卡片位于本 worktree 的 `.task/` 且状态未以“已”开头
(已完成/已放弃等闭合任务拒绝);收据内 `[task-state]` 的登记路径与 R0 等于当前登记任务;收据前后与当前 HEAD
一致、工作区干净且组件状态未变;收据 `root_target/immediate_target` 等于卡片范围;目标只允许快进落后,回退或分叉拒绝。
远端跟踪目标 ref 缺失时,local 模式的 precheck 与 `resume-local` 只在当前登记任务身份、本地 R0 对象、R0 为本地 HEAD 祖先、
工作区干净、分支/worktree、组件与范围全部核验通过时继续。缺失或过期的远端 ref 从不证明新鲜度;只要有任一目标历史可用,
其祖先关系须一致。local precheck 刷新失败时,远端不可查询按上述本地核验继续;远端可查询时,以缓存目标(无缓存时为活动任务卡
登记的 R0)为基线,通告提交须本地存在且为基线后代才继续,目标 ref 缺失、回退/分叉或通告提交本地缺失无法比较均判 REMOTE_UNVERIFIED。
正式 Review 与合入仍须先完成新鲜的权威同步。
`resume-delivery` 仍要求 READY 且收据目标等于当前权威目标。LOCAL_READY 始终是 SELF 本地工作记录,
不能用于建任务、正式交付、Review、合入、CI、GATE 或 REPLAY。
旧收据允许作为历史证据原样导入,不自动成为当前恢复或交付准入;格式继续为 schema 1。
堆叠(standalone)任务使用 `PARENT=feature/parent PARENT_PR=<父PR链接>`;子任务改用 `KIND=child`。父分支须包含本批主干 R0;
卡片同时记录父分支、父 SHA 和父 PR。父先合入,子同步最新 main 并改回 main 为 PR base。
当前 `make task-pr-check` 与 CI `PR base gate` 对 standalone PR 只接受 base 为 `main`,因此堆叠 PR 在 base 改回 `main` 前不能通过这两道门禁。
PR 门禁:`make task-pr-check [PR=N] [FINAL=1]` 核验当前分支 PR 的状态、base 与 head(远端为准)。子任务期望 base 为卡片 `immediate_target`(所属大任务分支,且其父仍有开放 PR 指向 `main`);普通任务与大任务为 `main`。`FINAL=1` 仅用于大任务收口,要求 `accepting_requirements=false` 且必需子任务已合入或已延期。
## 被测对象
`make task-sync` 在父仓合并后按固定 gitlink 物化未修改组件,并核对实际组件工作树。
同步目标取卡片 `immediate_target`:子任务为远端所属大任务分支头,其余为 `origin/main`。
组件 feature 分支若与新指针不同,先保留其分支,交给 owner 显式同步并更新组合;
不能用自动 checkout 丢弃组件分支现场。任何失败都保留现场并阻止同步成功声明。
`make test-worktree` 核对递归子模块:未初始化、冲突、指针漂移及子仓未保存改动均拒绝。
它是组合测试和构建的前置检查。父仓未提交改动可以局部测试,但证据必须记录实际对象状态;
正式验收使用已提交的固定对象,不能仅写一个与工作树不同的 HEAD。
`task-sync` 对同一基线重复调用只核验,保留 HEAD、索引和卡片;实际合并新目标才追加一次记录。
输出完整 sync_base、记录完成后的 tested_head、checked_at 及 changed;changed 表示是否实际纳入新目标,组件仍须核对。
## 本地记录与独立证据
本地 `make evidence` 一律生成 SELF。`SRC=GATE/REPLAY` 不可把本地执行升级为权威来源。
GATE 引用受信平台的运行链接、执行身份、完整 SHA 和结果;REPLAY 引用独立审阅者的
环境、命令、对象和结果。审核者核验这些来源,不能只读作者填入的标签。
PR 合入由智能体执行:先完成有效 Review,再同步并解决冲突,核验当前 HEAD 的全部
必需 CI 通过及平台准入后合入;具体步骤与失败出口见 [迭代交付](delivery.md#智能体-review-与-pr-合入)。
闭合 PR 使用同一流程,不以任务卡已回填或本地测试通过代替 CI。
收据中的摘要检测损坏,不是签名或身份凭据。保存的是完整脱敏输出及其 SHA-256;
命令含敏感值时展示脱敏形式,并记录原命令摘要。执行前后对象分别记录;命令改变 HEAD
时不把执行前 SHA 冒充执行后对象。不能读取执行后状态时明确记录缺项。
写入任务卡(`CMD` 直写或 `IMPORT_RECEIPT` 导入)时,卡内只放摘要块(命令、退出码、前后 HEAD、
输出尾部及各摘要);完整收据以 0600 一次性写到仓外的记录路径(默认
`~/.cache/agent-system-dev/evidence/<receipt_sha256>.json`,可用 `AGENT_EVIDENCE_DIR` 覆盖),
不覆盖不同内容。`check-evidence` 在本机可读时用完整收据核对摘要,缺失则警告未验证;两者仍是 SELF。
### 候选固定前后
固定前,完成同步、必要检查、任务卡及本地收据提交,核对干净的组件组合,再读取和推送最终 HEAD。
将这个 head、base、完整组件及相关配置引用到调度尝试;任务卡表内“记录前对象”不当作最终候选。
固定后,本地命令使用源码外唯一 RECEIPT 保存完整输出,平台 CI/Review/合入结果写调度记录:
```bash
RECEIPT=/tmp/my-attempt-worktree-check.json CMD="make test-worktree" make evidence
```
执行者选择位于当前 checkout 和 Git 元数据之外的未用绝对路径,工具保留 before/after、原命令退出码和 SELF 来源。
这是 manual 流程,工具不提供工作树冻结或路径范围的 OS 强制隔离。命令改变源码、组件或相关配置时,
保留实际记录,重新建立尝试及受影响验证;新增提交必须核验新 HEAD 的必需 CI。
后续实际合入/清理后按授权闭合任务,再原样导入已保存收据;不向仍冻结的候选追加记录提交或补写未来结果。
凭据从环境或受保护文件引用,避免出现在命令字面量。脱敏是补充防护,不是允许输出秘密。
执行脚本不通过 shell tracing 暴露环境;管道任何一段失败应传回非零退出码。
工具写入失败本身也必须报错,不能只保留一个看似成功的退出状态。
## 回收
仅在登记的任务 worktree 根目录回收。owner 先确认全部写者已退出、任务成果与证据已保存,
以 `TASK_WRITERS_STOPPED=1 make task-finish` 明确确认;
脚本检查主检出/子目录误用、Git 操作和锁、父子仓修改及未跟踪/ignored 文件;
子模块另有登记 worktree 时拒绝回收,避免删除其他检出依赖的 Git 管理目录。
可再生缓存由 owner 按已识别路径单独处置;无法确认用途的文件保留。
任务合入需以本次成功获取的权威目标验证:子任务为其所属大任务分支的远端头,其余为 `origin/main`(即 `immediate_target`)。合入提交不能证明未提交文件已经落盘。
Git 对含子模块的工作区需要显式删除选项时,只有全部现场检查通过才允许该路径;
它不豁免任何脏状态、忽略文件、独有提交/引用或锁检查。普通删除失败不转入强删兜底。
保留无法确认安全的目录和分支,输出下一步处理依据。
子仓 pin 之外的 refs/stash/reflog 历史采取保守拒绝,即使其中部分可能已在远端:
owner 须先独立确认其保存与归属,工具不把缓存的远端引用当作唯一数据已经备份的证据。
远端分支删除与本地回收分别报告,失败不能声明两者全部完成。
任务卡默认在合入前闭合:最终同步/合入前在任务 worktree 运行 `make task-close SELF=1`,本卡改为"已完成(合入前闭合)"并归档,随同一 PR 合入,无需单独闭合 PR;回收命令不顺带改写共享主检出。
主检出的 `make task-close`(闭合 PR base 为 `main`)或 `FOLD=--fold`(随任务分支合入,base 为卡片 `immediate_target`)只用于已合入未闭合的遗留卡。
post-merge 仅提示,不自动调用闭合。`make task-close` 会提交、推送并可能创建 PR,
执行者先按迭代交付规则核对该动作的授权及所选任务,保留未授权的其他任务现场。
回收命令使用待删目录之外的 `RECEIPT` 保存输出,清理结果由后续闭合记录引用。
## CI 凭据边界
候选代码执行前结束有凭据的源码获取阶段。获取只访问受信主机及登记的组件仓,
不根据候选提供的任意 URL 携带 token;认证配置限单次进程,不写全局 Git 配置或 remote URL。
测试/构建阶段检查配置中不存在凭据,并使用不含 checkout token 的环境。
仓内测试只能证明脚本边界。runner 隔离、token 权限、工作流来源和平台分支保护
由平台维护者验证;没有对应 GATE/REPLAY 时标未验证,不由本地测试推断。
## 持续回归
`make test-governance` 在临时真实 Git 仓库中覆盖回收、组件同步、离线启动、收据捕获/导入、
管道失败、假凭据脱敏、写路径及 CI 凭据隔离;临时 remote 均为本地路径,禁止使用真实秘密。
它纳入 `make test`,新机制必须有正常、拒绝和故障分支。历史临时测试记录仅作定位线索。
普通文档核对真实入口和相对链接;规范升级检查条文、命令、模板与能力矩阵是否一致。
机制未变可按固定版本复用证据,变更的机制重新运行对应负例。