Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
9 changes: 9 additions & 0 deletions .codex/agents/workflow-implementer.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
name = "workflow-implementer"
description = "在隔离 worktree 内实施任务契约明确授权的单一模块改动,并交接可复现的验证证据。"
developer_instructions = """
你是 MultiWeb 的 Workflow Implementer。Supervisor 只在角色 worktree 中已存在 AGENTS.md、docs/agent-workflow.md 和 docs/agent-workflow-autonomous-handoff.md 三份文件时启动你;缺少任一文件时,必须报告“集成不完整”并停止。开始工作前必须阅读并遵守这三份文件;发生冲突时严格按 AGENTS.md > docs/agent-workflow.md > docs/agent-workflow-autonomous-handoff.md 的顺序处理并向 Supervisor 报告。仅在任务契约明确授予、且由你独占的文件和模块范围内工作。

必须使用独立 worktree,实施最小改动并执行契约指定的最小相关验证。交接中必须列出实际修改文件与授权范围的对应关系、可应用 diff 或 worktree、执行命令及结果、未验证范围,以及公共 API、跨平台差异和安全默认值影响。

不得写入其他任务的所有权范围,不得修改 API 基线、跨平台契约、发布或 Gradle 设置,除非任务契约明确且已串行授权;不得集成其他 Agent 改动、擅自解决接口签名、默认值、导航策略、JS 桥、安全设置或测试预期冲突。不得创建提交、推送或创建 PR,除非维护者另行明确授权。
"""
9 changes: 9 additions & 0 deletions .codex/agents/workflow-integrator.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
name = "workflow-integrator"
description = "在专用集成 worktree 应用已交接改动,仅整理不改变语义的机械冲突并提供候选版本证据。"
developer_instructions = """
你是 MultiWeb 的 Workflow Integrator。Supervisor 只在角色 worktree 中已存在 AGENTS.md、docs/agent-workflow.md 和 docs/agent-workflow-autonomous-handoff.md 三份文件时启动你;缺少任一文件时,必须报告“集成不完整”并停止。开始工作前必须阅读并遵守这三份文件;发生冲突时严格按 AGENTS.md > docs/agent-workflow.md > docs/agent-workflow-autonomous-handoff.md 的顺序处理并向 Supervisor 报告。仅在任务契约授权的专用集成 worktree 和已交接改动范围内工作。

只可应用完整交接,并处理不改变语义的机械冲突,例如无关 import 排序或相邻文本合并。集成前检查交接范围不重叠,完成后提供合并清单、git diff --check 结果和固定候选提交所需证据;是否创建候选提交仍须遵守 AGENTS.md 和维护者的明确授权。

不得修改产品业务逻辑、公共 API、默认值、导航策略、JS 桥、安全设置、测试预期或 API 基线来消除冲突或失败。遇到这些语义冲突、P0/P1 或交接不完整时,必须退回原 Implementer 或 Planner,不得自行猜测。不得写入契约未授权范围、推送或创建 PR。
"""
10 changes: 10 additions & 0 deletions .codex/agents/workflow-planner.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name = "workflow-planner"
description = "只读规划 MultiWeb 中大型任务,输出可执行任务契约、依赖、独占文件范围和验证要求。"
sandbox_mode = "read-only"
developer_instructions = """
你是 MultiWeb 的 Workflow Planner。Supervisor 只在角色 worktree 中已存在 AGENTS.md、docs/agent-workflow.md 和 docs/agent-workflow-autonomous-handoff.md 三份文件时启动你;缺少任一文件时,必须报告“集成不完整”并停止。开始工作前必须阅读并遵守这三份文件;发生冲突时严格按 AGENTS.md > docs/agent-workflow.md > docs/agent-workflow-autonomous-handoff.md 的顺序处理并向 Supervisor 报告。

仅进行只读分析。不得写入仓库、任务账本、产品代码、测试、API 基线、构建或发布配置,也不得创建提交、推送或创建 PR。将任务契约、任务 DAG、基线 SHA、独占文件/模块所有权、依赖、最小验证命令以及公共 API、跨平台和安全默认值影响仅以结构化结果返回 Supervisor;只能由 Supervisor 使用临时文件后原子替换落盘。

不得实施修复、替其他角色裁决语义冲突,或通过省略风险、放宽默认安全策略、修改接口约定来使任务看似可执行。契约不完整、需要维护者授权或发现 P0/P1 时,明确标记阻断原因与唯一下一步。
"""
10 changes: 10 additions & 0 deletions .codex/agents/workflow-verify-reviewer.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,10 @@
name = "workflow-verify-reviewer"
description = "对固定候选提交进行只读验证与公共 API、安全、跨平台审查,并给出可复现裁决。"
sandbox_mode = "read-only"
developer_instructions = """
你是 MultiWeb 的 Workflow Verify-Reviewer。Supervisor 只在角色 worktree 中已存在 AGENTS.md、docs/agent-workflow.md 和 docs/agent-workflow-autonomous-handoff.md 三份文件时启动你;缺少任一文件时,必须报告“集成不完整”并停止。开始工作前必须阅读并遵守这三份文件;发生冲突时严格按 AGENTS.md > docs/agent-workflow.md > docs/agent-workflow-autonomous-handoff.md 的顺序处理并向 Supervisor 报告。仅在干净 worktree 中针对固定候选提交 SHA 做只读验证和审查。

先执行任务契约中的最小验证,再根据实际改动审查公共 API、跨平台一致性、JS 桥与安全默认值。结果必须包含候选 SHA、实际命令与退出结果、未验证项、按 P0/P1/P2 分类的问题、文件位置,以及唯一的 PASS 或 REJECT 裁决。P0/P1 必须 REJECT;P2 必须写入风险记录;候选 SHA 变化后旧裁决立即失效。

不得写入候选代码、测试、API 基线、任务契约或账本,不得修改任何内容来制造 PASS,不得替 Integrator 处理语义冲突,也不得创建提交、推送或创建 PR。将审查报告仅返回 Supervisor;只能由 Supervisor 使用临时文件后原子替换落盘。
"""
55 changes: 55 additions & 0 deletions .codex/workflow/README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,55 @@
# Agent Workflow 运行账本

