ECC 控制平面实时视图:ecc.control-plane.view.v1¶
状态:随控制面板发布(scripts/lib/control-pane/control-plane-view.js)。只读。仅建议。
该视图将仓库中已分别计算的三部分内容合并,并以任务、泳道和事件为结构,作为一个 JSON 文档提供,使另一个控制平面(Ito 运维看板、Hermes 或 Codex 读取器、钩子)可以在不了解 ECC 内部细节的情况下消费它。
| 输入 | 来源 |
|---|---|
| 会话 | scripts/lib/control-pane/state.js,ECC2 sessions 表 |
| 成对邻近度 | scripts/lib/agent-proximity/(对 x_tree、x_overlap、x_dep 的 noisy-OR)通过 scripts/lib/control-pane/proximity.js |
| 2D 投影 | scripts/lib/agent-proximity/projection.js(滚动 z-score,尾部在 2.5 / 97.5 处截断,PCA) |
| 协调清单 | scripts/lib/coordination-inventory.js(PR #3028):已声明的任务和会话、心跳新鲜度、租约冲突 |
端点¶
由 node scripts/control-pane.js 提供(仅限 loopback,与面板其余部分使用相同的 Host 和 Origin 门控):
| 路由 | 返回 |
|---|---|
GET /control-plane |
自包含 HTML 页面:2D 投影画布、泳道和任务、事件流。无外部脚本。 |
GET /api/control-plane |
下方完整视图文档。 |
GET /api/control-plane/events |
仅 { schemaVersion, generatedAt, thresholds, events, counts },供钩子和轮询器使用。 |
服务器每个进程保留一个投影窗口。两个 API 路由共享一个缓存五秒的快照,并合并并发刷新请求。该间隔内的读取不会添加样本。过期后,下一次读取会刷新一次快照;空闲间隔不会生成合成样本。刷新失败时返回错误,而不是看似健康的空数据。页面拒绝失败的 HTTP 响应和无效视图信封,并显示 offline。createControlPaneServer 的选项:projection(windowSize、clipPercentiles)、viewOptions(thresholds、manifest、channelWeights、minWindowForZscore)、proximityOptions(传递给扫描)。
文档¶
{
"schemaVersion": "ecc.control-plane.view.v1",
"generatedAt": "2026-09-11T20:01:00.000Z",
"source": { "snapshotSchema": "ecc.control-pane.snapshot.v1", "repoRoot": "...", "dbPath": "..." },
"thresholds": { "ta": 0.35, "ra": 0.7, "source": "static" },
"lanes": [ { "id": "harness:codex", "label": "codex", "kind": "harness", "taskIds": ["session-a"] } ],
"tasks": [ { "...": "see Task" } ],
"pairs": [ { "...": "see Pair" } ],
"events": [ { "...": "see Event" } ],
"projection": { "...": "see Projection" },
"inventory": { "...": "see Inventory" },
"counts": { "lanes": 1, "tasks": 1, "agents": 1, "pairs": 0, "events": 0, "advisories": 0, "resolutions": 0 },
"limits": [ "..." ]
}
任务¶
每个会话对应一个任务。没有更改文件的会话仍然是任务;它没有投影点,也没有配对。
| 字段 | 含义 |
|---|---|
id |
会话 id,保持不变。 |
lane |
该任务所属的泳道 id。 |
label |
会话任务文本,或 id。 |
harness、agentType、state、pid |
来自会话行。 |
worktree |
{ path, branch, base } 或 null。 |
heartbeatAt、updatedAt |
ISO 时间戳或 null。 |
workingSet |
{ fileCount, files }:工作树相对于其 base 的差异。 |
projection |
{ point, pairs, maxRisk },其中 point 为 [x, y] 或 null。point 是任务配对点在 PCA 空间中的风险加权质心。 |
inventory |
{ id, heartbeat, process, authority: "declared-only" }。id 是 inventory 清单中使用的清理后的标识符;heartbeat 和 process 是 #3028 的观察值。 |
泳道¶
任务的分组。优先级:task-group(会话 task_group),然后是 project,再是 harness。id 带有前缀(group:、project:、harness:),因此消费者无需读取 kind 即可区分类型。
配对¶
来自空域扫描的每个 agent 配对对应一行(只有包含编辑的会话参与)。
| 字段 | 含义 |
|---|---|
a、b |
会话 id。 |
risk、level |
Noisy-OR 风险以及扫描在扫描阈值下的级别(clear、advisory、resolution)。 |
channels |
原始 { x_tree, x_overlap, x_dep },取值在 [0, 1]。 |
normalized |
经过 z-score、截断和映射回原尺度后的相同值;窗口冷启动时等于 channels。 |
point |
[pc1, pc2] PCA 得分。 |
事件¶
操作员或钩子可能采取操作的事项。id 在轮询之间是确定性的,因此消费者可以据此去重。
{
"id": "proximity.advisory:session-a|session-b:resolution",
"kind": "proximity.advisory",
"level": "resolution",
"severity": "critical",
"at": "2026-09-11T20:01:00.000Z",
"subject": { "a": "session-a", "b": "session-b", "aLabel": "...", "bLabel": "..." },
"risk": 1,
"distance": 0,
"channels": { "x_tree": 1, "x_overlap": 1, "x_dep": 0 },
"threshold": { "ta": 0.35, "ra": 0.7, "crossed": "ra", "source": "static" },
"action": { "type": "steer", "steer": "session-b", "hold": "session-a" },
"message": "Resolution advisory: session-b steers, session-a holds (risk 100%, static threshold 0.7)."
}
| 类型 | 级别 | 操作类型 | 来源 |
|---|---|---|---|
proximity.advisory |
traffic(风险达到或超过 ta)、resolution(达到或超过 ra) |
transmit(两个 agent 共享意图)、steer(steer 移动,hold 保持航向) |
每个配对链接,按视图阈值评估。优先权:进度更多,然后开始更早,然后稳定 id。 |
inventory.lease-conflict |
conflict |
review |
#3028 leaseConflicts。仅声明,绝不锁定。 |
每个视图的阈值是静态的(source: "static")。学习阈值、闭合率升级以及 pause 和 wait 机动属于 slice (b),参见 TCAS-HOOK.md。
投影¶
{
"method": "pca",
"channels": ["x_tree", "x_overlap", "x_dep"],
"weights": { "x_tree": 0.25, "x_overlap": 1, "x_dep": 0.9 },
"normalization": "zscore-clipped",
"window": { "samples": 12, "percentiles": [2.5, 97.5], "channels": [ { "channel": "x_tree", "mean": 0.39, "stddev": 0.42, "clipLow": -0.92, "clipHigh": 1.45 } ] },
"pca": { "loadings": [ { "x_tree": 0.12, "x_overlap": 0.87, "x_dep": -0.47 }, { "...": "..." } ], "explainedVariance": [0.6, 0.39] },
"agents": [ { "agentId": "session-a", "point": [0.18, 0.41], "pairs": 3, "maxRisk": 1 } ]
}
每次轮询的流水线:每个配对的通道向量都会被推入滚动窗口(默认 512 个样本)。当窗口中至少包含 8 个样本时,每个通道都会相对于窗口进行 z 分数化,裁剪到窗口的 2.5 和 97.5 百分位数(以 z 为单位),映射回 [0, 1],乘以静态通道权重,然后加权矩阵经过 PCA(对 3x3 协方差使用 Jacobi)。少于 8 个样本时,使用原始通道值,且 normalization 为 raw。零方差通道映射为 0.5。退化输入(少于两个配对、总方差为零)会产生零分数,永不产生 NaN。
投影仅用于展示。它从不改变 risk、建议级别或通行权。
清单¶
该 #3028 报告,其中按任务拆分的行被折叠到 tasks[].inventory 中。顶层保留:status(ok 或带 reason 的 unavailable)、truncated(超过 64 个会话)、observedAt、mode: "read-only"、activity、leaseConflicts、warnings、coverage、limits。清单由实时会话构建(id 会被清理为清单字符集,路径来自工作集,心跳来自会话行,声明的会话状态对 running/pending/idle 为 open,对 completed/failed/stopped 为 closed)。外部清单(viewOptions.manifest)可以添加 goals、leases、repositories 以及额外的 tasks;随后清单会为它们报告租约冲突和目标活动。
在 Ito 运维控制平面中的复用¶
需要复制的结构是 task、lane、event:
- task 具有
id、lane、state、可选位置,以及一个观察块,其authority表示应给予它多少信任; - lane 是一个具名分组,包含有序的
taskIds; - event 具有稳定的
id、kind、level、severity、at、subject、带type的action,以及面向人类的message。
除事件类型外,该结构中的任何内容都不是 ECC 特有的。渲染任务泳道和事件流的运维看板可以原样渲染此文档,并可以向同一事件流发出自己的类型(deal.stalled、bridge.down)。
本功能不会做什么¶
- 不会获取租约,也不会暂停或引导代理。消费者执行操作;视图仅报告。
- 不声称冲突降低百分比。推送计划中的 85% 目标是在切片 (b) 前后两周进行测量的,而不是在这里。
- 目前还没有语义、调用图或频率通道(切片 (g))。当新通道进入扫描时,PCA 会自动识别它们。
本页原文 Markdown:在 AtomGit 查看·内容源自开源项目 ev/ECC