merge: feature/project-control-center-plan
This commit is contained in:
@@ -0,0 +1,60 @@
|
||||
---
|
||||
title: "个人工程中控台:实时项目看板与离线 HTML 快照"
|
||||
status: planned
|
||||
created: 2026-09-17
|
||||
updated: 2026-09-17
|
||||
owner: unassigned
|
||||
branch: feature/engineering-dashboard
|
||||
worktree: "-"
|
||||
mutex: engineering-dashboard
|
||||
---
|
||||
|
||||
# 个人工程中控台:实时项目看板与离线 HTML 快照
|
||||
|
||||
## 目标
|
||||
|
||||
实现一个独立于产品后台的本地只读中控台,以同一不可变快照驱动实时页面、机器可读 JSON 与单文件 HTML 导出。
|
||||
|
||||
## 范围
|
||||
|
||||
- 聚合 `.doc`、Git/worktree、Docker/Compose、`/ready` 和晋升凭证。
|
||||
- 展示架构、模块、功能、任务、分支、验证和环境实装证据。
|
||||
- 提供 Markdown 搜索、阅读、正反向链接和证据链导航。
|
||||
- 显示来源、新鲜度、degraded 与 drift,不把声明状态当作观测状态。
|
||||
|
||||
## 非目标
|
||||
|
||||
- 不接入产品后台、产品数据库或产品权限体系。
|
||||
- 不写文档,不操作 Git、Docker、部署或 Herdr。
|
||||
- 不隐式联网或执行 `git fetch`。
|
||||
|
||||
## 步骤
|
||||
|
||||
1. [ ] U1:冻结快照、事实与四轴状态契约。
|
||||
2. [ ] U2:实现文档图谱与领域解析器。
|
||||
3. [ ] U3:实现 Git 与 worktree 采集。
|
||||
4. [ ] U4:实现运行态与部署证据采集。
|
||||
5. [ ] U5:实现对账、派生视图与新鲜度。
|
||||
6. [ ] U6:实现本地服务、总览与文档导航。
|
||||
7. [ ] U7:实现离线导出、脚本、浏览器验收和治理文档同步。
|
||||
|
||||
## 验收标准
|
||||
|
||||
- [ ] 实时 HTML、离线 HTML 和 JSON 引用同一 `generation_id` 与 `revision_id`。
|
||||
- [ ] 计划、实施、验证、实装四轴独立展示。
|
||||
- [ ] rdev、dev ahead、main events 分叉三个真实样本按方案输出。
|
||||
- [ ] 单源失败时页面仍可用,且显示 stale/error/last-success。
|
||||
- [ ] 默认仅监听 loopback,无写操作、凭证暴露、路径越界和远程资源执行。
|
||||
- [ ] 导出 HTML 离开仓库后仍可阅读 Markdown,且不嵌入 assets。
|
||||
|
||||
## 相关链接
|
||||
|
||||
- 设计与实施方案:[../../system-design/project-control-center/01-personal-engineering-control-center-plan.md](../../system-design/project-control-center/01-personal-engineering-control-center-plan.md)
|
||||
- Checklist: 待实施阶段创建
|
||||
- Handoff: 待需要时创建
|
||||
- Test report: 待实施阶段创建
|
||||
|
||||
## 证据 / 备注
|
||||
|
||||
- 本任务当前仅完成方案设计,尚未认领、未实现、未验证、未部署。
|
||||
- 实施开始前必须在 CURRENT 登记 owner、真实 branch、worktree 与 mutex;本文件中的 branch 是计划分支名。
|
||||
@@ -138,6 +138,18 @@
|
||||
|
||||
---
|
||||
|
||||
### 8. 个人工程中控台
|
||||
|
||||
| 项 | 链接 |
|
||||
|-----|------|
|
||||
| 设计与实施方案 | [project-control-center/01-personal-engineering-control-center-plan.md](project-control-center/01-personal-engineering-control-center-plan.md) |
|
||||
| 任务入口 | [../ops/short-term/2026-09-17-engineering-dashboard.md](../ops/short-term/2026-09-17-engineering-dashboard.md) |
|
||||
| 一句话总结 | 独立于产品后台的本地只读中控台,以同一不可变快照驱动实时项目看板、Agent JSON 和离线 HTML |
|
||||
|
||||
**核心边界**:计划、Git 实施、验证、环境实装四轴独立;冲突保留来源证据;不写文档、不操作 Git/Docker/部署/Herdr,不读取凭证。
|
||||
|
||||
---
|
||||
|
||||
## 🏗️ 在整体架构中的位置
|
||||
|
||||
```
|
||||
|
||||
+607
@@ -0,0 +1,607 @@
|
||||
---
|
||||
title: "个人工程中控台:实时项目看板与离线 HTML 快照"
|
||||
type: feat
|
||||
date: 2026-09-17
|
||||
artifact_contract: ce-unified-plan/v1
|
||||
product_contract_source: ce-plan-bootstrap
|
||||
execution: code
|
||||
---
|
||||
|
||||
# 个人工程中控台:实时项目看板与离线 HTML 快照
|
||||
|
||||
## Goal Capsule
|
||||
|
||||
为仓库所有者提供一个独立于产品后台的本地只读中控台。打开一个页面即可判断当前系统由什么组成、哪些任务正在计划或实施、真实分支和 worktree 在哪里、各环境实际运行了什么,并能在两次点击内到达对应的设计、审计、整改、任务和测试材料。
|
||||
|
||||
中控台同时提供两种输出:
|
||||
|
||||
1. `serve`:持续采集本地仓库、Git 和运行环境,提供自动刷新的 HTML 页面与机器可读 JSON;
|
||||
2. `export`:基于同一份不可变快照生成单文件 HTML,便于归档、离线查看和交接。
|
||||
|
||||
这不是产品功能,不接入产品后台、产品数据库或产品权限体系;它也不是发布系统,不执行 Git、Docker、部署或文档写操作。
|
||||
|
||||
### 成功标准
|
||||
|
||||
- 在当前仓库规模下,首次可用页面目标为 2 秒内出现;慢数据源可随后标记为 `degraded`,不得拖垮整页。
|
||||
- 正常情况下,本地文件、Git 或运行态变化在 5 秒内反映到新快照。
|
||||
- 页面分别展示“文档声明、Git 实施、验证证据、环境实装”,不把任务文档的 `done` 翻译为已合并或已部署。
|
||||
- 每个关键结论均显示来源、采集时间、新鲜度和可信类型;冲突保留双方证据,不静默选边。
|
||||
- 在线模式检索 allowlist 内未截断的 Markdown 正文;离线导出同时给出 included、truncated 和 metadata-only 清单,二进制附件只索引路径、类型、大小和归属。
|
||||
- 单文件 HTML 默认权限为 `0600`,可脱离仓库阅读已纳入 inclusion manifest 的 Markdown 正文,并醒目标出截断或仅元数据条目;不打包 `.doc/**/assets`。
|
||||
- 任一采集源失败时仍可查看最近成功数据,并明确显示 `stale/error/last_success_at`。
|
||||
|
||||
---
|
||||
|
||||
## Product Contract
|
||||
|
||||
### 用户与使用场景
|
||||
|
||||
唯一主要用户是仓库所有者。典型使用包括:
|
||||
|
||||
- 每天开始工作时查看焦点任务、阻塞、集成槽和环境异常;
|
||||
- 从模块进入设计、任务、测试和部署证据链;
|
||||
- 判断某项工作究竟只是有计划、正在实现、已经验证,还是已在某环境实装;
|
||||
- 查看本地分支、远端跟踪引用、ahead/behind、worktree 和未提交变更;
|
||||
- 发现 `CURRENT`、功能矩阵、发布门禁、Git 与 Docker 之间的漂移;
|
||||
- 导出一个自包含 HTML,作为某一时点的项目快照。
|
||||
|
||||
### 已确定的产品决策
|
||||
|
||||
#### PKD-1:独立本地工具
|
||||
|
||||
采用独立 Go CLI 和本地 Web 页面,不加入现有产品后台。
|
||||
|
||||
(session-settled: user-approved — chosen over product-admin integration: the console is for the repository owner’s local engineering management and the production image excludes `.doc` and `.git`)
|
||||
|
||||
#### PKD-2:只读实时页与离线快照共用数据模型
|
||||
|
||||
实时服务和导出文件必须由同一份版本化快照生成,避免在线页面与离线报告出现两套口径。
|
||||
|
||||
(session-settled: user-approved — chosen over a static-only report: the requested console must follow agent tasks and project state as they change)
|
||||
|
||||
### 核心需求
|
||||
|
||||
| ID | 需求 |
|
||||
|---|---|
|
||||
| R1 | CLI 默认解析当前 Git 仓库根,也接受显式 `--repo`;页面始终显示绝对根路径、当前分支、HEAD 和采集时间。 |
|
||||
| R2 | 仅监听 `127.0.0.1`,不依赖产品容器、产品数据库或产品登录。 |
|
||||
| R3 | 架构与模块页聚合 `module-boundaries.yaml`、系统设计索引和 `FEATURE-MATRIX`,展示模块、能力、依赖和证据链。 |
|
||||
| R4 | 任务状态至少拆为 `doc_status`、Git facets、`verification_result`/`verification_freshness`、deployment facets;可并存事实不得压成单值枚举。 |
|
||||
| R5 | Git 页展示本地/跟踪分支、ahead/behind、最近提交、worktree、dirty/untracked 和任务声明匹配情况;不得隐式 `fetch`。 |
|
||||
| R6 | 部署页按 shared/dev/test/main 分别展示容器状态、应用 readiness、服务完整性、schema、镜像与 promotion receipt;不得计算未经定义的综合绿灯。 |
|
||||
| R7 | 文档页支持按 taxonomy、状态、模块和关键词筛选,展示正文、正向链接、反向链接、broken、orphan 与 unindexed 状态;查询状态可通过 URL 恢复。 |
|
||||
| R8 | 一个不可变快照包含 `schema_version`、`generation_id`、`revision_id`、`generated_at`、仓库/提交身份、来源状态、事实与冲突。 |
|
||||
| R9 | 自动刷新采用完整快照原子切换;每个来源独立超时,失败时保留最近成功数据并标注过期。 |
|
||||
| R10 | 每条关键事实标注 `declared`、`observed`、`verified` 或 `inferred`,并保留来源路径和采集时间。 |
|
||||
| R11 | 单 HTML 内嵌结构化模型、页面资源和允许导出的 Markdown 正文;附件只保留元数据及相对链接,并显示内容覆盖清单。 |
|
||||
| R12 | 对 Agent 暴露稳定的只读 JSON,而不是让 Agent 解析 HTML;JSON 与页面引用同一 `generation_id` 和 `revision_id`。 |
|
||||
| R13 | TaskState 显示声明的 owner/Agent 类型/认领/mutex 与基于 Git 的最近活动证据;Herdr 工程 Agent 和产品 PI Agent Runner 使用不同类型。没有运行态来源时必须显示 unknown,不得把“已认领”写成“正在执行”。 |
|
||||
| R14 | 文件、命令和 HTTP 均采用 allowlist;拒绝路径穿越、symlink 越界、原始 HTML 执行、远程资源加载和凭证读取。 |
|
||||
|
||||
### 事实源与权威边界
|
||||
|
||||
| 领域 | 权威来源 | 中控台处理方式 |
|
||||
|---|---|---|
|
||||
| 发布门禁 | `.doc/remediation/gap-matrix.md` | 只解释发布 blocker,不替代能力完成度。 |
|
||||
| 能力成熟度 | `.doc/status/FEATURE-MATRIX.md` | 显示功能完成度,不据此推断是否部署。 |
|
||||
| 当前焦点、认领、集成槽 | `.doc/ops/CURRENT.md` | 作为团队声明,与 Git 和运行态对账。 |
|
||||
| 任务计划 | `ops/short-term`、`ops/long-term`、backlog front matter | 作为计划状态,不据此推断实现。 |
|
||||
| 分支与 worktree | Git plumbing | 作为本地观测;远端状态注明“基于本地 refs,未联网刷新”。 |
|
||||
| 环境运行态 | Docker/Compose 元数据与 `/ready` | 分开展示容器、应用与服务完整性。 |
|
||||
| 验收证据 | `.doc/test-reports` 及 promotion receipts | 显示证据存在性与身份,不以文件名替代内容校验。 |
|
||||
|
||||
来源之间不设全局覆盖顺序。各来源回答自己的问题;值不一致时生成 drift,并并列展示原值、时间和来源。
|
||||
|
||||
### 用户流程
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Start[启动 serve 或 export] --> Root[解析显式 repo root]
|
||||
Root --> Collect[并行采集文档 Git 运行态]
|
||||
Collect --> Snapshot[构建不可变快照]
|
||||
Snapshot --> Reconcile[按领域对账]
|
||||
Reconcile --> Live[本地实时页面和 JSON]
|
||||
Reconcile --> Export[单文件 HTML]
|
||||
Live --> Refresh[定时生成下一快照]
|
||||
Refresh --> Snapshot
|
||||
```
|
||||
|
||||
总览默认优先显示 `in_progress`、`blocked`、`planned`、`partial/deferred`、drift 和 degraded。`done` 与 archive 默认收起,避免历史材料淹没当前工作。
|
||||
|
||||
任务详情按照以下证据链导航:
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Audit[audit 问题] --> Remediation[remediation 方案]
|
||||
Remediation --> Task[任务声明]
|
||||
Task --> Git[分支 worktree commit merge]
|
||||
Git --> Test[测试与验收报告]
|
||||
Test --> Deploy[环境 artifact 与 readiness]
|
||||
```
|
||||
|
||||
显式 Markdown 链接和既定 taxonomy 属于强关系;仅由文件名或 slug 推断的关系标为“候选”,不得参与完成度计算。
|
||||
|
||||
### 状态模型
|
||||
|
||||
```mermaid
|
||||
flowchart TB
|
||||
D[doc_status: planned/in_progress/blocked/done] --> View[并列状态视图]
|
||||
G[Git facets: branch/worktree/merge/cleanliness/ahead-behind] --> View
|
||||
V[Verification: result + freshness + bound identity] --> View
|
||||
P[Deployment facets: container/readiness/services/artifact identity] --> View
|
||||
View --> Drift{来源是否一致}
|
||||
Drift -->|是| Consistent[consistent]
|
||||
Drift -->|否| Conflict[drift + 双方证据]
|
||||
```
|
||||
|
||||
“实装”定义为存在可核对的环境观测证据,而不是任务文档为 `done`。容器可达但 artifact identity 无法核对时显示“运行可见、版本未验证”,不得提升为 verified deployment。当文档声明 healthy、Docker 显示异常而 `/ready` 为 ok 时,页面保留多值并标记 drift,不输出统一绿灯。
|
||||
|
||||
### 真实验收样本
|
||||
|
||||
1. rdev:存在调研、设计、任务与 backlog,但若没有 CURRENT 认领和真实分支,应显示“已计划、未认领、未实施、未实装”。
|
||||
2. main 环境:若 CURRENT 声明整体 healthy,而 events 容器实际 restarting、应用 `/ready` 仍为 ok,应同时显示三项证据与 drift。
|
||||
3. 本地 dev:若分支领先 `origin/dev`,必须显示“本地已具备、远端未确认可用”,不得写成已远程发布。
|
||||
4. `system-admin-console`:作为产品管理后台能力,与本计划的个人工程中控台分开展示,名称和边界不得混淆。
|
||||
|
||||
### 安全与非目标
|
||||
|
||||
一期明确不做:
|
||||
|
||||
- 不写文档,不修改任务状态,不占用集成槽;
|
||||
- 不创建、切换、合并、删除或推送 Git 分支;
|
||||
- 不执行 `git fetch`,不调用远端托管平台 API;
|
||||
- 不启动、停止、重建或部署容器;
|
||||
- 不控制 Herdr 或向 Agent 派发任务;
|
||||
- 不读取 `.env`、`.secrets`、Docker `Config.Env`、数据库数据或 `.git` 内部文件正文;
|
||||
- 不加入产品 API、产品前端、产品数据库或生产镜像;
|
||||
- 不执行 Markdown 原始 HTML、脚本、Mermaid 或远程资源。
|
||||
|
||||
后续候选包括跨快照历史、远端 CI/Gitea 聚合、受限 Markdown/Mermaid 渲染、Agent 查询 API 和修复建议。任何写操作继续保持在本工具之外。
|
||||
|
||||
---
|
||||
|
||||
## Planning Contract
|
||||
|
||||
### High-Level Technical Design
|
||||
|
||||
以下图示冻结边界和协议,不规定具体函数签名。
|
||||
|
||||
```mermaid
|
||||
flowchart LR
|
||||
Docs[.doc sources] --> DC[Document collector]
|
||||
Git[Git/worktrees] --> GC[Git collector]
|
||||
Run[Docker/ready/receipts] --> RC[Runtime collector]
|
||||
DC --> Build[Snapshot builder]
|
||||
GC --> Build
|
||||
RC --> Build
|
||||
Build --> Rec[Reconcile facts and conflicts]
|
||||
Rec --> JSON[Read-only JSON]
|
||||
Rec --> Web[Local HTML]
|
||||
Rec --> File[Offline HTML]
|
||||
```
|
||||
|
||||
```mermaid
|
||||
sequenceDiagram
|
||||
participant UI as Browser
|
||||
participant C as Collection coordinator
|
||||
participant S as Sources
|
||||
participant P as Snapshot publisher
|
||||
UI->>C: poll with revision_id
|
||||
C-->>UI: current snapshot immediately
|
||||
C->>S: singleflight collection with deadlines
|
||||
S-->>C: facts or source error
|
||||
C->>P: publish complete generation atomically
|
||||
P-->>UI: new revision or not-modified
|
||||
```
|
||||
|
||||
```mermaid
|
||||
stateDiagram-v2
|
||||
[*] --> Loading
|
||||
Loading --> Fresh: first collection succeeds
|
||||
Loading --> ErrorUnknown: first collection fails
|
||||
Fresh --> Refreshing: TTL expires
|
||||
Refreshing --> Fresh: new generation succeeds
|
||||
Refreshing --> Stale: source fails and last-known exists
|
||||
Stale --> Fresh: source recovers
|
||||
ErrorUnknown --> Fresh: source first succeeds
|
||||
```
|
||||
|
||||
### 技术决策
|
||||
|
||||
#### KTD-1:采用仓库内独立 Go CLI
|
||||
|
||||
新增 `cmd/engineering-dashboard` 与 `internal/engineeringdashboard`,复用仓库 Go 工具链但不导入产品业务包。Go 标准库足以提供本地 HTTP、资源嵌入、JSON、并发和原子文件输出;现有 `yaml.v3` 可用于已定义的 YAML 契约。
|
||||
|
||||
#### KTD-2:快照是唯一交付模型
|
||||
|
||||
采集器只生产事实,reconcile 层只生产派生状态和冲突,HTTP/API/export 只消费已完成的不可变快照。快照至少包含:
|
||||
|
||||
```text
|
||||
schema_version, generation_id, revision_id, generated_at, collection_duration
|
||||
repository { root, branch, head, dirty }
|
||||
sources[] { name, status, observed_at, last_success_at, error }
|
||||
facts[] { subject, field, value, provenance, source_ref, observed_at, confidence }
|
||||
conflicts[] { subject, field, kind, fact_refs[] }
|
||||
documents[], modules[], tasks[], git[], environments[]
|
||||
```
|
||||
|
||||
`generation_id` 唯一标识一次采集,包含采集批次语义;`revision_id` 只由 schema、仓库身份和规范化的非易变事实、冲突、来源状态确定,明确排除 `generated_at`、`observed_at` 和采集耗时。HTML 与 JSON 必须展示同一对标识,HTTP ETag 和前端是否重绘使用 `revision_id`。一期不读取旧 schema 的外部 JSON;离线 HTML 自带对应 renderer,因此不依赖未来二进制迁移。
|
||||
|
||||
#### KTD-3:专用解析器与容错索引并存
|
||||
|
||||
对 CURRENT、FEATURE-MATRIX、gap-matrix、任务 front matter 和 module boundaries 编写契约化解析器。文档层只索引 promotion receipt 的路径与链接,结构化部署凭证由运行态采集器唯一负责。对其余 Markdown 只提取安全元数据、标题、正文与链接。专用解析器失败时保留原文入口并标记 degraded,不凭模糊规则编造状态。
|
||||
|
||||
#### KTD-4:命令执行采用固定 argv 和超时
|
||||
|
||||
Git 与 Docker 采集通过注入式 command runner 执行固定程序和分离 argv,不通过 shell 拼接。`--repo` 先转为绝对、symlink-resolved 的 Git 根并作为单个参数传递。每个来源默认 2 秒超时;错误输出做长度限制和敏感字段清理。Git 使用 porcelain/plumbing 输出,例如 `status --porcelain=v2`、`worktree list --porcelain`、`for-each-ref`、`rev-list`、`merge-base`。
|
||||
|
||||
#### KTD-5:一期采用短轮询,不引入持久数据库
|
||||
|
||||
服务端由单一采集协调器按 TTL 触发完整重采集,2–5 秒刷新;同一仓库最多一轮采集在途,请求只读取当前快照,不直接叠加扫描。每轮带单调 generation 序号和整轮 deadline,只有当前有效轮次能原子发布。页面使用 ETag/`revision_id` 避免重复传输。last-known 只在同一 `serve` 进程内有效;冷启动或单次 export 首次采集失败时显示 unknown/error,不伪造历史值。文件监听、SSE 通知、持久缓存和历史数据库均后置。
|
||||
|
||||
#### KTD-6:安全阅读优先于富渲染
|
||||
|
||||
在线详情页一期将 Markdown 全部作为纯文本安全转义,并保留换行和空白;标题、列表、链接、代码、图片和 Mermaid 均显示源码,不生成 HTML 节点或发起资源请求。静态导出内嵌同一正文和内部导航。所有文档 ID 都是规范化仓库相对路径,只允许 `.doc/**/*.md` 及明确列入 allowlist 的根 Markdown;读取前后都校验解析路径,直接拒绝 symlink,并对 `.git`、`.env*`、`.secrets`、`data` 等敏感路径执行最终目标 denylist。
|
||||
|
||||
#### KTD-7:导出为自包含、有限尺寸的证据快照
|
||||
|
||||
导出将模型、CSS、JS 和允许的 Markdown 正文写入单 HTML,采用临时文件加 rename 原子落盘,默认 `0600`。数据使用 HTML-safe JSON 或等价编码封装,正文只通过 `textContent`/DOM API 写入;CSP 禁止网络、外部资源和内联事件执行。默认只嵌入 Git tracked、allowlist 内的 Markdown;untracked Markdown 只列元数据,除非用户显式选择。导出前输出 inclusion manifest 与敏感模式告警;`.doc/**/assets`、数据库、构建产物和二进制报告不嵌入。
|
||||
|
||||
### 建议目录
|
||||
|
||||
```text
|
||||
cmd/engineering-dashboard/
|
||||
main.go
|
||||
internal/engineeringdashboard/
|
||||
model.go
|
||||
collector.go
|
||||
source_docs.go
|
||||
source_git.go
|
||||
source_runtime.go
|
||||
reconcile.go
|
||||
server.go
|
||||
export.go
|
||||
assets/
|
||||
index.html
|
||||
app.js
|
||||
app.css
|
||||
testdata/
|
||||
docs/
|
||||
git/
|
||||
runtime/
|
||||
scripts/
|
||||
engineering-dashboard.sh
|
||||
.doc/test-reports/
|
||||
YYYY-MM-DD-engineering-dashboard-test-report.md
|
||||
```
|
||||
|
||||
### 风险与缓解
|
||||
|
||||
| 风险 | 缓解 |
|
||||
|---|---|
|
||||
| 文档结构并不完全统一 | 只对 SSOT 和任务 front matter 使用严格契约;其余文档容错索引并暴露解析告警。 |
|
||||
| 看板制造“假完成” | 多轴 facets、事实 provenance、验证身份绑定、冲突不覆盖、真实反例测试。 |
|
||||
| Docker/Git 卡住或不可用 | 独立超时、并行采集、last-known 状态、degraded 页面。 |
|
||||
| 文档 XSS 或路径穿越 | 纯文本渲染、HTML-safe 数据封装、CSP、路径 allowlist、拒绝 symlink、最终目标敏感路径 denylist。 |
|
||||
| `.doc` 附件导致扫描/导出失控 | 默认跳过 assets 内容,只采集元数据;设置单文档和总正文上限并报告截断。 |
|
||||
| 导出副本离开本机后 `0600` 不再提供保护 | 页面首部标明敏感快照、仓库身份和生成时间;输出 inclusion manifest,交接者自行控制接收者、保留期与删除。 |
|
||||
| worktree 与主 checkout 混淆 | 只管理 `--repo` 指定/解析出的根,页面常驻显示根与 HEAD;其他 worktree 仅作为 Git 元数据。 |
|
||||
| 本地 remote refs 被误认为远端实时状态 | 显示 refs 观测时间和“未联网刷新”,不自动 fetch。 |
|
||||
| 与产品 `system-admin-console` 命名冲突 | CLI、包和文档统一使用 `engineering-dashboard` / “个人工程中控台”。 |
|
||||
|
||||
---
|
||||
|
||||
## Implementation Units
|
||||
|
||||
### U1:冻结快照、事实与状态契约
|
||||
|
||||
**目标**:先建立不会把计划、实现、验证、部署混为一谈的模型与测试夹具。
|
||||
|
||||
**覆盖需求**:R4、R8、R10、R12、R13;承接 PKD-2 的同源快照决策。
|
||||
|
||||
**依赖**:无。
|
||||
|
||||
**文件**:
|
||||
|
||||
- `internal/engineeringdashboard/model.go`
|
||||
- `internal/engineeringdashboard/model_test.go`
|
||||
- `internal/engineeringdashboard/testdata/**`
|
||||
|
||||
**实施要点**:
|
||||
|
||||
1. 定义版本化 `Snapshot`、`SourceState`、`Fact`、`Conflict`、`TaskState`、`AgentClaim`、`EnvironmentState`。
|
||||
2. provenance 固定为 `declared|observed|verified|inferred`;freshness 固定为 `fresh|stale|error|unknown`。
|
||||
3. 状态使用可组合 facets:Git 分为 branch/worktree/merge/cleanliness/ahead-behind;验证分为 result/freshness/subject identity;部署分为 container/readiness/services/artifact identity。
|
||||
4. TaskState 保留 owner、agent kind、claim、mutex、声明分支、观测 worktree、最近活动时间及证据;声明与观测不可互相提升。
|
||||
5. 建立 rdev、dev ahead、main events restarting、CURRENT/worktree 不匹配等夹具。
|
||||
|
||||
**测试场景**:
|
||||
|
||||
- 文档 `done` 但无 merge/deploy 时,Git 与部署 facets 不改变;
|
||||
- `claimed` 但无可观测运行信号时,Agent 活动保持 unknown;Herdr 与产品 PI Runner 不共享类型;
|
||||
- 同字段多来源不一致时生成 conflict 并保留所有 fact 引用;
|
||||
- JSON round-trip 保留 schema 与 snapshot identity;
|
||||
- 枚举未知值失败且错误可定位。
|
||||
|
||||
**完成证据**:模型测试通过,schema 示例落入 Go fixture,不存在页面专用的第二套状态类型。
|
||||
|
||||
### U2:实现文档图谱与领域解析器
|
||||
|
||||
**目标**:将 `.doc` taxonomy、模块、任务、测试和链接转换为可追溯文档图谱。
|
||||
|
||||
**覆盖需求**:R3、R7、R10、R11、R14。
|
||||
|
||||
**依赖**:U1。
|
||||
|
||||
**文件**:
|
||||
|
||||
- `internal/engineeringdashboard/source_docs.go`
|
||||
- `internal/engineeringdashboard/docs_test.go`
|
||||
|
||||
**实施要点**:
|
||||
|
||||
1. 扫描 allowlist 内 Markdown,默认跳过任何 `assets` 目录正文;记录附件元数据。
|
||||
2. 解析 front matter、标题、显式 Markdown 链接和反向链接。
|
||||
3. 为 CURRENT、FEATURE-MATRIX、gap-matrix、任务文、module boundaries 和 test report 建立专用适配器;receipt 只在文档图谱中作为文档与链接,结构化解析归 U4。
|
||||
4. 区分 `broken`、`orphan`、`unindexed`;slug 相似只形成候选关系。
|
||||
5. 规范化路径并阻止 `..`、绝对路径和任何 symlink;最终目标再次应用扩展名 allowlist 与敏感路径 denylist。
|
||||
|
||||
**测试场景**:
|
||||
|
||||
- taxonomy 内文档可检索且反向链接正确;
|
||||
- broken link 不导致整个索引失败;
|
||||
- front matter 缺失或非标准时产生告警并仍可阅读;
|
||||
- assets 不读正文,越界 symlink 被拒绝;
|
||||
- rdev 文档链被发现,但没有被推断为已实现。
|
||||
|
||||
**完成证据**:文档索引能从 fixture 生成稳定 JSON,路径安全负例通过。
|
||||
|
||||
### U3:实现 Git 与 worktree 采集
|
||||
|
||||
**目标**:以只读 Git plumbing 形成可复现的分支、提交和 worktree 观测。
|
||||
|
||||
**覆盖需求**:R1、R4、R5、R10、R14。
|
||||
|
||||
**依赖**:U1。
|
||||
|
||||
**文件**:
|
||||
|
||||
- `internal/engineeringdashboard/source_git.go`
|
||||
- `internal/engineeringdashboard/git_test.go`
|
||||
|
||||
**实施要点**:
|
||||
|
||||
1. 抽象 command runner,固定 argv、工作目录、超时和输出上限。
|
||||
2. 收集当前分支/HEAD、dirty/untracked、local/remote-tracking refs、ahead/behind、merge-base 和 worktree。
|
||||
3. 不执行 fetch;remote tracking ref 始终带本地观测时间与免责声明。
|
||||
4. 对账任务声明的 branch/worktree,但不因路径名相似而认定一致。
|
||||
|
||||
**测试场景**:
|
||||
|
||||
- 本地分支领先 origin 时显示 ahead 且不显示“远端可用”;
|
||||
- worktree 目录名与真实检出分支不一致时生成 drift;
|
||||
- 命令超时、Git 不存在、非 Git 目录时单源 degraded;
|
||||
- runner 记录中不存在 shell、fetch、push 或写命令。
|
||||
|
||||
**完成证据**:临时 Git 仓库集成测试和 fake runner 单元测试通过。
|
||||
|
||||
### U4:实现运行态与部署证据采集
|
||||
|
||||
**目标**:按环境独立呈现容器、应用 readiness、服务完整性、schema、镜像和晋升凭证。
|
||||
|
||||
**覆盖需求**:R4、R6、R10、R14。
|
||||
|
||||
**依赖**:U1。
|
||||
|
||||
**文件**:
|
||||
|
||||
- `internal/engineeringdashboard/source_runtime.go`
|
||||
- `internal/engineeringdashboard/runtime_test.go`
|
||||
|
||||
**实施要点**:
|
||||
|
||||
1. 从仓库内批准的 Compose 静态配置和 allowlist labels 映射环境与服务;无法明确映射时显示 unknown,不用名称猜测。容器 JSON 只提取容器名、image/digest、状态、restart count、health,以及 allowlist 内的 Compose project/service labels;不复制 Env、Mounts、完整 NetworkSettings 或任意 labels。
|
||||
2. 对 allowlist 中的本地 `/ready` 端点执行短超时、响应大小受限的请求;禁用重定向,或对每一跳重新校验 scheme、解析后 IP、端口和 host。
|
||||
3. 解析 promotion receipt/candidate image 等仓库证据,保留 artifact identity。
|
||||
4. 将 container health、app readiness、required-service completeness 分开建模。
|
||||
|
||||
**测试场景**:
|
||||
|
||||
- app ready 且 events restarting 时同时保留两项状态;
|
||||
- Docker 不可用或 HTTP 超时时,其他数据源仍可输出;
|
||||
- receipt 与容器 image 不一致时生成 deployment drift;容器可达但 identity 缺失时标记“运行可见、版本未验证”;
|
||||
- readiness 重定向到外网或非 allowlist 本地端口时拒绝访问;
|
||||
- 输出中不存在容器环境变量或凭证。
|
||||
|
||||
**完成证据**:fixture 和 fake HTTP/Docker runner 测试通过,main 分叉场景被覆盖。
|
||||
|
||||
### U5:实现对账、派生视图与新鲜度
|
||||
|
||||
**目标**:把来源事实组合成用户可判断的视图,但不替来源做未经定义的裁决。
|
||||
|
||||
**覆盖需求**:R3、R4、R6、R8、R9、R10、R13。
|
||||
|
||||
**依赖**:U2、U3、U4。
|
||||
|
||||
**文件**:
|
||||
|
||||
- `internal/engineeringdashboard/reconcile.go`
|
||||
- `internal/engineeringdashboard/reconcile_test.go`
|
||||
|
||||
**实施要点**:
|
||||
|
||||
1. 按领域 SSOT 规则构建 module、task、environment 和 evidence-chain 视图。
|
||||
2. 实现 conflict 分类:declared-vs-observed、task-vs-git、test-vs-subject、receipt-vs-runtime、stale-source、missing-evidence。
|
||||
3. 快照构建期间每个来源独立记录 `observed_at`、持续时间和错误;成功后一次性发布。
|
||||
4. 失败源只可复用同一 serve 进程的 last-known,并标注 stale、age 与 last-success;冷启动无缓存时为 unknown/error。过期数据不隐藏,但按年龄提升告警级别。
|
||||
5. 测试报告只有在 commit/artifact identity 与当前 subject 对齐时才能派生 pass;身份缺失为 unbound,身份不匹配为 stale/drift。
|
||||
|
||||
**测试场景**:
|
||||
|
||||
- 三个真实样本得到预期多轴状态;
|
||||
- 同一组输入顺序变化不改变规范化快照;
|
||||
- 单源失败不会删除其他源,也不会重写 last-known 的观测时间;冷启动失败没有伪造 last-known;
|
||||
- 旧测试报告、新 HEAD 与不同 image 不会派生当前验证通过;
|
||||
- 恢复后 stale 自动清除并产生新 snapshot ID。
|
||||
|
||||
**完成证据**:reconcile table tests 覆盖一致、漂移、缺失、过期和恢复。
|
||||
|
||||
### U6:实现本地服务、总览与文档导航
|
||||
|
||||
**目标**:提供能快速判断异常并下钻证据的本地只读页面和 JSON。
|
||||
|
||||
**覆盖需求**:R1、R2、R3、R7–R10、R12–R14;承接 PKD-1 和 PKD-2。
|
||||
|
||||
**依赖**:U5。
|
||||
|
||||
**文件**:
|
||||
|
||||
- `internal/engineeringdashboard/server.go`
|
||||
- `internal/engineeringdashboard/server_test.go`
|
||||
- `internal/engineeringdashboard/assets/index.html`
|
||||
- `internal/engineeringdashboard/assets/app.js`
|
||||
- `internal/engineeringdashboard/assets/app.css`
|
||||
- `cmd/engineering-dashboard/main.go`
|
||||
|
||||
**实施要点**:
|
||||
|
||||
1. `serve --repo <path> --addr 127.0.0.1:<port>`;一期无条件拒绝所有非 loopback 地址,包括通配、IPv6 非 loopback 和显式传入值。
|
||||
2. 暴露 `/api/v1/snapshot`、`/api/v1/doc/<id>`、`/healthz`;所有接口只读。严格校验 Host/Origin/Fetch Metadata,不信任代理转发头;页面和 API 使用每次启动生成的不可预测访问令牌,降低 DNS rebinding 与跨站读取风险。
|
||||
3. 页面分为总览、架构/模块、任务、Git、部署、文档和证据链。
|
||||
4. 自动刷新完整快照,保留当前筛选、滚动位置、焦点和选中文档;ETag 未变化时不重绘。
|
||||
5. 明确一级视图状态:initial loading、fresh empty、fresh success、partial/degraded with last-known、hard error without cache、refreshing、recovered。刷新中继续展示上一完整快照,直到下一版本原子替换。
|
||||
6. 搜索覆盖标题、仓库相对路径、front matter 和未截断正文;不同维度用 AND、同一维度多选用 OR,默认先排当前任务和异常证据,再按匹配度与路径稳定排序。筛选、查询和选中文档写入 URL 参数,支持浏览器前进/后退与深链。
|
||||
7. 桌面优先;窄屏下侧栏变为可关闭抽屉,宽表格保留可横向滚动的语义表头,详情区单列。所有功能可键盘完成,使用 landmark/标题/表格语义,drift/degraded 不只靠颜色表达,自动刷新通过非打断式 live region 报告且不抢焦点。
|
||||
8. Markdown 正文只进入文本节点;在线页与导出页均设置限制性 CSP,不执行 HTML、脚本、SVG、远程 URL 或事件属性。
|
||||
|
||||
**测试场景**:
|
||||
|
||||
- 只监听 loopback,方法 allowlist 拒绝写请求;Host/Origin/token、DNS rebinding 和跨 Origin 负例被拒绝;
|
||||
- HTML 与 JSON 的 generation/revision identity 一致;
|
||||
- 文档 ID 越界、symlink 越界、未知 ID 返回安全错误;
|
||||
- degraded source 在总览可见且页面仍可导航;
|
||||
- 任务状态四轴、drift 和来源时间在浏览器中可见。
|
||||
- 首次加载、空数据、无缓存错误、刷新、恢复状态可区分;键盘、焦点、语义结构、窄屏和非颜色告警验收通过。
|
||||
- 搜索组合逻辑、排序、无结果、URL 深链和刷新后的视图保持通过。
|
||||
|
||||
**完成证据**:HTTP tests、基本无障碍检查和真实浏览器验收通过。
|
||||
|
||||
### U7:实现离线导出、启动脚本与治理文档
|
||||
|
||||
**目标**:生成安全、可携带、可追踪的单文件快照,并完成仓库治理接线。
|
||||
|
||||
**覆盖需求**:R1、R8、R9、R11、R14;承接 PKD-1 和 PKD-2。
|
||||
|
||||
**依赖**:U6。
|
||||
|
||||
**文件**:
|
||||
|
||||
- `internal/engineeringdashboard/export.go`
|
||||
- `internal/engineeringdashboard/export_test.go`
|
||||
- `scripts/engineering-dashboard.sh`
|
||||
- `.doc/status/FEATURE-MATRIX.md`
|
||||
- `.doc/ops/CURRENT.md`
|
||||
- `.doc/test-reports/YYYY-MM-DD-engineering-dashboard-test-report.md`
|
||||
|
||||
**实施要点**:
|
||||
|
||||
1. `export --repo <path> --output <file>` 构建一次不可变快照并原子写入;首次采集失败的来源显示 unknown/error。
|
||||
2. 以 HTML-safe JSON/等价编码内嵌允许的 Markdown 正文、索引和页面资源;附件保持元数据与相对链接,所有正文只写入文本节点。
|
||||
3. 默认权限 `0600`,输出页显示生成时间、repo、HEAD、snapshot ID 和 degraded/drift。
|
||||
4. 薄脚本只负责定位仓库与调用 Go CLI,不隐藏参数或执行安装/部署副作用。
|
||||
5. 实施期间按仓库规范更新 CURRENT、FEATURE-MATRIX 和 test report;完成后再迁移任务生命周期状态。
|
||||
|
||||
**测试场景**:
|
||||
|
||||
- 导出文件脱离仓库后仍能搜索和阅读 Markdown;
|
||||
- 导出中不含附件字节、绝对凭证路径、env 值或远程请求;`</script>`、事件属性、SVG、危险 URL scheme 和 Unicode 边界载荷不能逃逸数据上下文;
|
||||
- 默认 tracked/untracked 与敏感模式策略、inclusion manifest 和覆盖清单符合契约;
|
||||
- 采集部分失败时仍能导出并保留错误;
|
||||
- 输出中 JSON/HTML snapshot identity 一致,权限符合预期;
|
||||
- 大文档和总正文上限触发时明确标记截断。
|
||||
|
||||
**完成证据**:export tests、离线浏览器验收和治理文档回链完整。
|
||||
|
||||
---
|
||||
|
||||
## Verification Contract
|
||||
|
||||
### 自动验证
|
||||
|
||||
实施阶段至少运行:
|
||||
|
||||
```bash
|
||||
go test ./internal/engineeringdashboard/...
|
||||
go test ./cmd/engineering-dashboard/...
|
||||
go vet ./...
|
||||
go test -short ./...
|
||||
git diff --check
|
||||
```
|
||||
|
||||
涉及共享容器的只读验收也必须遵守 CURRENT 集成槽规则;中控台本身不得为测试启动、停止或重建共享容器。
|
||||
|
||||
### 契约验证矩阵
|
||||
|
||||
| 领域 | 必须证明 |
|
||||
|---|---|
|
||||
| 模型 | 计划、Git facets、验证、部署 facets 互不覆盖;Agent 声明和运行观测分离;所有派生结论可追溯到 facts。 |
|
||||
| 文档 | taxonomy、全文检索、反链、broken/unindexed、路径安全与 assets 排除。 |
|
||||
| Git | ahead/behind、worktree、dirty、local refs 新鲜度和无隐式 fetch。 |
|
||||
| 部署 | container/app/service 三类信号分离,receipt/artifact 身份可核对。 |
|
||||
| 降级 | 每个源超时、错误、stale、恢复都不会让整页不可用。 |
|
||||
| 实时 | 变化在目标时间内形成完整新快照,不出现半新半旧卡片。 |
|
||||
| 导出 | 单文件离线可读、默认 `0600`、不嵌 assets、不产生网络请求。 |
|
||||
| 安全 | loopback、Host/Origin/startup token、read-only methods、命令 allowlist、路径边界、Docker 字段 allowlist、CSP 与输出脱敏。 |
|
||||
|
||||
### 浏览器验收
|
||||
|
||||
1. 从总览进入 rdev,确认“计划/实施/验证/实装”四轴与源文档链接均可见。
|
||||
2. 在仓库外复制导出 HTML,断网打开并全文搜索、阅读至少一份设计与一份测试报告。
|
||||
3. 制造 fixture 中的 CURRENT/Docker/readiness 冲突,确认页面保留多值且不出现综合绿灯。
|
||||
4. 切换 fixture 快照,确认页面刷新后筛选条件和当前文档保持不变。
|
||||
5. 尝试路径穿越、未知文档、POST、DNS rebinding、跨 Origin、readiness 重定向和含原始 HTML/脚本逃逸载荷的 Markdown,确认均不能越界、外联或执行。
|
||||
|
||||
### 性能与容量验证
|
||||
|
||||
- 记录当前 `.doc` 规模下的冷启动、增量刷新、JSON 大小和 HTML 导出大小。
|
||||
- 建议一期门槛:UI shell 与来源状态在 2 秒内可交互,P95 完整快照重建不超过 5 秒,单源超时不超过 2 秒;基线不达标时必须记录实测并拆分后台正文索引,不能伪造 PASS。
|
||||
- 导出达到配置上限时必须显式列出被截断文档,不允许静默丢失。
|
||||
|
||||
---
|
||||
|
||||
## Definition of Done
|
||||
|
||||
- [ ] `serve` 和 `export` 在显式仓库根下可重复运行,且没有产品后台依赖。
|
||||
- [ ] 实时 HTML、离线 HTML 与 JSON 使用同一版本化快照契约。
|
||||
- [ ] `generation_id` 标识采集实例,`revision_id` 标识内容版本并驱动 ETag;无内容变化不会触发重绘。
|
||||
- [ ] 架构、模块、功能、任务、Git、部署、文档和证据链均可从页面访问。
|
||||
- [ ] 计划、实施、验证、实装四轴独立,rdev、dev ahead、main events 分叉样本通过。
|
||||
- [ ] Agent 认领与可观测活动分开,Herdr 工程 Agent 与产品 PI Agent Runner 不混称。
|
||||
- [ ] 所有 drift、degraded、stale 都带来源和时间,不存在未经定义的综合绿灯。
|
||||
- [ ] 默认 loopback、Host/Origin/startup token、只读命令、路径边界、脱敏、CSP 和 Markdown 安全测试通过。
|
||||
- [ ] 首次加载、空数据、部分失败、无缓存失败、恢复、键盘、窄屏和 URL 深链验收通过。
|
||||
- [ ] 导出 HTML 脱离仓库可读 Markdown,且不包含二进制 assets 或凭证数据。
|
||||
- [ ] 单元、集成、全仓短测、浏览器验收和 `git diff --check` 均有真实输出。
|
||||
- [ ] `.doc/test-reports` 报告回链任务文,FEATURE-MATRIX 与 CURRENT 按实际状态更新。
|
||||
- [ ] 没有遗留调试入口、写操作按钮、未使用的替代模型或与产品后台重名的组件。
|
||||
|
||||
---
|
||||
|
||||
## Appendix
|
||||
|
||||
### 一期交付边界
|
||||
|
||||
一期交付:本地只读服务、版本化快照 JSON、架构/任务/Git/部署/文档视图、四轴状态、drift/degraded、全文搜索、安全文档阅读和单 HTML 导出。
|
||||
|
||||
后续评估:跨快照历史趋势、远端托管/CI 聚合、受限富文本与 Mermaid、跨仓库聚合、面向 Agent 的筛选查询 API。
|
||||
|
||||
永久排除:在页面中修改文档、切换或推送分支、控制 Agent、执行部署、读取密钥、成为产品后台模块。
|
||||
|
||||
### 方案依据
|
||||
|
||||
- `.doc/README.md` 定义的文档 taxonomy 与生命周期;
|
||||
- `.doc/ops/CURRENT.md` 的焦点、认领、集成槽与环境声明;
|
||||
- `.doc/status/FEATURE-MATRIX.md` 的模块完成度口径;
|
||||
- `.doc/remediation/gap-matrix.md` 的发布门禁口径;
|
||||
- `.doc/system-design/README.md` 与模块边界清单;
|
||||
- Git/worktree、Docker/Compose、`/ready` 和 promotion receipts 的当前可观测能力。
|
||||
Reference in New Issue
Block a user