每个中大型任务在 `runs/<task-id>/` 建立独立账本。账本只保存可公开的任务状态、证据相对路径和提交 SHA,禁止写入 Token、凭据或完整环境变量。

## 命令

在仓库根目录执行:

```shell
python3 tools/agent_workflow.py validate .codex/workflow/runs/<task-id>
python3 tools/agent_workflow.py transition .codex/workflow/runs/<task-id> <NEXT_STATUS> --actor <ROLE> --evidence <PATH> [--candidate-sha <SHA>] [--verdict PASS|REJECT]
python3 tools/agent_workflow.py resume .codex/workflow/runs/<task-id>
```

三个命令都会先获取运行目录内 `.workflow.lock` 的非阻塞 `fcntl` 租约。该能力要求 Unix-like 系统和 Python 3.11+,是当前的 P2 平台边界。租约被其他 Supervisor 持有时,命令会立即失败,不会读取或改写账本;`resume` 因此可确认不存在另一份有效租约。除这个运行时锁文件外,`resume` 完全只读,输出当前状态、阻断原因、唯一恢复目标和唯一下一步。

`validate` 检查状态字段、Git 可解析的基线/候选 SHA、任务契约、计划、完整事件链和审查证据。`transition` 仅接受状态机允许的下一状态:它先追加并 `fsync` 对应事件,再以同目录临时文件原子替换 `state.json`。如果事件追加失败,状态保持不变;如果替换在事件成功后中断,下一次 `validate` 会因事件末状态不一致而拒绝继续。

`--evidence` 必须是运行目录内已存在的文件。绝对路径或符号链接解析后越出该目录会被拒绝。进入 `VALIDATING` 时必须同时传入 `--candidate-sha`,且该值必须与已生成的 `candidate.sha` 一致;进入 `REVIEWED` 时必须传入 `--verdict PASS|REJECT`,并与审查报告一致。关键账本文件不得是符号链接。

## 必需文件

```text
runs/<task-id>/
├── state.json
├── task-contract.md
├── plan.json
├── events.jsonl # 首次迁移时创建
├── .workflow.lock # 运行时租约文件,不写入任务数据
├── handoffs/
├── candidate.sha # 生成候选后必需
├── review-report.md # REVIEWED 后必需
└── resume.md # 可选的人类可读恢复上下文
```

`state.json` 使用 schemaVersion `1`,必须包含 `taskId`、`baselineSha`、`status`、`mode`、`currentStage`、`attempts`、`candidateSha`、`verdict`、`nextAction`、`lastEventAt` 和 `stopReason`。`PAUSED` 时还必须有 `pausedFromStatus`,且只能恢复到该状态或迁移为 `BLOCKED`;恢复完成后必须移除该字段。

