docs(ops): finalize governance console P1 implementable design
Expand the P1 plan to a 12-section implementable spec (serve API, claim new, integrate prepare, pi packet, SPA, tests, risks) without code. Task record and CURRENT claim included.
This commit is contained in:
@@ -18,6 +18,7 @@
|
||||
|
||||
| owner | task | branch | worktree | mutex | status |
|
||||
|---|---|---|---|---|---|
|
||||
| Cursor | governance-console-p1-design-2026-09-24 | feature/governance-console-p1-design-2026-09-24 | .worktrees/governance-console-p1-design-2026-09-24 | agentctl-console-design | in_progress |
|
||||
| Cursor | governance-visibility-p0-2026-09-24 | feature/governance-visibility-p0-2026-09-24 | .worktrees/governance-visibility-p0-2026-09-24 | agentctl-visibility | done |
|
||||
| Cursor | worktree-cleanup-closeout-2026-09-24 | feature/worktree-cleanup-closeout-2026-09-24 | .worktrees/worktree-cleanup-closeout-2026-09-24 | worktree-cleanup | in_progress |
|
||||
| Cursor | non-author-closeout-2026-09-24 | feature/non-author-closeout-2026-09-24 | .worktrees/non-author-closeout-2026-09-24 | docs+git:dev | done |
|
||||
|
||||
@@ -0,0 +1,66 @@
|
||||
---
|
||||
title: "治理控制台 P1 设计定稿"
|
||||
task_id: "governance-console-p1-design-2026-09-24"
|
||||
status: in_progress
|
||||
created: 2026-09-24
|
||||
updated: 2026-09-24
|
||||
owner: Cursor
|
||||
task_type: research
|
||||
task_tier: small
|
||||
policy_revision: "agent-governance-2026-09-21-r1 + cursor-governance-2026-09-24-r1 @ 4844041b"
|
||||
branch: feature/governance-console-p1-design-2026-09-24
|
||||
worktree: .worktrees/governance-console-p1-design-2026-09-24
|
||||
base_dev_sha: "4844041b1b417b5ac415fe779a3784959c0afbbe"
|
||||
write_scope: [".doc"]
|
||||
allowed_environments: []
|
||||
head_sha: ""
|
||||
mutex: "agentctl-console-design"
|
||||
review_state: pending
|
||||
integration_state: pending
|
||||
deployment: not_required
|
||||
cleanup: pending
|
||||
cleanup_owner: "独立维护者"
|
||||
cleanup_trigger: "合入 local_dev 且文档验收通过后"
|
||||
remote_sync: not_requested
|
||||
---
|
||||
|
||||
# 治理控制台 P1 设计定稿
|
||||
|
||||
## 用户目标与授权
|
||||
|
||||
- 用户目标:把 P1 骨架扩成可实施规格(12 节),不写实现代码。
|
||||
- 交付终点:`.doc/ops/short-term/2026-09-24-governance-console-plan.md` 定稿合入 local `dev`。
|
||||
- 禁止:scripts 编码、产品 web/cmd/internal、push、晋升、跨机协调实施。
|
||||
|
||||
## 范围与非目标
|
||||
|
||||
- 允许:设计文档原地扩充、任务主记录、CURRENT 认领。
|
||||
- 非目标:P1-a…e 任何代码实施。
|
||||
|
||||
## 相关问题与经验
|
||||
|
||||
- catalog:`R-governance-console-p1`;overlap 探测无 hard/soft(与 R-governance-visibility-p0 语义相关但未命中门禁)。
|
||||
- 前序:P0 合入 `dev@4844041b`;证据见 [测试报告](../../test-reports/2026-09-24-governance-visibility-p0-test-report.md)。
|
||||
|
||||
## 步骤与验收
|
||||
|
||||
1. [x] 建场 / register / CURRENT 认领
|
||||
2. [x] 设计文档 12 节扩充
|
||||
3. [x] 链接/锚点/mermaid 检查(12 节 / 0 断链 / 4 mermaid / 594 行)
|
||||
4. [ ] 合入收口
|
||||
|
||||
## 验证与证据
|
||||
|
||||
| 范围 | 命令与环境 | 预期 | 实际 / 判定 | 证据 |
|
||||
|---|---|---|---|---|
|
||||
| 纯文档 | 链接/锚点/mermaid + 符号对照 | 无断链、可渲染 | PASS:links_ok=16 broken=0 mermaid=4 符号均存在 | 本任务验证节 |
|
||||
| 产品 PI / go test | — | NOT REQUIRED | — | 验证契约「工程规范/文档」层 |
|
||||
|
||||
## 收口与交接
|
||||
|
||||
待定稿后填写五态。
|
||||
|
||||
## 相关链接
|
||||
|
||||
- 设计主体:[2026-09-24-governance-console-plan.md](./2026-09-24-governance-console-plan.md)
|
||||
- P0 任务:[2026-09-24-governance-visibility-p0.md](./2026-09-24-governance-visibility-p0.md)
|
||||
@@ -1,174 +1,594 @@
|
||||
---
|
||||
title: "治理控制台 P1 方案"
|
||||
task_id: "governance-visibility-p0-2026-09-24"
|
||||
title: "治理控制台全景设计(P1 定稿)"
|
||||
task_id: "governance-console-p1-design-2026-09-24"
|
||||
status: planned
|
||||
created: 2026-09-24
|
||||
updated: 2026-09-24
|
||||
owner: Cursor
|
||||
task_type: research
|
||||
related_p0: governance-visibility-p0-2026-09-24
|
||||
design_revision: "governance-console-p1-r1"
|
||||
base_dev_sha: "4844041b1b417b5ac415fe779a3784959c0afbbe"
|
||||
---
|
||||
|
||||
# 治理控制台全景设计(P1)
|
||||
# 治理控制台全景设计(P1 定稿)
|
||||
|
||||
覆盖方向:**A 状态可视化**、**B 流程自动化**、**C MCP 只读巡览**、**D PI 派发包生成**。
|
||||
P0 已落地:`--format table`、`brief`、MCP 四只读工具、`claim archive`。本文件是后续实施蓝图,**不在 P0 编码**。
|
||||
本文件是**可实施规格**;实施须另开 task + `catalog overlap`。本轮不写代码。
|
||||
|
||||
## 1. 目标
|
||||
前置:P0 已合入 `dev@4844041b`(`--format table`、`brief`、MCP +4、`claim archive`)。证据:[测试报告](../../test-reports/2026-09-24-governance-visibility-p0-test-report.md)。
|
||||
|
||||
给人类与 Agent 一个本机治理面:一眼看到任务/租约/队列/漂移/清理积压,并把高频手工步骤(认领、归档、集成候选、PI packet)收成白名单动作——**全部复用既有租约与 `docs apply` CAS,不新增旁路写入口**。
|
||||
---
|
||||
|
||||
## 2. 架构
|
||||
## 1. 现状与缺口
|
||||
|
||||
```text
|
||||
Browser (localhost) ──► static SPA ──► agentctl serve (127.0.0.1)
|
||||
│
|
||||
Cursor MCP / CLI ────────────────────────────┤
|
||||
▼
|
||||
agentctl 核心
|
||||
(SQLite / leases / docs apply / queue / catalog)
|
||||
### 1.1 P0 已交付(机器权威层可读)
|
||||
|
||||
| 能力 | 入口 | 核心实现 |
|
||||
|---|---|---|
|
||||
| 人类可读表 | `agentctl status\|queue list\|claim list\|cleanup report --format table` | [`emit_payload`](../../../scripts/agentctl.py) + [`agentctl_visibility`](../../../scripts/agentctl_visibility.py) |
|
||||
| 一页简报 | `agentctl brief` | `collect_*` + `cmd_brief` |
|
||||
| done 行归档 | `agentctl claim archive [--apply]` | `claim_archive` → `@document` docs apply CAS |
|
||||
| MCP 只读 | `queue_list` / `claim_status` / `cleanup_report` / `catalog_drift` | [`agentctl-mcp.mjs`](../../../scripts/mcp/agentctl-mcp.mjs) |
|
||||
|
||||
### 1.2 仍存缺口(本设计覆盖)
|
||||
|
||||
| ID | 缺口 | 用户摩擦 |
|
||||
|---|---|---|
|
||||
| A2 | 无 dashboard / HTTP 面 | 终端 JSON/table 仍需手敲;多源聚合靠 `brief` 文本 |
|
||||
| B1 | 认领仍三步 | skill 要求 snapshot → 手写 JSON → apply |
|
||||
| B2 | 每任务双 worktree | 手工建 `integrate-*` + `--no-ff` |
|
||||
| D1 | PI packet 手工组装 | task_id/request_id/source_sha/approved_commands 易漏 |
|
||||
| C2 | MCP 未暴露 brief/archive | 会话内仍偶发 shell 拼装 |
|
||||
|
||||
跨机 claim 权威不在本方案:见 [coordination-db-daemon phased plan](../../remediation/2026-09-23-coordination-db-daemon-phased-plan.md)。
|
||||
|
||||
---
|
||||
|
||||
## 2. 目标与非目标
|
||||
|
||||
### 2.1 目标
|
||||
|
||||
1. 本机治理面:一眼看 tasks / runs / claims / queue / drift / cleanup。
|
||||
2. 高频动作白名单:`claim new`、`claim archive`、`integrate prepare`、`pi packet`——**全部复用既有租约与 `docs apply`,不新增旁路写入口**。
|
||||
3. CLI 与 HTTP 同构:同一 Python 函数;MCP 可薄封装。
|
||||
4. 可测:工程工具单测覆盖路由、错误码、幂等、loopback。
|
||||
|
||||
### 2.2 非目标
|
||||
|
||||
- 远程多用户 Web 登录 / 鉴权体系。
|
||||
- 产品 [`web/`](../../../web/) AdminConsole 内嵌治理页。
|
||||
- 绕过 `agentctl with` / `docs apply` 的文件写。
|
||||
- 自动 `--force` 清理 worktree、push、晋升 test/main。
|
||||
- 替代 Herdr / 产品 PI Agent Runner。
|
||||
- 把 `serve` 装进 systemd/launchd(保持手工前台进程)。
|
||||
|
||||
---
|
||||
|
||||
## 3. 总体架构
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
subgraph clients [Clients]
|
||||
Cursor[Cursor_MCP_CLI]
|
||||
Term[Terminal]
|
||||
Browser[Browser_localhost]
|
||||
end
|
||||
subgraph console [Governance_Console_P1]
|
||||
Spa[static_SPA]
|
||||
Serve[agentctl_serve]
|
||||
CliExt[claim_new_integrate_prepare_pi_packet]
|
||||
end
|
||||
subgraph core [Existing_agentctl_core]
|
||||
Collect[collect_star_pure_fns]
|
||||
Docs[docs_apply_CAS]
|
||||
Lease[Lease_with]
|
||||
Queue[queue_daemon_ff]
|
||||
Db[(governance_SQLite)]
|
||||
end
|
||||
Cursor --> Serve
|
||||
Cursor --> CliExt
|
||||
Term --> CliExt
|
||||
Browser --> Spa --> Serve
|
||||
Serve --> Collect
|
||||
Serve --> CliExt
|
||||
CliExt --> Docs
|
||||
CliExt --> Lease
|
||||
CliExt --> Queue
|
||||
Collect --> Db
|
||||
Docs --> Db
|
||||
Lease --> Db
|
||||
Queue --> Db
|
||||
```
|
||||
|
||||
| 组件 | 职责 | 约束 |
|
||||
### 3.1 进程拓扑
|
||||
|
||||
| 进程 | 生命周期 | 说明 |
|
||||
|---|---|---|
|
||||
| `agentctl serve` | HTTP JSON API + 静态文件;仅绑 `127.0.0.1` | 无鉴权外放;动作白名单;写路径内部调 `with`/`docs apply` |
|
||||
| 静态 SPA | 单页四区:任务租约 / 队列集成 / 文档漂移 / 清理积压 | **不进产品 `web/`**,避免发布门禁耦合;建议路径 `scripts/governance-console/` |
|
||||
| CLI 增强 | `claim new`、`integrate prepare`、`pi packet` | 与 HTTP 动作共用同一 Python 函数 |
|
||||
| `agentctl daemon` | 已装载 systemd/launchd | 仅队列 ff-only;**不**承载 HTTP |
|
||||
| `agentctl serve` | 人工前台 / 可选 tmux | 绑 `127.0.0.1:7432`;退出即停 |
|
||||
| SPA | 由 serve 静态托管 | 零构建单页;无独立 Node 服务 |
|
||||
|
||||
跨机权威认领不在本方案重复设计,衔接 [coordination-db-daemon phased plan](../remediation/2026-09-23-coordination-db-daemon-phased-plan.md)。
|
||||
### 3.2 组件职责
|
||||
|
||||
## 3. HTTP API(草案)
|
||||
|
||||
基址:`http://127.0.0.1:7432`(端口可配,默认避开产品 8080/8081)。
|
||||
|
||||
### 3.1 只读
|
||||
|
||||
| Method | Path | 映射 |
|
||||
| 组件 | 路径(建议) | 职责 |
|
||||
|---|---|---|
|
||||
| GET | `/api/status` | `collect_status_payload` + 可选 `?format=table` |
|
||||
| GET | `/api/brief` | `cmd_brief` Markdown 或 JSON |
|
||||
| GET | `/api/queue` | `queue list` |
|
||||
| GET | `/api/claims` | `claim list` |
|
||||
| GET | `/api/cleanup` | `cleanup report` |
|
||||
| GET | `/api/docs/drift` | `docs drift` |
|
||||
| GET | `/api/catalog/drift` | `catalog drift` |
|
||||
| GET | `/api/daemon` | `daemon status` |
|
||||
| `agentctl serve` | [`scripts/agentctl.py`](../../../scripts/agentctl.py) 子命令 | HTTP JSON + 静态文件 |
|
||||
| 动作实现 | `scripts/agentctl_console.py`(新建)或内嵌 | `claim_new` / `integrate_prepare` / `pi_packet` 纯逻辑 |
|
||||
| SPA | `scripts/governance-console/index.html` | 四区仪表盘 |
|
||||
| MCP 增补 | [`scripts/mcp/agentctl-mcp.mjs`](../../../scripts/mcp/agentctl-mcp.mjs) | 可选:`brief`、`claim_archive`、动作薄封装 |
|
||||
|
||||
### 3.2 动作白名单(均要求 `task` + 可选 `authorization_ref`)
|
||||
---
|
||||
|
||||
| Method | Path | 行为 |
|
||||
## 4. 数据模型与 API 资源映射
|
||||
|
||||
### 4.1 治理 SQLite(只读投影,不改 schema)
|
||||
|
||||
| 表 | 关键字段 | 消费端点 |
|
||||
|---|---|---|
|
||||
| POST | `/api/claim/new` | 见 §4.1:snapshot→delta→apply 封装 |
|
||||
| POST | `/api/claim/archive` | 既有 `claim archive --apply` |
|
||||
| POST | `/api/integrate/prepare` | 见 §4.2:候选 worktree + `--no-ff` |
|
||||
| POST | `/api/pi/packet` | 见 §4.3:生成 dispatch JSON |
|
||||
| `tasks` | id, owner, worktree, branch, state, scopes, capabilities | `GET /api/status` |
|
||||
| `runs` | id, task, state, pid, start, boot, resources | `GET /api/status` |
|
||||
| `queue_items` | id, task, head_sha, expected_dev, priority, state | `GET /api/queue` |
|
||||
| `claims` | id, task, resource, state, updated | `GET /api/claims` |
|
||||
| `documents` / `receipts` | run, task, file, hash | 动作审计;不直接暴露 |
|
||||
| `catalog_*` | requirements, features, overlaps | `GET /api/catalog/drift` |
|
||||
| `matrix_state_snapshot` | record_id, status | `GET /api/docs/drift` |
|
||||
|
||||
拒绝:任意 shell、env-service、push、晋升、删 worktree、绕过租约的文件写。
|
||||
CURRENT.md / FEATURE-MATRIX.md 仍是人类投影;机器权威在 SQLite + docs apply 收据。
|
||||
|
||||
## 4. B/D CLI 完整版
|
||||
### 4.2 只读 payload 契约(与 P0 `collect_*` 同源)
|
||||
|
||||
### 4.1 `agentctl claim new`(B)
|
||||
```text
|
||||
GET /api/status → collect_status_payload(repo)
|
||||
{status, lock_root, main, version, epoch, tasks[], runs[], queue[], policy}
|
||||
GET /api/brief → cmd_brief 逻辑;?format=markdown|json
|
||||
GET /api/queue → queue_list 同构 {status, items[]}
|
||||
GET /api/claims → claim_list 同构 {status, claims[]}
|
||||
GET /api/cleanup → collect_cleanup_payload {worktrees[]}
|
||||
GET /api/docs/drift → collect_docs_drift_payload {regressions[], open_capabilities[]}
|
||||
GET /api/catalog/drift → collect_catalog_drift_payload
|
||||
GET /api/daemon → collect_daemon_payload {manager_lock, heartbeat, queue}
|
||||
```
|
||||
|
||||
查询参数:
|
||||
|
||||
- `?format=json|table`(status/queue/claims/cleanup):table 时 `Content-Type: text/plain`,body 为 `render_*_table` 文本。
|
||||
- `?all=1`(queue/claims):含终态行。
|
||||
|
||||
### 4.3 动作请求/响应信封
|
||||
|
||||
```json
|
||||
{
|
||||
"request_id": "uuid-or-client-supplied",
|
||||
"task": "governance-…",
|
||||
"authorization_ref": "optional-user-chat-ref",
|
||||
"...action_fields": {}
|
||||
}
|
||||
```
|
||||
|
||||
成功:
|
||||
|
||||
```json
|
||||
{"status": "ok|archived|prepared|created", "run_id": "…", "request_id": "…", "...": {}}
|
||||
```
|
||||
|
||||
失败(HTTP 状态见 §5.3):
|
||||
|
||||
```json
|
||||
{"status": "denied", "code": "BASE_CHANGED", "message": "…", "...details": {}}
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 5. 后端 `agentctl serve` 详细设计
|
||||
|
||||
### 5.1 启动
|
||||
|
||||
```bash
|
||||
agentctl serve [--host 127.0.0.1] [--port 7432] [--static scripts/governance-console]
|
||||
```
|
||||
|
||||
约束:
|
||||
|
||||
- 默认 host **仅** `127.0.0.1`;传入 `0.0.0.0` → 启动前拒绝 `INVALID_REQUEST`。
|
||||
- 单线程或 `ThreadingHTTPServer`;写动作串行化靠既有 Lease/SQLite,不另造全局锁。
|
||||
- 不注册为 daemon;SIGINT 干净退出。
|
||||
|
||||
### 5.2 路由表
|
||||
|
||||
#### 只读(8)
|
||||
|
||||
| Method | Path | 处理 |
|
||||
|---|---|---|
|
||||
| GET | `/api/status` | `collect_status_payload` |
|
||||
| GET | `/api/brief` | brief 聚合 |
|
||||
| GET | `/api/queue` | `queue_list` |
|
||||
| GET | `/api/claims` | `claim_list` |
|
||||
| GET | `/api/cleanup` | `collect_cleanup_payload` |
|
||||
| GET | `/api/docs/drift` | `collect_docs_drift_payload` |
|
||||
| GET | `/api/catalog/drift` | `collect_catalog_drift_payload` |
|
||||
| GET | `/api/daemon` | `collect_daemon_payload` |
|
||||
| GET | `/` 与 `/static/*` | SPA |
|
||||
|
||||
#### 动作白名单(4)——同进程函数调用,禁止 `subprocess` 再调 CLI
|
||||
|
||||
| Method | Path | 函数 |
|
||||
|---|---|---|
|
||||
| POST | `/api/claim/new` | `claim_new(repo, args)` |
|
||||
| POST | `/api/claim/archive` | 既有 `claim_archive`(`apply=True`) |
|
||||
| POST | `/api/integrate/prepare` | `integrate_prepare(repo, args)` |
|
||||
| POST | `/api/pi/packet` | `pi_packet(repo, args)` |
|
||||
|
||||
未列出的 `/api/*` → 404。任意 shell / env-service / push / 删 worktree → **永不实现**。
|
||||
|
||||
### 5.3 错误码 → HTTP
|
||||
|
||||
| agentctl `Denied.code` | HTTP | 客户端建议 |
|
||||
|---|---|---|
|
||||
| `INVALID_REQUEST` | 400 | 修请求体 |
|
||||
| `CAPABILITY_REQUIRED` / `PATH_OUT_OF_SCOPE` | 403 | 补 capability 或换 task |
|
||||
| `BASE_CHANGED` / `WORKTREE_MISMATCH` / `LOCK_BUSY` / `UNMANAGED_DOCUMENT_CHANGE` | 409 | 重新 snapshot / prepare;不自动重试 |
|
||||
| `EVIDENCE_REQUIRED` | 422 | 补证据后重试 |
|
||||
| `UNKNOWN_*` | 404 | 检查 id |
|
||||
| 未捕获异常 | 500 | 查 run 审计;`RECOVERY_REQUIRED` |
|
||||
|
||||
### 5.4 幂等
|
||||
|
||||
- 客户端可传 `request_id`;缺省服务端生成 uuid。
|
||||
- 写路径进入 `Lease(..., request_id, digest)`:与现有 `docs_apply` replay 一致——相同 request_id 返回 `replayed`,不二次写。
|
||||
- `integrate prepare`:若 integrate worktree 已存在且 tip 已含任务分支 merge → 返回既有 `{head, integrate_task}`(幂等成功),不强制重建。
|
||||
|
||||
### 5.5 并发与 expected-dev 竞态
|
||||
|
||||
```text
|
||||
prepare 冻结 expected_dev = tip(dev)
|
||||
→ validate
|
||||
→ enqueue(expected_dev, head)
|
||||
daemon:若 tip(dev) != expected_dev → 该项失败/取消(既有行为)
|
||||
客户端:收到失败或 BASE_CHANGED → 重新 prepare,禁止盲重试同 head
|
||||
```
|
||||
|
||||
HTTP 层不自动重试;SPA 按钮在 409 时提示「dev 已前进,请重新 prepare」。
|
||||
|
||||
### 5.6 安全
|
||||
|
||||
1. Loopback only。
|
||||
2. 无 Cookie / Bearer;本机信任模型(与 CLI 相同)。
|
||||
3. 动作白名单硬编码;请求体禁止 `command` / `shell` / `argv` 字段。
|
||||
4. 所有写动作写 `runs`/`documents` 审计(既有 Lease)。
|
||||
5. CORS:仅同 origin(静态同 host);或不设 CORS(同源足够)。
|
||||
|
||||
### 5.7 实现落点(实施时)
|
||||
|
||||
- argparse:`serve` 子命令。
|
||||
- 标准库 `http.server` 或轻量 handler;**零新 pip 依赖**。
|
||||
- 静态根默认 `scripts/governance-console/`(gitignore 可选缓存,源码入库)。
|
||||
|
||||
---
|
||||
|
||||
## 6. CLI 动作详细设计
|
||||
|
||||
HTTP 与 CLI **共用**下列函数;CLI 为 argparse 薄包装。
|
||||
|
||||
### 6.1 `agentctl claim new`(B1)
|
||||
|
||||
```bash
|
||||
agentctl claim new --task "$ID" --owner Cursor --mutex <key> \
|
||||
[--branch feature/$ID] [--worktree .worktrees/$ID]
|
||||
[--branch feature/$ID] [--worktree .worktrees/$ID] \
|
||||
[--status in_progress] [--replace] [--request-id RID]
|
||||
```
|
||||
|
||||
内部:
|
||||
**内部步骤**
|
||||
|
||||
1. `docs snapshot --file CURRENT --record $ID`
|
||||
2. 若 `sha256` 已存在 → 拒绝或 `--replace` 显式更新
|
||||
3. 构造一行 `| owner | task | … | in_progress |`
|
||||
4. `docs apply`(单行 CAS;无需 `@document`)
|
||||
1. `task_row` 校验:cwd == 注册 worktree;需 `docs:publish`(单行写 CURRENT,无需 admin)。
|
||||
2. `docs_snapshot(CURRENT, record=task)`。
|
||||
3. 若 `sha256` 非空且未 `--replace` → `deny('INVALID_REQUEST', 'row exists; pass --replace')`。
|
||||
4. 构造一行:`| {owner} | {task} | {branch} | {worktree} | {mutex} | {status} |`(worktree 用相对 `.worktrees/…`)。
|
||||
5. `docs_apply` 单行 CAS(`expected_sha256` 来自 snapshot;新建为 null)。
|
||||
6. emit `{status:'created'|'replaced', record_id, run_id}`。
|
||||
|
||||
消除当前 skill 里 snapshot → 手写 JSON → apply 三步。
|
||||
**拒绝码**:`WORKTREE_MISMATCH`、`CAPABILITY_REQUIRED`、`BASE_CHANGED`、`AMBIGUOUS_RECORD`。
|
||||
|
||||
### 4.2 `agentctl integrate prepare`(B)
|
||||
**替代关系**:取代 skill [`agentctl-worktree-setup`](../../../.cursor/skills/agentctl-worktree-setup/SKILL.md) 中「CURRENT 认领」三段手工;建 worktree / `task register` 仍由 skill 前半段负责(本命令不创建 git worktree)。
|
||||
|
||||
**幂等**:同 request_id replay;`--replace` 在 BASE_CHANGED 后需新 snapshot。
|
||||
|
||||
### 6.2 `agentctl integrate prepare`(B2)
|
||||
|
||||
```bash
|
||||
agentctl integrate prepare --task "$ID" --expected-dev <sha> \
|
||||
[--integrate-id integrate-$ID]
|
||||
agentctl integrate prepare --task "$ID" --expected-dev <full_sha> \
|
||||
[--integrate-id integrate-$ID] [--request-id RID]
|
||||
```
|
||||
|
||||
内部(仍在租约内):
|
||||
**前置**:调用方 cwd 可为任务 worktree 或 main;函数内切换到新建 integrate worktree 执行 merge。
|
||||
|
||||
1. 从 freeze 的 `expected-dev` 建 `feature/integrate-<id>` worktree(若已存在则复用并校验干净)
|
||||
2. 在 integrate worktree `task register`(scope 含 git:dev 所需能力)
|
||||
3. `--no-ff` 合并任务分支到候选 HEAD
|
||||
4. 输出 `{integrate_task, worktree, head}` 供后续 `validate` / `queue enqueue`
|
||||
**内部步骤**
|
||||
|
||||
不替代 daemon ff-only;只去掉「手工第二个 worktree」摩擦。
|
||||
1. 校验 `expected-dev == rev-parse(refs/heads/dev)`,否则 `BASE_CHANGED`。
|
||||
2. `integrate_id = integrate-id or f"integrate-{task}"`;branch `feature/{integrate_id}`。
|
||||
3. 若 worktree 不存在:调用与 `agent-worktree.sh create` 等价逻辑(`git worktree add -b … expected-dev`)。
|
||||
4. 在 integrate worktree:`task register --capability git:dev`(若已注册且匹配则跳过)。
|
||||
5. Lease(`path:.`,`git:index`,`git:dev`) 内:`git merge --no-ff -m "merge: candidate {task} into dev" feature/{task-branch}`。
|
||||
6. 校验 `HEAD^1 == expected-dev`。
|
||||
7. emit `{status:'prepared', integrate_task, worktree, head, expected_dev, first_parent}`。
|
||||
|
||||
### 4.3 `agentctl pi packet`(D)
|
||||
**不做**:validate、enqueue(留给既有命令 / SPA 分步按钮,避免隐式合入)。
|
||||
|
||||
**拒绝码**:`BASE_CHANGED`、`LOCK_BUSY`、`CAPABILITY_REQUIRED`、`GIT_ERROR`、worktree 脏 → `INVALID_REQUEST`。
|
||||
|
||||
**替代关系**:压缩 skill [`agentctl-integrate-closeout`](../../../.cursor/skills/agentctl-integrate-closeout/SKILL.md) 的「候选」段;后续仍 `validate` → `queue enqueue`。
|
||||
|
||||
### 6.3 `agentctl pi packet`(D1)
|
||||
|
||||
```bash
|
||||
agentctl pi packet --task "$ID" --role research|planning|… \
|
||||
agentctl pi packet --task "$ID" --role research|planning|reviews|diagnosis|test_run|acceptance_check|report \
|
||||
--goal '…' --authorization-ref '…' \
|
||||
[--approved-command '…']…
|
||||
[--source-sha FULL] [--timeout-seconds 600] \
|
||||
[--input-file PATH]… [--approved-command 'argv…']… \
|
||||
[--request-id RID] [--write]
|
||||
```
|
||||
|
||||
从 task 行读取 `worktree`/`HEAD`,生成:
|
||||
**内部步骤**
|
||||
|
||||
1. 读 task 行 → worktree;`source_sha = freeze_source_sha(worktree, arg or HEAD)`(复用 [`pi_subagents.freeze_source_sha`](../../../scripts/pi_subagents.py) 规则:必须满 40/64 hex)。
|
||||
2. `request_id = arg or uuid`;校验 `REQUEST_ID_RE`。
|
||||
3. 组装 packet:
|
||||
|
||||
```json
|
||||
{
|
||||
"task_id": "…",
|
||||
"request_id": "<uuid>",
|
||||
"request_id": "…",
|
||||
"role_id": "research",
|
||||
"goal": "…",
|
||||
"authorization_ref": "…",
|
||||
"source_sha": "<frozen>",
|
||||
"input_files": [],
|
||||
"source_sha": "<40hex>",
|
||||
"input_files": ["…"],
|
||||
"timeout_seconds": 600,
|
||||
"approved_commands": []
|
||||
"approved_commands": [["python3","-B","-m","unittest", "…"]]
|
||||
}
|
||||
```
|
||||
|
||||
写出到 `.doc/test-reports/assets/pi-subagents/<task>/<request>/packet.json`(路径仍须在 `pi_subagents` 租约约定内)。不自动 `run`——生成与派发分离,避免误触模型。
|
||||
4. 默认 stdout JSON;`--write` 时原子写入
|
||||
`.doc/test-reports/assets/pi-subagents/<task>/<request>/packet.json`
|
||||
(目录与 [`REPORT_ROOT_REL`](../../../scripts/pi_subagents.py) 一致),并要求 Lease `path:.doc/test-reports/…`。
|
||||
5. **不**调用 `pi_subagent_run`——生成与派发分离。
|
||||
|
||||
## 5. 前端 SPA(A)
|
||||
**拒绝码**:`UNKNOWN_TASK`、`INVALID_SOURCE_SHA`、`UNKNOWN_ROLE`(对照模型配置角色表)、`PATH_OUT_OF_SCOPE`。
|
||||
|
||||
单页四区,无路由也可:
|
||||
**替代关系**:减少 [`pi-subagent-dispatch`](../../../.cursor/skills/pi-subagent-dispatch/SKILL.md) 手工拼包;skill 改为「packet 路径 → run」。
|
||||
|
||||
1. **任务 / 租约**:活跃 tasks、live runs、held claims;链到 worktree 路径文本。
|
||||
2. **队列与集成**:pending/claimed;按钮「prepare」(调 `/api/integrate/prepare`,需确认)。
|
||||
3. **文档漂移**:MATRIX hard regressions + catalog drift。
|
||||
4. **清理积压**:`cleanup report` 表;仅展示,删除仍人工/`agent-worktree remove`。
|
||||
### 6.4 `claim archive`(已有,HTTP 暴露)
|
||||
|
||||
技术选型建议:零构建或 Vite 单包静态资源,依赖控制台已有 `brief`/`--format table` 文案风格,不套产品 Admin UI。
|
||||
行为维持 P0:默认 dry-run;POST 等同 `--apply`。需 `docs:admin` + 任务 worktree。
|
||||
|
||||
## 6. 与 P0 / 既有系统衔接
|
||||
---
|
||||
|
||||
| 能力 | 状态 |
|
||||
## 7. 前端 SPA 设计
|
||||
|
||||
### 7.1 技术选型
|
||||
|
||||
- **零构建**:单 `index.html` + 内联 CSS/JS(或同目录 `app.js`)。
|
||||
- 原生 `fetch`;轮询间隔默认 **10s**(可配置);可选后续 SSE(P1-e)。
|
||||
- 不引入 React/Vite;不依赖产品 `web/node_modules`。
|
||||
|
||||
### 7.2 线框(四区)
|
||||
|
||||
```text
|
||||
+------------------------------------------------------------------+
|
||||
| agentctl console daemon: ok queue: 0 [刷新] [10s] |
|
||||
+-------------------------------+----------------------------------+
|
||||
| 1. 任务 / 租约 | 2. 队列与集成 |
|
||||
| active tasks table | pending/claimed table |
|
||||
| live runs | [Prepare…] 需选 task+确认 |
|
||||
| held claims | [Enqueue…] 仅展示指引/复制命令 |
|
||||
+-------------------------------+----------------------------------+
|
||||
| 3. 文档漂移 | 4. 清理积压 |
|
||||
| MATRIX hard regressions | cleanup report table |
|
||||
| catalog drift | 无删除按钮(只读) |
|
||||
+-------------------------------+----------------------------------+
|
||||
| brief 预览(折叠) |
|
||||
+------------------------------------------------------------------+
|
||||
```
|
||||
|
||||
### 7.3 区 ↔ 端点
|
||||
|
||||
| 区 | 数据 | 动作按钮 |
|
||||
|---|---|---|
|
||||
| 1 | `/api/status` + `/api/claims` | 「认领」→ modal → `POST /api/claim/new`(二次确认) |
|
||||
| 2 | `/api/queue` + status.queue | 「Prepare」→ `POST /api/integrate/prepare`;Enqueue 默认复制 CLI(避免 SPA 误合入) |
|
||||
| 3 | `/api/docs/drift` + `/api/catalog/drift` | 无写 |
|
||||
| 4 | `/api/cleanup` | 无写 |
|
||||
| 顶栏 | `/api/daemon` + `/api/brief` | 刷新 |
|
||||
|
||||
### 7.4 UX 规则
|
||||
|
||||
- 所有 POST 前 modal:展示将发送的 JSON;确认后才发。
|
||||
- 409/403 用红色 toast + 原始 `code`。
|
||||
- 路径只显示文本,不 `file://` 链出(避免浏览器限制)。
|
||||
|
||||
---
|
||||
|
||||
## 8. 关键时序图
|
||||
|
||||
### 8.1 claim new
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as User_or_SPA
|
||||
participant S as agentctl_serve_or_CLI
|
||||
participant D as docs_apply
|
||||
participant DB as SQLite
|
||||
U->>S: claim_new task owner mutex
|
||||
S->>S: snapshot CURRENT row
|
||||
alt row_exists_without_replace
|
||||
S-->>U: 400 INVALID_REQUEST
|
||||
else
|
||||
S->>D: apply single_row CAS
|
||||
D->>DB: lease documents receipts
|
||||
D-->>S: applied run_id
|
||||
S-->>U: 200 created
|
||||
end
|
||||
```
|
||||
|
||||
### 8.2 integrate prepare → enqueue → daemon ff
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as User
|
||||
participant P as integrate_prepare
|
||||
participant V as validate
|
||||
participant Q as queue_enqueue
|
||||
participant Daemon as agentctl_daemon
|
||||
participant Dev as refs_heads_dev
|
||||
U->>P: expected_dev tip
|
||||
P->>Dev: rev_parse
|
||||
alt tip_mismatch
|
||||
P-->>U: 409 BASE_CHANGED
|
||||
else
|
||||
P->>P: worktree_add_merge_no_ff
|
||||
P-->>U: head first_parent
|
||||
U->>V: unittest_or_scope_checks
|
||||
V-->>U: validated
|
||||
U->>Q: expected_dev head
|
||||
Q->>Daemon: pending_item
|
||||
Daemon->>Dev: ff_only_if_tip_matches
|
||||
Daemon-->>U: merged_or_failed
|
||||
end
|
||||
```
|
||||
|
||||
### 8.3 pi packet(生成与派发分离)
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant U as User
|
||||
participant Gen as pi_packet
|
||||
participant Disk as report_assets
|
||||
participant Run as pi_subagent_run
|
||||
U->>Gen: role goal auth_ref
|
||||
Gen->>Gen: freeze_source_sha
|
||||
Gen->>Disk: optional_write_packet_json
|
||||
Gen-->>U: packet
|
||||
Note over U,Run: 另一步:用户或 skill 显式 run
|
||||
U->>Run: packet_fields_plus_lease
|
||||
Run-->>U: receipt_pending_verdict
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## 9. 测试矩阵
|
||||
|
||||
验证层级:验证契约「工程工具验收」(非产品 PI)。
|
||||
|
||||
### 9.1 `scripts/tests/test_agentctl_serve.py`(实施时新增)
|
||||
|
||||
| 用例 | 预期 |
|
||||
|---|---|
|
||||
| `--format table` / `brief` / MCP 只读 / `claim archive` | **P0 done** |
|
||||
| MCP 再暴露 `brief`、`claim_archive` | P1 可选 |
|
||||
| `serve` + SPA | P1 |
|
||||
| `claim new` / `integrate prepare` / `pi packet` | P1 |
|
||||
| 跨机 claim 权威 | 见 coordination-db-daemon 方案,本控制台只读本地 SQLite |
|
||||
| bind 127.0.0.1 成功;0.0.0.0 拒绝 | 启动失败码 |
|
||||
| GET 八端点 200 且字段与 CLI collect 一致 | JSON 同构 |
|
||||
| 未知 POST `/api/shell` | 404 |
|
||||
| POST claim/new 缺 task | 400 |
|
||||
| POST claim/new 无 docs:publish | 403 |
|
||||
| 幂等:同 request_id 两次 | 第二次 replayed |
|
||||
| 非 loopback 模拟(若可) | 拒绝或无法连接 |
|
||||
|
||||
## 7. 分阶段实施顺序
|
||||
### 9.2 CLI 黑盒(扩展 `test_agentctl.py` fixture)
|
||||
|
||||
1. **P1-a**:抽出 `collect_*` 为稳定库(P0 已部分完成)→ `agentctl serve` 只读 API + 极简 HTML。
|
||||
2. **P1-b**:`claim new` + 控制台认领表单。
|
||||
3. **P1-c**:`integrate prepare` + 队列区按钮。
|
||||
4. **P1-d**:`pi packet` + 可选把 packet 路径注入 `pi-subagent-dispatch` skill。
|
||||
5. **P1-e**(可选):把 SPA 挂进 Cursor 简单 Browser tab 工作流说明。
|
||||
| 命令 | 覆盖 |
|
||||
|---|---|
|
||||
| `claim new` | 新建行 / `--replace` / BASE_CHANGED |
|
||||
| `integrate prepare` | first_parent==expected_dev;脏树拒绝 |
|
||||
| `pi packet` | source_sha 拒绝符号名;`--write` 路径落盘 |
|
||||
|
||||
## 8. 验收标准(实施时)
|
||||
复用临时 git 仓 + 拷贝 `agentctl*.py` 模式(与 P0 visibility fixture 一致)。
|
||||
|
||||
- 只读 API 与 CLI 同构(同 payload 字段)。
|
||||
- 任一写动作在审计表留下 run_id;CURRENT/MATRIX 变更有 `docs apply` 收据。
|
||||
- `serve` 默认拒绝非 loopback;集成测试用临时端口。
|
||||
- 工程工具单测:`scripts/tests/test_agentctl_serve.py` + 既有 visibility 测试。
|
||||
- 不改产品 compose / 不占用 8080。
|
||||
### 9.3 SPA 手动验收清单
|
||||
|
||||
## 9. 非目标
|
||||
- [ ] 四区数据在 daemon ok 时非空或显式 empty
|
||||
- [ ] 轮询不导致写动作
|
||||
- [ ] Prepare 确认框取消无请求
|
||||
- [ ] 409 展示 code 文本
|
||||
|
||||
- 产品 AdminConsole 内嵌治理页。
|
||||
- 远程多用户 Web 登录。
|
||||
- 自动 `--force` 清理 worktree。
|
||||
- 替代 Herdr / 产品 PI Runner。
|
||||
### 9.4 本设计任务验证(文档层)
|
||||
|
||||
## 10. 授权与下一步
|
||||
- 链接/锚点可达;mermaid 三角可渲染;与 P0 符号名一致。
|
||||
- **不**要求独立 `*-test-report.md`(NOT REQUIRED:纯设计文档)。
|
||||
|
||||
本文件为方案;实施需单独授权并新开 task(建议 `governance-console-p1-YYYY-MM-DD`),先 `catalog overlap` 再编码。
|
||||
---
|
||||
|
||||
## 10. 分阶段实施
|
||||
|
||||
| 阶段 | 范围 | 依赖 | 验收 |
|
||||
|---|---|---|---|
|
||||
| **P1-a** | `serve` 只读 8 端点 + 极简 HTML 展示 status/brief | P0 `collect_*` | test_agentctl_serve 只读用例绿;本机浏览器打开 |
|
||||
| **P1-b** | `claim new` CLI + POST + SPA 认领表单 | P1-a | 黑盒新建行;CURRENT 有收据 |
|
||||
| **P1-c** | `integrate prepare` CLI + POST + SPA Prepare | P1-b | first_parent 断言;不自动 enqueue |
|
||||
| **P1-d** | `pi packet` CLI + POST;skill 文档改为引用 packet | P1-a | packet JSON schema 单测;不触发 run |
|
||||
| **P1-e** | SPA 打磨、可选 MCP `brief`/`claim_archive`、可选 SSE | P1-a…d | 手动清单勾完 |
|
||||
|
||||
每阶段独立 task_id + catalog overlap + 工程工具单测;禁止跨阶段大揉。
|
||||
|
||||
---
|
||||
|
||||
## 11. 风险与缓解
|
||||
|
||||
| 风险 | 影响 | 缓解 |
|
||||
|---|---|---|
|
||||
| expected-dev 竞态(多会话并行合入) | enqueue 失败 | 明确 409/失败提示;prepare 可重入;不隐藏错误 |
|
||||
| serve 闲置占端口 | 本机冲突 | 默认 7432;文档说明与产品 8080/8081 隔离 |
|
||||
| `@document` 归档与并行 docs apply | BASE_CHANGED | archive 持 docs:admin;短租约;冲突则重跑 dry-run |
|
||||
| SPA 误 enqueue 推进 dev | 错误合入 | SPA 默认不提供一键 enqueue;仅 Prepare |
|
||||
| 与产品 web 目录混淆 | 发布门禁污染 | 静态资源仅 `scripts/governance-console/` |
|
||||
| packet 被当成已派发 | 假 PASS | 生成不写 verdict;skill 强制 run_status≠叙事 |
|
||||
|
||||
---
|
||||
|
||||
## 12. 衔接与授权
|
||||
|
||||
### 12.1 外部衔接
|
||||
|
||||
| 主题 | 文档 | 本方案关系 |
|
||||
|---|---|---|
|
||||
| 跨机权威 | [coordination-db-daemon phased plan](../../remediation/2026-09-23-coordination-db-daemon-phased-plan.md) | 不重复;控制台只读本机 SQLite |
|
||||
| P0 可视化 | [governance-visibility-p0](./2026-09-24-governance-visibility-p0.md) | 本设计复用 collect/archive |
|
||||
| Cursor hooks | 规则 `cursor-hooks` | serve 不经 hooks;CLI 写仍走既有钩子 |
|
||||
| PI 执行器 | [pi-subagent-executor](../2026-09-24-pi-subagent-executor.md) | packet 字段对齐;不改执行器门禁 |
|
||||
|
||||
### 12.2 实施授权门槛
|
||||
|
||||
1. 用户显式授权「实施 P1-a(或指明阶段)」。
|
||||
2. 新 task(建议 `governance-console-p1a-YYYY-MM-DD`)+ `catalog overlap`(相对本 R-ID / mutex `agentctl-console`)。
|
||||
3. 写路径限 `scripts/` + 必要 `.doc`;产品树禁止。
|
||||
4. 合入走 validate → queue enqueue;不 push。
|
||||
|
||||
### 12.3 设计修订
|
||||
|
||||
- `design_revision`: `governance-console-p1-r1`
|
||||
- 变更本规格须更新 revision 并在实施 task 记录 `policy_revision` 差分。
|
||||
|
||||
---
|
||||
|
||||
## 附录 A. 符号索引(实施对照)
|
||||
|
||||
| 符号 | 文件 | 状态 |
|
||||
|---|---|---|
|
||||
| `collect_status_payload` | `scripts/agentctl.py` | P0 已有 |
|
||||
| `collect_cleanup_payload` | 同上 | P0 已有 |
|
||||
| `collect_docs_drift_payload` | 同上 | P0 已有 |
|
||||
| `collect_daemon_payload` | 同上 | P0 已有 |
|
||||
| `collect_catalog_drift_payload` | 同上 | P0 已有 |
|
||||
| `claim_archive` | 同上 | P0 已有 |
|
||||
| `emit_payload` / `visibility.render_*` | agentctl + visibility | P0 已有 |
|
||||
| `claim_new` | 待建 | P1-b |
|
||||
| `integrate_prepare` | 待建 | P1-c |
|
||||
| `pi_packet` | 待建 | P1-d |
|
||||
| `agentctl serve` | 待建 | P1-a |
|
||||
| SPA `index.html` | `scripts/governance-console/` | P1-a/e |
|
||||
|
||||
## 附录 B. 端口与路径速查
|
||||
|
||||
| 项 | 值 |
|
||||
|---|---|
|
||||
| HTTP | `http://127.0.0.1:7432` |
|
||||
| 静态根 | `scripts/governance-console/` |
|
||||
| PI packet 根 | `.doc/test-reports/assets/pi-subagents/<task>/<request>/` |
|
||||
| CURRENT 归档追加 | `.doc/archive/ops/2026-09-21-current-history.md` |
|
||||
|
||||
Reference in New Issue
Block a user