自动尝试次数上限为两次。初始规划计为一次;`PLANNED -> PAUSED -> PLANNED` 会增加 `attempts.PLANNING`,达到上限后必须保持 `PAUSED` 或迁移为 `BLOCKED`。实施、验证和审查阶段同样受各自计数限制。

除从未离开 `PLANNED` 的新账本外,`events.jsonl` 必须存在,首条事件的 `from` 必须为 `PLANNED`,每条事件连续且证据路径位于任务目录内,末条 `to` 必须等于 `state.json.status`。

## 审查门禁

从 `REVIEWED` 进入 `COMMIT_READY` 前,验证器要求:

- `state.json.verdict` 与审查报告均为 `PASS`;
- `candidateSha`、`candidate.sha`、审查报告中的候选 SHA 完全一致且可由 Git 解析;
- 审查报告没有未解决的 `P0` 或 `P1`;明确的“无 P1”“P1 已修复”等记录不阻断;
- 候选 SHA 自审查后没有变化。

任一项失败都会拒绝迁移,并在错误信息中给出任务目录和可执行修复建议。

`REJECT` 报告可以记录待返工的 P0/P1,并可从 `REVIEWED` 返回 `IMPLEMENTING`;只有 PASS 证据链或 `COMMIT_READY`/`PR_READY` 会被未解决的 P0/P1 阻断。

`REVIEWED -> IMPLEMENTING` 会清除旧的 `reviewedCandidateSha`。返工后的新候选必须再次经过 `VALIDATING -> REVIEWED`,并由新的报告和 verdict 重新建立审查绑定;未走返工路径时,候选变化仍会使既有 `REVIEWED`、`COMMIT_READY` 或 `PR_READY` 证据失效。
1 change: 1 addition & 0 deletions .codex/workflow/runs/.gitkeep
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
# Supervisor 在此目录创建每个任务的运行账本。
1 change: 1 addition & 0 deletions .codex/workflow/runs/MW-20260817-001/candidate.sha
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
b56d13c3f02b4aaa2866c482f3fa8fe63920dfb0
6 changes: 6 additions & 0 deletions .codex/workflow/runs/MW-20260817-001/events.jsonl
Original file line number Diff line number Diff line change
@@ -0,0 +1,6 @@
{"actor": "SUPERVISOR", "at": "2026-08-17T13:45:24.094193+00:00", "evidence": "task-contract.md", "from": "PLANNED", "summary": "状态迁移已验证", "to": "IMPLEMENTING"}
{"actor": "INTEGRATOR", "at": "2026-08-17T13:45:24.170369+00:00", "evidence": "candidate.sha", "from": "IMPLEMENTING", "summary": "状态迁移已验证", "to": "READY_TO_INTEGRATE"}
{"actor": "INTEGRATOR", "at": "2026-08-17T13:45:24.255419+00:00", "evidence": "candidate.sha", "from": "READY_TO_INTEGRATE", "summary": "状态迁移已验证", "to": "VALIDATING"}
{"actor": "VERIFY_REVIEWER", "at": "2026-08-17T13:45:24.349908+00:00", "evidence": "review-report.md", "from": "VALIDATING", "summary": "状态迁移已验证", "to": "REVIEWED"}
{"actor": "SUPERVISOR", "at": "2026-08-17T13:45:24.439268+00:00", "evidence": "review-report.md", "from": "REVIEWED", "summary": "状态迁移已验证", "to": "COMMIT_READY"}
{"actor": "SUPERVISOR", "at": "2026-08-17T13:45:24.521050+00:00", "evidence": "pr-body.md", "from": "COMMIT_READY", "summary": "状态迁移已验证", "to": "PR_READY"}
73 changes: 73 additions & 0 deletions .codex/workflow/runs/MW-20260817-001/plan.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,73 @@
{
"schemaVersion": 1,
"taskId": "MW-20260817-001",
"baselineSha": "645e0bfe043b17a3db22cfaef080914e9e1fe6d8",
"tasks": [
{
"id": "workflow-framework",
"owner": "WORKFLOW_IMPLEMENTERS",
"scope": [
".codex/agents/",
".codex/workflow/",
"tools/agent_workflow.py",
"tools/tests/",
"AGENTS.md",
"docs/agent-workflow.md",
"docs/agent-workflow-task-template.md",
".github/pull_request_template.md",
".github/workflows/pr-governance.yml"
],
"dependsOn": [],
"verification": [
"PYTHONDONTWRITEBYTECODE=1 python3 -m unittest tools.tests.test_agent_workflow -v",
"git diff --check 645e0bf...b56d13c"
]
},
{
"id": "desktop-close-race",
"owner": "DESKTOP_IMPLEMENTER",
"scope": [
"webview-desktop/src/main/",
"webview-desktop/src/test/"
],
"dependsOn": [],
"verification": [
"./gradlew :webview-desktop:test --no-daemon"
]
},
{
"id": "ios-file-chooser-boundary",
"owner": "IOS_IMPLEMENTER",
"scope": [
"webview-ios/src/iosMain/",
"webview-ios/src/iosTest/"
],
"dependsOn": [],
"verification": [
"./gradlew :webview-ios:compileTestKotlinIosSimulatorArm64 --no-daemon"
]
},
{
"id": "fixed-candidate-review",
"owner": "VERIFY_REVIEWER",
"scope": [
"固定候选 b56d13c3f02b4aaa2866c482f3fa8fe63920dfb0"
],
"dependsOn": [
"workflow-framework",
"desktop-close-race",
"ios-file-chooser-boundary"
],
"verification": [
"./gradlew apiCheck --no-daemon",
"./gradlew :webview-android:assembleRelease --no-daemon",
"./gradlew :sample-compose:compileKotlinJs :sample-compose:compileKotlinWasmJs --no-daemon"
]
}
],
"acceptanceCriteria": [
"固定候选通过 Verify-Reviewer 审查且无 P0/P1。",
"候选提交、审查报告和状态账本形成可验证证据链。",
"PR 正文包含全部平台和公共 API 的验证证据。"
]
}
43 changes: 43 additions & 0 deletions .codex/workflow/runs/MW-20260817-001/pr-body.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
## 目的

建立可恢复、可验证的 MultiWeb Agent 工作流,并修复 Desktop 浏览器创建前关闭竞态与 iOS 文件选择器 URI 安全边界。

## 改动内容

- 增加项目级角色配置、状态账本验证器、运行样例和恢复文档。
- 将候选 SHA、审查报告、平台验证记录接入 PR 治理门禁。
- 将既有扩展与生命周期接口成员改为默认空实现,并同步 API 基线,以保持既有实现方兼容。
- 在 Desktop 创建已发起时延后关闭到 `onAfterCreated`;iOS 仅接受无 host、query、fragment 的绝对 `file://` URI。

## 平台影响

- 公共 API:受影响;验证证据:`./gradlew apiCheck --no-daemon` 通过。
- Android:受影响;验证证据:`./gradlew :webview-android:assembleRelease --no-daemon` 通过。
- iOS:受影响;验证证据:`./gradlew :webview-ios:compileTestKotlinIosSimulatorArm64 --no-daemon` 通过。
- Desktop:受影响;验证证据:`./gradlew :webview-desktop:test --no-daemon` 通过。
- JS/Wasm:受影响;验证证据:`./gradlew :webview-browser:jsBrowserTest :webview-browser:wasmJsBrowserTest --no-daemon` 的 JS 与 Wasm ChromeHeadless 报告各 3/3 通过。

## 验证命令与结果

- `PYTHONDONTWRITEBYTECODE=1 python3 -m unittest tools.tests.test_agent_workflow -v`:40/40 通过。
- `git diff --check 645e0bf...b56d13c`:通过。
- 已通过 `apiCheck`、Android Release、Desktop 单测、iOS 测试编译、Compose JS/Wasm 编译,以及 JS/Wasm ChromeHeadless 报告各 3/3。
- iOS 文件面板和 Desktop 真实窗口运行时测试受本机工具条件限制,详见风险与兼容性。

## 风险与兼容性

- API 兼容性:Kotlin 2.4.10 的基线表示变化尚未做旧版二进制扩展消费者链接回归;公共 API 的规范验证记录见“平台影响”。
- 安全:未放宽 JS 桥、Cookie、文件访问、下载或外部导航默认权限;iOS 文件选择器仅收紧 URI 接受范围。
- 平台:iOS 18.4+ 文件面板需要在 Xcode 模拟器或真机确认;Desktop JCEF/Compose 首帧与关闭竞态需要真实窗口验收;账本 CLI 仅支持 Python 3.11+ 的 Unix 环境。
- JS:最终干净审查的浏览器重跑被 Yarn network mutex 阻塞,但集成候选的 JS 与 Wasm ChromeHeadless 报告各 3/3 通过。

## 文档变更

- 新增 Agent 工作流、账本和任务契约文档,更新贡献指南与 PR 模板。

## Agent 工作流记录

- 任务契约路径:`.codex/workflow/runs/MW-20260817-001/task-contract.md`
- 候选提交 SHA:`b56d13c3f02b4aaa2866c482f3fa8fe63920dfb0`
- 账本验证:`PASS`
- 审查裁决:`PASS`
7 changes: 7 additions & 0 deletions .codex/workflow/runs/MW-20260817-001/resume.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# 恢复上下文

- 任务:`MW-20260817-001`。
- 基线:`645e0bfe043b17a3db22cfaef080914e9e1fe6d8`。
- 固定候选:`b56d13c3f02b4aaa2866c482f3fa8fe63920dfb0`。
- 当前阶段:`PR_READY`。
- 下一步:维护者将本地分支推送后,使用同目录 `pr-body.md` 创建远程 PR;当前流程不执行 `git push`。
35 changes: 35 additions & 0 deletions .codex/workflow/runs/MW-20260817-001/review-report.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,35 @@
# 固定候选审查报告

候选 SHA: b56d13c3f02b4aaa2866c482f3fa8fe63920dfb0
基线 SHA: 645e0bfe043b17a3db22cfaef080914e9e1fe6d8

## 验证结果

- `git diff --check 645e0bf...b56d13c`:通过。
- `PYTHONDONTWRITEBYTECODE=1 python3 -m unittest tools.tests.test_agent_workflow -v`:40/40 通过。
- `./gradlew :webview-desktop:test --no-daemon`:通过。
- `./gradlew :webview-ios:compileTestKotlinIosSimulatorArm64 --no-daemon`:通过。
- `./gradlew apiCheck --no-daemon`:通过。
- `./gradlew :webview-android:assembleRelease --no-daemon`:通过。
- `./gradlew :sample-compose:compileKotlinJs :sample-compose:compileKotlinWasmJs --no-daemon`:通过。
- `./gradlew :webview-browser:jsBrowserTest :webview-browser:wasmJsBrowserTest --no-daemon`:集成候选工作目录的 JS 与 Wasm ChromeHeadless 报告各 3/3 通过。

## 审查结论

- 公共 API:`apiCheck` 通过。既有扩展与生命周期接口的抽象成员变为默认空实现,未新增既有实现方必须实现的抽象成员;API 基线已同步。
- JS 桥与安全默认值:候选没有放宽 JavaScript、Cookie、文件访问或浏览器全局权限。iOS 文件选择器拒绝带 host、query 或 fragment 的 URI,并在销毁或迟到回调时取消请求。
- Desktop:创建已发起时等待 `onAfterCreated` 后走正常关闭路径,覆盖创建前 `dispose()` 的关闭竞态。
- CI 与账本:候选 SHA、审查报告和 PR 正文会由门禁交叉校验,候选必须是 PR HEAD 的祖先。

无 P0。
无 P1。

## P2 与未验证范围

- P2:iOS 18.4+ `WKUIDelegate` 文件面板仍需在安装 Xcode 的模拟器或真机运行时验证。
- P2:Desktop JCEF/Compose 真实窗口的首帧和退出竞态尚未进行运行时验收。
- P2:Kotlin 2.4.10 API 基线表示变化尚未执行旧版二进制扩展消费者链接回归。
- P2:账本 CLI 依赖 Python 3.11+ 和 Unix `fcntl`,Windows 环境不适用。
- P2:最终干净审查中的 JS 浏览器重跑受共享 Yarn network mutex 阻塞;集成候选已有 JS 与 Wasm 各 3/3 的通过报告。

裁决: PASS
20 changes: 20 additions & 0 deletions .codex/workflow/runs/MW-20260817-001/state.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
{
"schemaVersion": 1,
"taskId": "MW-20260817-001",
"baselineSha": "645e0bfe043b17a3db22cfaef080914e9e1fe6d8",
"status": "PR_READY",
"mode": "FULL",
"currentStage": "PR",
"attempts": {
"PLANNING": 1,
"IMPLEMENTING": 1,
"VALIDATING": 1,
"REVIEWING": 1
},
"candidateSha": "b56d13c3f02b4aaa2866c482f3fa8fe63920dfb0",
"verdict": "PASS",
"nextAction": "维护者推送当前分支后,使用 pr-body.md 创建远程 PR",
"lastEventAt": "2026-08-17T13:45:24.521050+00:00",
"stopReason": null,
"reviewedCandidateSha": "b56d13c3f02b4aaa2866c482f3fa8fe63920dfb0"
}
Loading
Loading